Skip to content

Releases: video-commander/mp4box

v0.12.1

Choose a tag to compare

@alfg alfg released this 19 Jul 09:43

[0.12.1]

Fixed

Hardening pass against malformed input, found by fuzzing the box tree with
cargo-fuzz. Every fix bounds a value the file controls; none change how
well-formed files decode.

  • stz2 reserved capacity from sample_count before validating
    field_size.
    A 21-byte box declaring ~1.7 billion samples requested a
    single ~6.9 GB allocation, and an invalid field_size still paid for it
    before bailing. The count is now clamped to what the remaining payload can
    describe, and field_size is validated first.
  • trun grew its sample vector without bound. With none of the
    per-sample flags set, the decode loop reads nothing per iteration, so
    sample_count alone drove growth past 2 GB with no end-of-input to stop it.
    The count is now bounded by the payload, with a ceiling for the flagless
    case. Those entries stay materialized — they carry meaning via the
    tfhd/trex defaults — so sample enumeration on fragmented files is
    unchanged.
  • irot reported the wrong angle for 270° rotation. (byte & 0x03) * 90
    was computed in u8, and 3 * 90 = 270 overflows it: a panic in debug
    builds and a wrap to angle=14° in release. This affected well-formed
    files, not just malformed ones.
  • Box offset arithmetic overflowed on 64-bit largesize boxes. A box
    declaring a size near u64::MAX overflowed h.start + h.size in the
    container-overrun check. In release this wrapped, so the overrun went
    unreported and the box was not clamped to its parent. Every offset
    computation in parser.rs and api.rs now saturates (15 sites), and
    extract_ilst_data_value additionally clamps a box end to its enclosing
    range before using it to size a buffer.

v0.12.0

Choose a tag to compare

@alfg alfg released this 16 Jul 12:15

mp4box 0.12.0

Richer HDR/colour inspection and a new hex-highlighting primitive.

Highlights

Per-field payload byte spans (field_spans) — Decoders can now report where each payload field lives inside a box, so consumers can highlight individual fields in a hex view and cross-reference them with decoded values. New FieldSpan { name, start, length } type and an opt-in BoxDecoder::field_spans(version, flags, payload_len) method that defaults to empty (existing decoders unchanged). Spans are derived from box metadata without reading the payload, so they're cheap and independent of decode(); Box gains a field_spans field populated under decode=true.

Implemented for the fixed-layout boxes — mvhd, tkhd, mdhd, hdlr, tenc, tfhd, tfdt, trex, sidx, elst, trun, emsg (v1), and the sample-table headers (stsz/stco/co64/stts/stss/ctts/stsc), with widths and presence tracking version and flag bits. Variable-first/descriptor-based layouts and repeating array bodies stay header-only by design.

Human-readable CICP colour code pointscolr (nclx) and vpcC now name colour primaries, transfer characteristics, and matrix coefficients (ISO/IEC 23091-2) instead of bare integers — e.g. transfer=16 (PQ / SMPTE ST 2084), transfer=18 (HLG / ARIB STD-B67). Lookup tables are exposed at registry::cicp for reuse.

Dolby Vision configuration (dvcC / dvvC) — Both records now decode into dv_version, dv_profile, dv_level, the RPU/EL/BL presence flags, and the base-layer cross-compatibility id with its meaning (e.g. bl_compatibility=1 (HDR10 (BT.2020 PQ))). dvvC is newly recognized as a known box.

Structured HDR/colour metadatacolr, dvcC/dvvC, mdcv, and clli now expose typed data (StructuredData::ColourInformation, DolbyVisionConfig, MasteringDisplayColourVolume, ContentLightLevel) instead of only a text summary, so callers can read fields directly and UIs render them as attribute lists. Text summaries are unchanged.

Compatibility

Additive, backward-compatible. New public API: FieldSpan, Box.field_spans, BoxDecoder::field_spans (defaulted), registry::cicp, and the new StructuredData variants.

Full changelog: v0.11.0...v0.12.0

v0.11.0

Choose a tag to compare

@alfg alfg released this 13 Jul 09:34

mp4box 0.11.0

Adds recognition and decoding for the MPEG-4 Object Descriptor Box (iods), labels a family of Google/YouTube proprietary boxes, and reorganizes the registry module internally. Fully backward-compatible — no breaking API changes.

Added

  • iods (Object Descriptor Box) decoding. The box is now recognized (ISO/IEC 14496-14 §5.1) and its wrapped MPEG-4 InitialObjectDescriptor is decoded (ISO/IEC 14496-1 §7.2.6.4):
    • Object descriptor ID, inline URL (when the URL flag is set), and the five profile-level indications — OD, scene, audio, visual, and graphics.
    • Accepts both the InitialObjectDescrTag (0x02) and the MP4 IOD tag (0x10); malformed descriptors degrade gracefully to raw bytes.
    • Surfaced as StructuredData::ObjectDescriptor(IodsData).
  • Recognition of Google/YouTube proprietary boxes found under moov/udta: gsst, gstd, gssd, gspu, gspm, gshh. These now display with human-readable names instead of showing as unknown. Their payload layouts are undocumented, so contents are intentionally left as raw leaves rather than guessed at.

Changed

  • registry module split. The single ~3.2k-line registry.rs is now a directory module — mod (registry machinery), data (structured payload types), decoders (decoder implementations), and codec_config (shared AudioSpecificConfig / MPEG-4 descriptor parsing). This is an internal reorganization only: every registry::* path is preserved via re-exports, so no downstream code needs to change.

