From 38e75cb5cf29f8e66c36f5e228a12c7821137a85 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 20 Sep 2022 22:29:27 -0400 Subject: [PATCH] Upgrade oggreader to be segment aware --- examples/decode/main.go | 41 ++++++++++++++++++++------------- pkg/oggreader/oggreader.go | 46 +++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/examples/decode/main.go b/examples/decode/main.go index 658f0dd..4595609 100644 --- a/examples/decode/main.go +++ b/examples/decode/main.go @@ -2,8 +2,8 @@ package main import ( "bytes" + "encoding/binary" "errors" - "fmt" "io" "os" @@ -11,15 +11,18 @@ import ( "github.com/pion/opus/pkg/oggreader" ) -func main() { - decoder := opus.NewDecoder() +func convertFloatToByteSlice(i []float32) []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, i) + return buf.Bytes() +} - homeDir, err := os.UserHomeDir() - if err != nil { - panic(err) +func main() { + if len(os.Args) != 3 { + panic("Usage: ") } - file, err := os.Open(homeDir + "/opus/silk.ogg") + file, err := os.Open(os.Args[1]) if err != nil { panic(err) } @@ -29,12 +32,19 @@ func main() { panic(err) } - out := make([]float64, 320) + out := make([]float32, 320) + f, err := os.Create(os.Args[2]) + if err != nil { + panic(err) + } + + decoder := opus.NewDecoder() for { - pageData, _, err := ogg.ParseNextPage() + segments, _, err := ogg.ParseNextPage() + if errors.Is(err, io.EOF) { break - } else if bytes.HasPrefix(pageData, []byte("OpusTags")) { + } else if bytes.HasPrefix(segments[0], []byte("OpusTags")) { continue } @@ -42,11 +52,12 @@ func main() { panic(err) } - bandwidth, isStereo, err := decoder.Decode(pageData, out) - if err != nil { - panic(err) - } + for i := range segments { + if _, _, err = decoder.Decode(segments[i], out); err != nil { + panic(err) + } - fmt.Printf("bandwidth(%s) isStereo(%t) framesCount(%d)\n", bandwidth.String(), isStereo, len(out)) + f.Write(floatarrtobytes(out)) + } } } diff --git a/pkg/oggreader/oggreader.go b/pkg/oggreader/oggreader.go index cd14a01..67fce7c 100644 --- a/pkg/oggreader/oggreader.go +++ b/pkg/oggreader/oggreader.go @@ -89,7 +89,7 @@ func newWith(in io.Reader, doChecksum bool) (*OggReader, *OggHeader, error) { } func (o *OggReader) readHeaders() (*OggHeader, error) { - payload, pageHeader, err := o.ParseNextPage() + segments, pageHeader, err := o.ParseNextPage() if err != nil { return nil, err } @@ -103,27 +103,27 @@ func (o *OggReader) readHeaders() (*OggHeader, error) { return nil, errBadIDPageType } - if len(payload) != idPagePayloadLength { + if len(segments[0]) != idPagePayloadLength { return nil, errBadIDPageLength } - if s := string(payload[:8]); s != idPageSignature { + if s := string(segments[0][:8]); s != idPageSignature { return nil, errBadIDPagePayloadSignature } - header.Version = payload[8] - header.Channels = payload[9] - header.PreSkip = binary.LittleEndian.Uint16(payload[10:12]) - header.SampleRate = binary.LittleEndian.Uint32(payload[12:16]) - header.OutputGain = binary.LittleEndian.Uint16(payload[16:18]) - header.ChannelMap = payload[18] + header.Version = segments[0][8] + header.Channels = segments[0][9] + header.PreSkip = binary.LittleEndian.Uint16(segments[0][10:12]) + header.SampleRate = binary.LittleEndian.Uint32(segments[0][12:16]) + header.OutputGain = binary.LittleEndian.Uint16(segments[0][16:18]) + header.ChannelMap = segments[0][18] return header, nil } -// ParseNextPage reads from stream and returns Ogg page payload, header, +// ParseNextPage reads from stream and returns Ogg page segments, header, // and an error if there is incomplete page data. -func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { +func (o *OggReader) ParseNextPage() ([][]byte, *OggPageHeader, error) { h := make([]byte, pageHeaderLen) n, err := io.ReadFull(o.stream, h) @@ -149,14 +149,15 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { return nil, nil, err } - payloadSize := 0 - for _, s := range sizeBuffer { - payloadSize += int(s) - } + segments := [][]byte{} - payload := make([]byte, payloadSize) - if _, err = io.ReadFull(o.stream, payload); err != nil { - return nil, nil, err + for _, s := range sizeBuffer { + segment := make([]byte, int(s)) + if _, err = io.ReadFull(o.stream, segment); err != nil { + return nil, nil, err + } + + segments = append(segments, segment) } if o.doChecksum { @@ -177,8 +178,11 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { for _, s := range sizeBuffer { updateChecksum(s) } - for index := range payload { - updateChecksum(payload[index]) + + for i := range segments { + for index := range segments[i] { + updateChecksum(segments[i][index]) + } } if binary.LittleEndian.Uint32(h[22:22+4]) != checksum { @@ -186,7 +190,7 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { } } - return payload, pageHeader, nil + return segments, pageHeader, nil } // ResetReader resets the internal stream of OggReader. This is useful