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::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;
|
||||||
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue