From 5ee28c08b96cf419a62f144747afda3c879a6f96 Mon Sep 17 00:00:00 2001 From: MattJackson <1085847+MattJackson@users.noreply.github.com> Date: Sun, 10 May 2026 20:58:33 -0700 Subject: [PATCH] labels/mpls_universal: dense stream numbering across playlists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-playlist stream_number counters were resetting between MPLS files, so a disc with 2 MPLS files each listing the same 8 audio streams produced labels with stream_number 1..8 then 1..8 again (dedup kept whichever PID was different, leaving the numbering visibly broken — multiple "audio1: eng" rows). Move the counters outside the per-file loop and increment only when an entry survives dedup. Surviving entries now get dense 1..N numbering across the whole disc per stream_type. Verified on corpus disc-02 (HDMV-only): was `audio1, audio1, audio1` for the 3 distinct audio codecs (TrueHD/AC-3/DTS-HD MA), now `audio1, audio2, audio3`. Same fix applies to disc-01 (12 audio streams across multiple MPLS) and disc-09 (14 audio streams). --- src/labels/mpls_universal.rs | 38 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/labels/mpls_universal.rs b/src/labels/mpls_universal.rs index ed2b9be..059278e 100644 --- a/src/labels/mpls_universal.rs +++ b/src/labels/mpls_universal.rs @@ -68,6 +68,15 @@ pub fn parse(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option // to share a PID across playlists with different metadata. let mut seen: Vec<(u8, String, String, u16)> = Vec::new(); + // Global 1-based counters keyed by StreamLabelType. Incremented + // only when an entry survives dedup, so stream_numbers are dense + // (1, 2, 3, ...) per type across the whole disc — not reset per + // playlist. A disc with 2 MPLS files that each list the same + // 8 audio streams ends up with audio_1..audio_8, not audio_1.. + // audio_16 or audio_1..audio_8 with audio_1 duplicated. + let mut audio_idx: u16 = 0; + let mut sub_idx: u16 = 0; + for name in &mpls_names { let path = format!("/BDMV/PLAYLIST/{}", name); let Ok(data) = udf.read_file(reader, &path) else { @@ -77,13 +86,6 @@ pub fn parse(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option continue; }; - // Per-MPLS-file 1-based counters keyed by StreamLabelType. - // The dedup pass below removes duplicates across files; the - // numbering of the *surviving* entries comes from whichever - // playlist contributed each PID first. - let mut audio_idx: u16 = 0; - let mut sub_idx: u16 = 0; - for entry in &playlist.streams { let label_type = match entry.stream_type { 2 | 5 => StreamLabelType::Audio, // primary + secondary audio @@ -95,17 +97,6 @@ pub fn parse(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option _ => continue, }; - let stream_number = match label_type { - StreamLabelType::Audio => { - audio_idx += 1; - audio_idx - } - StreamLabelType::Subtitle => { - sub_idx += 1; - sub_idx - } - }; - let language = normalize_language(&entry.language); let name = language_display_name(&language); let codec_hint = build_codec_hint(label_type, entry); @@ -117,6 +108,17 @@ pub fn parse(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option } seen.push(key); + let stream_number = match label_type { + StreamLabelType::Audio => { + audio_idx += 1; + audio_idx + } + StreamLabelType::Subtitle => { + sub_idx += 1; + sub_idx + } + }; + labels.push(StreamLabel { stream_number, stream_type: label_type,