Repository navigation
Conversation
ehfd
added a commit
to selkies-project/pixelflux
that referenced
this pull request
Sep 29, 2026
…ch served never comes from Selkies' clients This reverts 362f11e, which vendored openh264-sys2 0.9.8 (344 files of OpenH264's source) to carry a three-line fix to its single-threaded FlushFrame, together with 4b725e3's release note and 93a3b08's twelve-frame VA-API device check, which passed on Mesa 24.0.5 only through that fix. The flush stalls only on H.264 above the baseline profile, and every H.264 stream Selkies' clients send is Constrained Baseline: the WebSockets webcam encodes avc1.42E01F, and the WebRTC codec list carries Baseline, Constrained Baseline, and High 4:4:4, which no browser encodes. OpenH264 never holds a Baseline picture, so the flush never runs on one. The fix is proposed upstream as cisco/openh264#4037, against master, which still has the bug. Reproduced upstream with DecodeFrameNoDelay and a FlushFrame after each access unit that returned no picture: a High-profile stream without B-frames whose picture order count steps by two gives 4 of 30 pictures and then none on v2.6.0 and on master, an x264 Main stream with B-frames 7 and 10; with the fix, 30 of 30 each, and an x264 Baseline stream 30 of 30 on every version. The scalable-extension test now decodes a Constrained Baseline stream, and still fails with the extension units let through; the flush's comment names the limitation. cargo test --lib passes in both configurations (403 and 396), and scripts/check-licenses.py passes.
Author
|
The |
FlushFrame() releases the pictures it hands over through
ReleaseBufferedReadyPictureReorder() and ReleaseBufferedReadyPictureNoReorder()
with a NULL context. Both then drop the picture's reference through
m_pPicBuff, which only threaded decoding sets (in ParseAccessUnit()), so a
single-threaded decoder never gets the picture's buffer back. A flush at the
end of a stream hides this, but a low-latency caller that flushes after each
access unit that returns no picture runs the pool dry after a few pictures,
and the decode stops with
Error:DecodeCurrentAccessUnit()::::::PrefetchPic ERROR, pSps->iNumRefFrames:2.
A High profile stream without B-frames whose picture order count steps by
two has every picture held for reordering: flushing after each access unit
took 4 of its 30 pictures, then none, on v2.6.0 and on master. An x264 Main
profile stream with B-frames flushed the same way stopped after 10 pictures.
Both functions now take the single-threaded context when given none, before
choosing the picture buffer; ReleaseBufferedReadyPictureReorder() already
took it, but only after that choice. Threaded decoding keeps using
m_pPicBuff. The new DecoderFlushFrame test decodes such a stream that way
and expects a picture from every access unit.
ehfd
force-pushed
the
flush-frame-release
branch
from
October 20, 2026 08:13
6b49ebf to
c167a4a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FlushFrame() hands the pictures it releases to ReleaseBufferedReadyPictureReorder() and ReleaseBufferedReadyPictureNoReorder() with a NULL context. Both then drop the picture's reference through m_pPicBuff, which only threaded decoding sets (in ParseAccessUnit()), so a single-threaded decoder never gets the picture's buffer back. A flush at the end of a stream hides this, but a low-latency caller that flushes after each access unit that returns no picture runs the pool dry after a few pictures, and decoding stops with
PrefetchPic ERROR(dsOutOfMemory).It bites a High profile stream without B-frames whose picture order count steps by two, which some hardware encoders write (we met it with AMD VCE output under Mesa 24.0): the decoder holds every such picture for reordering, and a flush after each access unit is the only way to take each one without a frame of delay. With DecodeFrameNoDelay() and a FlushFrame() after each access unit that returned no picture:
Both functions now take the single-threaded context when given none, before choosing the picture buffer; ReleaseBufferedReadyPictureReorder() already took it, but only after that choice. Threaded decoding is unchanged and keeps using m_pPicBuff.
The new
DecoderFlushFrame.FlushAfterEachAccessUnitKeepsDecodingtest decodesres/High_POC_step2_32x32_30frames.264(1.8 KB: an I_PCM IDR, then P pictures of skipped macroblocks) that way and expects a picture from every access unit. On Linux x86_64 with meson (release):test_api209 of 209 andtest_decoder61 of 61 with the change; without it,test_apifails only the new test.