Releases: video-commander/mp4box
Release list
v0.12.1
[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.
stz2reserved capacity fromsample_countbefore validating
field_size. A 21-byte box declaring ~1.7 billion samples requested a
single ~6.9 GB allocation, and an invalidfield_sizestill paid for it
before bailing. The count is now clamped to what the remaining payload can
describe, andfield_sizeis validated first.trungrew its sample vector without bound. With none of the
per-sample flags set, the decode loop reads nothing per iteration, so
sample_countalone 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/trexdefaults — so sample enumeration on fragmented files is
unchanged.irotreported the wrong angle for 270° rotation.(byte & 0x03) * 90
was computed inu8, and3 * 90 = 270overflows it: a panic in debug
builds and a wrap toangle=14°in release. This affected well-formed
files, not just malformed ones.- Box offset arithmetic overflowed on 64-bit
largesizeboxes. A box
declaring a size nearu64::MAXoverflowedh.start + h.sizein 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 inparser.rsandapi.rsnow saturates (15 sites), and
extract_ilst_data_valueadditionally clamps a box end to its enclosing
range before using it to size a buffer.
v0.12.0
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 points — colr (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 metadata — colr, 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
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
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
psshpayload decoding (newdrmmodule):- Widevine — a dependency-free protobuf decoder for the
WidevinePsshDataschema: 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
WRMHEADERXML (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.
- Widevine — a dependency-free protobuf decoder for the
drm::parse_pssh_boxes— parse one or more concatenated rawpsshboxes outside a file context (the form carried by DASHcenc:psshelements).drm::pssh_from_raw_widevine— wrap bare Widevine payloads (e.g. from packager logs).WIDEVINE_SYSTEM_ID/PLAYREADY_SYSTEM_IDconstants.util::base64_decode— dependency-free standard/URL-safe base64 decoding (padding optional).
Changed
⚠️ Breaking:PsshDatagainedwidevineandplayreadyfields (boxed,Option, omitted from JSON when absent). Code constructingPsshDatawith a struct literal, or destructuring it exhaustively, must be updated. JSON consumers are unaffected.- The
psshone-line summary now surfaces decoded payload highlights (provider, protection scheme,WRMHEADERversion, license URL).
Full Changelog: v0.9.0...v0.10.0
v0.9.0
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 (
editmodule,mp4editCLI — 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
mdatis streamed rather than held in memory. - Ancestor box sizes are recomputed bottom-up (correct by construction);
stco/co64offsets 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. Setpatches 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.SetTagbuilds themoov/udta/meta/ilstchain (ffmpeg-compatiblehdlr)
when missing.- Faststart: move
moovbeforemdatfor progressive playback (like
qt-faststart/ffmpeg -movflags +faststart); idempotent.
- Extent-tree design: unmodified boxes stay as byte-range references into the
- Fragmented MP4 (fMP4 / DASH / CMAF) sample extraction.
track_samples_from_reader/_from_pathnow walkmoof/traf/trun,
implementing the ISO 14496-12 §8.8 defaulting chain (trun → first_sample_flags
→ tfhd → trex), with decode times fromtfdt(running-DTS fallback across
fragments) and byte offsets fromtfhdbase or the enclosingmoof. - Tolerant parsing.
parse_boxes_tolerant/get_boxes_tolerantreturn the
partial tree plus locatedParseIssues (offset + description); damage is
contained to the enclosing container.mp4dumpis now tolerant by default
(partial tree, issues on stderr, exit code 2);--strictrestores 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:
esdsnow decodesAudioSpecificConfig(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) andcli(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 alwaystrack_id=0). - tkhd v0 now reads 4-byte timestamps; mdhd honors v1 64-bit times.
- New
FullContainernode kind fixesmeta/iref/trep/stsdchildren
previously parsed as garbage; QuickTime-stylemetais auto-detected. stsdnow 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 specOpusfourcc). tfhdflag mixup fixed (0x010000is 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;mp4samplesprints 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): droppedbyteorder(smallReadExttrait),thiserror
(hand-written impls), andhex(unused). clap and serde_json are gated behind
the default-onclifeature; 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
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
trun→TrackFragmentRunwith per-sample duration/size/flags/CTO arraystfhd,tfdt,trex→ fragmented MP4 track/fragment metadataesds→ parses ES_Descriptor chain to extractobjectTypeIndicationand peak/average bitratesav1C,vpcC→ codec profile/level/bit-depthdOps→ Opus channel count, pre-skip, input sample rate (correct LE byte order per spec)dfLa→ FLAC STREAMINFO: sample rate, channels, bits-per-sample, total samplesdac3/dec3→ AC-3/EC-3 bitstream infocolr,pasp→ colour info and pixel aspect ratiomdcv,clli→ HDR mastering display and content light level valueskind→ track kind URI/valueirot,imir→ HEIF rotation/mirror transformsilstdata,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.5.0
Full Changelog: v0.4.0...v0.5.0