Retry FFmpeg decoder packets rejected with EAGAIN - #119
Blackspirits wants to merge 1 commit into
Conversation
Blackspirits
left a comment
There was a problem hiding this comment.
Final adversarial review on frozen HEAD 7d4322e310d4c8eef6ebb8de61daaafda7834b84 after CI SubtitleEdit#250.
Rechecked libavcodec packet ownership and send/receive ordering for video, audio, drain packets, hardware fallback, close, and a newer seek arriving while a rejected packet is being drained. A packet rejected with AVERROR(EAGAIN) is retained until receive-side progress is drained and is then resent; it is not retried after close/seek invalidates its serial, and it is freed exactly once on every exit path.
Also rechecked the impossible-state guard: FFmpeg documents that send and receive may not both remain in EAGAIN, so the no-progress path logs and drops instead of spinning forever.
CI SubtitleEdit#250 passed restore, build, and the full suite on this exact HEAD: SeConv 488/2/0, LibUiLogic 905/0/0, LibSE 2017/0/0, UI 5231/9/0. Retry was not used.
No blocking defect found in this tranche. This remains an audit draft only; no merge/promotion intended.
|
Adversarial final review of HEAD Scope: libavcodec send/receive state machine in the FFmpeg player, isolated on common audit base Confirmed the original defect: both decode loops freed a compressed Final patch review confirms:
CI SubtitleEdit#250 passed on this exact HEAD:
No unresolved correctness blocker remains in this EAGAIN/packet-ownership tranche. PR intentionally remains draft; no merge/promotion performed. |
Purpose
Fifth independent FFmpeg-player follow-up to merged upstream PR SubtitleEdit#14878 ("FFmpeg player: fix eight teardown, seek and clock defects"), kept on the common audited base
3e4d052adc78464e71bbd5154880d935fd592960.Current upstream main was rechecked immediately before this tranche and remains
4ecc74a92a630e62824e92c8f64aa42c7de1b84d; its four commits after the audit base do not touchFfmpegPlayer.csor the FFmpeg player tests.This PR is deliberately separate from #118 (playback-speed clock re-anchoring).
Finding fixed
avcodec_send_packet(EAGAIN)dropped compressed inputBoth the video and audio decode loops previously did this:
avcodec_send_packet(codec, packet);AVERROR(EAGAIN);avcodec_receive_frame();That violates libavcodec's send/receive contract.
When
avcodec_send_packet()returnsAVERROR(EAGAIN), the input packet was not accepted. FFmpeg requires the caller to receive pending output and then resend that same packet once output has been drained. Freeing it and advancing to the next demux packet can therefore lose compressed video/audio input.The issue also applies to the flush/drain packet state machine: receive-side progress must happen before a rejected send is retried.
Fix
The decode loops now:
avcodec_send_packet()returnsEAGAIN;avcodec_receive_frame()as before;EAGAINwithout permitting receive-side progress.The implementation is intentionally compact; an earlier structurally equivalent patch was reworked because it caused hundreds of lines of indentation-only diff noise.
Regression coverage
A focused pure helper test pins that retry is allowed only when all three conditions hold:
AVERROR(EAGAIN);Non-EAGAIN and EOF cases are explicitly rejected.
FFmpeg API contract
Current FFmpeg documentation states that for
avcodec_send_packet():AVERROR(EAGAIN)means the input is not accepted in the current state;avcodec_receive_frame();FFmpeg also guarantees that send and receive cannot both remain in
EAGAINat the same point in the state machine.Scope / branch state
0252d55fd2f95752425c2e30b70363e6af7a93e83e4d052adc78464e71bbd5154880d935fd5929604ecc74a92a630e62824e92c8f64aa42c7de1b84d(no relevant FFmpeg drift)7d4322e310d4c8eef6ebb8de61daaafda7834b84AI assistance: ChatGPT was used for adversarial libavcodec state-machine/ownership review, FFmpeg API verification, and focused regression design.
Final CI
Authoritative run: SubtitleEdit#250 on
7d4322e310d4c8eef6ebb8de61daaafda7834b84Compiler warnings are confined to pre-existing accessibility/VoiceManager files outside this PR's changed set.