Commit Graph
2142 Commits
Author SHA1 Message Date
Matthew Jackson a27431d962 aacs: a Stop while reading index.bdmv is Halted
The stride resolver's index.bdmv read, and the live UHD check, took a Stop for an unreadable
index and went on with a default stride. The capture and the scan's version read now end as
Halted, like their other reads.
2026-10-04 12:25:45 -07:00
Matthew Jackson ff96202a22 dvd: plan the forced-subtitle probe over the whole title
Windows were planned per extent, and each small extent planned a read of itself, so a title of
thousands of interleaved units spent the 256 MiB budget on its first minutes. The windows are
now planned over the title's sectors end to end and mapped onto the extents they cross.
2026-10-04 12:25:45 -07:00
Matthew Jackson dc1a0cec5a labels: one control-character filter for disc-authored titles
bdmt title and description text kept raw control characters from CDATA and plain bodies,
so a disc could put a terminal escape sequence into a shown title or a file name. It now
goes through the same filter as the Blu-ray di:name title.
2026-10-04 12:25:45 -07:00
Matthew Jackson 3b0c1f2c6c dvd: the unit walk stops on Stop; duration and chapter names follow the chapter marks
The interleaved-unit walk polls halt before each read, passes a drive's Halted up instead of
taking it for an unreadable chain, gives the cell back whole on a short read rather than
reparsing the last pack, and cannot overflow on a cell spanning every sector.

A title's duration no longer subtracts the dropped leading angle pieces: the PGC time never
counted them, and the cell-sum fallback now counts an angle block once, as the chapter marks
do. Text-data chapter names are placed by the part-of-title table on the program each
chapter starts at; names that cannot be placed one per program are dropped. A text-data
name is looked for within its longest accepted length, not to the end of the table.
2026-10-04 12:25:45 -07:00
Matthew Jackson 1ea2b22ced dvd: the DVD scan marks its titles DvdPs; DVD-only stages run on those alone
ContentFormat::MpegPs covered DVD VOBs, HD DVD EVOs and mpg:// files alike, so every stage
keyed on it ran on all three. The VOBU cell filter dropped every cell after the first of an
mpg:// VOB file (one extent, the whole file) and of an HD DVD .evo; the CSS crack, the forced
VobSub probe and the AC-3 diagnostic probe also ran on HD DVD titles.

The DVD scan now sets ContentFormat::DvdPs. The VOBU navigation, CSS key resolution, forced
VobSub probe and AC-3 probe run only on it; the demuxer, codec parsers, timeline and AACS PS
checks treat both as a program stream (ContentFormat::is_program_stream). mpg:// stays
MpegPs and gets no DVD stage.
2026-10-04 12:25:45 -07:00
Matthew Jackson 4d5987b21e hddvd: read AACS-wrapped playlists, judge encryption from the packs, join PEVOB_n features
- A genuine disc's VPLST*.XPL is an AACS-encapsulated ARF ([HD] §4.4.2,
  Table 4-13: "AACS", type 12h, Nfs at bytes 7..11, a 272-byte file name field,
  then the XML). The wrapper is stripped before parsing; rips ship it bare.
- An AACS directory no longer marks an HD DVD encrypted on its own: rips keep it
  renamed (ANY!, AAC!) over clear EVOs. Identify and scan sample the largest
  EVOs' packs and keep the AACS verdict only when a pack is scrambled.
- The clip-derived feature also joins PEVOB_1/PEVOB_2 splits.
- Comments: the VTI is the Advanced VTS information file; 0xFD ext 0x56 is the
  VC-1 sub video, and TrueHD rides private_stream_1.
