pub struct Mp4StreamingDemuxer { /* private fields */ }Expand description
MP4 / MOV streaming demuxer. Owns the input bytes (so its
Mp4Reader<Cursor<Vec<u8>>> cursor is self-contained) and walks
read_sample(track_id, idx) one sample at a time. Per-sample
AVCC→Annex-B + parameter-set tracking (Squad-14) is preserved.
Per-sample location record built when the input is a fragmented
MP4. The mp4 crate (v0.14) returns garbage (typically the bytes
of an adjacent moof box) from read_sample on fragmented inputs
— affects BOTH video and audio tracks. Side-stepping read_sample
for fragmented input by pre-computing sample
(file_offset, size, pts, duration) from the moof->traf->trun chain
produces correct bytes regardless of track kind. The track filter
is track_id (parameter on the walker chain) — generic across
video/audio/anything else with a track_id.
Bug history: the audio-extraction path WAS originally claimed to
“walk boxes itself” (per a prior comment here) but in fact it
called reader.read_sample(audio_track_id, idx) — the same buggy
path video uses. Burned 2026-05-09: malformed audio segments
(8-byte first AU containing the source’s moof header bytes
00 00 NN NN 6d 6f 6f 66, every following AU mid-box-tree)
passed dedup hash unchanged because they’re size-deterministic
per source, MSE rejected them with Number of bands exceeds limit
→ SourceBuffer error → MediaSource readyState ended → all video
appendBuffer calls failed.
Trait Implementations§
Source§impl StreamingDemuxer for Mp4StreamingDemuxer
impl StreamingDemuxer for Mp4StreamingDemuxer
Source§fn header(&self) -> &DemuxHeader
fn header(&self) -> &DemuxHeader
DemuxHeader populated at
construction time.Source§fn next_video_sample(&mut self) -> Result<Option<Sample>>
fn next_video_sample(&mut self) -> Result<Option<Sample>>
Ok(None) at EOF.
Allocates a fresh Vec per sample; nothing is retained
internally beyond the reader’s per-format cursor state.