1pub mod boxes;
9pub mod cenc;
10pub mod cenc_cipher;
11pub mod codec_id;
12pub mod demux;
13pub mod frag;
14pub mod muxer;
15pub mod options;
16mod sample_entries;
17pub mod sample_groups;
18pub mod styp;
19
20pub use options::{BrandPreset, FragmentCadence, FragmentedOptions, Mp4MuxerOptions};
21
22use oxideav_core::ContainerRegistry;
23
24pub fn register_containers(reg: &mut ContainerRegistry) {
25 reg.register_demuxer("mp4", demux::open);
26 reg.register_muxer("mp4", muxer::open);
27 reg.register_muxer("mov", muxer::open_mov);
28 reg.register_muxer("ismv", muxer::open_ismv);
29 reg.register_muxer("dash", muxer::open_dash);
34 reg.register_muxer("cmaf", muxer::open_dash);
35 reg.register_extension("mp4", "mp4");
36 reg.register_extension("m4a", "mp4");
37 reg.register_extension("m4v", "mp4");
38 reg.register_extension("mov", "mov");
39 reg.register_extension("3gp", "mp4");
40 reg.register_extension("ismv", "ismv");
41 reg.register_extension("m4s", "dash");
42 reg.register_probe("mp4", probe);
43}
44
45pub fn register(ctx: &mut oxideav_core::RuntimeContext) {
55 register_containers(&mut ctx.containers);
56}
57
58oxideav_core::register!("mp4", register);
59
60fn probe(p: &oxideav_core::ProbeData) -> u8 {
64 if p.buf.len() < 8 {
65 return 0;
66 }
67 if &p.buf[4..8] == b"ftyp" {
68 return 100;
69 }
70 if p.buf.len() >= 16
71 && matches!(&p.buf[4..8], b"wide" | b"free" | b"skip")
72 && &p.buf[12..16] == b"ftyp"
73 {
74 return 90;
75 }
76 if &p.buf[4..8] == b"moov" {
78 return 50;
79 }
80 0
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn register_via_runtime_context_installs_container() {
89 let mut ctx = oxideav_core::RuntimeContext::new();
90 register(&mut ctx);
91 assert_eq!(ctx.containers.container_for_extension("mp4"), Some("mp4"));
92 assert_eq!(ctx.containers.container_for_extension("mov"), Some("mov"));
93 assert_eq!(ctx.containers.container_for_extension("m4s"), Some("dash"));
94 }
95}