2026-10-04 12:02:43 -07:00
Matthew Jackson b3e1a93e9e hddvd: decrypt AACS per pack, keyed by each EVOBU's CPI, and prove keys on payload
HD DVD encrypts each 2048-byte pack on its own ([HD] AACS HD DVD and DVD
Pre-recorded Book 0.952, §4.3), not in 6144-byte aligned units. Bytes 0..128 stay
clear; bytes 128..2048 are AES-128-CBC under the AACS IV with
Kc = AES-G(Kt, Dtk || CPI_lsb96), Dtk = pack bytes 84..88 (§4.3.2, Table 4-7).
Kt is the Title Key named by TITLE_KEY_PTR in the CPI (Table 4-2), carried in the
GCI packet of the NV_PCK that leads each EVOBU (CPI at GCI data offset 12).

- aacs::hddvd: pack classification (NV_PCK with its CPI, scrambled PES pack,
  HL_PCK), the content key, per-pack decrypt, and a payload check past byte 128
  (PES/padding start codes, AC-3/E-AC-3 sync at the first-access-unit pointer).
- The encrypted flag is PES_scrambling_control of every pack, not byte 20 of a
  unit's first pack (an NV_PCK there hid the encrypted packs after it).
- is_clean for MpegPs no longer passes ciphertext: an encrypted pack keeps its
  pack start code, so cleanliness is judged on the flags and the payload check.
- The decrypting reader carries the CPI between reads and looks back for the
  NV_PCK when a read starts mid-EVOBU; a pack with no CPI is blanked and counted,
  one under a Segment Key or an unheld Title Key fails loud.
- Key resolution holds every Title Key under its VTKF entry number (a source's
  key index is its position among the present entries; genuine discs populate
  all 64 slots) and proves them by decrypting packs from three 2048-sector
  windows of the main title; keys that open none refuse (E7013).
- Spec registry: KS-30 quotes [HD] §4.3.2; KS-31 records the disc-measured CPI
  location. The spec guards now pin the per-pack flag and the 128-byte head.

The parity_image_hddvd_clear golden changes because its clear fixture is now
judged clear (no key asked, every file extracted) instead of keyed best effort.
2026-10-04 12:02:43 -07:00
Matthew Jackson ae7ca7a457 mpls: describe the hdr_plus_flag bit without a reference citation 2026-10-04 11:42:28 -07:00
Matthew Jackson 5d3bc2edb3 aacs: find a plain /AACS HD DVD dir, one stride-version resolver, report Class II MKBs
- HD DVD: the AACS directory is any root directory holding MKBROM.AACS, whatever
  its name. Both encrypted "300" HD DVDs use a plain /AACS (mirror AACS_BAK), which
  the old "name ends in !" rule missed, so they could not be keyed. A *_BAK
  mirror is used only when no primary copy exists.
