v0.0.2
Other
- composite SPU into RGBA overlay (palette + contrast + BT.601)
- add DVD Sub-Picture Unit decoder
- scrub enumerated-denial / decorative-attribution prose (r131 disclaimer-hygiene sweep follow-up)
- add Phase-3c-precursor NavInstruction disassembler
- decode NAV-pack DSI typed sub-sections (SML_PBI / SML_AGLI / SYNCI)
- decode NAV-pack PCI highlight (HLI_GI + SL_COLI + BTN_IT)
- re-export PaletteEntry / NavCommand / PgcCommandTable at crate root
- decode PGC palette colour-LUT + pre/post/cell command table
- Phase 3b: VOB → MKV mux glue + convert_dvd_to_mkv pipeline
- Phase 3a: VOB demuxer — MPEG-PS pack + nav-pack + DVD substream router
- Phase 2: IFO body parser — VMGI/VTSI MAT + TT_SRPT + VTS_PTT_SRPT + VTS_PGCI + VTS_C_ADT
Added
-
SPU RGBA compositor —
SubPictureUnit::composite(buf, palette)
turns a parsed sub-picture plus the PGC's 16-entryPaletteEntry
colour-LUT into a finishedSpuBitmapoverlay (row-major
[R, G, B, A]pixels + on-screen rectangle), completing the
"final framebuffer left to the caller" gap entirely inside the
crate. Clean-room perdocs/container/dvd/application/mpucoder-spu.html
(SET_COLOR/SET_CONTR semantics,0x0transparent …0xFopaque,
top/bottom field interleave) +stnsoft-color_pick.html(BT.601
studio-swing luma scaleY = 160 % …Y = 235100 %). No
libdvdread / libdvdnav / libdvdcss / FFmpeg / VLC / mpv / xine
source consulted; no web search.ycbcr_to_rgb— standalone BT.601 studio-swing
(Y, Cb, Cr) -> (R, G, B)inverse-matrix conversion in fixed
point (1.164 / 1.596 / 0.391 / 0.813 / 2.018 coefficients scaled
by1<<16, round-half-up, clamped to0..=255).SpuBitmap—{ x, y, width, height, rgba }overlay: the
SET_DAREArectangle plus the composited pixels, ready to blend
onto the decoded MPEG-2 frame by the player.- The four 2-bit pixel codes are resolved through the unit's own
SET_COLOR(→0..=15palette index) andSET_CONTR
(→0..=15alpha, expanded to 8-bit by nibble replication);
a unit lacking those uses well-defined fallbacks (background
index, fully-opaque). ReturnsNonewhenSET_DAREA/
SET_DSPXAare absent (a malformed unit per the spec). - +5 unit tests (BT.601 known-point conversion incl. clamp +
red/blue dominance, contrast-nibble expansion, full solid-rect
composite round-trip, missing-SET_DAREA→None).
126 lib tests (was 121 after the SPU decoder landed).
-
spumodule — DVD Sub-Picture Unit decoder, the overlay
graphics stream that carries subtitles, menu button highlights,
and karaoke captions. Pure-bytes decoder clean-room per
docs/container/dvd/application/mpucoder-spu.html(sole 160-line
source; no libdvdread / libdvdnav / libdvdcss / FFmpeg / VLC / mpv
/ xine / HandBrake source consulted; no web search).SpuHeader— the 4-byte SPUH (SPDSZtotal size +
SP_DCSQTAoffset to the Sub-Picture Display Control Sequence
Table).SpuCommand— typed enum for the eight SP_DCSQ command
codes:ForcedStartDisplay(0x00) /StartDisplay(0x01)
/StopDisplay(0x02) /SetColor(0x03, four 4-bit
palette indices) /SetContrast(0x04, four 4-bit alpha
values) /SetDisplayArea(0x05, four 12-bit coordinates)
/SetPixelDataAddresses(0x06, top/bottom field offsets) /
ChangeColorContrast(0x07, rawLN_CTLI/PX_CTLI
parameter blob preserved for the caller) /EndOfSequence
(0xFF, theCMD_ENDterminator).SpDcSq— one display-control sequence: a 4-byte header
(90 kHz/1024start_time+next_offsetchain pointer) plus
the decoded command list. Chain-walk validates per-block
forward progress and rejects loops.SubPictureUnit::parse— top-level entry that walks SPUH- every chained DCSQ from the
SP_DCSQTAoffset until a
terminal block (whosenext_offsetpoints back at itself).
Convenience accessorspixel_data_offsets()/display_dimensions()
pull the PXDtf/PXDbf offsets and rectangle width/height out of
the command stream.
- every chained DCSQ from the
decode_rle_field— the 2-bit / four-form PXD run-length
decoder. Implements the nested-prefix encoding (n n c c/
0 0 n n n n c c/0 0 0 0 n n n n n n c c/
0 0 0 0 0 0 n n n n n n n n c c) and the 16-bit
"count=0 = until end of line" terminator, with byte alignment
at every row boundary per mpucoder-spu.html §PXDtf.render_field— flattens the run vector into a row-major
Vec<u8>of palette indices (0..=3), one byte per pixel,
ready for blending against the PGC's 16-entryPaletteEntry
table.spdcsq_stm_to_ms— converts anSP_DCSQ_STM90 kHz/1024
delay to integer milliseconds via the inverse of the
mpucoder-spu.html conversion table.
Producing a final framebuffer (YCrCb + alpha) is intentionally
left to the caller — that step needs the PGCPaletteEntry
table (already exposed bycrate::ifo) plus the renderer's
preferred pixel format, both outside the SPU bitstream itself.+13 unit tests (header parse / delay conversion / one-run RLE
for all four forms / end-of-line marker / EOL row padding /
full-unit round-trip with six commands /CHG_COLCONraw
round-trip / DCSQTA-out-of-range rejection / runaway-DCSQ
rejection / opcode table). 132 tests total (was 119). -
navmodule — typed VM instruction decoder (Phase 3c precursor).
The previousNavCommandsurface exposed only an 8-byte raw word
plus the 3-bitcommand_typeclassifier; the newNavCommand::decode() -> NavInstructionreturns a typed-enum disassembly tree clean-room
perdocs/container/dvd/application/mpucoder-vmi.html+
mpucoder-vmi-sum.html+mpucoder-vmi-jmp.html+
mpucoder-sprm.html(no libdvdread / libdvdnav / libdvdcss /
FFmpeg / VLC / mpv / xine / HandBrake source consulted; no web
search). No execution — an interpreter that owns
SPRMs / GPRMs / PC / RSM stack is the bulk of Phase 3c proper;
decoding the stream is the prerequisite step shared by a future
executor, an analyser, and a disc debugger.Register— 8-bit operand classifier:Gprm(0..=15)/
Sprm(0..=23)/Invalid(raw)per the asterisk note on the VMI
spec page (only0x00..=0x0Fand0x80..=0x97are valid).SetOp+CmpOp— the SET (12 named codes:mov,
swp,add,sub,mul,div,mod,rnd,and,or,
xor) and CMP (7 named codes:BC,EQ,NE,GE,GT,
LE,LT) sub-op tables from the same page.LinkSubset— the 13-entry inner table for theType-1 0x20 0x01Link command:LinkTopCell/LinkNextCell/
LinkPrevCell/LinkTopPG/LinkNextPG/LinkPrevPG/
LinkTopPGC/LinkNextPGC/LinkPrevPGC/LinkGoupPGC/
LinkTailPGC/Rsm+Nop, with the spec's invalid bag
(0x04, 0x08, 0x0E, 0x0F, 0x11..0x1F) preserved via
Invalid(raw).JumpSSTarget+CallSSTarget— the four-way
destination selector (FirstPlay/VmgmMenu { menu }/
VtsmMenu { vts, ttn, menu }/VmgmPgcn { pgcn }) from the
JumpSS/CallSSrows inmpucoder-vmi.html.CallSSTarget
additionally carries thersm_cellresume-cell byte shared by
all four CallSS variants.NavInstruction— top-level decode enum. Variants for the
well-defined opcodes:Nop,Goto { line },Break,
SetTmpPml { level, line },LinkSub { subset, hl_bn },
LinkPgcn { pgcn },LinkPttn { pttn, hl_bn },
LinkPgn { pgn, hl_bn },LinkCn { cn, hl_bn },Exit,
JumpTT { ttn },JumpVtsTt { ttn },
JumpVtsPtt { ttn, pttn },JumpSs(JumpSSTarget),
CallSs(CallSSTarget),SetStn(withaf/sf/nfflag
bits and per-channel register-or-immediate source),SetNvtmr,
SetGprmMd(withcountermode bit),SetAmxMd,SetHlBtnn,
Set { op, dst, src }. Compound Type 4..6 forms surface their
classifierSetOp+CmpOpsub-ops viaSetCLnk(Type 4),
CSetCLnk(Type 5),CmpSetLnk(Type 6); the per-operand
sub-decode is deferred to the executor. Type 7 returns
Unknown(the VMI page documents the family has never been
observed in real-world streams); structurally-impossible
encodings returnInvalid.- 42 new unit tests covering the
RegisterGPRM / SPRM /
invalid-hole classifier, the fullSetOp/CmpOp/
LinkSubsetnamed-code tables, the spec's named-but-invalid
sub-codes (SetSystemsub=5,Setsub=0/C/F, Type 0 cmd
nibble 4..F, Link cmd nibble 2), the round-trip from a
NavCommand::default()(all zero) decoding toNop, and one
decoded form perNavInstructionvariant including the
JumpSS four-way target selector and the CallSS rsm_cell field.
-
NAV-pack DSI typed sub-section decode (Data Search Information):
theDsiPacketdecoder previously surfaced only the DSI_GI preamble
and a flat 43-entry VOBU_SRI array; it now returns a typed
DsiPacket { general_info, sml_pbi, sml_agli, vobu_sri, synci }
with every spec-listed field exposed by name, clean-room per
mpucoder-dsi_pkt.html(no libdvdread / libdvdnav / FFmpeg / VLC /
mpv / xine source consulted).DsiGi— DSI_GI general information (packet 0x00..0x20):
nv_pck_scr,nv_pck_lbn,vobu_ea, the 1st/2nd/3rd reference-
frame end-address triplet, the(vobu_vob_idn, vobu_c_idn)
identifier pair, and the BCDc_eltmcell-elapsed-time + frame-
rate bits field. Convenience getters
(DsiPacket::nv_pck_scr()etc.) mirror the pre-refactor flat-field
accessors so the bump stays source-compatible for call-sites that
only read DSI_GI.SmlPbi+SmlAudioGap— SML_PBI seamless-playback info
(packet 0x20..0xB4, 148 bytes): the 16-bitilvuflag word with
preu()/is_ilvu()/unit_start()/unit_end()bit
decoders, the(ilvu_ea, nxt_ilvu_sa, nxt_ilvu_sz)interleaved-
block jump pointers, the VOB-span video PTM pair, and the 8 ×
16-byte per-audio-stream gap table (stp_ptm1,stp_ptm2,
gap_len1,gap_len2per stream).SmlAgli+SmlAngleCell— SML_AGLI seamless-angle info
(packet 0xB4..0xEA, 54 bytes): 9 angle cells, each 6 bytes wide
(dsta: u32with bit-31 direction flag + sentinel values for
"absent" and "no more video";sz: u16ILVU size in sectors).VobuSri— VOBU search-information table (packet 0xEA..0x192,
168 bytes = 42 × 4):sri_nvwv(next-VOBU-with-video), 19 forward
scaled-distance entries,sri_nv+sri_pvbrackets, 19 backward
entries,sri_pvwv(previous-VOBU-with-video). The bit-31
VALID_BIT, bit-30INTERMEDIATE_BIT, and 30-bitOFFSET_MASK
constants make sentinel handling explicit. (Previous flat-array
decode over-read by 4 bytes into SYNCI; the typed layout fixes
that.)Synci— SYNCI A/V-sync pointer table (packet 0x192..0x222,
144 bytes):a_synca: [u16; 8]audio +sp_synca: [u32; 32]
subpicture per-stream first-packet offsets.AUDIO_DIRECTION_BIT
(bit 15) andSP_DIRECTION_BIT(bit 31) constants surface the
spec-defined direction flag.- 9 new unit tests (
dsi_section_offsets_match_spec,
dsi_parses_general_info_block,
dsi_parses_sml_pbi_block_and_ilvu_flags,
dsi_pbi_ilvu_flag_decoders_isolate_bits,
dsi_parses_sml_agli_block,
dsi_parses_vobu_sri_block_and_brackets,
dsi_parses_synci_block,dsi_rejects_short_buffer,
dsi_nav_pack_round_trip_through_full_sector) and a new
build_dsi_bodyhelper that emits a fully-populated 546-byte DSI
body so every per-section offset is pinned exactly.
Changed
-
Breaking —
DsiPacket's public field layout. The previous flat
{ nv_pck_scr, nv_pck_lbn, vobu_ea, vobu_1stref_ea, vobu_2ndref_ea, vobu_3rdref_ea, vobu_vob_idn, vobu_c_idn, c_eltm, vobu_sri: Box<[u32; 43]> }shape was replaced by the typed sub-section struct described
above. Source-compatible getters (nv_pck_scr()etc.) are provided
for the DSI_GI fields; thevobu_srifield is now aVobuSristruct
rather than a flat boxed array. Pre-0.0.2 release — no published
consumer to break. -
NAV-pack PCI highlight information (menu buttons): the
PciPacketdecoder previously read onlyhli_ss; it now
materialises the full HLI_GI / SL_COLI / BTN_IT sub-structure when
a VOBU declares buttons, clean-room permpucoder-pci_pkt.html(no
libdvdread / libdvdnav / libdvdcss / FFmpeg / VLC / mpv / xine
source consulted).HighlightInfo+PciPacket::highlight: Option<HighlightInfo>
— the HLI_GI general-information block (hli_s_ptm,hli_e_ptm,
btn_sl_e_ptm, rawbtn_mdgrouping word,btn_sn,btn_ns,
nsl_btn_ns,fosl_btnn,foac_btnn).Nonewhen the VOBU
declares no buttons (btn_ns == 0) — the common case, not an
error.SlColi+SlColiCell— the threeSL_COLI_1..3
selection/action colour-and-contrast schemes. Each 8-byte scheme
is decoded into selection + action arrays of four
{ color, contrast }cells, indexed by emphasis code
(0= background,1= pattern,2= emphasis1,3=
emphasis2).coloris a 4-bit PGC colour-LUT index;contrast
is the 4-bit blend weight a subpicture/menu renderer applies.ButtonInfo— one 18-byteBTN_ITentry:btn_coln
colour-scheme selector, the 10-bit X/Y rectangular region
(start_x/end_x/start_y/end_y), the auto-action flag, the
fourup/down/left/rightD-pad adjacency selectors, and the
raw 8-byte VMcommand(executing it is Phase 3c VM work per
mpucoder-vmi.html). The button table holds exactlybtn_ns
entries; an over-long count (> 36) or a body too short to carry
the declared table raisesError::InvalidUdf.- 4 new unit tests (
pci_without_buttons_yields_no_highlight,
pci_decodes_single_button_highlight,
pci_rejects_overlong_btn_ns,
pci_rejects_truncated_button_table); a newadd_one_button_hli
test helper injects a known single-button HLI block into the
synthetic nav sector so every decoded field is asserted exactly. - Note:
PciPacketandNavPackno longer deriveCopy
(HighlightInfoowns aVec<ButtonInfo>); they remainClone.
-
PGC palette + command-table parse (richer Phase 2 IFO body): the
Pgcmaterialiser now decodes the two PGC-header tables it
previously skipped, both clean-room permpucoder-pgc.html(no
libdvdread / libdvdnav / libdvdcss / FFmpeg / VLC / mpv / xine
source consulted).PaletteEntry+Pgc::palette: [PaletteEntry; 16]— the
subpicture/highlight colour-LUT at PGC offset0x00A4, sixteen
(0, Y, Cr, Cb)cells (leading reserved byte dropped) surfaced
as{ y, cr, cb }. This is the table an SPU display-control
sequence indexes into via its 4-bit colour codes
(mpucoder-spu.html), so a subtitle/menu renderer needs it to
resolve a pixel to an actual YCrCb value.NavCommand+PgcCommandTable+Pgc::commands: Option<PgcCommandTable>— the command table at
offset_commands(previously only the offset was read). The
8-byte header (pre/post/cell counts +end_address) is decoded
and each list is carved into fixed 8-byteNavCommandwords.
Thepre + post + cell <= 128spec invariant is enforced;
truncated lists and over-long counts raiseError::InvalidUdf.
Executing the words is deferred to the Phase 3c VM
(mpucoder-vmi.html); at the container layer we expose the raw
words plus aNavCommand::command_type()convenience (top three
bits of byte 0 — the VMI command-group selector) so a downstream
interpreter has what it needs without a full opcode model here.- 6 new unit tests (
palette_entry_skips_reserved_byte,
command_table_carves_three_lists,
command_table_rejects_overlong_count,
command_table_rejects_truncated_list,
pgc_without_command_table_yields_none, plus extended
palette/command assertions in
pgci_parses_one_pgc_with_three_cells). The
build_pgc_with_cellstest helper now emits a real palette +
4-word command table so the existing round-trip exercises the
new fields.
-
Phase 3b (VOB → MKV mux): clean-room glue between the Phase 3a VOB
demuxer andoxideav-mkv'sMkvMuxer::{add_chapter,write_packet, write_trailer}. Gated behind a default-offmkv-outputcargo
feature so the dvd crate stays useful for chapter-introspection
consumers and so default-feature CI doesn't have to pull the
(still-unreleased at time of writing) MKV chapter API in. No
external library source (libdvdread, libdvdnav, libdvdcss, FFmpeg,
VLC, mpv, xine, HandBrake) was consulted.pgc_time_to_ns(PgcTime) -> u64— RFC 9559 §5.1.7 needs
ChapterTimeStart/ChapterTimeEndin nanoseconds; DVD's BCD
hh:mm:ss:fffield uses 30 fps (NTSC) or 25 fps (PAL) per
mpucoder-pgc.html. Conversion is exact rational math so
0:0:1.15 @ 30 fpsbecomes the spec-exact 1_500_000_000 ns
(truncating with the obvious1e9 / 30constant would have
rounded to 1_499_999_995 ns — see the regression test).mkv_writer::write_title_to_mkv(disc, title_idx, image_path, out_path)— two-pass DVD → MKV converter. Pass 1 probes the
title's cells to enumerate the (video, AC-3 × N, DTS × N, LPCM
× N, subpicture × N) stream set so MKV's mandatory upfront
Trackselement can be sized correctly. Pass 2 re-walks the
cells and forwards each PES packet toMkvMuxer::write_packet
with PTS preserved verbatim in the PES's 90 kHz time base; the
muxer rescales to its internal 1 msTimecodeScale. Chapter
atoms are queued viaMkvMuxer::add_chapterbefore
write_header, one perDvdChapterfrom the PGC's PTT list,
titled"Chapter N".pipeline::convert_dvd_to_mkv(source, title_idx, out_path)
— high-level front door accepting either advd://...URI or a
bare filesystem path. Auto-detect (dvd://) is rejected as a
Phase-2 followup, matching the existing source-driver semantics.pipeline::list_titles(source)— convenience wrapper around
DvdDisc::enumerate_titlesfor CLI front-ends that want to
surface the title list before letting the user pick one.- Sector walker —
walk_cell_sectorsre-uses the constants
fromvob::{SC_*, looks_like_nav_pack, PackHeader, PesPacket}
so the pack-header + system-header + nav-pack + padding
transitions are decoded once across the round. Nav-packs are
consumed (validated viaNavPack::parse) but not surfaced
further; subpicture / DTS / LPCM PES payloads' first byte (the
substream ID) is stripped before the body lands in MKV.
-
Phase 3b tests (10 cases, all gated behind
--features mkv-output): PgcTime → ns for NTSC 30 fps / PAL 25 fps / illegal-
frame-rate / hour-boundary; stream classification (codec id +
media type) for video / AC-3 / DTS / LPCM / subpicture; sort
determinism for the stream set; plus threepipeline::resolve_*
tests covering URI parsing (dvd:///abs, bare path,dvd://
auto-detect rejection). -
Phase 3a (VOB demuxer): clean-room MPEG-PS pack + nav-pack walker
- DVD-substream router per mpucoder-{packhdr,pes-hdr,mpeghdrs,
pci_pkt,dsi_pkt,dvdmpeg}.html + stnsoft-{vobov,sys_hdr}.html. No
libdvdread, libdvdnav, FFmpeg, VLC, mpv, or xine source consulted.
PackHeader— 14-byte MPEG-2 Program Stream pack header
decoder:00 00 01 BAsync + 33-bit SCR base + 9-bit SCR_ext +
22-bitprogram_mux_rate+ 3-bitpack_stuffing_length. All
five marker bits are validated; bad sync / missing marker /
mux_rate == 0raiseError::InvalidUdf.PesPacket<'a>— zero-copy PES decoder for the DVD subset:
0xBApack,0xBBsystem header,0xBDprivate_stream_1,
0xBEpadding,0xBFprivate_stream_2 (no extension), and
0xC0..=0xDF/0xE0..=0xEF(MPEG-2 extension with 5-byte PTS
or 10-byte PTS+DTS).PTS_DTS_flags == 01is rejected per spec.DvdSubstream— typed substream classifier for the first
payload byte of a 0xBD packet:Subpicture(0x20..=0x3F),
Ac3(0x80..=0x87),Dts(0x88..=0x8F),Lpcm(0xA0..=0xA7)
withtrack()accessor normalising to 0..=7 (audio) / 0..=31
(subpicture).PciPacket— Presentation Control Information decoder for
the DVD-Video NAV-pack's PCI half:nv_pck_lbn,vobu_cat,
vobu_uop_ctl,vobu_s_ptm,vobu_e_ptm,vobu_se_e_ptm,
c_eltm,hli_ss.DsiPacket— Data Search Information decoder for the
DSI half:nv_pck_scr,nv_pck_lbn,vobu_ea,
vobu_{1,2,3}stref_ea,vobu_vob_idn,vobu_c_idn,c_eltm,
and the 43-entryvobu_srisearch-pointer table (0xEA..0x196)
used for chapter-accurate forward/backward seek.NavPack— 2048-byte sector-level decoder that validates
pack header + system header + 0xBF/0x00 PCI prefix + 0xBF/0x01
DSI prefix and surfaces(pci, dsi). A cheaplooks_like_nav_pack
probe skips the full parse on demux routing.VobDemuxer— stateful walker that consumes 2048-byte
sectors and routes packets into per-stream buffers. Nav-packs
are consumed and stashed inVobStreams::nav_packs; video PES
payloads append tovideo; private_stream_1 payloads are
classified and routed to AC-3 / DTS / LPCM / subpicture
BTreeMap<u8, Vec<u8>>per track. The first substream-ID byte
is stripped before append so consumers see clean substream
bytes.0xC0..=0xC7(MPEG audio) is pooled intoac3so
callers can probe codec from the first frame.demux_vobs(&mut reader, &disc, ts, &cells) -> VobStreamsdemux_vobs_path(...)convenience wrapper: resolves
(VobId, CellId)pairs throughVtsCAdt::lookup, translates
title-relative sector positions to absolute LBA via
VTS_xx_1.VOB's base LBA, then runs each cell's range through
VobDemuxer.
- DVD-substream router per mpucoder-{packhdr,pes-hdr,mpeghdrs,
-
Phase 3a tests (all synthetic, 12 cases): pack-header roundtrip
- bad-sync + zero-mux-rate rejection, PES with/without PTS +
bad-start-code rejection, DVD substream classification across all
four substream families, NavPack parse + corrupt-DSI rejection,
and an end-to-end synthetic VOBU (nav sector + video PES sector +
AC-3 PES sector) showing the demuxer routes payloads correctly
while preserving nav-pack metadata.
- bad-sync + zero-mux-rate rejection, PES with/without PTS +
-
Phase 2 (IFO body parsing): clean-room IFO structural decoder per
mpucoder + stnsoft DVD-Video reference pages (no libdvdread /
libdvdnav / libdvdcss / FFmpeg / VLC / mpv / xine source consulted).- VMGI_MAT — full
VIDEO_TS.IFOVideo Manager Information
Management Table parse: last-sector + IFO-end + version + VMG
category + provider ID + number-of-title-sets + sector pointers
to FP_PGC / menu VOB / TT_SRPT / VMGM_PGCI_UT / VMG_PTL_MAIT /
VMG_VTS_ATRT / TXTDT_MG / VMGM_C_ADT / VMGM_VOBU_ADMAP. - VTSI_MAT — full
VTS_xx_0.IFOVideo Title Set Information
Management Table parse: title-set last sector + IFO-end + version- VTS category + sector pointers to PTT_SRPT / PGCI / VTSM_PGCI_UT
/ TMAPTI / VTSM_C_ADT / VTSM_VOBU_ADMAP / VTS_C_ADT / VTS_VOBU_ADMAP.
- VTS category + sector pointers to PTT_SRPT / PGCI / VTSM_PGCI_UT
- TT_SRPT — Title Search Pointer Table walker (8-byte header
- N × 12-byte entries) exposing per-title
(VTS_number, VTS_TTN, chapter_count, angle_count, parental_mask, vts_start_sector).
- N × 12-byte entries) exposing per-title
- VTS_PTT_SRPT — Part-of-Title (chapter) search pointer table
walker with per-title PTT body inferred from the offset list
(boundaries derived from the next-title offset, orend_address + 1for the last title). - VTS_PGCI — Program Chain Information table: 8-byte header +
SRP list (per-PGC category + offset) + each PGC's 0xEC-byte
header (nr_of_programs, nr_of_cells, BCD playback time +
frame-rate bits, prohibited UOPs, next/prev/goup PGCN, still
time, playback mode) + program map + Cell Playback Information
Table (24 bytes per cell — category, restricted flag, still
time, cell command, BCD playback time, first/last VOBU start +
ILVU/last-VOBU end sectors) + Cell Position Information Table
(4 bytes per cell — VOB ID + Cell ID). - VTS_C_ADT — Cell Address Table walker (shared format with
VMGM_C_ADT + VTSM_C_ADT) — entry count recovered from the
end_addressheader field,(vob_id, cell_id) → (start_sector, end_sector)lookup helper. PgcTime— BCD playback-time decoder for thehh:mm:ss:ff
field withFrameRate::{Pal25, Ntsc30, Illegal, Reserved}
discrimination (bits 7+6 of frame byte per mpucoder-pgc.html).VtsIfomaterialiser —parse(buf, vts_number) -> VtsIfo
pulls VTSI_MAT, PTT_SRPT, PGCI, and C_ADT into a single view
and rebuilds per-title chapter lists (DvdTitle→Vec<DvdChapter>,
each chapter carrying its first/last cell numbers derived from
the PGC's program map).DvdDiscPhase-2 API —parse_vmg(&reader) -> VmgIfo,
parse_vts(&reader, ts_index) -> VtsIfo,enumerate_titles( &reader) -> Vec<DvdTitleEntry>, and aparse_vmg_tt_srpt
convenience accessor.
- VMGI_MAT — full
-
Phase 2 tests (all synthetic): VMGI_MAT parse + bad-magic
rejection, VTSI_MAT parse, TT_SRPT walk (3 titles), PGCI with one
PGC + 3 cells, VTS_PTT_SRPT walking 2 titles × 5 chapters, VTS_C_ADT
with 4 cell entries, PgcTime decode (NTSC 30 fps + PAL 25 fps), and
a full hand-built 4-sector composite VTS_xx_0.IFO image (VTSI_MAT- PTT_SRPT + PGCI + C_ADT) round-tripped through
VtsIfo::parse
with chapter-cell-range assertions.
- PTT_SRPT + PGCI + C_ADT) round-tripped through
-
Bootstrap (Phase 1 — filesystem + disc detection): clean-room
read-only DVD-Video support per ECMA-267 (DVD-ROM) + ECMA-268
(DVD-ROM file system) + OSTA UDF 1.02 + the ECMA-167 UDF base
standard. NO libdvdread, libdvdnav, libdvdcss, FFmpeg, xine, mpv,
or VLC source consulted.- ISO 9660 reader (
iso9660module) — Primary Volume Descriptor
at sector 16, root directory record + path-table walk, A-string /
D-string decode, recursive directory enumeration. - UDF 1.02 mount (
udfmodule) — Anchor Volume Descriptor
Pointer probing (sectors 256 / 512 / N-256), Volume Descriptor
Sequence (Primary VD, Partition Descriptor, Logical Volume
Descriptor, Terminating Descriptor), File Set Descriptor, root
File Identifier Descriptor walk, File Entry / ICB with Short_ad
/ Long_ad / Ext_ad allocation descriptors, OSTA compressed
Unicode (compression IDs 8 + 16) per UDF 1.02 §2.1.3. - DVD-Video disc detection (
discmodule) — sniff for ISO 9660
PVD + UDF AVDP on a file or block device, require a top-level
VIDEO_TS/directory containingVIDEO_TS.IFO, enumerate
VIDEO_TS.IFO+.VOB+.BUP+ per-VTSVTS_xx_0.IFO/
VTS_xx_0.VOB(menu) /VTS_xx_1..9.VOB(title) /VTS_xx_0.BUP. dvd://source driver (sourcemodule, default-onregistry
feature) — registers underoxideav_core::SourceRegistryso a
dvd:///path/to/disc.isoURL surfaces a typedDvdDiscSource
that carries the file enumeration + byte-range read.
- ISO 9660 reader (
-
Tests (all synthetic, no real disc data): ISO 9660 PVD / d-string /
path-table / dir walk / nested dir / EOF rejection; UDF 1.02 AVDP /
tag checksum / LVID / FSD / FID iteration / Short_ad / Long_ad /
Ext_ad / d-string compression-mode 8 vs 16; DVD-Video single-VTS,
multi-VTS, AUDIO_TS-empty, rejection-when-no-VIDEO_TS; one full
round-trip against a hand-assembled ~64 KB synthetic disc image
undertests/data/.