Say when a title set is dropped from a DVD scan

parse_vmg skipped any title set whose parse failed, with no log and no
counter. A real disc enumerated 38 titles from one image and 10 from
another, and the 28 discarded failures were invisible — the symptom read
as a scan difference rather than as dropped reads, which is most of why
it took so long to localise.

Behaviour is unchanged: a disc may legitimately carry placeholder TT_SRPT
entries, so one failure is still not fatal. It now warns per skip with the
title set and the error, and once at the end with kept-versus-declared.

Also adds an opt-in diagnostic that reads every VTS IFO from an image, to
separate a read failure from a parse failure. It reports all 13 sets
reading identically from both a CSS image and its decrypted copy, which is
what proves the 38-to-10 loss is downstream of these reads.
This commit is contained in:
Matthew Jackson
2026-08-05 19:41:43 -07:00
parent 1f70398774
commit 5c64662213
2 changed files with 52 additions and 2 deletions
+26 -2
View File
@@ -421,16 +421,40 @@ pub fn parse_vmg(reader: &mut dyn SectorSource, udf: &UdfFs) -> Result<DvdInfo>
// Parse each VTS IFO
let mut title_sets = Vec::new();
let mut skipped = 0usize;
for (&vts_number, titles_info) in &title_set_map {
match parse_vts(reader, udf, vts_number, titles_info) {
Ok(ts) => title_sets.push(ts),
Err(_) => {
// Skip unreadable title sets — some DVDs have placeholder entries.
Err(e) => {
// Some discs carry placeholder TT_SRPT entries for title sets
// that are not really there, so one failure is not fatal. But
// the failure must not be INVISIBLE: every skipped set is a
// title the user will never see, and swallowing the reason made
// a disc that enumerated 38 titles from one image and 10 from
// another look like a scan difference rather than 28 dropped
// reads.
skipped += 1;
tracing::warn!(
target: "freemkv::scan",
vts = vts_number,
titles = titles_info.len(),
error = %e,
"title set could not be parsed; its titles are omitted"
);
continue;
}
}
}
if skipped > 0 {
tracing::warn!(
target: "freemkv::scan",
skipped,
kept = title_sets.len(),
declared = title_set_map.len(),
"some title sets were omitted from the scan"
);
}
Ok(DvdInfo { title_sets })
}