Files
libfreemkv/docs/disc-to-rip.md
T
MattJackson 7cd2c937ed 0.18.1 docs: refresh README, CHANGELOG, and docs/ for the trait split
The library's public-facing docs were sitting on the 0.17 trait
surface — Disc::copy, pes::Stream, SectorReader, etc. — even though
all in-tree callers migrated in 0.18 rounds 1-3. With 0.18.1 about
to ship, a user copy-pasting the README sample from crates.io would
have hit a compile error.

This commit is purely doc-side:

- README.md: Quick Start rewritten onto Disc::sweep + Disc::patch
  with caller-orchestrated multipass; Streams table footnote and
  Architecture row reference FrameSource / FrameSink.
- CHANGELOG.md: 0.18.1 entry describing the redesign — primitives,
  trait splits, deprecations (kept alive through 0.18.x, deletion
  target 0.18.2), throughput numbers.
- docs/{rip-recovery,api-design,architecture,disc-to-rip,
  drive-access,udf}.md: every Disc::copy / pes::Stream /
  SectorReader reference updated to the 0.18 trait surface.
- FEATURES.md: deleted (8+ versions stale; capabilities live in
  README.md and CHANGELOG.md now, matching the workspace-top
  FEATURES.md removal in 84acd65).
- examples/iso_dump.rs: verified compiles against 0.18.1.

No code changes.

See (internal)/memory/0_18_redesign.md.

Single contributor: MattJackson.
2026-05-09 12:13:51 -07:00

5.2 KiB

Disc to Rip: End-to-End Flow

How libfreemkv goes from a disc in the drive to decrypted content ready for backup. This is the starting point for understanding the library.

The Pipeline

Insert disc
    │
    ▼
1. Open drive (drive/mod.rs)
    │  INQUIRY → identify drive
    │  Match bundled profile → chipset, unlock parameters
    │
    ▼
2. Init drive (drive/mod.rs → platform/mt1959)
    │  Firmware upload (if needed, 10s recovery wait)
    │  Unlock → vendor-specific command activates raw read mode
    │  Speed calibration → probe_disc()
    │
    ▼
3. AACS handshake (aacs/handshake.rs) — optional
    │  Allocate AGID
    │  Exchange certificates + nonces (ECDH)
    │  Derive bus key
    │  Read Volume ID + read_data_key
    │  (fails gracefully if drive doesn't support AACS for this disc)
    │
    ▼
4. Read UDF filesystem (udf.rs)
    │  Sector 256: AVDP → find Volume Descriptor Sequence
    │  VDS: Partition Descriptor (physical start) + Logical Volume (metadata start)
    │  Metadata partition → File Set Descriptor → Root directory
    │  Walk directory tree: BDMV/, AACS/, CERTIFICATE/
    │  → docs/udf.md
    │
    ▼
5. Read AACS files from disc (aacs/mod.rs)
    │  AACS/Unit_Key_RO.inf → SHA1 = disc hash
    │  AACS/Content000.cer → AACS version (1.0 or 2.0), bus encryption flag
    │  MKB via SCSI → for key derivation fallback
    │
    ▼
6. Resolve encryption keys (decrypt.rs → resolve_encryption)
    │  BD AACS:
    │    Path 1: disc hash → KEYDB.cfg → VUK (fast, 99% of discs)
    │    Path 2: KEYDB media key + Volume ID → VUK
    │    Path 3: MKB + processing keys → media key → VUK
    │    Path 4: MKB + device keys → subset-difference tree → VUK
    │    VUK → decrypt unit keys from Unit_Key_RO.inf
    │  DVD CSS:
    │    Table-driven cipher — no KEYDB needed
    │  → docs/aacs.md
    │
    ▼
7. Parse playlists (mpls.rs) — BD/UHD only
    │  BDMV/PLAYLIST/*.mpls → titles with play items
    │  Each play item: clip ID, in/out timestamps
    │  STN table: video, audio, subtitle streams with codec + language
    │  → docs/mpls.md
    │
    ▼
8. Parse clip info (clpi.rs) — BD/UHD only
    │  BDMV/CLIPINF/*.clpi → EP map (timestamp → sector mapping)
    │  Coarse + fine entries → full PTS and SPN
    │  SPN → byte offset → sector extents for reading
    │  → docs/clpi.md
    │
    ▼
9. Parse BD-J labels (labels/) — optional
    │  BDMV/JAR/*.jar → Java class constant pool strings
    │  5 format parsers: Paramount, Criterion, Pixelogic, CTRM, Deluxe
    │  Audio track labels: "English Descriptive Audio", "French 5.1", etc.
    │
    ▼
10. Stream content (mux/disc.rs → DiscStream)
     │  Read sectors → decrypt → TS demux → PES frames
     │  Or: read sectors → decrypt → raw bytes (for ISO output)
     │  Drive::read() is single-shot. DiscStream::fill_extents adapts the
     │  batch size on failure (halve / probe-up). Bad-range retry is layer
     │  1 above this — Disc::patch re-runs against the mapfile.
     │
     ▼
  PES frames → output stream (MKV, M2TS, network, etc.)

API Summary

// Open + init drive
let mut drive = Drive::open(Path::new("/dev/sg4"))?;
drive.wait_ready()?;
drive.init()?;
drive.probe_disc()?;

// Scan disc (UDF + playlists + AACS — all automatic)
let disc = Disc::scan(&mut drive, &ScanOptions::default())?;

// Stream pipeline — PES frames from any source to any output.
// 0.18: input() returns Box<dyn FrameSource>, output() returns Box<dyn FrameSink>;
// direction is type-checked, so calling .write() on an input is a compile error.
let opts = InputOptions::default();
let mut input = libfreemkv::input("disc:///dev/sg4", &opts)?;
let title = input.info().clone();
let mut output = libfreemkv::output("mkv://Movie.mkv", &title)?;
while let Ok(Some(frame)) = input.read() {
    output.write(&frame)?;
}
output.finish()?;

Module Reference

Module Doc Purpose
drive/ drive-access.md Open, identify, init, unlock, single-shot read
scsi/ drive-access.md Platform SCSI transport (Linux, macOS, Windows)
udf.rs udf.md UDF 2.50 filesystem
mpls.rs mpls.md MPLS playlists + STN streams
clpi.rs clpi.md CLPI clip info + EP map
ifo.rs -- DVD IFO parser
aacs/ aacs.md Key resolution + content decrypt + bus handshake
css/ -- DVD CSS cipher
decrypt.rs -- Unified decrypt dispatcher (AACS/CSS/None)
disc/ rip-recovery.md Disc::scan + Disc::sweep + Disc::patch + mapfile
labels/ -- BD-J stream labels (5 format parsers)
mux/ -- Stream implementations (7 stream types)
pes.rs -- PES frame types + FrameSource / FrameSink traits
sector/ -- SectorSource / SectorSink + DecryptingSectorSource decorator
io/ -- Pipeline<I, R> + Sink trait + WritebackFile
halt.rs -- Halt cancellation token
keydb.rs -- KEYDB download, parse, save
error.rs -- Error codes (E1xxx-E8xxx)
event.rs -- Drive event system