- Unit_Key_RO.inf stride: one resolver (content certificate, then a pre-recorded
  MKB's type, then index.bdmv INDX0300, then UHD) for the scan, read_aacs_inputs
  and resolve_candidate, which now takes the version instead of re-deriving it
  from the MKB with a V10 default.
- A Class II MKB (0x000A1003) keeps its media key data in record 0x0c, which the
  PK/DK derivation does not read: check_mkb_class reports it as MkbClassError
  (E7109) and derivation stops with a warning instead of failing silently.
2026-10-04 11:31:30 -07:00
Matthew Jackson 318a1d6768 bd: unassigned STN rate nibbles are unknown, skip the "Blu-ray" title placeholder, drop /BDMV/AACS
- STN frame-rate nibbles 5 and 8 are unassigned (libbluray, MediaInfo, tsMuxer);
  map them to Unknown instead of 30 and 60 fps. Fight Club UHD's menu clip
  carries 8 and was shown as 60fps.
- bdmt titles: Warner's non-English files carry "Blu-ray" in di:name; skip it and
  fall through to the next candidate. One placeholder check is shared with the
  META title read in bluray.rs.
- /BDMV/AACS no longer marks a disc encrypted: no disc has it, libaacs reads only
  root AACS/, and our key readers never look there.
- Doc fixes: the bdmt namespaces are urn:BDA:bdmv;disclib + urn:BDA:bdmv;discinfo,
  di:description is a container, and index versions include 0240.
2026-10-04 11:23:19 -07:00
Matthew Jackson b998aa1261 uhd: keep mastering metadata without content light, read hdr_plus_flag, dvcC bl_present=0 on the EL track
- HEVC: the mastering-display SEI alone now yields HDR10 metadata; MaxCLL/MaxFALL
  are optional and omitted from Colour when the stream has no content-light SEI
  (Deadpool, Sicario, Lucy, Life of Pi and others carry 137 without 144).
- MPLS: read the HEVC hdr_plus_flag (bit 6 of the byte after color_space, as
  libbluray mpls_parse.c) and label an HDR10 base with it HDR10+.
- MKV: the disc's DV track is the EL + RPU stream beside the HDR10 base track, so
  its dvcC now says bl_present=0 with the base's compatibility id 6 (Dolby TS
  spec 7.2.2; mkvmerge's profile 7 id).
- BD audio_format 6 ("multi-channel", no count) no longer claims 5.1 for
  DTS-HD and DD+, which reach 7.1 and are not re-read from the stream.
2026-10-04 11:20:46 -07:00
Matthew Jackson 3992cee538 dvd: the unit chain's end is 0xFFFFFFFF by the book; the seamless bit is not a clock statement 2026-10-04 11:01:03 -07:00
Matthew Jackson 2b8133ed5d dvd: decode the VMG region mask, label streams from IFO code extensions, probe FSTA_DSP forced subtitles
Region: a DVD reports its VIDEO_TS.IFO region mask (VMGI_MAT 0x23, bit n
set = region n+1 prohibited) as DiscRegion::Dvd or Free; UHD/FMTS stay
Free; Blu-ray and HD DVD report the new DiscRegion::Unknown instead of a
false Region-free.

Labels: audio code extension 2 is Descriptive, 3/4 Commentary; subpicture
code extension 5-7 (captions) is SDH and 9 is forced. The attributes are
per logical stream, so each label follows AST_CTL/SPST_CTL routing.

Forced probe: with probe_forced_subtitles, sample each DVD title's VobSub
streams under the PGS probe's budget and windows and mark a stream forced
when every sampled displayed SPU opens with FSTA_DSP. Scrambled packs are
descrambled after the title's keyless CSS crack, or skipped.
2026-10-04 10:48:35 -07:00
Matthew Jackson ff48331f02 dvd: read an interleaved cell as its own units, and an angle block as one angle
An interleaved cell's sector range also holds another program's units. The scan now follows
the cell's navigation packs (each unit's end, then the next unit's start) so a title's extents,
and its size, are exactly what it plays. Discs write "no next unit" as 0x7FFFFFFF or
0xFFFFFFFF; both end the chain, and an unreadable chain falls back to the whole range.

An angle block plays one angle: extents keep its first cell wherever the block sits, and
chapter times count it once. labels::audio_codec_label exposes the library's friendly codec
name for front ends that show the codec apart from a track's variant tag.
v1.7.7-rc13
2026-10-03 21:35:29 -07:00
Matthew Jackson bdc5e39463 dvd: read chapter names from the VMG text data
VIDEO_TS.IFO can carry a text data manager (pointer at VMGI 0xD4) with
per-title chapter names. Parse its first language unit, map titles onto
TT_SRPT order and use the names as Chapter.name, keeping the numeric
ordinal for any chapter the disc does not name. A title whose name count
differs from its chapter count is ignored, and every read is bounded by
the table's last byte and the IFO length.
v1.7.7-rc12
2026-10-03 20:10:37 -07:00
Matthew Jackson 68dfffda94 dvd: play a title the way its navigation packs say
A cell in an interleaved block shares its sectors with another program's units (a second
language version), and each VOB runs its own clock. The mux read every sector of a cell and
inferred joins from timestamp jumps, so a title mixed in the other version's video, froze at
the jumps, and lost about half a second of audio at each VOB join.

