most atoms now have binary marshalling
This commit is contained in:
parent
f0b7a3504a
commit
358b69f450
3 changed files with 176 additions and 4 deletions
|
@ -1,10 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
use std::io::Write;
|
||||
use std::fs::File;
|
||||
|
||||
use crate::util;
|
||||
|
||||
trait MP4Atom {
|
||||
fn size(&self) -> u32;
|
||||
|
||||
pub trait MP4Atom {
|
||||
fn marshall(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,22 @@ struct WindowMatrix {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
WindowMatrix {
|
||||
|
@ -37,14 +53,31 @@ impl Default for WindowMatrix {
|
|||
}
|
||||
|
||||
struct Edits {
|
||||
long_version: bool,
|
||||
duration: u64,
|
||||
start: i64,
|
||||
start: u64,
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
Edits {
|
||||
long_version: false,
|
||||
duration: 0,
|
||||
start: 0,
|
||||
play_rate: 1 << 16,
|
||||
|
@ -58,6 +91,16 @@ pub struct MOOV {
|
|||
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 {
|
||||
version: u8,
|
||||
flags: u32,
|
||||
|
@ -71,6 +114,34 @@ struct MVHD {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
MVHD {
|
||||
|
@ -94,6 +165,15 @@ struct TRAK {
|
|||
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 {
|
||||
version: u8,
|
||||
flags: u32,
|
||||
|
@ -109,6 +189,37 @@ struct TKHD {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
TKHD {
|
||||
|
@ -132,6 +243,12 @@ struct EDTS {
|
|||
elst: ELST,
|
||||
}
|
||||
|
||||
impl MP4Atom for EDTS {
|
||||
fn marshall(&self) -> Vec<u8> {
|
||||
make_box(self.elst.marshall(), *b"edts")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EDTS {
|
||||
fn default() -> Self {
|
||||
EDTS {elst: ELST {..Default::default()}}
|
||||
|
@ -145,6 +262,19 @@ struct ELST {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
ELST {
|
||||
|
@ -440,6 +570,14 @@ struct MVEX {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
MVEX {
|
||||
|
@ -458,6 +596,20 @@ struct TREX {
|
|||
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 {
|
||||
fn default() -> Self {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@ use std::sync::Arc;
|
|||
|
||||
use crate::util;
|
||||
use crate::muxer::hls::mp4;
|
||||
use crate::muxer::hls::mp4::atoms::MP4Atom;
|
||||
|
||||
impl mp4::MP4Muxer {
|
||||
pub fn gen_init(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let stsd_v = self.handle_a_cc()?;
|
||||
let stsd_a = self.handle_v_cc()?;
|
||||
let init_tree = mp4::atoms::construct_moov(stsd_v, stsd_a, &self.metadata);
|
||||
mp4::atoms::dump_init_tree(init_tree)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -224,3 +224,7 @@ pub fn thread_freeze(err_sender: mpsc::Sender<Box<dyn Error + Send + Sync>>, err
|
|||
err_sender.send(err).unwrap();
|
||||
thread::park();
|
||||
}
|
||||
|
||||
pub fn blank_vec(n: usize) -> Vec<u8> {
|
||||
return vec![0u8; n];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue