Chapters, DVD subtitle palette, MKV track flags, progress total_bytes

Chapters:
- MPLS PlayList marks parsed (mark_type 1 = chapter)
- Chapter struct on DiscTitle (time_secs, name)
- MKV Chapters element with EditionEntry/ChapterAtom per mark
- 3 MPLS mark tests + 2 MKV chapter tests

DVD subtitle palette:
- IFO palette extraction (PGC offset 0xA4, 16 × YCbCr colors)
- YCbCr→RGB conversion for VobSub .idx format
- DvdSubParser codec_private returns formatted palette
- codec_data field on SubtitleStream flows through pipeline
- 5 palette tests (YCbCr conversion, formatting, overflow)

MKV track flags:
- FlagDefault: primary video/audio = 1, secondary = 0
- FlagForced: forced subtitles = 1
- Language: set from stream language code
- Already implemented, verified with 4 new tests

Progress total_bytes:
- IOStream trait: total_bytes() -> Option<u64>
- DiscStream, IsoStream: from disc_title.size_bytes
- M2tsStream, MkvStream: from file metadata on open
- NetworkStream, StdioStream, NullStream: None

316 tests total, all passing.
This commit is contained in:
MattJackson
2026-04-11 17:43:47 +00:00
parent 9cb0c369e4
commit c91d6e371f
21 changed files with 690 additions and 12 deletions
+24
View File
@@ -97,8 +97,31 @@ impl Disc {
.map(|e| e.sector_count as u64 * 2048)
.sum();
// Build pre-formatted palette codec_data for VobSub subtitle streams
let codec_data = dvd_title
.palette
.as_ref()
.map(|pal| crate::mux::codec::dvdsub::format_palette(pal));
// Map DvdSubtitleAttr to Stream::Subtitle
let subtitle_streams: Vec<Stream> = ts
.subtitle_streams
.iter()
.enumerate()
.map(|(i, s)| {
Stream::Subtitle(SubtitleStream {
pid: 0x20 + i as u16, // DVD sub-stream IDs 0x20-0x3F
codec: Codec::DvdSub,
language: s.language.clone(),
forced: false,
codec_data: codec_data.clone(),
})
})
.collect();
let mut streams = vec![video_stream.clone()];
streams.extend(audio_streams.iter().cloned());
streams.extend(subtitle_streams);
titles.push(DiscTitle {
playlist: format!("VTS_{:02}_{}.VOB", ts.vts_number, title_number),
@@ -107,6 +130,7 @@ impl Disc {
size_bytes,
clips: Vec::new(),
streams,
chapters: Vec::new(),
extents,
content_format: ContentFormat::MpegPs,
});