Compatibility

No breaking changes. Existing registry::* imports, StructuredData consumers, and JSON output are unaffected.

Full changelog: v0.10.0...v0.11.0

v0.10.0

Choose a tag to compare

@alfg alfg released this 11 Jul 10:00

mp4box 0.10.0

This release turns pssh parsing from "identify the DRM system" into "decode the payload." The 0.9.0 decoders told you which DRM system protected a file; 0.10.0 decodes the encrypted-metadata blob itself for both Widevine and PlayReady — with zero new dependencies.

Added

  • System-specific pssh payload decoding (new drm module):
    • Widevine — a dependency-free protobuf decoder for the WidevinePsshData schema: algorithm, key IDs, provider, content ID (hex + printable-text form), policy, crypto period index, and protection scheme (cenc/cbcs/cens/cbc1). Unknown fields are skipped; garbage input is rejected rather than misdecoded.
    • PlayReady — a PlayReady Object parser: length-prefixed records, UTF-16LE WRMHEADER XML (versions 4.0–4.3), key IDs converted from the little-endian GUID layout to CENC byte order, LA_URL, and the full header XML.
  • drm::parse_pssh_boxes — parse one or more concatenated raw pssh boxes outside a file context (the form carried by DASH cenc:pssh elements).
  • drm::pssh_from_raw_widevine — wrap bare Widevine payloads (e.g. from packager logs).
  • WIDEVINE_SYSTEM_ID / PLAYREADY_SYSTEM_ID constants.
  • util::base64_decode — dependency-free standard/URL-safe base64 decoding (padding optional).

Changed

  • ⚠️ Breaking: PsshData gained widevine and playready fields (boxed, Option, omitted from JSON when absent). Code constructing PsshData with a struct literal, or destructuring it exhaustively, must be updated. JSON consumers are unaffected.
  • The pssh one-line summary now surfaces decoded payload highlights (provider, protection scheme, WRMHEADER version, license URL).

Full Changelog: v0.9.0...v0.10.0

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.

v0.7.0

Choose a tag to compare

@alfg alfg released this 18 Mar 03:41

Full Changelog: v0.6.0...v0.7.0

v0.7.0

57 new box types recognized

Codec config: esds (MPEG-4 ES_Descriptor), av1C (AV1), vpcC (VP8/VP9), dOps (Opus), dac3/dec3 (AC-3/EC-3), dfLa (FLAC), dvcC/dvcE (Dolby Vision), btrt (bitrate info)
Subtitle/text: tx3g, wvtt, stpp, sthd, vttc
iTunes/Apple metadata: ilst container, data, mean, name
HDR: mdcv (mastering display colour volume), clli (content light level)
HEIF/still image: irot, imir, rloc, lsel, tols, a1lx, a1op, idat, ipro
360° video: st3d, sv3d, proj, prhd, equi, cbmp
Fragmented MP4: tfhd, tfdt, trex (in addition to existing trun)
Audio: srat, chnl, pcmc, wave, chan
QuickTime: gmhd, gmin, glbl, tmcd, tcmi
Miscellaneous: kind, ludt, pdin, xml , bxml, ainf, leva, trep, dvh1, dvhe, dav1, encv, enca, enct, ipcm, fpcm

22 new structured decoders

  • trunTrackFragmentRun with per-sample duration/size/flags/CTO arrays
  • tfhd, tfdt, trex → fragmented MP4 track/fragment metadata
  • esds → parses ES_Descriptor chain to extract objectTypeIndication and peak/average bitrates
  • av1C, vpcC → codec profile/level/bit-depth
  • dOps → Opus channel count, pre-skip, input sample rate (correct LE byte order per spec)
  • dfLa → FLAC STREAMINFO: sample rate, channels, bits-per-sample, total samples
  • dac3/dec3 → AC-3/EC-3 bitstream info
  • colr, pasp → colour info and pixel aspect ratio
  • mdcv, clli → HDR mastering display and content light level values
  • kind → track kind URI/value
  • irot, imir → HEIF rotation/mirror transforms
  • ilst data, mean, name → iTunes metadata atom content

Improvements

  • mp4dump: box output now includes the full human-readable box name alongside the FourCC (e.g. tkhd (Track Header Box)), and structured data is formatted as readable summaries (codec, sample counts, keyframes, HDR values, etc.)
  • examples/boxes.rs: rewritten with a recursive tree walker showing indentation, size, version/flags for FullBoxes, decoded values, and a post-walk summary of file type, tracks, and per-track sample table stats (codec, sample count, keyframe count)

v0.6.0

v0.6.0 Pre-release
Pre-release

Choose a tag to compare

@alfg alfg released this 15 Dec 07:03

What's Changed

  • feat: add structured parsing sample data support by @alfg in #2

Full Changelog: v0.5.0...v0.6.0

v0.5.0

v0.5.0 Pre-release
Pre-release

Choose a tag to compare

@alfg alfg released this 06 Dec 05:35

Full Changelog: v0.4.0...v0.5.0

v0.4.0

v0.4.0 Pre-release
Pre-release

Choose a tag to compare

@alfg alfg released this 28 Nov 09:51

What's Changed

  • feat: add examples, fixes and clear warnings. by @alfg in #1

New Contributors

  • @alfg made their first contribution in #1

Full Changelog: v0.3.0...v0.4.0