oxideav-mp4
Pure-Rust MP4 / ISO Base Media File Format container — demuxer
(probe + sample-table expansion + seek) and muxer (moov-at-end by
default, optional faststart rewrite). Three brand presets share one
implementation: mp4, mov (QuickTime), and ismv (Smooth Streaming
ftyp, non-fragmented layout). Zero C dependencies.
Part of the oxideav framework but usable standalone.
Installation
[]
= "0.1"
= "0.1"
= "0.1"
= "0.0"
Quick use
Demux an MP4 and feed packets into a codec
use CodecRegistry;
use ContainerRegistry;
let mut codecs = new;
let mut containers = new;
register;
// ... register whichever codecs you care about (aac, flac, h264, mjpeg, ...)
let input: =
Boxnew;
let mut dmx = containers.open?;
// Sample entries are resolved to concrete codec ids. For `mp4a`/`mp4v`
// tracks the esds `objectTypeIndication` is honoured, so MP3-in-mp4
// comes out as "mp3", MPEG-1 video as "mpeg1video", AAC as "aac", etc.
let stream = &dmx.streams;
let mut dec = codecs.make_decoder?;
loop
# Ok::
Mux packets into an MP4
use WriteSeek;
let f = create?;
let ws: = Boxnew;
let mut mux = open?;
mux.write_header?;
for pkt in packets
mux.write_trailer?;
# Ok::
Faststart (moov-at-front) layout
use ;
let opts = Mp4MuxerOptions ;
let mut mux = open_with_options?;
In faststart mode the muxer buffers mdat in memory and writes
[ftyp][moov][mdat] at write_trailer time, patching chunk offsets so
the file is streamable from the first byte.
Scope
Demuxer
Sample-entry FourCCs resolve to these codec ids:
| FourCC | Codec id |
|---|---|
mp4a |
aac (default) or mp3 via esds OTI |
mp4v |
mpeg4video (default); esds OTI refines to mpeg1video, mpeg2video, h264, h265, mjpeg |
alac |
alac |
fLaC / flac |
flac |
Opus / opus |
opus |
avc1 / avc3 |
h264 |
hvc1 / hev1 |
h265 |
vp08 |
vp8 |
vp09 |
vp9 |
av01 |
av1 |
jpeg / mjpa / mjpb |
mjpeg |
s263 / h263 |
h263 |
lpcm / sowt / twos |
pcm_s16le (endianness of twos is not re-swapped) |
| any other | mp4:<fourcc> — callers can register their own decoder |
- Codec-specific config records (
avcC,hvcC,av1C,vpcC,dfLa,dOps, esds DSI) are forwarded asextradata. - Sample-table expansion:
stts,stsc,stsz/stz2,stco/co64,stss.next_packetserves samples in file-offset order. - Seek:
seek_to(stream, pts)lands on the nearest sync-sample ≤ pts (or the first keyframe of the stream if none qualify). - Metadata: 3GPP
udtaboxes (titl/auth/…) and iTunes-stylemeta/ilstare surfaced viaDemuxer::metadata().
Muxer
Only codecs with an mp4 sample-entry packaging are accepted. Codec
knowledge is confined to sample_entries::sample_entry_for; the rest
of the muxer appends opaque packet bytes.
Supported encode codec ids (produced sample entry FourCC in parentheses):
pcm_s16le→sowtflac→fLaCwithdfLaconfig (requires STREAMINFO extradata)aac→mp4awithesds(requires AudioSpecificConfig extradata)h264→avc1withavcC(requires AVCConfigurationRecord extradata)mjpeg→jpeg
Other codec ids fail with Error::Unsupported at open, never at
write_packet time.
Chunk offsets auto-promote from stco (32-bit) to co64 (64-bit) when
any offset exceeds 4 GiB. The mdat box header stays 32-bit — files
whose mdat payload exceeds 4 GiB fail at write_trailer.
Not (yet) supported
- Fragmented MP4 (moof / mfra / trun). The muxer emits a single
moovper file; the demuxer ignoresmoof/trunentirely. - Edit lists (
elst) on demux or mux. - Sample groups (
sbgp/sgpd), subtitle tracks, DRM (sinf/pssh). - Multiple sample descriptions per track (only the first entry of
stsdis used). - mdat payloads larger than 4 GiB (the 32-bit box header is not
promoted to
largesize).
Container registry
let mut reg = new;
register;
Registers:
- Demuxer
"mp4"(also serving.mp4,.m4a,.m4v,.3gp,.mov,.ismv). - Muxers
"mp4","mov","ismv". - A content probe that recognises
ftyp/wide+ftyp/moov.
License
MIT — see LICENSE.