Skip to content

Wait for a fresh FFmpeg replay serial after hardware fallback - #145

Draft
Blackspirits wants to merge 1 commit into
audit/ffmpeg-hardware-fallback-replay-3e4dfrom
audit/ffmpeg-hardware-replay-serial-0ee7
Draft

Blackspirits wants to merge 1 commit into
audit/ffmpeg-hardware-fallback-replay-3e4dfrom
audit/ffmpeg-hardware-replay-serial-0ee7

Conversation

@Blackspirits

@Blackspirits Blackspirits commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Purpose

Dependent hardware-fallback follow-up to #122 ("Replay FFmpeg video after fatal hardware send failures").

#122 correctly reopens the failed hardware decoder in software and requests a seek/replay. This audit found one remaining asynchronous boundary: requesting the seek does not instantly remove compressed packets that were already queued under the failed hardware serial.

This is a current-stack revalidation of the core replay-serial guarantee previously audited in #93, adapted to #122's EAGAIN-safe send/receive state machine.

Current upstream SubtitleEdit/subtitleedit main was rechecked at 6c6b83dd043d8d38fb7a2b1800fdb9465526833b; the latest upstream delta is Burn-in/encoder-settings work and does not touch the FFmpeg player. No competing upstream PR was found.

Finding fixed

After hardware fallback, #122 reopens a fresh software decoder and queues Seek(Position). Until the demux thread actually performs that asynchronous seek, _videoPackets may still contain packets from the failed hardware serial.

A fresh software decoder has none of the old decoder's GOP/reference-picture state. Feeding those old-serial P/B packets into it can therefore reproduce the mid-GOP corruption/loss the replay is meant to prevent.

The gap exists for both fatal avcodec_send_packet() fallback and hardware receive/frame-transfer fallback.

Fix

  • record the requested replay serial;
  • while that minimum serial is active, free/drop compressed video packets with older serials;
  • accept the replay serial itself;
  • accept any newer serial too, so a racing user seek wins naturally;
  • clear the gate as soon as a safe serial arrives;
  • leave Retry FFmpeg decoder packets rejected with EAGAIN #119's EAGAIN resend/packet-ownership state machine untouched.

The filter runs before decoder serial switching and before avcodec_send_packet(), so stale compressed packets never enter the fresh software decoder.

Deliberate difference from old #93

The older #93 also flushed VideoFrameQueue immediately.

This current-stack port deliberately does not: frame queue flushing has a separate ownership/presenter race covered by #132/#133. The normal replay seek still flushes decoded frames when it actually commits.

Regression coverage

Pure tests pin:

  • inactive gate drops nothing;
  • packet serial below replay minimum is stale;
  • equal replay serial is accepted;
  • newer racing user-seek serial is accepted.

Existing #119 EAGAIN tests and #122 fatal-hardware-send classification remain unchanged.

Scope / branch state

AI assistance: ChatGPT was used for adversarial asynchronous replay analysis, old-vs-current stack comparison, EAGAIN ownership compatibility review and focused serial-gate regression design.

Final CI

Authoritative run: SubtitleEdit#284 on ed2e6129d4c84ed0651941331e080dcc559050f1

  • SeConv: 488 passed / 2 skipped / 0 failed
  • LibUiLogic: 905 passed / 0 skipped / 0 failed
  • LibSE: 2017 passed / 0 skipped / 0 failed
  • UI: 5236 passed / 9 skipped / 0 failed
  • build: 0 errors / 7 pre-existing warnings
  • retry step skipped
  • failure-artifact upload skipped

Final adversarial review was performed on this exact HEAD after CI; no blocker found.

@Blackspirits Blackspirits left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Final adversarial review on ed2e6129d4c84ed0651941331e080dcc559050f1 after CI SubtitleEdit#284: no blocker found. Rechecked both hardware fallback paths, old-serial packet ownership/freeing, compatibility with #119's EAGAIN resend state machine, and the racing-user-seek case. A packet older than the replay minimum never reaches the fresh software decoder; equal or newer serials are accepted. No immediate frame-queue flush is introduced, leaving #132/#133 as the sole owners of that boundary. No merge/promotion performed.

@Blackspirits Blackspirits left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Final adversarial review on ed2e6129d4c84ed0651941331e080dcc559050f1 after CI SubtitleEdit#284: no blocker found. Old compressed packets are dropped before decoder serial switching/send; equal replay serial and newer racing user-seek serial are accepted; the gate covers both send-side and receive/transfer hardware fallback; #119 EAGAIN resend/ownership logic is unchanged; no immediate VideoFrameQueue flush is introduced. No merge/promotion performed.

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.

1 participant