diff --git a/go.mod b/go.mod index 438d886..a1251c5 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module git.netflux.io/rob/avframes go 1.15 + +require github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7b4dc41 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index ed4d18d..75e0c42 100644 --- a/main.go +++ b/main.go @@ -2,16 +2,32 @@ package main import ( "bufio" + "errors" "fmt" "io" "log" "os" ) -const fname = "/home/rob/Desktop/example.mp3" +const fname = "/home/rob/home-office/example.mp3" -const syncHeader1 = 0xFF -const syncHeader2 = 0xFE +const ( + maskSync = 0b11111111111000000000000000000000 + maskVersion = 0b00000000000110000000000000000000 + maskLayer = 0b00000000000001100000000000000000 + maskProtection = 0b00000000000000010000000000000000 + maskBitrate = 0b00000000000000001111000000000000 + maskSamplerate = 0b00000000000000000000110000000000 + maskPadding = 0b00000000000000000000001000000000 + maskPrivate = 0b00000000000000000000000100000000 + maskChannelMode = 0b00000000000000000000000011000000 + maskExtension = 0b00000000000000000000000000110000 + maskCopyright = 0b00000000000000000000000000001000 + maskOriginal = 0b00000000000000000000000000000100 + maskEmphasis = 0b00000000000000000000000000000011 +) + +type header uint32 func main() { f, err := os.Open(fname) @@ -26,18 +42,34 @@ func main() { for { _, err := io.ReadFull(bufreader, buf) if err != nil { + if err == io.EOF { + break + } log.Fatal(err) } - if parseBytes(buf) { - fmt.Printf("Got possible header %X at %d\n", buf, i) - } + header, err := newHeader(buf) + if err == nil { + fmt.Printf("Got header: %08X\n", header) + } i++ - bufreader.UnreadByte() + + bufreader.Discard(3) } } -func parseBytes(buf []byte) bool { - return buf[0]&syncHeader1 == syncHeader1 || buf[0]&syncHeader2 == syncHeader2 +// TODO use unsafe here? https://codereview.stackexchange.com/a/60161 +func newHeader(buf []byte) (header, error) { + if len(buf) < 4 { + return 0, errors.New("insufficient bytes") + } + if buf[0] != 0xFF || buf[1]&0xE0 != 0xE0 { + return 0, errors.New("no header") + } + + // always little-endian for now + n := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + + return header(n), nil } diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..11f2218 --- /dev/null +++ b/main_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMain(t *testing.T) { + testCases := []struct { + input []byte + expectedError string + }{ + { + input: []byte{0, 0, 0, 0}, + expectedError: "no header", + }, + { + input: []byte{0, 0, 0, 1}, + expectedError: "no header", + }, + { + input: []byte{0xff, 0xfe, 0, 0}, // wrong + expectedError: "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Header %08b", tc.input), func(t *testing.T) { + _, err := newHeader(tc.input) + assert.EqualError(t, err, tc.expectedError) + }) + } +}