Commit Graph
268 Commits
Author SHA1 Message Date
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.
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 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 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 00cd0d42cf sink: dir:// is a TreeSink; extract runs the read/decrypt chain into it 2026-10-01 08:04:48 -07:00
Matthew Jackson 96e538c559 cleanup: drop dead error variants (E9009, E9063, E9082), the io::sink and fmp4/m2ts_mux/HevcMux scaffolding, stale comments and doc links 2026-09-30 22:50:43 -07:00
Matthew Jackson 9ab985fbb2 sink: iso:// and null:// block sinks; a live DVD extracts descrambled; an encrypted folder is keyed like its image; platform null device 2026-09-30 22:15:08 -07:00
Matthew Jackson 064679b201 read: one Read stage (live and image policies) behind one prefetcher and demux; DiscStream removed 2026-09-30 21:58:08 -07:00
Matthew Jackson 01507ddb10 pes: PesSource and PesSink replace pes::Stream; sink caps; TrueHD labels completed in-stream on every path; selection on container inputs 2026-09-30 21:44:58 -07:00
Matthew Jackson ed02bc1392 source: open_source opens every input incl. disc://; MuxSource replaced by Source; one image probe; disc-named output titles 2026-09-30 21:28:56 -07:00
Matthew Jackson 1f5f5df8cb keys: acquire from KeyEvidence into a KeyRing, not from a scanned Disc 2026-09-30 21:11:07 -07:00
Matthew Jackson 79b7893f2e ctx: one run context (halt, events, loss counters) for every stage 2026-09-30 20:36:53 -07:00
Matthew Jackson 9f87155c95 docs: name the m2ts private-data audio by its layout, not a reference implementation 2026-09-30 20:11:59 -07:00
Matthew Jackson 8b165585b8 mux: m2ts output paces a PCR and arrival stamps; ADTS keeps every raw_data_block
M2TS output had no PCR and zero TP_extra_header arrival stamps, and an AAC
access unit from a multi-block ADTS frame was re-framed as one block. Write
adaptation-only PCR packets on PID 0x1001 (the PMT's PCR_PID) at most 100 ms
apart, stamp every packet's ATS from the same 27 MHz clock (at most 1 s before
its DTS, 128 Mb/s per packet), restart with the discontinuity_indicator on a
timeline jump past 10 s, and declare the ADTS block count from the duration.

Parity goldens re-blessed: only the m2ts output lines change (the added PCR
packets and non-zero ATS).
2026-09-30 20:09:33 -07:00
Matthew Jackson 98b17c3898 decrypt: one CSS pack test for disc and file; stage re-review fixes (blank heads, damaged stale-CPI units, refused-read retry) 2026-09-30 19:41:58 -07:00
Matthew Jackson ff3c18c404 mux: m2ts output declares tracks in an HDMV PMT; carry AAC/MP2/MP3 through m2ts input, m2ts and mp4 output
M2TS output had no PAT/PMT, so FFmpeg could not name BD LPCM (or AAC):
write PAT + HDMV-registered PMT every 100 ms of PTS progress, re-frame AAC
as ADTS from its ASC, and give MPEG audio the 0xC0 stream_id. Loose m2ts
input types FFmpeg's stream_type 0x06 audio from its stream_id and ES sync.
mp4:// carries AAC/MP2/MP3 as mp4a + esds.

