Validate integrated FFmpeg audio core hardening stack - #147
Blackspirits wants to merge 1 commit into
Conversation
3cfd5a5 to
017540a
Compare
Blackspirits
left a comment
There was a problem hiding this comment.
Final adversarial integration review on 017540a328cfb460a90cd3b6bace32d698edb1c7 after CI SubtitleEdit#289: no blocker found. Verified transactional seek/audio-track commit, serial-fenced sink reset/write, one-path PCM accounting, EAGAIN exact ownership, decoder+resampler EOF ordering, selected-stream duration semantics, speed-position preservation, wall-clock failover, and decode-only continuation after sink failure so unknown-duration EOF remains observable. No merge/promotion performed.
Blackspirits
left a comment
There was a problem hiding this comment.
Final adversarial integration review on 017540a328cfb460a90cd3b6bace32d698edb1c7 after CI SubtitleEdit#289: no blocker found. Verified transactional seek/audio-track commit, serial-fenced reset/write, unified normal+resampler PCM accounting, audio-side EAGAIN ownership, speed re-anchor before rate mutation, and the final decode-only sink-failure path. The integration-only packet-drop vs unknown-duration EOF bug was fixed before this run: after device failure the decoder/resampler continue producing timing and EOF while native PCM output is skipped, so wall-clock playback does not freeze or truncate unknown-duration audio. No merge/promotion performed.
Purpose
Integration-only validation of the current FFmpeg audio core hardening stack.
The base is #144, so it already includes the serial-fenced sink/reset/start chain:
This integration commit layers the audited player behavior from:
It is audit evidence only and is not a merge candidate.
Current upstream
SubtitleEdit/subtitleeditmain was rechecked at6c6b83dd043d8d38fb7a2b1800fdb9465526833b; the latest upstream change is unrelated Burn-in/encoder work.Why this integration matters
These PRs were developed on different branches but all mutate the same audio transaction:
Independent CI cannot prove that the old/new contracts compose.
Integration conflicts found and resolved
Pre-PR adversarial reconstruction found several real composition bugs that were not visible in the isolated PRs:
Old parameterless sink reset was reintroduced.
Fail closed when FFmpeg seek fails #117 still called the pre-Fence FFmpeg audio writes by seek serial #125
_audioSink.Reset()after queue flush. The integrated tree now performs exactly one serial-awareReset(serial)before serial commit.Fix FFmpeg EOF handling for unknown durations #116's helper still used the old
Write(pcm)contract.WriteAudioChunk()now usesWrite(pcm, serial).Normal PCM bypassed Fix FFmpeg EOF handling for unknown durations #116 EOF accounting after Fall back to wall clock after FFmpeg audio sink failure #144 was layered.
The direct Fall back to wall clock after FFmpeg audio sink failure #144 write path meant normal decoded PCM no longer updated
queuedAudioEndand also bypassed Fix FFmpeg EOF handling for unknown durations #116's gain path. Both normal PCM and resampler-tail PCM now pass through the sameWriteAudioChunk().Fall back to wall clock after FFmpeg audio sink failure #144's packet-drop failover did not compose with Fix FFmpeg EOF handling for unknown durations #116 unknown-duration EOF.
Dropping compressed audio packets after device failure avoids backpressure, but also discards the timestamps needed to discover the end of an unknown-duration audio stream. The integrated tree now enters decode-only mode: decoder/resampler timing and EOF accounting continue, while native PCM output is skipped. This also covers failure during final resampler drain without losing the observed media end.
Audio EAGAIN ownership from Retry FFmpeg decoder packets rejected with EAGAIN #119 was absent from the Fall back to wall clock after FFmpeg audio sink failure #144 ancestry.
The integrated tree retains a rejected packet until receive-side progress makes it legal to resend. Sink failover counts as an interruption, so a device failure does not loop/retry the retained packet indefinitely.
Composition invariants
Seek is transactional.
Native seek must succeed before audio track, sink serial, clock/EOF state and packet queues commit.
Audio-track switch is transactional.
The old track keeps routing until seek succeeds; failed seek rolls back only the failed latest request.
Sink ownership is serial-fenced.
Every normal PCM write and resampler-tail write carries the current seek serial.
One accepted PCM path owns audio accounting.
Gain, sink write, failover classification and
queuedAudioEndupdate are performed by one helper.EAGAIN retains packet ownership exactly once.
Rejected input is resent only after decoder output and only while the serial remains current.
EOF is not published before decoder + resampler drain.
After a real sink failure, decode-only mode still drains decoder/resampler timing so unknown-duration media retains an observed end even though PCM is no longer sent to the device.
Unknown duration remains data-driven.
Playback end uses observed decoder/sink state rather than treating a partial sibling stream duration as authoritative.
Speed changes do not reinterpret elapsed wall-clock time.
Position is captured before mutating the playback rate.
Runtime sink failure does not freeze or truncate unknown-duration playback.
The last audible media position becomes the wall-clock base; decoding continues without native output so packet backpressure is avoided while timestamps and EOF remain observable.
Scope / branch state
2c444f33caeecc886804dabb6a25f60f7376c89d017540a328cfb460a90cd3b6bace32d698edb1c76c6b83dd043d8d38fb7a2b1800fdb9465526833bAcceptance
AI assistance: ChatGPT was used for cross-branch semantic reconstruction, detection and repair of integration-only sink-reset/write/EOF/EAGAIN conflicts, discovery of the packet-drop vs unknown-duration composition bug, decode-only recovery design, and integration acceptance design.
Final CI
Authoritative run: SubtitleEdit#289 on
017540a328cfb460a90cd3b6bace32d698edb1c7Final adversarial integration review was performed on this exact HEAD after CI; all nine composition invariants remain satisfied.