labels+disc: codec from stream, audio-richness title tiebreak

Two validated audio-correctness fixes (proven on real discs Wicked/
Paddington/Dune/Fight Club via head-captures):

labels: apply_labels now derives the codec/channel descriptor from the
stream's OWN codec/channels unless the parser's codec_hint is BOTH
consistent with it AND richer (e.g. "Dolby Atmos" on a TrueHD stream).
A mis-bound hint ("AC-3 2.0" on a TrueHD track) is rejected and the
stream's own codec used — killing the cross-labeled shuffle (Wicked) and
the compat-core mislabel (Paddington), while keeping rich hints and
normalizing plain ones to uniform marketing names. (codec_hint_consistent
+ codec_hint_adds_detail, 5 tests.)

disc: canonical_title_order gains an audio-richness tiebreak
(lossless > channels > track-count) for titles that tie on
duration+clips — so a movie authored as a full-audio playlist plus a
stereo-only twin (Fight Club 00800 vs 00004) picks the full-audio one
instead of falling to array order.
This commit is contained in:
MattJackson
2026-06-04 19:10:11 -07:00
parent b96f6206fe
commit 36d1af1b7f
2 changed files with 222 additions and 4 deletions
+38
View File
@@ -1356,6 +1356,44 @@ impl Disc {
.cmp(&b_oversize)
.then_with(|| a.clips.len().cmp(&b.clips.len()))
.then_with(|| b.duration_secs.total_cmp(&a.duration_secs))
// Same length + clip count = the same feature authored as multiple
// playlists (a full-audio main vs an audio-reduced twin, e.g. Fight
// Club's 00800 [DTS-HD MA + 13 tracks] vs 00004 [stereo AC-3 only]).
// Prefer the richer audio so we never rip a stereo-only variant over
// the lossless-multichannel main feature.
.then_with(|| Self::audio_richness(b).cmp(&Self::audio_richness(a)))
}
/// Audio-richness rank for `canonical_title_order`'s same-length tiebreak.
/// Higher is better: `(any lossless track, best channel count, audio count)`.
fn audio_richness(t: &DiscTitle) -> (u8, u8, usize) {
let mut lossless = 0u8;
let mut max_ch = 0u8;
let mut count = 0usize;
for s in &t.streams {
if let Stream::Audio(a) = s {
count += 1;
if matches!(
a.codec,
Codec::TrueHd | Codec::DtsHdMa | Codec::DtsHdHr | Codec::Lpcm | Codec::Flac
) {
lossless = 1;
}
let ch = match a.channels {
AudioChannels::Surround71 => 8,
AudioChannels::Surround61 => 7,
AudioChannels::Surround51 => 6,
AudioChannels::Surround50 => 5,
AudioChannels::Quad => 4,
AudioChannels::Stereo21 => 3,
AudioChannels::Stereo => 2,
AudioChannels::Mono => 1,
AudioChannels::Unknown => 0,
};
max_ch = max_ch.max(ch);
}
}
(lossless, max_ch, count)
}
fn detect_format(titles: &[DiscTitle]) -> DiscFormat {