Skip to content

Always send PictureID 0 in VP8Payloader - #376

Merged
JoTurk merged 1 commit into
pion:mainfrom
lordbasex:vp8-pictureid-zero
Oct 8, 2026
Merged

JoTurk merged 1 commit into
pion:mainfrom
lordbasex:vp8-pictureid-zero

Conversation

@lordbasex

Copy link
Copy Markdown
Contributor

Description

With EnablePictureID, VP8Payloader sends the frame whose PictureID is 0 without the X and I bits, so that frame carries no PictureID (case p.pictureID == 0: keeps the bare 1-byte descriptor). The ID wraps to 0 every 32768 frames, so any stream longer than that has one frame without a PictureID among thousands that have one.

Chrome then loses the frame references and drops every frame until the next keyframe. At 60 fps this is a freeze every 546 s (9 min 6 s), with no lost packets, no NACKs and no PLIs. Its length depends on how far the next keyframe is: with a keyframe every 180 frames, 32768 = 182 × 180 + 8, so each freeze was 8 frames (~133 ms) shorter than the one before.

We found it in a game-streaming app built on Pion (TrackLocalStaticSample + VP8). The browser's inbound-rtp stats showed framesReceived dropping to 17-24 per second for under a second at exactly every 546 s, while the sender kept 60 fps. The predicted times matched to the second (three in a row), and the freezes were gone after sending a PictureID on every frame (two hours, 443,928 frames, 13 wraps, no freezes).

This change sends frame 0 with a 7-bit PictureID, like every other ID under 128. The new WithPictureID_wrap test fails without it (frame 0 comes out as {0x10, 0x91, 0x91}).

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.

@JoTurk JoTurk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. ty

@codecov

codecov Bot commented Oct 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.48%. Comparing base (d312bf6) to head (40ff060).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #376      +/-   ##
==========================================
+ Coverage   87.45%   87.48%   +0.02%     
==========================================
  Files          28       28              
  Lines        3173     3172       -1     
==========================================
  Hits         2775     2775              
+ Misses        398      397       -1     
Flag Coverage Δ
go 87.48% <ø> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JoTurk
JoTurk merged commit cbf78a2 into pion:main Oct 8, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants