fragment boxes implementation, generation is limited to common duration, flags and size per and no composition time
This commit is contained in:
parent
f70f8c05cb
commit
fc7ecd62bd
3 changed files with 193 additions and 0 deletions
|
@ -3,6 +3,7 @@ use std::io::Write;
|
|||
use std::fs::File;
|
||||
|
||||
use crate::util;
|
||||
use crate::muxer::hls::mp4::samples;
|
||||
|
||||
pub trait MP4Atom {
|
||||
fn marshall(&self) -> Vec<u8>;
|
||||
|
@ -1014,6 +1015,192 @@ pub fn dump_init_tree(moov: MOOV) -> Result<(), Box<dyn std::error::Error>> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub struct MOOF {
|
||||
mfhd: MFHD,
|
||||
trafs: [TRAF; 2],
|
||||
}
|
||||
|
||||
impl MP4Atom for MOOF {
|
||||
fn marshall(&self) -> Vec<u8> {
|
||||
let mut content = self.mfhd.marshall();
|
||||
content.append(&mut self.trafs[0].marshall());
|
||||
content.append(&mut self.trafs[1].marshall());
|
||||
make_box(content, *b"moof")
|
||||
}
|
||||
}
|
||||
|
||||
struct MFHD {
|
||||
version: u8,
|
||||
flags: u32,
|
||||
seq_num: u32,
|
||||
}
|
||||
|
||||
impl Default for MFHD {
|
||||
fn default() -> Self {
|
||||
MFHD {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
seq_num: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MP4Atom for MFHD {
|
||||
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.seq_num.to_be_bytes());
|
||||
make_box(content, *b"mfhd")
|
||||
}
|
||||
}
|
||||
|
||||
struct TRAF {
|
||||
tfhd: TFHD,
|
||||
trun: TRUN,
|
||||
}
|
||||
|
||||
impl MP4Atom for TRAF {
|
||||
fn marshall(&self) -> Vec<u8> {
|
||||
let mut content = self.tfhd.marshall();
|
||||
content.append(&mut self.trun.marshall());
|
||||
make_box(content, *b"traf")
|
||||
}
|
||||
}
|
||||
|
||||
struct TFHD {
|
||||
version: u8,
|
||||
flags: u32,
|
||||
track_id: u32,
|
||||
default_duration: u32,
|
||||
}
|
||||
|
||||
impl MP4Atom for TFHD {
|
||||
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_duration.to_be_bytes());
|
||||
make_box(content, *b"tfhd")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TFHD {
|
||||
fn default() -> Self {
|
||||
TFHD {
|
||||
version: 0,
|
||||
flags: 0x00020008,
|
||||
track_id: 0,
|
||||
default_duration: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TRUN {
|
||||
version: u8,
|
||||
flags: u32,
|
||||
num_samples: u32,
|
||||
offset: u32,
|
||||
samples: Vec<SampleData>,
|
||||
}
|
||||
|
||||
impl Default for TRUN {
|
||||
fn default() -> Self {
|
||||
TRUN {
|
||||
version: 0,
|
||||
flags: 0x00000601,
|
||||
num_samples: 0,
|
||||
offset: 0,
|
||||
samples: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MP4Atom for TRUN {
|
||||
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_samples.to_be_bytes());
|
||||
content.extend_from_slice(&self.offset.to_be_bytes());
|
||||
for sample in &self.samples {
|
||||
content.append(&mut sample.marshall());
|
||||
}
|
||||
make_box(content, *b"trun")
|
||||
}
|
||||
}
|
||||
|
||||
struct SampleData {
|
||||
size: u32,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
impl MP4Atom for SampleData {
|
||||
fn marshall(&self) -> Vec<u8> {
|
||||
let mut content = Vec::new();
|
||||
content.extend_from_slice(&self.size.to_be_bytes());
|
||||
content.extend_from_slice(&self.flags.to_be_bytes());
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
struct MDAT {
|
||||
v_samples: Vec<u8>,
|
||||
a_samples: Vec<u8>,
|
||||
}
|
||||
|
||||
impl MP4Atom for MDAT {
|
||||
fn marshall(&self) -> Vec<u8> {
|
||||
let mut content = self.v_samples.clone();
|
||||
content.append(&mut self.a_samples.clone());
|
||||
make_box(content, *b"mdat")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_moof(v_samples: &Vec<samples::Sample>, default_dur_v: u32, a_samples: &Vec<samples::Sample>, default_dur_a: u32, mdat_v_offset: usize, mdat_a_offset: usize, moof_idx: usize) -> MOOF {
|
||||
let mdat_data_start = 120 + v_samples.len() * 8 + a_samples.len() * 8 + 8;
|
||||
MOOF {
|
||||
mfhd: MFHD { seq_num: moof_idx as u32, ..Default::default() },
|
||||
trafs: [ TRAF {
|
||||
tfhd: TFHD {
|
||||
track_id: 1,
|
||||
default_duration: default_dur_v,
|
||||
..Default::default()
|
||||
},
|
||||
trun: new_trun(v_samples, mdat_v_offset + mdat_data_start),
|
||||
}, TRAF{
|
||||
tfhd: TFHD {
|
||||
track_id: 2,
|
||||
default_duration: default_dur_a,
|
||||
..Default::default()
|
||||
},
|
||||
trun: new_trun(a_samples, mdat_a_offset + mdat_data_start),
|
||||
} ],
|
||||
}
|
||||
}
|
||||
|
||||
fn new_trun(samples: &Vec<samples::Sample>, data_offset: usize) -> TRUN {
|
||||
TRUN {
|
||||
num_samples: samples.len() as u32,
|
||||
offset: data_offset as u32,
|
||||
samples: make_sample_table(samples),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_sample_table(samples: &Vec<samples::Sample>) -> Vec<SampleData> {
|
||||
let mut table = Vec::new();
|
||||
for sample in samples {
|
||||
table.push( SampleData {
|
||||
size: sample.size,
|
||||
flags: sample.flags,
|
||||
});
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
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());
|
||||
|
@ -1021,3 +1208,5 @@ fn make_box(mut content: Vec<u8>, box_name: [u8; 4]) -> Vec<u8> {
|
|||
head.append(&mut content);
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -74,7 +74,9 @@ impl mp4::MP4Muxer {
|
|||
return Some(segments::Segment {
|
||||
filename: idx.to_string() + ".m4s",
|
||||
segment_video: self.v_samples.get_segment_samples(time),
|
||||
sample_duration_v: self.v_samples.default_duration,
|
||||
segment_audio: self.a_samples.get_segment_samples(time),
|
||||
sample_duration_a: self.a_samples.default_duration,
|
||||
})
|
||||
}
|
||||
return None
|
||||
|
|
|
@ -4,7 +4,9 @@ use crate::muxer::hls::mp4::samples;
|
|||
pub struct Segment {
|
||||
pub filename: String,
|
||||
pub segment_video: Vec<samples::Sample>,
|
||||
pub sample_duration_v: u32,
|
||||
pub segment_audio: Vec<samples::Sample>,
|
||||
pub sample_duration_a: u32,
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
|
|
Loading…
Reference in a new issue