fix(video): treat NOT_READY as transient with one IDR on resume#594
Open
mariotaku wants to merge 2 commits into
Open
fix(video): treat NOT_READY as transient with one IDR on resume#594mariotaku wants to merge 2 commits into
mariotaku wants to merge 2 commits into
Conversation
Pairs with the ss4s FeedGuard exclusive primitive (ss4s #16) that drains in-flight Feeds across SetHDRInfo and SizeChanged. During those brief windows, SS4S_PlayerVideoFeed returns SS4S_VIDEO_FEED_NOT_READY instead of running on a half-torn-down decoder. vdec_delegate_submit previously treated any non-OK / non-KEYFRAME return as fatal and called session_interrupt(STREAMING_INTERRUPT_DECODER), which tore the stream down on every HDR toggle and every resolution change. Handle NOT_READY as transient: - Drop the current frame silently (return DR_OK), set need_idr_on_resume = true. - On the next successful Feed, consume the flag and return one DR_NEED_IDR so Limelight resends a keyframe and the decoder resyncs from a known-good frame instead of decoding the next P-frame against the data it never saw. - Exactly one IDR request per outage, regardless of how many frames got dropped during the exclusive window. Reset the flag in vdec_delegate_setup so stream restarts don't inherit stale state. Bumps the ss4s submodule to pick up #16 (FeedGuard exclusive), #17 (CI test pipeline), and #18 (ASan CI pipeline). Supersedes #593 (which suppressed the SetHDRInfo(NULL) call on MAIN10 as a workaround). With this fix the toggle works correctly without suppression, and SizeChanged gets the same treatment for free.
This was referenced May 31, 2026
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.
Summary
Companion to ss4s #16 (FeedGuard exclusive primitive) — closes the original race that #593 worked around, but does it correctly so HDR toggle and resolution changes actually work mid-stream instead of being silently suppressed.
Background
SS4S_PlayerVideoSetHDRInfo(NULL)onndl-webos5(andSS4S_PlayerVideoSizeChangedon most LG/NDL backends) internally callsNDL_DirectMediaUnload + NDL_DirectMediaLoad. Before ss4s #16, an in-flightdriver->Feedcould be running on the half-torn-down decoder and crash the stream. PR #593 worked around this by skipping theSetHDRInfo(NULL)call entirely for MAIN10 streams.ss4s #16 added a proper drain primitive (
BeginExclusive/EndExclusiveon theFeedGuard): during the destructive op,FeedreturnsSS4S_VIDEO_FEED_NOT_READYso it never reaches the driver. But the app side still tears down the stream onNOT_READYbecause it falls into the default error path:So the race is gone, but every HDR toggle still kills the stream.
Fix
Handle
NOT_READYas a transient signal invdec_delegate_submit:OK(first one afterNOT_READY)DR_NEED_IDR— server resends a keyframe so the decoder resyncs from known-good data instead of a P-frame referencing the gapOK(steady state)DR_OK, normal stats bookkeepingNOT_READYDR_OK), setneed_idr_on_resume = true. Nosession_interrupt, noDR_NEED_IDRspam — exactly one IDR request per outage no matter how long it lasts.REQUEST_KEYFRAMEDR_NEED_IDR(existing)session_interrupt(STREAMING_INTERRUPT_DECODER)(existing — real driver errors still tear the stream down)Resets
need_idr_on_resume = falseinvdec_delegate_setupso stream restarts don't inherit stale state.Bumps
Submodule pin
60d980a2→ab442770. Picks up:fix(video): drain Feed during SetHDRInfo and SizeChanged (#16)— the exclusive primitive this PR pairs withci: run tests on every push and pull request (#17)ci: add AddressSanitizer pipeline (with dynamic libasan) (#18)Comparison with #593
SizeChangedraceRecommend closing #593 in favor of this combined fix.
Test plan
cmake --build build/webos-debug --target moonlightcleanSizeChangeduses the same primitive; should also survive without tear-down (previously this race was latent — same shape as the HDR one but no one had hit it)NOT_READYpath is new)🤖 Generated with Claude Code