Skip to content

Validate integrated FFmpeg runtime hardening stack - #150

Draft
Blackspirits wants to merge 1 commit into
audit/ffmpeg-audio-clock-health-fd98from
audit/ffmpeg-runtime-integration-3a40
Draft

Blackspirits wants to merge 1 commit into
audit/ffmpeg-audio-clock-health-fd98from
audit/ffmpeg-runtime-integration-3a40

Conversation

@Blackspirits

@Blackspirits Blackspirits commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Purpose

Integration-only validation of the current FFmpeg runtime hardening stack.

The base is #149, which already contains the integrated audio core, WinMM hardening, runtime wall-clock failover, decode-only continuation after sink failure, and explicit native clock-health handling.

This integration commit layers the remaining audited runtime/lifetime/video behavior from:

This PR is audit evidence only and is not a merge candidate.

Current upstream SubtitleEdit/subtitleedit main was rechecked at dda1fce8f9d4a605b1b6732acc072c7109dc6323; the current upstream delta is Auto-Translate work and does not touch this FFmpeg runtime.

Why this integration matters

By this point the individual fixes are well tested, but runtime correctness depends on the composition of three independent generations/ownership domains:

  1. load generation — old Session vs replacement Session;
  2. seek serial — old pipeline vs committed/requested seek;
  3. native sink generation/serial — stale PCM vs reset/failed device.

The integrated tree must preserve ordering across all three while also keeping UI teardown non-blocking and retaining fail-closed native resources when a worker refuses to stop.

Composition invariants

  1. A stale Session cannot publish into a newer load.
    Decoder name and presented frame publication are load-generation fenced.

  2. A stale CloseFile cannot erase a newer load.
    Owner frame/decoder cleanup is accepted only for the current load generation.

  3. Startup and teardown are serialized.
    Session.Start and Dispose share the lifecycle lock; partial Thread.Start failure tears down every worker that did start.

  4. Timed-out teardown remains fail closed but reclaimable.
    Worker-visible format/sink/events remain alive; the last late worker schedules one-shot cleanup instead of converting a temporary timeout into a permanent leak.

  5. UI final teardown is non-blocking and exactly-once.
    FFmpeg defers final CloseFile to background Dispose, the render host relinquishes ownership before detach, and repeated CloseAndDisposePlayer cannot schedule a second Dispose.

  6. Seek serial is the video publication fence.
    A frame can only be claimed/published while holding the same seek lock that commits current serial.

  7. Seek flush cannot recycle an object still held by the presenter.
    Flushed queued VideoFrames are disposed rather than immediately returned to the pool.

  8. Detached seek-frame ownership closes on all video-loop exits.
    lastDropped is returned from finally.

  9. Hardware fallback never feeds pre-replay compressed packets into the fresh software decoder.
    Equal/newer replay serials are accepted; older packets are freed.

  10. Recoverable demux errors do not create false EOF.
    Only AVERROR_EOF / ended AVIO state publish end-of-input.

  11. Hardware decoder-open failure is recoverable once.
    If hardware was actually attached and avcodec_open2 fails, the failed context is freed and software open is attempted once.

  12. The entire Fail over when FFmpeg audio clock queries fail #149 audio stack remains intact.

    • serial-aware Reset/Write only;
    • native clock-health contract;
    • wall-clock failover;
    • decode-only continuation for unknown-duration EOF;
    • EAGAIN packet ownership;
    • transactional seek/audio-track switching;
    • speed-position preservation;
    • WinMM open/position/teardown hardening.

Structural gate before CI

The integrated HEAD was checked for regressions and confirmed:

  • TryGetPlayedSeconds still present;
  • decode-only audio path still present;
  • no parameterless _audioSink.Reset();
  • all PCM writes still carry a serial;
  • transactional PerformSeek still present;
  • no direct _owner.Present(...);
  • no direct Session write to _owner._decoderName;
  • load-generation publication and cleanup fences present;
  • lifecycle lock / deferred cleanup / partial-startup cleanup present;
  • hardware replay serial gate present;
  • lastDropped finally cleanup present;
  • demux EOF classification and software decoder-open fallback present;
  • VideoFrameQueue seek flush disposes queued frames;
  • VideoPlayerControl final teardown is deferred/idempotent.

Scope / branch state

  • PR base: Fail over when FFmpeg audio clock queries fail #149
  • base HEAD: ee6ca3a2a1aebdd4f2be7871cc3b61bb1cdcab39
  • integration HEAD: 3e2971cbbdb1376d2029f2ee37878c66bb326ce9
  • 1 integration commit
  • 8 changed files
  • current upstream main checked: dda1fce8f9d4a605b1b6732acc072c7109dc6323
  • evidence only; no merge/promotion intended

Acceptance

  • full restore/build/test suite must pass on this exact integrated HEAD;
  • no new warning;
  • retry step must remain unused;
  • final adversarial review must re-check all twelve composition invariants.

AI assistance: ChatGPT was used for cross-stack runtime/lifetime/video reconciliation, generation/serial ownership review, regression-gate inspection, and integration acceptance design.

Final CI

Authoritative run: SubtitleEdit#308 on 3e2971cbbdb1376d2029f2ee37878c66bb326ce9

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

Final adversarial integration review was performed on this exact HEAD after CI; all twelve runtime composition invariants remain satisfied.

This run supersedes the earlier #150 HEAD 70a0619926a7bd9666c45469e70cfcd918ea4d4d / CI SubtitleEdit#294. The branch was rebuilt after #149 hardened post-reset clock baselines and transient native-query handling; the runtime integration preserves those corrected sink blobs and the added health-policy regressions.

@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 integration review on 70a0619926a7bd9666c45469e70cfcd918ea4d4d after CI SubtitleEdit#294: no blocker found. Verified load-generation and seek-serial publication fences compose, stale CloseFile cleanup cannot erase a replacement load, startup/teardown and deferred reclamation remain ordered, UI final dispose is exactly-once/off-thread, seek flush and lastDropped ownership are closed, hardware replay rejects pre-replay packets, recoverable demux errors do not truncate input, software decoder-open fallback remains one-shot, and the complete #149 audio/clock-health stack remains intact. Evidence-only PR; no merge/promotion performed.

@Blackspirits
Blackspirits force-pushed the audit/ffmpeg-runtime-integration-3a40 branch from 11161a9 to 3e2971c Compare September 16, 2026 16:48

@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 integration review on 3e2971cbbdb1376d2029f2ee37878c66bb326ce9 after CI SubtitleEdit#308: no blocker found. Rechecked all twelve runtime invariants after rebuilding on corrected #149. The new post-reset baseline latch and two-consecutive-query health policy remain intact in WinMM/Core Audio, while load-generation fencing, lifecycle reclamation, transactional seek, hardware replay serials, frame ownership/publication, demux retry, decoder-open fallback, serial-fenced PCM, wall-clock failover and decode-only unknown-duration EOF behavior remain unchanged. 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