From 40ff0605e5fe480488bb1f399e9433d509f909fc Mon Sep 17 00:00:00 2001 From: Federico Pereira Date: Wed, 7 Oct 2026 16:19:26 -0300 Subject: [PATCH] Always send PictureID 0 in VP8Payloader With EnablePictureID, the frame whose PictureID is 0 was sent without the X and I bits, so it carried no PictureID at all. The ID wraps every 32768 frames (9 min 6 s at 60 fps), so a long stream had one frame without a PictureID among frames that had one. Chrome then lost the frame references and dropped every frame until the next keyframe: a freeze every 546 s, with no lost packets, NACKs or PLIs. Frame 0 now carries a 7-bit PictureID like every other ID under 128. --- codecs/vp8_packet.go | 1 - codecs/vp8_packet_test.go | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/codecs/vp8_packet.go b/codecs/vp8_packet.go index 569853c..f080532 100644 --- a/codecs/vp8_packet.go +++ b/codecs/vp8_packet.go @@ -39,7 +39,6 @@ func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { //nolint:c usingHeaderSize := vp8HeaderSize if p.EnablePictureID { switch { - case p.pictureID == 0: case p.pictureID < 128: usingHeaderSize = vp8HeaderSize + 2 default: diff --git a/codecs/vp8_packet_test.go b/codecs/vp8_packet_test.go index eb2d6cf..7b97946 100644 --- a/codecs/vp8_packet_test.go +++ b/codecs/vp8_packet_test.go @@ -143,6 +143,29 @@ func TestVP8Payloader_Payload(t *testing.T) { }, }, }, + "WithPictureID_wrap": { + payloader: VP8Payloader{ + EnablePictureID: true, + pictureID: 0x7FFF, + }, + mtu: 6, + payload: [][]byte{ + {0x90, 0x90}, + {0x91, 0x91}, + {0x92, 0x92}, + }, + expected: [][][]byte{ + { + {0x90, 0x80, 0xFF, 0xFF, 0x90, 0x90}, + }, + { + {0x90, 0x80, 0x00, 0x91, 0x91}, + }, + { + {0x90, 0x80, 0x01, 0x92, 0x92}, + }, + }, + }, } for name, testCase := range testCases { t.Run(name, func(t *testing.T) {