fragment boxes implementation, generation is limited to common duration, flags and size per and no composition time

This commit is contained in:
Muaz Ahmad 2023-10-24 16:45:51 +05:00
parent f70f8c05cb
commit fc7ecd62bd
3 changed files with 193 additions and 0 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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 {