Bound the forced-subtitle probe, make it cancellable, and stop re-reading clips

The probe's only natural exit was "every PGS track has shown a non-forced
display set". A genuinely FORCED track never satisfies that, so on the common
authoring — a forced-narrative track for foreign dialogue — the loop read the
title's entire extent set at 2 MiB per call with no byte cap, no time cap and
no halt check. It was also invoked once per title rather than once per distinct
clip, and a disc's playlists overwhelmingly reference the same few clips (main
feature, play-all, seamless-branch variants), so the same physical extents were
re-read 30-150 times. The two defects multiplied: tens of GB, times the
playlist count, off an optical drive.

Reached via ScanOptions::probe_forced_subtitles, whose only consumer is
`freemkv info -v` (freemkv/src/disc_info.rs). The rip path leaves it off. So
the symptom is `info -v` never returning on an ordinary UHD, not a corrupt rip.

Three changes:

  * PROBE_BUDGET_SECTORS caps a probe at 256 MiB. A forced track's display sets
    appear throughout the title, so a bounded prefix classifies it; the budget
    only decides how long we keep looking for a non-forced set before accepting
    the forced verdict.
  * ScanOptions::halt is now plumbed in and checked per chunk, so `info -v` is
    cancellable. The probe previously took no halt at all.
  * A ForcedProbeCache memoises verdicts against the title's exact extent list.
    Keying on byte-identical input means a hit cannot change any result — it
    only removes the re-read.

Verdict application is factored into apply_verdicts so the cached and freshly
probed paths cannot diverge.

Three tests pin the behaviour, each against a reader that counts sectors and
never ends: the budget stops at exactly PROBE_BUDGET_SECTORS, a cancelled halt
reads zero sectors, and a second title with identical extents costs no further
reads while a different extent list still misses the cache.

Also worth recording: the CLI acceptance harness never exercised `info -v`
against an optical drive — it reads ISOs from local SSD, where a full-extent
read is fast enough to hide both defects.
This commit is contained in:
Matthew Jackson
2026-07-29 18:38:25 -07:00
parent ea72e6df5f
commit a39045adf1
2 changed files with 179 additions and 12 deletions
+12 -1
View File
@@ -1945,9 +1945,20 @@ impl Disc {
// one shared PGS classifier); the rip path leaves it off — the muxer
// detects forced while muxing, without a second read of the clip.
if opts.probe_forced_subtitles {
// One cache across every title: a disc's playlists overwhelmingly
// reference the same handful of clips (main feature, play-all,
// seamless-branch variants), so without memoisation the same physical
// extents are re-read from the drive once per playlist — 30-150 times
// on a typical Blu-ray.
let mut cache = pgs_forced_probe::ForcedProbeCache::new();
for title in &mut titles {
if title.content_format == ContentFormat::BdTs {
pgs_forced_probe::probe_and_set_forced(reader, title);
pgs_forced_probe::probe_and_set_forced(
reader,
title,
&mut cache,
opts.halt.as_ref(),
);
}
}
}