From 71a21b5c6f1582e8af2269b96bcedb6b98d5c49f Mon Sep 17 00:00:00 2001 From: MattJackson <1085847+MattJackson@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:14:39 -0700 Subject: [PATCH] Fix PGS subtitle misclassified as audio in STN parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When MPLS STN table parsing drifts (disc-specific alignment issue), a PGS subtitle entry (coding_type 0x90/0x91) can appear in the audio stream section. Previously this showed as garbled "ng PGS 5.1" audio. Fix: guard in stream builder checks if audio-typed streams have subtitle codecs and reclassifies them as subtitles. Also: unknown stream types now filtered out (filter_map) instead of creating fake Video entries that showed as "?" in output. Tested on V for Vendetta BD — "ng PGS 5.1" gone, clean output. --- src/disc.rs | 55 +++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/disc.rs b/src/disc.rs index 5a066c5..9ec00ea 100644 --- a/src/disc.rs +++ b/src/disc.rs @@ -671,10 +671,10 @@ impl Disc { } // Build streams from STN table - let streams: Vec = parsed.streams.iter().map(|s| { + let streams: Vec = parsed.streams.iter().filter_map(|s| { let codec = Codec::from_coding_type(s.coding_type); match s.stream_type { - 1 | 6 | 7 => Stream::Video(VideoStream { + 1 | 6 | 7 => Some(Stream::Video(VideoStream { pid: s.pid, codec, resolution: format_resolution(s.video_format, s.video_rate), @@ -694,32 +694,37 @@ impl Disc { 7 => "Dolby Vision EL".to_string(), _ => String::new(), }, - }), - 2 | 5 => Stream::Audio(AudioStream { - pid: s.pid, - codec, - channels: format_channels(s.audio_format), - language: s.language.clone(), - sample_rate: format_samplerate(s.audio_rate), - secondary: s.stream_type == 5, - label: String::new(), - }), - 3 => Stream::Subtitle(SubtitleStream { + })), + 2 | 5 => { + // Guard: if coding_type is a subtitle codec (PGS 0x90/0x91), + // this is a misaligned stream — treat as subtitle, not audio + if matches!(codec, Codec::Pgs) { + Some(Stream::Subtitle(SubtitleStream { + pid: s.pid, + codec, + language: s.language.clone(), + forced: false, + })) + } else { + Some(Stream::Audio(AudioStream { + pid: s.pid, + codec, + channels: format_channels(s.audio_format), + language: s.language.clone(), + sample_rate: format_samplerate(s.audio_rate), + secondary: s.stream_type == 5, + label: String::new(), + })) + } + } + 3 => Some(Stream::Subtitle(SubtitleStream { pid: s.pid, codec, language: s.language.clone(), - forced: false, // TODO: parse from MPLS stream attributes - }), - _ => Stream::Video(VideoStream { - pid: s.pid, - codec, - resolution: String::new(), - frame_rate: String::new(), - hdr: HdrFormat::Sdr, - color_space: ColorSpace::Unknown, - secondary: false, - label: String::new(), - }), + forced: false, + })), + // Stream type 4 = IG, unknown types — skip + _ => None, } }).collect();