Fix PGS subtitle misclassified as audio in STN parsing

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.
This commit is contained in:
MattJackson
2026-04-08 21:14:39 -07:00
parent eb4d89b251
commit c5b0ab3156
+30 -25
View File
@@ -671,10 +671,10 @@ impl Disc {
} }
// Build streams from STN table // Build streams from STN table
let streams: Vec<Stream> = parsed.streams.iter().map(|s| { let streams: Vec<Stream> = parsed.streams.iter().filter_map(|s| {
let codec = Codec::from_coding_type(s.coding_type); let codec = Codec::from_coding_type(s.coding_type);
match s.stream_type { match s.stream_type {
1 | 6 | 7 => Stream::Video(VideoStream { 1 | 6 | 7 => Some(Stream::Video(VideoStream {
pid: s.pid, pid: s.pid,
codec, codec,
resolution: format_resolution(s.video_format, s.video_rate), resolution: format_resolution(s.video_format, s.video_rate),
@@ -694,32 +694,37 @@ impl Disc {
7 => "Dolby Vision EL".to_string(), 7 => "Dolby Vision EL".to_string(),
_ => String::new(), _ => String::new(),
}, },
}), })),
2 | 5 => Stream::Audio(AudioStream { 2 | 5 => {
pid: s.pid, // Guard: if coding_type is a subtitle codec (PGS 0x90/0x91),
codec, // this is a misaligned stream — treat as subtitle, not audio
channels: format_channels(s.audio_format), if matches!(codec, Codec::Pgs) {
language: s.language.clone(), Some(Stream::Subtitle(SubtitleStream {
sample_rate: format_samplerate(s.audio_rate), pid: s.pid,
secondary: s.stream_type == 5, codec,
label: String::new(), language: s.language.clone(),
}), forced: false,
3 => Stream::Subtitle(SubtitleStream { }))
} 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, pid: s.pid,
codec, codec,
language: s.language.clone(), language: s.language.clone(),
forced: false, // TODO: parse from MPLS stream attributes forced: false,
}), })),
_ => Stream::Video(VideoStream { // Stream type 4 = IG, unknown types — skip
pid: s.pid, _ => None,
codec,
resolution: String::new(),
frame_rate: String::new(),
hdr: HdrFormat::Sdr,
color_space: ColorSpace::Unknown,
secondary: false,
label: String::new(),
}),
} }
}).collect(); }).collect();