Parity goldens re-blessed: only m2ts output bytes change (the added
PAT/PMT packets).
2026-09-30 19:41:46 -07:00
Matthew Jackson d335fe5f89 mux: network:// allows LAN and loopback targets 2026-09-30 19:22:35 -07:00
Matthew Jackson 880bbcab4a decrypt: stage review fixes: early stream verdict, strict stale CPI, partial units at EOF only
A byte stream is ruled out from five bytes, so network:// and stdio:// parse
the FMKV header as soon as it arrives. A stale CPI flag is cleared only on
wholly clear TS. A flagged partial unit is blanked only when it ends the
source. A file stage finds a VOB's first aligned pack past damaged sectors,
and one damaged unit at a clip's head no longer hides its source packets.
Raw mpg falls back to the raw head on E7022 too; an uncrackable PS verdict is
kept so a retry does not scan again; SectorBytes reports a short source as
UnexpectedEof; disc_root_of canonicalizes, follows SSIF and drops HD DVD.
2026-09-30 18:53:31 -07:00
Matthew Jackson 10d85b2444 damage: keep going where usable content remains (E7031, UDF FID, MPLS/CLPI truncation, whole-disc E7032) 2026-09-30 18:49:12 -07:00
Matthew Jackson d552ffed88 lpcm: keep the source bit depth (16-bit stays 16-bit, 20/24-bit output 24-bit) 2026-09-30 18:45:38 -07:00
Matthew Jackson 7c35ce6ef4 mux: timeline origin is the earliest sample of any track (mkv, mp4) 2026-09-30 18:43:34 -07:00
Matthew Jackson b6b888bb55 mux: zero read batch is coded E9085; de-flake two sleep tests; changelog and doc fixes from the 1.7.7 review 2026-09-30 18:42:56 -07:00
Matthew Jackson e52f190f89 changelog: 1.8.0 entry (changes since 1.7.7) 2026-09-30 18:33:07 -07:00
Matthew Jackson 6561bcc1c2 error: E9081 is WorkerLost { op } for the copy and verify workers 2026-09-30 15:26:25 -07:00
Matthew Jackson 24c3234b2f error: codes E9077-E9084 for engine remux and preflight refusals 2026-09-30 14:51:08 -07:00
Matthew Jackson bd35fee5d7 disc: MKV staging ranges and E6022 for a staged (partial) image
Disc::mkv_staging_ranges(reader, titles) lists what an image staged for an
MKV rip needs: the volume structures before the partition, the Metadata File,
every directory and File Entry (stream files' too), the data of every file
outside /BDMV/STREAM, and the chosen titles' extents. AACS BD Pre-recorded
Book 0.953 section 3.7: "the BEF shall be set to 0b for the sectors that do not
correspond to Clip AV stream files under \BDMV\STREAM directory", and every
title extent is in the drive's bus map, so the staged image holds no
bus-encrypted byte even when a stream file is unmapped.

Error::ImageScoped (E6022) names an image staged that way when it is offered
as a whole-disc source.
2026-09-28 01:08:34 -07:00
Matthew Jackson a303d9d3a0 disc: re-read an unreadable stream File Entry; forward the unmapped list everywhere
Review fixes for the unlocatable bus-encrypted stream file:

- A File Entry whose read fails gets at most 2 recovery+FUA re-reads (past the
  buffered reader's cache), from a budget of 4 per scan, each after the
  engine's 5 s FAIL_PAUSE, which a Stop ends as Halted. A count, not a
  timeout: HARDWARE ERROR / ILLEGAL REQUEST sense (the BU40N fast-fail wedge)
  gets no re-read, nor does a dead transport, a gone source or an entry that
  read but does not parse. Only then is the file recorded as unmapped.
- E6021 names each file with its read cause: `path (cause)`.
- DecryptingSectorSource, whole_disc::UnitAligned, PrefetchedSectorSource
  (snapshotted at construction) and FileReadAhead forward
  unmapped_stream_files(). A source-scan test fails any production
  SectorSource impl that neither forwards nor is a listed leaf.
2026-09-28 01:08:33 -07:00
Matthew Jackson 163f8e08bc disc: record, don't drop or fail on, an unlocatable bus-encrypted stream file
On a host-key (cert-route) bus-encrypted disc the bus map is built from every
/BDMV/STREAM file. A file whose File Entry extents could not be read was
dropped with a warning, so its sectors passed through still bus-encrypted
into iso://, sweep and dir:// output.

AACS BD Pre-recorded Book 0.953 section 3.7 sets the BEF on the Clip AV
stream files under \BDMV\STREAM, and its Note requires the PC host to decrypt
a bus-encrypted Clip AV stream file. A file that cannot be located cannot be.

The scan now records such files (path, ICB, cause) on the drive's bus map
and carries on: titles that play the clip are dropped as before, and every
locatable file is still de-bussed, so MKV rips and disc info are unaffected.
ensure_image_debussable() refuses a whole-disc image with the new
Error::BusStreamUnmapped (E6021) naming the file(s); SectorSource gains
unmapped_stream_files(), forwarded by every wrapper. extract_tree never reads
or writes such a file and counts it lost in bytes_unreadable.
stream_content_ranges fails closed with E6021. A Stop during the walk still
returns Halted and is not logged as a disc fault; an embedded file holds no
6144-byte Aligned Unit (section 3.10.1) and is skipped. Tests quote the spec.
2026-09-28 01:08:33 -07:00
Matthew Jackson 21b6665537 mux: public header-only MKV probe
probe_mkv reads the EBML header, Segment Info and Tracks and stops before
the first cluster, returning the muxing/writing app, declared duration,
title, timestamp scale and a minimal per-track view (number, kind, codec
id, language). parse_mkv_header now captures MuxingApp and WritingApp and
keeps "no Duration" distinct from a zero one; MkvStream::open is otherwise
unchanged.

parse_freemkv_version pulls (major, minor, patch) out of the stamp our
writer puts in MuxingApp ("freemkv 1.7.7 (gc8e67f1)"). Older builds wrote
a bare "freemkv" and get None.

On Duration: finish() only back-patches it when the title declared no
runtime (the placeholder path, e.g. HD-DVD). A title with a declared
duration keeps that value in the header whatever was actually muxed, so
the header alone can't tell a short mux from a full one. For that,
probe_mkv_with_cues follows the SeekHead to the Cues (seeking past the
clusters, never reading one) and reports the last cue time as a lower
bound on the muxed runtime. declared_duration_is_kept_not_measured pins
the current writer behaviour.
2026-09-27 22:25:28 -07:00
Matthew Jackson fc64ecd01b whole_disc: name a missing stream folder; stop after a late halt
Titles with no /BDMV/STREAM (or /HVDVD_TS) fail as E6003 naming the folder, not
E7013's key-refresh advice. A stop landing in the last key lookup ends before any
output. Docs: CSS is descrambled; the mid-pass E7032 is the one late refusal.
2026-09-27 20:17:01 -07:00
Matthew Jackson e2fc55cf01 whole_disc: one shared reader for every whole-disc/image → ISO copy
Moved from freemkv-engine and freemkv so the GUI, CLI and image paths share one
set of rules. A key must open two probed units before it keys an unplayed file,
and alternates are the held base keys only (forensic FMTS keys never).
2026-09-27 20:13:23 -07:00
Matthew Jackson 52131315a3 error: add E7032 WholeDiscKeyMissing
A decrypted whole-disc image would keep encrypted pieces: a stream file no
title plays is encrypted and no held key opens it. The fix is an MKV rip or a
raw copy, not a key, so it gets its own code instead of E7013.
2026-09-27 20:13:22 -07:00
Matthew Jackson 7cf94da55e changelog: DecryptingSectorSource unit base is required; clear_unit_base 2026-09-27 18:54:29 -07:00
Matthew Jackson f9dcda21e6 disc: read UDF and the AACS files before the handshake
Standard order: UDF, then Unit_Key_RO.inf, the content cert and the MKB as plain
reads, then the handshake only on an AACS disc. An unreadable key file on a live
disc fails the scan with the new E7031 unless ScanOptions::raw_copy is set; a dead
bus or Stop during the AACS/CSS handshake aborts it; no drive MKB read for certs.
2026-09-27 17:50:57 -07:00
Matthew Jackson 866a0733e6 hddvd: XPL timecode frames count in timeBase, not tickBase
tickBase is the markup clock; timeBase (fallback tickBase, then 60) sets FF and
the measured 60000/1001 gate. Other timeBases stay unadjusted.
2026-09-27 17:04:05 -07:00
Matthew Jackson e0e679b108 changelog: note the mp4 DTS, mkv PCM probe and network keepalive fixes 2026-09-27 11:55:07 -07:00
Matthew Jackson 740cfcb9cf mux: address review of audit fixes
Keepalive instead of a network idle limit, mkvmerge-style MKV origin, PCM depth
inference, VobSub open-end patching, DTS-based monotonic PCR, and numeric codes.
2026-09-27 11:54:55 -07:00
Matthew Jackson 1225ecea81 scsi: a cleaning cartridge reads as no disc
30/03 and 30/07 were Settling, which counts as a disc, so autorip would rip a
cleaning cartridge. Nothing is rippable and it does not settle: Absent.
2026-09-27 11:45:57 -07:00
Matthew Jackson 5ede33de4a drive/scsi: empty-drive fail-fast, no inline ALLOW on a full cap, EACCES unlisted
wait_ready returns the 3Ah sense after 10 empty polls with no 04/01 seen; Drop
sends ALLOW inline only if the spawn fails; no-sysfs list drops EACCES/EPERM
nodes; start_unit moved off spin_cycle's doc; presence docs say "derived".
2026-09-27 11:45:57 -07:00
Matthew Jackson dda18dd483 drive/scsi: tri-state DiscPresence per MMC-6; wait_ready dead-bus budget
disc_presence(path) -> Present/Absent/Settling (only 3Ah absent; 04/01 Settling);
drive_has_disc counts Settling as a disc. wait_ready: 5 s budget from the first
failure's completion, START UNIT on 04/02, fail fast on 30h. Drop/list fixes.
2026-09-27 11:45:57 -07:00
Matthew Jackson 5b78796da8 disc: note the TrueHD layout fix and its unnamed-layout limit
CHANGELOG lists the label correction under Fixed with the old-receiver caveat.
2026-09-27 11:42:56 -07:00
Matthew Jackson 4512f641ef disc: fall back to the TrueHD count for unnamed layouts
A layout with no N.M variant (e.g. 5.2) used to keep the container value,
understating MKV Channels; use from_count instead. Note the new layout strings.
2026-09-27 11:24:12 -07:00
Matthew Jackson 248341bbe5 css/keys: honour halt in scan crack paths; surface read faults and rejections
CrackOutcome gains Unreadable and is non_exhaustive; decrypt_keys_for_title
takes a halt token and returns Result; all-rejected read-time keys are
AacsKeyRejected; Disc::inputs_with_samples fills validation samples.
2026-09-26 19:31:25 -07:00
Matthew Jackson a42241eb15 Prepare 1.7.7 with concise comments and shared CI policy 2026-09-26 11:46:32 -07:00
Matthew Jackson 3f156f1f03 v1.7.6: bump version (freemkv-unlock git-pinned for the tag) 2026-09-26 04:05:38 +00:00
Matthew Jackson df43373f41 docs: neutral wording in changelog [skip-media] 2026-09-25 17:10:05 -07:00
Matthew Jackson b52e3c8292 chore(release): bump to 1.7.6, follow the CI-required release-notes shape
Bumps Cargo.toml + Cargo.lock to 1.7.6. Also fixes a CI-shape defect the
previous release left behind: dev's CHANGELOG still said
`## [1.7.5] — UNRELEASED` after 1.7.5 shipped (release-orchestrate dated
main but did not push a fresh UNRELEASED heading back to dev). Corrects
that here so the changelog job accepts 1.7.6 on the way to qa:

  ## [1.7.6] — UNRELEASED
    - Version aligned; unified release driven by freemkv 1.7.6.
  ## [1.7.5] — 2026-09-23
    - Version aligned (or actual content, per the shipped main entry).

The driver for 1.7.6 is the freemkv Linux desktop shell (GTK4 +
libadwaita) + rip-finished desktop notification (issue #56).
2026-09-24 20:23:08 -07:00
Matthew Jackson c1caac3a7e docs: 1.7.5 changelog entry for the unified release [skip-media]
Version aligned to 1.7.5. No functional change to this crate — the release
is driven by freemkv-unlock mirroring the freemkv-firmware 0.9.0 ABI, where
the drive's separate Ake (0x06) and Bus (0x07) levers are retired into a
single Encryption (0x06) lever.
2026-09-22 21:04:54 -07:00
Matthew Jackson 8ce40edba3 v1.7.4: bump version (freemkv-unlock git-pinned for the tag) 2026-09-21 23:03:33 +00:00