Skip to content

v0.9.0

Choose a tag to compare

@alfg alfg released this 05 Jul 07:48

0.9.0

A correctness-focused overhaul that also adds non-destructive editing,
fragmented-MP4 support, tolerant parsing, and DRM/DASH decoders. The library now
depends only on anyhow + serde for parse-only builds.

Added

  • Non-destructive box editing (edit module, mp4edit CLI — on by default).
    • Extent-tree design: unmodified boxes stay as byte-range references into the
      source; serializing an unedited tree reproduces the file byte-for-byte, and
      mdat is streamed rather than held in memory.
    • Ancestor box sizes are recomputed bottom-up (correct by construction);
      stco/co64 offsets are remapped through an exact old→new extent map — no
      heuristics.
    • Commands: Remove / RemoveAll / Insert / Replace / Set / SetTag /
      Faststart, addressed by slash paths with [n] indexing and © fourccs.
    • Set patches named fields in place (mvhd/tkhd/mdhd timestamps, timescale,
      duration, rate, volume, track_id, layer, width/height, language) with
      version-aware offsets — no re-encoding.
    • SetTag builds the moov/udta/meta/ilst chain (ffmpeg-compatible hdlr)
      when missing.
    • Faststart: move moov before mdat for progressive playback (like
      qt-faststart / ffmpeg -movflags +faststart); idempotent.
  • Fragmented MP4 (fMP4 / DASH / CMAF) sample extraction.
    track_samples_from_reader / _from_path now walk moof/traf/trun,
    implementing the ISO 14496-12 §8.8 defaulting chain (trun → first_sample_flags
    → tfhd → trex), with decode times from tfdt (running-DTS fallback across
    fragments) and byte offsets from tfhd base or the enclosing moof.
  • Tolerant parsing. parse_boxes_tolerant / get_boxes_tolerant return the
    partial tree plus located ParseIssues (offset + description); damage is
    contained to the enclosing container. mp4dump is now tolerant by default
    (partial tree, issues on stderr, exit code 2); --strict restores fail-fast.
  • Typed structured decoders for movie/fragment boxes: MovieHeader,
    EditList, SegmentIndex, TrackFragmentHeader, TrackFragmentDecodeTime,
    TrackExtends (elst/sidx include full entry lists with SAP info).
  • DRM/DASH decoders: pssh (Widevine/PlayReady/FairPlay/ClearKey/Marlin
    recognition, v1 KIDs), tenc, emsg, senc, schm, frma — verified
    end-to-end against a real CENC-encrypted file.
  • AAC: esds now decodes AudioSpecificConfig (object type, profile,
    core/extension sample rates, channels, SBR/PS) — HE-AAC and HE-AAC v2 now
    report correctly instead of as AAC-LC.
  • New decoders: stz2, avcC, hvcC.
  • New cargo features: edit (default, no extra deps) and cli (default; gates
    clap + serde_json).
  • New examples: edit.rs, fragments.rs, media_info.rs.

Fixed

  • FullBox decoding: mvhd/tkhd/elst/sidx no longer re-parse already-stripped
    version/flags (every field was shifted 4+ bytes — mvhd reported garbage
    timescale/duration, tkhd always track_id=0).
  • tkhd v0 now reads 4-byte timestamps; mdhd honors v1 64-bit times.
  • New FullContainer node kind fixes meta/iref/trep/stsd children
    previously parsed as garbage; QuickTime-style meta is auto-detected.
  • stsd now recurses into sample entries and their codec-config children, making
    the esds/dOps/colr/pasp/btrt decoders reachable on real files.
  • Box classification fixes (dinf/tref/schi as containers; schm/tenc/senc/emsg/…
    as FullBoxes; accept the spec Opus fourcc).
  • tfhd flag mixup fixed (0x010000 is duration_is_empty, not
    default_base_is_moof).
  • Sample tables: track_samples_* work again on v0-tkhd files; sample building
    is a single O(n) pass; mp4samples prints real stts/ctts/stsc/stco/stsz
    instead of values scraped from Debug strings.

Changed

  • Dependencies slimmed 7 → 2 for library consumers (transitive tree 33 → 11
    crates): dropped byteorder (small ReadExt trait), thiserror
    (hand-written impls), and hex (unused). clap and serde_json are gated behind
    the default-on cli feature; parse-only builds use
    default-features = false, features = ["edit"].
  • MSRV set to Rust 1.88; refreshed crate metadata (description, keywords,
    categories); added MIT LICENSE file.