Skip to content

Implement non-destructive box editing and enhance decoder documentation#7

Merged
alfg merged 3 commits into
mainfrom
feat/mp4-editing
Jul 4, 2026
Merged

Implement non-destructive box editing and enhance decoder documentation#7
alfg merged 3 commits into
mainfrom
feat/mp4-editing

Conversation

@alfg

@alfg alfg commented Jul 4, 2026

Copy link
Copy Markdown
Member

No description provided.

alfg added 3 commits July 4, 2026 13:45
Supersedes the PR #5 splice-based prototype with an extent-tree design
whose two correctness gaps (stale ancestor sizes, heuristic chunk-offset
fixup) are impossible by construction.

Design:
- edit/tree.rs: the file parses into a tree where unmodified boxes are
  byte-range references into the source, not copies. Container prefix
  bytes (stsd entry_count, sample-entry fixed headers), padding, and
  original header forms (compact/largesize/to-EOF) are preserved.
  Serialization streams extents in chunks (mdat never held in memory)
  and recomputes box sizes bottom-up, so every ancestor of an edited
  box is correct by construction. Invariant: serializing an unedited
  tree reproduces the source byte for byte.
- edit/fixup.rs: layout produces an exact old->new extent map; each
  stco/co64 entry is remapped through the extent containing it. No
  heuristics: unmoved data keeps its offsets, moved data shifts by
  exactly its extent's delta. Entries pointing at removed data are
  left unchanged and reported.
- edit/fields.rs: Set patches named fields (mvhd/tkhd/mdhd timestamps,
  timescale, duration, rate, volume, track_id, layer, width/height,
  language) in place with version-aware offsets; matrices, reserved
  regions, and unknown bytes are untouched — no re-encoding.
- edit/mod.rs + tags.rs: Editor with Remove/RemoveAll/Insert/Replace/
  Set/SetTag commands; slash paths with [n] indexing and © fourccs;
  SetTag creates the moov/udta/meta/ilst chain (ffmpeg-compatible
  hdlr) when missing. Fragmented and HEIF files (moof/sidx/iloc) are
  refused with a clear error since their internal offsets are not yet
  covered by fixup; no-op pass-through still works.

Packaging: "edit" cargo feature (on by default; disable for a
parse-only build), mp4edit binary (--remove/--remove-all/--insert/
--replace/--set/--tag), and examples/edit.rs.

Tests (tests/edit_roundtrip.rs): byte-identical zero-edit round-trips
on synthetic and real files; removal before mdat shifts stco entries
by exactly the removed size while removal after mdat leaves them
untouched; samples still resolve to identical media bytes after every
edit; ancestor sizes re-tile the file with no gaps; Set changes only
the addressed bytes; tag create/replace; fragmented-file guard.
Verified on a real file with ffprobe/ffmpeg: tags readable, all 2336
chunk offsets adjusted, zero decode errors.
The extension point already existed (get_boxes_with_registry +
Registry::with_decoder) but was invisible enough that PR #3 was opened
to add what was already there. No new functionality:

- add a worked doc example on get_boxes_with_registry showing the
  intended pattern: extend the default registry with a custom decoder
  (default_registry().with_decoder(...)) rather than replace it
- re-export default_registry at the crate root
- add an integration test proving a custom decoder fires through
  get_boxes_with_registry alongside the built-in decoders

Supersedes PR #3.
@alfg
alfg merged commit 0594018 into main Jul 4, 2026
1 check passed
@alfg
alfg deleted the feat/mp4-editing branch July 4, 2026 05:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant