most atoms now have binary marshalling

This commit is contained in:
Muaz Ahmad 2023-10-19 16:41:29 +05:00
parent f0b7a3504a
commit 358b69f450
3 changed files with 176 additions and 4 deletions

View file

@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use std::io::Write;
use std::fs::File;
use crate::util; use crate::util;
trait MP4Atom { pub trait MP4Atom {
fn size(&self) -> u32;
fn marshall(&self) -> Vec<u8>; fn marshall(&self) -> Vec<u8>;
} }
@ -20,6 +20,22 @@ struct WindowMatrix {
w: u32, w: u32,
} }
impl MP4Atom for WindowMatrix {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.extend_from_slice(&self.a.to_be_bytes());
content.extend_from_slice(&self.b.to_be_bytes());
content.extend_from_slice(&self.u.to_be_bytes());
content.extend_from_slice(&self.c.to_be_bytes());
content.extend_from_slice(&self.d.to_be_bytes());
content.extend_from_slice(&self.v.to_be_bytes());
content.extend_from_slice(&self.x.to_be_bytes());
content.extend_from_slice(&self.y.to_be_bytes());
content.extend_from_slice(&self.w.to_be_bytes());
return content;
}
}
impl Default for WindowMatrix { impl Default for WindowMatrix {
fn default() -> Self { fn default() -> Self {
WindowMatrix { WindowMatrix {
@ -37,14 +53,31 @@ impl Default for WindowMatrix {
} }
struct Edits { struct Edits {
long_version: bool,
duration: u64, duration: u64,
start: i64, start: u64,
play_rate: u32, play_rate: u32,
} }
impl MP4Atom for Edits {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
if self.long_version {
content.extend_from_slice(&self.duration.to_be_bytes());
content.extend_from_slice(&self.start.to_be_bytes());
} else {
content.extend_from_slice(&(self.duration as u32).to_be_bytes());
content.extend_from_slice(&(self.start as u32).to_be_bytes());
}
content.extend_from_slice(&self.play_rate.to_be_bytes());
return content;
}
}
impl Default for Edits { impl Default for Edits {
fn default() -> Self { fn default() -> Self {
Edits { Edits {
long_version: false,
duration: 0, duration: 0,
start: 0, start: 0,
play_rate: 1 << 16, play_rate: 1 << 16,
@ -58,6 +91,16 @@ pub struct MOOV {
mvex: MVEX, mvex: MVEX,
} }
impl MP4Atom for MOOV {
fn marshall(&self) -> Vec<u8> {
let mut out = self.mvhd.marshall();
out.append(&mut self.traks[0].marshall());
out.append(&mut self.traks[1].marshall());
out.append(&mut self.mvex.marshall());
make_box(out, *b"moov")
}
}
struct MVHD { struct MVHD {
version: u8, version: u8,
flags: u32, flags: u32,
@ -71,6 +114,34 @@ struct MVHD {
next_track_id: u32, next_track_id: u32,
} }
impl MP4Atom for MVHD {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
if self.version == 1 {
content.extend_from_slice(&self.create_time.to_be_bytes());
content.extend_from_slice(&self.modify_time.to_be_bytes());
} else {
content.extend_from_slice(&(self.create_time as u32).to_be_bytes());
content.extend_from_slice(&(self.modify_time as u32).to_be_bytes());
}
content.extend_from_slice(&self.time_scale.to_be_bytes());
if self.version == 1 {
content.extend_from_slice(&self.duration.to_be_bytes());
} else {
content.extend_from_slice(&(self.duration as u32).to_be_bytes());
}
content.extend_from_slice(&self.playrate.to_be_bytes());
content.extend_from_slice(&self.volume.to_be_bytes());
content.append(&mut util::blank_vec(10));
content.append(&mut self.matrix.marshall());
content.append(&mut util::blank_vec(24));
content.extend_from_slice(&self.next_track_id.to_be_bytes());
make_box(content, *b"mvhd")
}
}
impl Default for MVHD { impl Default for MVHD {
fn default() -> Self { fn default() -> Self {
MVHD { MVHD {
@ -94,6 +165,15 @@ struct TRAK {
mdia: MDIA, mdia: MDIA,
} }
impl MP4Atom for TRAK {
fn marshall(&self) -> Vec<u8> {
let mut content = self.tkhd.marshall();
content.append(&mut self.edts.marshall());
content.append(&mut self.mdia.marshall());
make_box(content, *b"trak")
}
}
struct TKHD { struct TKHD {
version: u8, version: u8,
flags: u32, flags: u32,
@ -109,6 +189,37 @@ struct TKHD {
height: u32, height: u32,
} }
impl MP4Atom for TKHD {
fn marshall(&self) -> Vec<u8> {
let content = Vec::new();
content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
if self.version == 1 {
content.extend_from_slice(&self.create_time.to_be_bytes());
content.extend_from_slice(&self.modify_time.to_be_bytes());
} else {
content.extend_from_slice(&(self.create_time as u32).to_be_bytes());
content.extend_from_slice(&(self.modify_time as u32).to_be_bytes());
}
content.extend_from_slice(&self.track_id.to_be_bytes());
content.append(&mut util::blank_vec(8));
if self.version == 1 {
content.extend_from_slice(&self.duration.to_be_bytes());
} else {
content.extend_from_slice(&(self.duration as u32).to_be_bytes());
}
content.append(&mut util::blank_vec(4));
content.extend_from_slice(&self.layer.to_be_bytes());
content.extend_from_slice(&self.alt_group.to_be_bytes());
content.extend_from_slice(&self.volume.to_be_bytes());
content.append(&mut util::blank_vec(2));
content.append(&mut self.matrix.marshall());
content.extend_from_slice(&self.width.to_be_bytes());
content.extend_from_slice(&self.height.to_be_bytes());
make_box(content, *b"tkhd")
}
}
impl Default for TKHD { impl Default for TKHD {
fn default() -> Self { fn default() -> Self {
TKHD { TKHD {
@ -132,6 +243,12 @@ struct EDTS {
elst: ELST, elst: ELST,
} }
impl MP4Atom for EDTS {
fn marshall(&self) -> Vec<u8> {
make_box(self.elst.marshall(), *b"edts")
}
}
impl Default for EDTS { impl Default for EDTS {
fn default() -> Self { fn default() -> Self {
EDTS {elst: ELST {..Default::default()}} EDTS {elst: ELST {..Default::default()}}
@ -145,6 +262,19 @@ struct ELST {
edits: Vec<Edits>, edits: Vec<Edits>,
} }
impl MP4Atom for ELST {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
content.extend_from_slice(&self.num_edits.to_be_bytes());
for edit in self.edits {
content.append(&mut edit.marshall());
}
make_box(content, *b"elst")
}
}
impl Default for ELST { impl Default for ELST {
fn default() -> Self { fn default() -> Self {
ELST { ELST {
@ -440,6 +570,14 @@ struct MVEX {
trexs: [TREX; 2], trexs: [TREX; 2],
} }
impl MP4Atom for MVEX {
fn marshall(&self) -> Vec<u8> {
let mut content = self.trexs[0].marshall();
content.append(&mut self.trexs[1].marshall());
make_box(content, *b"mvex")
}
}
impl Default for MVEX { impl Default for MVEX {
fn default() -> Self { fn default() -> Self {
MVEX { MVEX {
@ -458,6 +596,20 @@ struct TREX {
default_flags: u32, default_flags: u32,
} }
impl MP4Atom for TREX {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
content.extend_from_slice(&self.track_id.to_be_bytes());
content.extend_from_slice(&self.default_desc_idx.to_be_bytes());
content.extend_from_slice(&self.default_duration.to_be_bytes());
content.extend_from_slice(&self.default_size.to_be_bytes());
content.extend_from_slice(&self.default_flags.to_be_bytes());
make_box(content, *b"trex")
}
}
impl Default for TREX { impl Default for TREX {
fn default() -> Self { fn default() -> Self {
TREX { TREX {
@ -566,3 +718,17 @@ fn new_stbl(stsd: STSD, metadata: &Arc<util::Metadata>) -> STBL {
} }
} }
pub fn dump_init_tree(moov: MOOV) -> Result<(), Box<dyn std::error::Error>> {
let content = moov.marshall();
let mut f = File::create("init.mp4")?;
f.write_all(content.as_slice())?;
Ok(())
}
fn make_box(mut content: Vec<u8>, box_name: [u8; 4]) -> Vec<u8> {
let mut head = vec![0u8; 8];
head.splice(..4, ((content.len() + 8) as u32).to_be_bytes());
head.splice(4..8, box_name);
head.append(&mut content);
return head;
}

View file

@ -3,12 +3,14 @@ use std::sync::Arc;
use crate::util; use crate::util;
use crate::muxer::hls::mp4; use crate::muxer::hls::mp4;
use crate::muxer::hls::mp4::atoms::MP4Atom;
impl mp4::MP4Muxer { impl mp4::MP4Muxer {
pub fn gen_init(&mut self) -> Result<(), Box<dyn Error>> { pub fn gen_init(&mut self) -> Result<(), Box<dyn Error>> {
let stsd_v = self.handle_a_cc()?; let stsd_v = self.handle_a_cc()?;
let stsd_a = self.handle_v_cc()?; let stsd_a = self.handle_v_cc()?;
let init_tree = mp4::atoms::construct_moov(stsd_v, stsd_a, &self.metadata); let init_tree = mp4::atoms::construct_moov(stsd_v, stsd_a, &self.metadata);
mp4::atoms::dump_init_tree(init_tree)?;
Ok(()) Ok(())
} }

View file

@ -224,3 +224,7 @@ pub fn thread_freeze(err_sender: mpsc::Sender<Box<dyn Error + Send + Sync>>, err
err_sender.send(err).unwrap(); err_sender.send(err).unwrap();
thread::park(); thread::park();
} }
pub fn blank_vec(n: usize) -> Vec<u8> {
return vec![0u8; n];
}