diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9ae683c..f3f9366 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,6 +22,9 @@ jobs: - run: go fmt . + - name: Patch + run: make patch + - uses: dominikh/staticcheck-action@v1.3.1 with: version: "2023.1.6" diff --git a/CHANGES.md b/CHANGES.md index e3484e8..96dff15 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,9 @@ ## develop +- [FIX] 高ビットレートの音声データの場合に、解析結果が送られてこない不具合を修正する + - @Hexa + ### misc ## 2024.4.0 diff --git a/Makefile b/Makefile index 806b282..4a92547 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ all: patch go build -o bin/suzu cmd/suzu/main.go patch: - patch -o oggwriter.go ./pion/oggwriter.go ./patch/oggwriter.go.patch + patch -o oggwriter.go ./_third_party/pion/oggwriter.go ./patch/oggwriter.go.patch + patch -o util.go ./_third_party/pion/util.go ./patch/util.go.patch test: diff --git a/pion/oggwriter.go b/_third_party/pion/oggwriter.go similarity index 90% rename from pion/oggwriter.go rename to _third_party/pion/oggwriter.go index 7c179e3..0852e38 100644 --- a/pion/oggwriter.go +++ b/_third_party/pion/oggwriter.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package oggwriter implements OGG media container writer package oggwriter @@ -7,9 +10,9 @@ import ( "io" "os" - "github.com/pion/randutil" "github.com/pion/rtp" "github.com/pion/rtp/codecs" + "github.com/pion/webrtc/v4/internal/util" ) const ( @@ -65,7 +68,7 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, stream: out, sampleRate: sampleRate, channelCount: channelCount, - serial: randutil.NewMathRandomGenerator().Uint32(), + serial: util.RandUint32(), checksumTable: generateChecksumTable(), // Timestamp and Granule MUST start from 1 @@ -146,7 +149,9 @@ const ( func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uint64, pageIndex uint32) []byte { i.lastPayloadSize = len(payload) - page := make([]byte, pageHeaderSize+1+i.lastPayloadSize) + nSegments := (len(payload) / 255) + 1 // A segment can be at most 255 bytes long. + + page := make([]byte, pageHeaderSize+i.lastPayloadSize+nSegments) copy(page[0:], pageHeaderSignature) // page headers starts with 'OggS' page[4] = 0 // Version @@ -154,14 +159,23 @@ func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uin binary.LittleEndian.PutUint64(page[6:], granulePos) // granule position binary.LittleEndian.PutUint32(page[14:], i.serial) // Bitstream serial number binary.LittleEndian.PutUint32(page[18:], pageIndex) // Page sequence number - page[26] = 1 // Number of segments in page, giving always 1 segment - page[27] = uint8(i.lastPayloadSize) // Segment Table inserting at 27th position since page header length is 27 - copy(page[28:], payload) // inserting at 28th since Segment Table(1) + header length(27) + page[26] = uint8(nSegments) // Number of segments in page. + + // Filling segment table with the lacing values. + // First (nSegments - 1) values will always be 255. + for i := 0; i < nSegments-1; i++ { + page[pageHeaderSize+i] = 255 + } + // The last value will be the remainder. + page[pageHeaderSize+nSegments-1] = uint8(len(payload) % 255) + + copy(page[pageHeaderSize+nSegments:], payload) // Payload goes after the segment table, so at pageHeaderSize+nSegments. var checksum uint32 for index := range page { checksum = (checksum << 8) ^ i.checksumTable[byte(checksum>>24)^page[index]] } + binary.LittleEndian.PutUint32(page[22:], checksum) // Checksum - generating for page data and inserting at 22th position into 32 bits return page diff --git a/_third_party/pion/util.go b/_third_party/pion/util.go new file mode 100644 index 0000000..966a623 --- /dev/null +++ b/_third_party/pion/util.go @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package util provides auxiliary functions internally used in webrtc package +package util + +import ( + "errors" + "strings" + + "github.com/pion/randutil" +) + +const ( + runesAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +) + +// Use global random generator to properly seed by crypto grade random. +var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals + +// MathRandAlpha generates a mathematical random alphabet sequence of the requested length. +func MathRandAlpha(n int) string { + return globalMathRandomGenerator.GenerateString(n, runesAlpha) +} + +// RandUint32 generates a mathematical random uint32. +func RandUint32() uint32 { + return globalMathRandomGenerator.Uint32() +} + +// FlattenErrs flattens multiple errors into one +func FlattenErrs(errs []error) error { + errs2 := []error{} + for _, e := range errs { + if e != nil { + errs2 = append(errs2, e) + } + } + if len(errs2) == 0 { + return nil + } + return multiError(errs2) +} + +type multiError []error //nolint:errname + +func (me multiError) Error() string { + var errstrings []string + + for _, err := range me { + if err != nil { + errstrings = append(errstrings, err.Error()) + } + } + + if len(errstrings) == 0 { + return "multiError must contain multiple error but is empty" + } + + return strings.Join(errstrings, "\n") +} + +func (me multiError) Is(err error) bool { + for _, e := range me { + if errors.Is(e, err) { + return true + } + if me2, ok := e.(multiError); ok { //nolint:errorlint + if me2.Is(err) { + return true + } + } + } + return false +} diff --git a/go.mod b/go.mod index 5cdb61c..c5e3d95 100644 --- a/go.mod +++ b/go.mod @@ -8,12 +8,12 @@ require ( github.com/labstack/echo-contrib v0.17.1 github.com/labstack/echo/v4 v4.12.0 github.com/pion/randutil v0.1.0 - github.com/pion/rtp v1.8.6 + github.com/pion/rtp v1.8.9 github.com/rs/zerolog v1.32.0 github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f - golang.org/x/net v0.24.0 - golang.org/x/sync v0.7.0 + golang.org/x/net v0.29.0 + golang.org/x/sync v0.8.0 google.golang.org/api v0.176.1 google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.33.0 @@ -46,6 +46,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/pion/webrtc/v4 v4.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.19.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -59,10 +60,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/oauth2 v0.19.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect diff --git a/go.sum b/go.sum index 7bb725a..f640911 100644 --- a/go.sum +++ b/go.sum @@ -203,6 +203,10 @@ github.com/pion/rtp v1.8.5 h1:uYzINfaK+9yWs7r537z/Rc1SvT8ILjBcmDOpJcTB+OU= github.com/pion/rtp v1.8.5/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw= github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= +github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/webrtc/v4 v4.0.1 h1:6Unwc6JzoTsjxetcAIoWH81RUM4K5dBc1BbJGcF9WVE= +github.com/pion/webrtc/v4 v4.0.1/go.mod h1:SfNn8CcFxR6OUVjLXVslAQ3a3994JhyE3Hw1jAuqEto= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -308,6 +312,8 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= @@ -362,6 +368,8 @@ golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= @@ -384,6 +392,8 @@ golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -408,6 +418,8 @@ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -416,6 +428,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/handler.go b/handler.go index eddb06b..17683c2 100644 --- a/handler.go +++ b/handler.go @@ -326,13 +326,6 @@ func opus2ogg(ctx context.Context, opusReader io.Reader, oggWriter io.Writer, sa } defer o.Close() - if err := o.writeHeaders(); err != nil { - if w, ok := oggWriter.(*io.PipeWriter); ok { - w.CloseWithError(err) - } - return err - } - var r io.Reader if c.AudioStreamingHeader { r, err = readPacketWithHeader(opusReader) diff --git a/oggwriter.go b/oggwriter.go index d0f95a7..0504a86 100644 --- a/oggwriter.go +++ b/oggwriter.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package oggwriter implements OGG media container writer package suzu import ( @@ -6,7 +10,6 @@ import ( "io" "os" - "github.com/pion/randutil" "github.com/pion/rtp" "github.com/pion/rtp/codecs" ) @@ -19,7 +22,6 @@ const ( idPageSignature = "OpusHead" commentPageSignature = "OpusTags" pageHeaderSignature = "OggS" - vendorName = "pion" ) var ( @@ -65,7 +67,7 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, stream: out, sampleRate: sampleRate, channelCount: channelCount, - serial: randutil.NewMathRandomGenerator().Uint32(), + serial: RandUint32(), checksumTable: generateChecksumTable(), // Timestamp and Granule MUST start from 1 @@ -73,6 +75,9 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, previousTimestamp: 1, previousGranulePosition: 1, } + if err := writer.writeHeaders(); err != nil { + return nil, err + } return writer, nil } @@ -80,6 +85,7 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, /* ref: https://tools.ietf.org/html/rfc7845.html https://git.xiph.org/?p=opus-tools.git;a=blob;f=src/opus_header.c#l219 + Page 0 Pages 1 ... n Pages (n+1) ... +------------+ +---+ +---+ ... +---+ +-----------+ +---------+ +-- | | | | | | | | | | | | | @@ -95,6 +101,7 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, | ID header is contained on a single page | 'Beginning Of Stream' + Figure 1: Example Packet Organization for a Logical Ogg Opus Stream */ @@ -119,11 +126,11 @@ func (i *OggWriter) writeHeaders() error { i.pageIndex++ // Comment Header - oggCommentHeader := make([]byte, (8 + len(vendorName) + 4 + 4)) - copy(oggCommentHeader[0:], commentPageSignature) // Magic Signature 'OpusTags' - binary.LittleEndian.PutUint32(oggCommentHeader[8:], uint32(len(vendorName))) // Vendor Length - copy(oggCommentHeader[12:], vendorName) // Vendor name 'pion' - binary.LittleEndian.PutUint32(oggCommentHeader[16:], 0) // User Comment List Length + oggCommentHeader := make([]byte, 21) + copy(oggCommentHeader[0:], commentPageSignature) // Magic Signature 'OpusTags' + binary.LittleEndian.PutUint32(oggCommentHeader[8:], 5) // Vendor Length + copy(oggCommentHeader[12:], "pion") // Vendor name 'pion' + binary.LittleEndian.PutUint32(oggCommentHeader[17:], 0) // User Comment List Length // RFC specifies that the page where the CommentHeader completes should have a granule position of 0 data = i.createPage(oggCommentHeader, pageHeaderTypeContinuationOfStream, 0, i.pageIndex) @@ -141,7 +148,9 @@ const ( func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uint64, pageIndex uint32) []byte { i.lastPayloadSize = len(payload) - page := make([]byte, pageHeaderSize+1+i.lastPayloadSize) + nSegments := (len(payload) / 255) + 1 // A segment can be at most 255 bytes long. + + page := make([]byte, pageHeaderSize+i.lastPayloadSize+nSegments) copy(page[0:], pageHeaderSignature) // page headers starts with 'OggS' page[4] = 0 // Version @@ -149,14 +158,23 @@ func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uin binary.LittleEndian.PutUint64(page[6:], granulePos) // granule position binary.LittleEndian.PutUint32(page[14:], i.serial) // Bitstream serial number binary.LittleEndian.PutUint32(page[18:], pageIndex) // Page sequence number - page[26] = 1 // Number of segments in page, giving always 1 segment - page[27] = uint8(i.lastPayloadSize) // Segment Table inserting at 27th position since page header length is 27 - copy(page[28:], payload) // inserting at 28th since Segment Table(1) + header length(27) + page[26] = uint8(nSegments) // Number of segments in page. + + // Filling segment table with the lacing values. + // First (nSegments - 1) values will always be 255. + for i := 0; i < nSegments-1; i++ { + page[pageHeaderSize+i] = 255 + } + // The last value will be the remainder. + page[pageHeaderSize+nSegments-1] = uint8(len(payload) % 255) + + copy(page[pageHeaderSize+nSegments:], payload) // Payload goes after the segment table, so at pageHeaderSize+nSegments. var checksum uint32 for index := range page { checksum = (checksum << 8) ^ i.checksumTable[byte(checksum>>24)^page[index]] } + binary.LittleEndian.PutUint32(page[22:], checksum) // Checksum - generating for page data and inserting at 22th position into 32 bits return page diff --git a/patch/oggwriter.go.patch b/patch/oggwriter.go.patch index 093a6d6..fe84ef7 100644 --- a/patch/oggwriter.go.patch +++ b/patch/oggwriter.go.patch @@ -1,60 +1,28 @@ ---- oggwriter.go.org 2023-01-17 12:52:08 -+++ oggwriter.go 2023-01-17 16:18:23 -@@ -1,5 +1,4 @@ --// Package oggwriter implements OGG media container writer +--- oggwriter.go.org 2024-10-24 10:52:25 ++++ oggwriter.go 2024-10-24 10:49:11 +@@ -2,7 +2,7 @@ + // SPDX-License-Identifier: MIT + + // Package oggwriter implements OGG media container writer -package oggwriter +package suzu import ( "encoding/binary" -@@ -20,6 +19,7 @@ - idPageSignature = "OpusHead" - commentPageSignature = "OpusTags" - pageHeaderSignature = "OggS" -+ vendorName = "pion" - ) - - var ( -@@ -73,9 +73,6 @@ - previousTimestamp: 1, - previousGranulePosition: 1, - } -- if err := writer.writeHeaders(); err != nil { -- return nil, err -- } +@@ -12,7 +12,6 @@ - return writer, nil - } -@@ -83,7 +80,6 @@ - /* - ref: https://tools.ietf.org/html/rfc7845.html - https://git.xiph.org/?p=opus-tools.git;a=blob;f=src/opus_header.c#l219 -- - Page 0 Pages 1 ... n Pages (n+1) ... - +------------+ +---+ +---+ ... +---+ +-----------+ +---------+ +-- - | | | | | | | | | | | | | -@@ -99,7 +95,6 @@ - | ID header is contained on a single page - | - 'Beginning Of Stream' -- - Figure 1: Example Packet Organization for a Logical Ogg Opus Stream - */ - -@@ -124,11 +119,11 @@ - i.pageIndex++ + "github.com/pion/rtp" + "github.com/pion/rtp/codecs" +- "github.com/pion/webrtc/v4/internal/util" + ) - // Comment Header -- oggCommentHeader := make([]byte, 21) -- copy(oggCommentHeader[0:], commentPageSignature) // Magic Signature 'OpusTags' -- binary.LittleEndian.PutUint32(oggCommentHeader[8:], 5) // Vendor Length -- copy(oggCommentHeader[12:], "pion") // Vendor name 'pion' -- binary.LittleEndian.PutUint32(oggCommentHeader[17:], 0) // User Comment List Length -+ oggCommentHeader := make([]byte, (8 + len(vendorName) + 4 + 4)) -+ copy(oggCommentHeader[0:], commentPageSignature) // Magic Signature 'OpusTags' -+ binary.LittleEndian.PutUint32(oggCommentHeader[8:], uint32(len(vendorName))) // Vendor Length -+ copy(oggCommentHeader[12:], vendorName) // Vendor name 'pion' -+ binary.LittleEndian.PutUint32(oggCommentHeader[16:], 0) // User Comment List Length + const ( +@@ -68,7 +67,7 @@ + stream: out, + sampleRate: sampleRate, + channelCount: channelCount, +- serial: util.RandUint32(), ++ serial: RandUint32(), + checksumTable: generateChecksumTable(), - // RFC specifies that the page where the CommentHeader completes should have a granule position of 0 - data = i.createPage(oggCommentHeader, pageHeaderTypeContinuationOfStream, 0, i.pageIndex) + // Timestamp and Granule MUST start from 1 diff --git a/patch/util.go.patch b/patch/util.go.patch new file mode 100644 index 0000000..2a923c6 --- /dev/null +++ b/patch/util.go.patch @@ -0,0 +1,11 @@ +--- util.go.org 2024-10-24 10:53:48 ++++ util.go 2024-10-24 10:50:15 +@@ -2,7 +2,7 @@ + // SPDX-License-Identifier: MIT + + // Package util provides auxiliary functions internally used in webrtc package +-package util ++package suzu + + import ( + "errors"