5.22.1
probeDetectingAtmos failed on exactly the media it was written for (#214)
The bounded JOC pass sets AVDISCARD_ALL on every non-target stream so its caps budget the audio rather than the interleave. That part worked. What did not: the pass runs straight after the base probe, and avformat_find_stream_info leaves its own packets queued inside libavformat. av_read_frame hands those back regardless of the discard hint, because they were read before the hint existed.
On a source whose audio sits at the head that is invisible, since the first queued packets include audio. On a remux whose audio starts well into the container it is fatal: the foreign-packet fuse is spent entirely on the queued video, the pass returns .packetCap having fed the decoder nothing, and a genuinely Atmos track reports as not-Atmos. A feature-length remux with a coarse interleave is precisely the shape this API exists for.
The queue is now discarded with a bounded seek to the start before the decode pass, so the discard takes effect from the first read. Measured on Dolby's Online Delivery Kit JOC signal remuxed with its audio 70 s in: not confirmed before, confirmed off the first audio packet in 3 ms after. Audio at the head is unchanged, and a source that cannot seek is no worse off than before.
LoadOptions.confirmAtmos (5.22.0) never had this bug. Its side demuxer opens with skipStreamInfo, so there is no queue to inherit.
A correction to the 5.21.0 notes
Chasing this produced a measurement worth publishing, because it makes the earlier framing wrong.
With the audio at the head of the container, avformat_find_stream_info decodes an E-AC-3 frame on its own and codecpar.profile comes back as 30. On MP4 and on MKV, and still at a 50 KB probe budget. probe(url:) therefore already reported TrackInfo.isAtmos correctly for that content, and the 5.21.0 notes calling the pre-decode flag effectively a coin flip overstated the problem.
What is true is narrower: nothing in libavformat sets the profile itself, so the flag depends entirely on find_stream_info reaching and decoding an audio frame. It reliably does until the audio moves away from the head, which is what a coarse interleave over a slow link produces. That case is real, it is reproducible (ffmpeg -i src.mp4 -itsoffset 70 -i src.mp4 -map 0:v -map 1:a -c copy out.mkv leaves find_stream_info reporting profile=unknown), and it is what both probeDetectingAtmos and LoadOptions.confirmAtmos are for. It is not the common case.
Covered by: 1055 tests green across 170 suites. AtmosConfirmationJOCTests is new and runs against real E-AC-3 JOC media, skipping unless the fixtures are present locally, since no JOC bitstream can be synthesized (FFmpeg's E-AC-3 encoder does not write the flag) or committed. The regression test fails without this fix. Strict-concurrency clean, macOS plus tvOS and iOS Simulator builds green.