From 5a7ea12182385ab0e751b8b73a4f9942de28148c Mon Sep 17 00:00:00 2001 From: Jo Turk Date: Sat, 31 Jan 2026 17:14:48 +0200 Subject: [PATCH] Do not validate non spec obu-size --- codecs/av1_depacketizer.go | 31 ++++++++++++++++++++----------- codecs/av1_depacketizer_test.go | 24 ++++++++++++++++++++---- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/codecs/av1_depacketizer.go b/codecs/av1_depacketizer.go index d9dbbcd..8b04e49 100644 --- a/codecs/av1_depacketizer.go +++ b/codecs/av1_depacketizer.go @@ -21,6 +21,20 @@ type AV1Depacketizer struct { videoDepacketizer } +func (d *AV1Depacketizer) appendOBUWithCalculatedSize( + buff []byte, + obuHeader *obu.Header, + obuBuffer []byte, + payloadOffset int, +) []byte { + obuPayloadSize := len(obuBuffer) - payloadOffset + buff = append(buff, obuHeader.Marshal()...) + buff = append(buff, obu.WriteToLeb128(uint(obuPayloadSize))...) // nolint: gosec // G104 + buff = append(buff, obuBuffer[payloadOffset:]...) + + return buff +} + // Unmarshal parses an AV1 RTP payload into its constituent OBUs stream with obu_size_field, // It assumes that the payload is in order (e.g. the caller is responsible for reordering RTP packets). // If the last OBU in the payload is fragmented, it will be stored in the buffer until the @@ -144,22 +158,17 @@ func (d *AV1Depacketizer) Unmarshal(payload []byte) (buff []byte, err error) { return nil, err } - // We validate the obu_size_field if it is present. + // Ignore obu_size_field if it is present and doesn't match the calculated size. sizeFromOBUSize := obuHeader.Size() + int(obuSize) + int(n) //nolint:gosec if lengthField != sizeFromOBUSize { - return nil, fmt.Errorf( - "%w: OBU size %d does not match calculated size %d", - errShortPacket, obuSize, sizeFromOBUSize, - ) + payloadOffset := obuHeader.Size() + int(n) //nolint:gosec // n is small, LEB128. + buff = d.appendOBUWithCalculatedSize(buff, obuHeader, obuBuffer, payloadOffset) + } else { + buff = append(buff, obuBuffer...) } - - buff = append(buff, obuBuffer...) } else { obuHeader.HasSizeField = true - buff = append(buff, obuHeader.Marshal()...) - size := len(obuBuffer) - obuHeader.Size() - buff = append(buff, obu.WriteToLeb128(uint(size))...) // nolint: gosec // G104 - buff = append(buff, obuBuffer[obuHeader.Size():]...) + buff = d.appendOBUWithCalculatedSize(buff, obuHeader, obuBuffer, obuHeader.Size()) } if isLast { diff --git a/codecs/av1_depacketizer_test.go b/codecs/av1_depacketizer_test.go index 2fd725c..bdfa00e 100644 --- a/codecs/av1_depacketizer_test.go +++ b/codecs/av1_depacketizer_test.go @@ -114,6 +114,7 @@ func TestAV1Depacketizer_validateOBUSize(t *testing.T) { tests := []struct { name string payload []byte + expect []byte err error }{ { @@ -135,7 +136,11 @@ func TestAV1Depacketizer_validateOBUSize(t *testing.T) { 0x04, // LEB128 size 0x03, 0x01, 0x02, // OBU data }, - err: errShortPacket, + expect: []byte{ + 0x22, // OBU header + 0x03, // Corrected size + 0x03, 0x01, 0x02, // OBU data + }, }, { name: "OBU size smaller than length field", @@ -146,15 +151,26 @@ func TestAV1Depacketizer_validateOBUSize(t *testing.T) { 0x02, // LEB128 size 0x03, 0x01, 0x02, // OBU data }, - err: errShortPacket, + expect: []byte{ + 0x22, // OBU header + 0x03, // Corrected size + 0x03, 0x01, 0x02, // OBU data + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := AV1Depacketizer{} - _, err := d.Unmarshal(tt.payload) - assert.ErrorIs(t, err, tt.err) + obu, err := d.Unmarshal(tt.payload) + if tt.err != nil { + assert.ErrorIs(t, err, tt.err) + + return + } + + assert.NoError(t, err) + assert.Equal(t, tt.expect, obu) }) } }