Each VOBU's navigation pack names its cell and its start/end time: keep only the VOBUs of
the cell each extent opens with, and shift each new VOB's clock to start where the last
kept VOBU ended, on every track at once.
2026-10-03 20:09:44 -07:00
Matthew Jackson 5dfb680493 chore(dependabot): monthly grouped version updates v1.7.7-rc11 2026-10-02 20:24:26 -07:00
Matthew Jackson 5bf8ef5303 mpeg2 notes: describe the program-stream packing without naming a muxer v1.7.7-rc10 2026-10-02 17:00:51 -07:00
Matthew Jackson a8b6a2c1e0 au assembly: a PES opened inside a picture times the picture commencing in it
A PES PTS belongs to the first access unit commencing in that PES
(ISO/IEC 13818-1 2.4.3.7). The assembler gave every mark in an AU's byte
range to that AU, so in a program stream that packs pictures back to back
(ffmpeg's MPEG-PS) each picture took its successor's PTS. MPEG-2 GOPs whose
first displayed picture is a leading B then re-locked their origin a frame
off, read as a join, and dropped that open GOP's leading Bs: the synthetic
A1 fixture lost 3 of 180 frames.

A mark opened inside an AU that runs past it now times the next AU; one
running into the first AU after pre-sync bytes times that AU. Source
provenance is unchanged. DVD and HD DVD titles, which open a PES at each
timed picture, are byte-identical.
2026-10-02 15:27:13 -07:00
Matthew Jackson 04f28447bc timeline: the module doc links the sink entry point, map_picture v1.7.7-rc9 2026-10-02 10:43:31 -07:00
Matthew Jackson 53e94576ad seam plan: drop a picture whose reference a clip mark trimmed
The plan trims video by each picture's own PTS in decode order, so an IN
mark inside a GOP dropped the I-picture before it and kept the pictures
predicted from it, and an OUT mark dropped an anchor displayed after it
while keeping the B-pictures displayed before it that decode from it.

Under a seam plan each video picture is now also judged by what the marks
took: once a picture that may be a reference is trimmed (any but an MPEG-2
B or a leading picture), the track drops up to the next keyframe, and that
keyframe's leading pictures with it. These drops count with the frames
outside the marks; kept frames keep their PTS. Sinks pass the picture's
keyframe flag and coding to the plan.
2026-10-02 10:37:58 -07:00
Matthew Jackson 6a17e560fc h264, hevc, vc1: drop pictures a decoder cannot reconstruct at a start, join or gap resync
The MPEG-2 fix left its siblings emitting pictures whose reference is not in
the output, and every codec, MPEG-2 included, resumed after a gap on a
keyframe whose leading pictures predict from an anchor the resync gate
dropped.

H.264, HEVC and VC-1 now decide each picture in decode order against the
anchors the output holds, as MPEG-2 does: none before the first
random-access picture, at a join (the decode clock, else the PTS frontier,
moves at the random-access picture), at a VC-1 BROKEN_LINK, and from the
keyframe the gate resumes on after a discontinuity (MPEG-2 too); the gate
still drops and counts the gap itself. Open-GOP leading B-pictures (H.264
by PTS, VC-1 CLOSED_ENTRY 0 by decode order, interlaced field pairs from
FCM/FPTYPE) and HEVC RASL are dropped when that anchor is missing; a CRA
at any join, not only a 3 s step back, is written as BLA. Dropped pictures
keep their display slots, so every kept frame keeps its PTS, and an MVC
dependent unit goes with its base picture. Closed-GOP and IDR-only titles
are unchanged.

connection_condition 1 is the non-seamless join and 5/6 the seamless ones;
the PlayItem and mark_clip_boundary docs had them reversed.
2026-10-02 10:37:53 -07:00
Matthew Jackson 8d15f5211e tests: pin pictures emitted without their reference at a start, join or gap resync
Thirteen ignored tests, each failing on current code, cover H.264 (stream
start, join and gap resync onto an open GOP; inter pictures before the
first random-access picture), HEVC (a forward-PTS join and a gap resync
onto a CRA hand its RASL to the decoder; pictures before the first IRAP),
VC-1 (an open entry point at the start or after a gap; BROKEN_LINK), the
MPEG-2 gap resync onto an open GOP, and the seam plan keeping a picture
whose reference it dropped at a clip's IN mark. Two passing tests pin
the cases that are already right: a closed VC-1 entry point and RASL
after a seamless HEVC join.
2026-10-02 09:48:16 -07:00
Matthew Jackson 8a0cb2adbf mpeg2: drop pictures a decoder cannot reconstruct at a title start or join
A title that opens on an open GOP emitted the GOP's leading B-pictures,
whose forward reference precedes the title; players without ffmpeg's
open-GOP skip showed them as a green or corrupt opening frame.

The parser now decides each picture in decode order against the anchors
the output holds: pictures before the first I-picture and leading
B-pictures of an open GOP whose forward reference is missing (stream
start, broken_link, or a join where the PES timeline jumps) are dropped.
Dropped pictures keep their display slots, so every kept frame keeps its
PTS. Closed GOPs are untouched.
2026-10-02 09:31:38 -07:00
Matthew Jackson 71b6df577a tests: the flapping-answer wait steps by wall time, so a slow runner's late polls cannot outlast the window v1.7.7-rc8 2026-10-02 01:46:33 -07:00
Matthew Jackson a53d40bfac m2ts: sink rides the clip-join timeline
A multi-clip playlist's source PTS restarts at each clip join. The m2ts sink passed it
through, so one TS stepped back in time at every join, and the DTS deriver's order guard
then wrote every later reordered AU as PTS only (a 34-clip UHD title kept DTS on its first
clip alone). The sink now maps each frame through TimelineContinuity, driven by the base
video view, and fails a seam plan that dropped most of the title, as the other sinks do.
v1.7.7-rc7
2026-10-02 01:07:32 -07:00
Matthew Jackson 7c718e31e4 read: an image extent's sub-unit tail is read and judged by the decrypt stage, not refused E9030
The image Read policy refused any extent tail shorter than one 3-sector AACS unit. Blu-ray
stream files always end on the unit grid, but an HD DVD .EVO need not, and a clear HD DVD
now rips through the keyed pipeline (unit_align 3), so the main title of a real disc failed
E9030 at the end of its first off-grid extent. The tail is now one short read, as the live
policy already did; the decrypt stage passes it when clear and refuses it (E7013) when it is
the head of an encrypted unit.
2026-10-02 01:07:32 -07:00
Matthew Jackson 37fde516af Harden wall-clock-sensitive tests against slow runners 2026-10-02 00:24:41 -07:00
Matthew Jackson 54b50a815e disc tests: DVD takes the one encryption decision on its CSS scramble flag
Clear content passes with no key source asked, scrambled content with no recovered key refuses
E7027, a recovered key descrambles.
v1.7.7-rc6
2026-10-01 22:46:14 -07:00
Matthew Jackson dc6d0fe693 keys: one encryption decision for every AACS format, the HD DVD clear case folded into it
KeyRing::acquire probes the pieces in scope once, each unit judged by its format's detector
(BD/UHD: the CPI flag; HD DVD: flagged or not whole MPEG-PS). Content read in the clear asks
no source, whatever key files the disc declares; for FMTS the forensic segments must read clear
too. Encrypted content goes to the format's keying (BD/UHD per piece, HD DVD best effort) and is
refused E7022 / E7032 when no source has the key. Replaces 9e9ff21's HD DVD-only check.
2026-10-01 22:46:14 -07:00
Matthew Jackson 6727fe893a mkv: an MPEG-2 track's DefaultDuration follows its measured frame period
DefaultDuration came from the IFO's video standard (29.97 for NTSC). A soft-telecined film
title carries 23.976 coded frames a second, so the header disagreed with the frame count
(11440 frames over 476 s on the dvd fixture's title 2). finish() now rewrites the value when
the kept frames' PTS span measures another standard rate.
2026-10-01 22:03:31 -07:00
Matthew Jackson 07a7ea8aad dvd: warn about titles split across PGCs once per disc, not per title per scan
62d56df warned from parse_pgcit for every split title on every scan; a CLI rip scans its disc
three times, so a DVD with four split titles logged the same warning twelve times. The scan
now logs one line per disc naming every split title, and a rescan of that disc logs it at
debug.
2026-10-01 22:03:30 -07:00
Matthew Jackson 8e317afc16 source: an image or folder names its title by the meta title, else the playlist, as 1.7.7
ed02bc1 named every disc layout's output title by its meta title, else its volume id. A
folder's volume id is its directory name, so a DVD title ripped from an image and from its
extracted folder got different segment titles and the two MKVs stopped being byte-identical.
A drive still names by meta title, else volume id.
2026-10-01 22:03:30 -07:00
Matthew Jackson 9e9ff21ba1 keys: an HD DVD copy already in the clear needs no key, whatever its title-key file declares
e44ee04/1f5f5df refused every HD DVD declaring more than one CPS unit before reading any
content (E7022), so a decrypted image that kept its AACS directory stopped ripping. Acquisition
now samples each piece first: unflagged, structurally whole MPEG-PS packs make a clear set.
2026-10-01 21:44:18 -07:00
Matthew Jackson 414766ec44 tests: the progressing-consumer join test applies one item per quarter window, so a slow runner's sleep overshoot is not a stall v1.7.7-rc5 2026-10-01 18:29:34 -07:00
Matthew Jackson de4658dab8 scsi(macos): take the default IOKit port as MACH_PORT_NULL, no availability check for the Rust link to resolve v1.7.7-rc4 2026-10-01 17:19:24 -07:00
Matthew Jackson f7ed7278b2 Keep a Stop over the empty-output MkvInvalid it causes v1.7.7-rc3 2026-10-01 15:27:23 -07:00
Matthew Jackson ca0f9d5bc8 Keep a strict read error over the empty-output MkvInvalid it causes 2026-10-01 15:23:31 -07:00
Matthew Jackson 134fdd973f Cargo.lock: drop local patch.unused entries 2026-10-01 15:17:42 -07:00
Matthew Jackson 09b9324903 Merge branch 'audit-lib-G6' into audit-fix-lib 2026-10-01 15:17:42 -07:00
Matthew Jackson 6af1dcd912 Merge branch 'audit-lib-G5' into audit-fix-lib 2026-10-01 15:16:36 -07:00
Matthew Jackson 735efac62b mkv tests: drop redundant cast 2026-10-01 15:15:06 -07:00
Matthew Jackson 92b14006a2 mux: EditionFlagDefault uses its registered ID, SeekHead refuses an unreserved target; tests for decode_ts reorder clamp, VobSub stop, field order, late AAC CodecPrivate 2026-10-01 15:14:54 -07:00
Matthew Jackson f49f966c46 video codecs: pin param-set re-assert, SEI, discontinuity, slice types, field pairing, reorder; warn on unparseable HEVC SPS 2026-10-01 15:14:11 -07:00
Matthew Jackson d3534bafdd audio codecs: pin ADTS/PCE, DTS CRC/EXSS, LPCM tables, free-format padding, TrueHD LFE; doc and naming fixes 2026-10-01 15:14:11 -07:00
Matthew Jackson 566c9c8df3 Merge branch 'audit-lib-G8' into audit-fix-lib 2026-10-01 15:12:46 -07:00
Matthew Jackson 92a79afef0 Merge branch 'audit-lib-G7' into audit-fix-lib 2026-10-01 15:12:46 -07:00
Matthew Jackson b14e6f1113 Merge branch 'audit-lib-G4' into audit-fix-lib 2026-10-01 15:12:45 -07:00
Matthew Jackson 8f5b45b907 Merge branch 'audit-lib-G3' into audit-fix-lib 2026-10-01 15:12:45 -07:00
Matthew Jackson 31a0f0d4d2 Merge branch 'audit-lib-G2b' into audit-fix-lib 2026-10-01 15:12:45 -07:00