init.mp4 segment creation and writing finished

This commit is contained in:
Muaz Ahmad 2023-10-20 14:18:34 +05:00
parent 358b69f450
commit 28a43ecdaa
2 changed files with 298 additions and 7 deletions

View file

@ -191,7 +191,7 @@ struct TKHD {
impl MP4Atom for TKHD { impl MP4Atom for TKHD {
fn marshall(&self) -> Vec<u8> { fn marshall(&self) -> Vec<u8> {
let content = Vec::new(); let mut content = Vec::new();
content.push(self.version); content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]); content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
if self.version == 1 { if self.version == 1 {
@ -268,7 +268,7 @@ impl MP4Atom for ELST {
content.push(self.version); content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]); content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
content.extend_from_slice(&self.num_edits.to_be_bytes()); content.extend_from_slice(&self.num_edits.to_be_bytes());
for edit in self.edits { for edit in &self.edits {
content.append(&mut edit.marshall()); content.append(&mut edit.marshall());
} }
make_box(content, *b"elst") make_box(content, *b"elst")
@ -292,6 +292,15 @@ struct MDIA {
minf: MINF, minf: MINF,
} }
impl MP4Atom for MDIA {
fn marshall(&self) -> Vec<u8> {
let mut content = self.mdhd.marshall();
content.append(&mut self.hdlr.marshall());
content.append(&mut self.minf.marshall());
make_box(content, *b"mdia")
}
}
struct MDHD { struct MDHD {
version: u8, version: u8,
flags: u32, flags: u32,
@ -299,7 +308,31 @@ struct MDHD {
modify_time: u64, modify_time: u64,
time_scale: u32, time_scale: u32,
duration: u64, duration: u64,
language: u32, language: u16,
}
impl MP4Atom for MDHD {
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.language.to_be_bytes());
content.append(&mut util::blank_vec(2));
make_box(content, *b"mdhd")
}
} }
impl Default for MDHD { impl Default for MDHD {
@ -323,6 +356,20 @@ struct HDLR {
name: String, name: String,
} }
impl MP4Atom for HDLR {
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.append(&mut util::blank_vec(4));
content.extend_from_slice(&self.handler.to_be_bytes());
content.append(&mut util::blank_vec(12));
content.extend_from_slice(&self.name.as_bytes());
content.push(0);
make_box(content, *b"hdlr")
}
}
impl Default for HDLR { impl Default for HDLR {
fn default() -> Self { fn default() -> Self {
HDLR { HDLR {
@ -339,12 +386,30 @@ enum MINF {
Audio(MINF_A), Audio(MINF_A),
} }
impl MP4Atom for MINF {
fn marshall(&self) -> Vec<u8> {
match self {
MINF::Video(x) => x.marshall(),
MINF::Audio(x) => x.marshall()
}
}
}
struct MINF_V { struct MINF_V {
vmhd: VMHD, vmhd: VMHD,
dinf: DINF, dinf: DINF,
stbl: STBL, stbl: STBL,
} }
impl MP4Atom for MINF_V {
fn marshall(&self) -> Vec<u8> {
let mut content = self.vmhd.marshall();
content.append(&mut self.dinf.marshall());
content.append(&mut self.stbl.marshall());
make_box(content, *b"minf")
}
}
struct VMHD { struct VMHD {
version: u8, version: u8,
flags: u32, flags: u32,
@ -352,6 +417,19 @@ struct VMHD {
opcolor: [u16; 3], opcolor: [u16; 3],
} }
impl MP4Atom for VMHD {
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.mode.to_be_bytes());
for col in &self.opcolor {
content.extend_from_slice(&col.to_be_bytes());
}
make_box(content, *b"vmhd")
}
}
impl Default for VMHD { impl Default for VMHD {
fn default() -> Self { fn default() -> Self {
VMHD { VMHD {
@ -369,12 +447,32 @@ struct MINF_A {
stbl: STBL, stbl: STBL,
} }
impl MP4Atom for MINF_A {
fn marshall(&self) -> Vec<u8> {
let mut content = self.smhd.marshall();
content.append(&mut self.dinf.marshall());
content.append(&mut self.stbl.marshall());
make_box(content, *b"minf")
}
}
struct SMHD { struct SMHD {
version: u8, version: u8,
flags: u32, flags: u32,
balance: u16, balance: u16,
} }
impl MP4Atom for SMHD {
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.balance.to_be_bytes());
content.append(&mut util::blank_vec(2));
make_box(content, *b"smhd")
}
}
impl Default for SMHD { impl Default for SMHD {
fn default() -> Self { fn default() -> Self {
SMHD { SMHD {
@ -389,6 +487,12 @@ struct DINF {
dref: DREF, dref: DREF,
} }
impl MP4Atom for DINF {
fn marshall(&self) -> Vec<u8> {
make_box(self.dref.marshall(), *b"dinf")
}
}
impl Default for DINF { impl Default for DINF {
fn default() -> Self { fn default() -> Self {
DINF { DINF {
@ -404,6 +508,19 @@ struct DREF {
refs: Vec<Refs> refs: Vec<Refs>
} }
impl MP4Atom for DREF {
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_refs.to_be_bytes());
for i in &self.refs {
content.append(&mut i.marshall());
}
make_box(content, *b"dref")
}
}
impl Default for DREF { impl Default for DREF {
fn default() -> Self { fn default() -> Self {
DREF { DREF {
@ -424,18 +541,49 @@ enum Refs {
RefURN(URN), RefURN(URN),
} }
impl MP4Atom for Refs {
fn marshall(&self) -> Vec<u8> {
match self {
Refs::RefURL(x) => x.marshall(),
Refs::RefURN(x) => x.marshall()
}
}
}
struct URL { struct URL {
version: u8, version: u8,
flags: u32, flags: u32,
url: String, url: String,
} }
impl MP4Atom for URL {
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.url.as_bytes());
content.push(0);
make_box(content, *b"url ")
}
}
struct URN { struct URN {
version: u8, version: u8,
flags: u32, flags: u32,
urn: String, urn: String,
} }
impl MP4Atom for URN {
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.urn.as_bytes());
content.push(0);
make_box(content, *b"urn ")
}
}
struct STBL { struct STBL {
stsd: STSD, stsd: STSD,
stts: STTS, stts: STTS,
@ -445,6 +593,20 @@ struct STBL {
opts: Vec<Vec<u8>>, opts: Vec<Vec<u8>>,
} }
impl MP4Atom for STBL {
fn marshall(&self) -> Vec<u8> {
let mut content = self.stsd.marshall();
content.append(&mut self.stts.marshall());
content.append(&mut self.stsc.marshall());
content.append(&mut self.stsz.marshall());
content.append(&mut self.stco.marshall());
for opt in &self.opts {
content.extend_from_slice(opt.as_slice());
}
make_box(content, *b"stbl")
}
}
pub struct STSD { pub struct STSD {
pub version: u8, pub version: u8,
pub flags: u32, pub flags: u32,
@ -452,12 +614,33 @@ pub struct STSD {
pub entry: SampleEntry, pub entry: SampleEntry,
} }
impl MP4Atom for STSD {
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_entries.to_be_bytes());
content.append(&mut self.entry.marshall());
make_box(content, *b"stsd")
}
}
pub enum SampleEntry { pub enum SampleEntry {
Visual(VisualSampleEntry), Visual(VisualSampleEntry),
Sound(SoundSampleEntry), Sound(SoundSampleEntry),
} }
impl MP4Atom for SampleEntry {
fn marshall(&self) -> Vec<u8> {
match self {
SampleEntry::Visual(x) => x.marshall(),
SampleEntry::Sound(x) => x.marshall()
}
}
}
pub struct VisualSampleEntry { pub struct VisualSampleEntry {
pub sample_name: [u8; 4],
pub dref_idx: u16, pub dref_idx: u16,
pub width: u16, pub width: u16,
pub height: u16, pub height: u16,
@ -468,7 +651,30 @@ pub struct VisualSampleEntry {
pub codec_config: CodecConfig, pub codec_config: CodecConfig,
} }
impl MP4Atom for VisualSampleEntry {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.append(&mut util::blank_vec(6));
content.extend_from_slice(&self.dref_idx.to_be_bytes());
content.append(&mut util::blank_vec(16));
content.extend_from_slice(&self.width.to_be_bytes());
content.extend_from_slice(&self.height.to_be_bytes());
content.extend_from_slice(&self.resolution.to_be_bytes());
content.append(&mut util::blank_vec(4));
content.extend_from_slice(&self.sample_per_frame.to_be_bytes());
content.extend_from_slice(&(self.encoder_name.len() as u8).to_be_bytes());
let mut encoder_bytes = vec![0u8; 31];
encoder_bytes.splice(..self.encoder_name.len(), self.encoder_name.bytes());
content.append(&mut encoder_bytes);
content.extend_from_slice(&self.pixel_depth.to_be_bytes());
content.extend_from_slice(&(0xffff as u16).to_be_bytes());
content.append(&mut self.codec_config.marshall());
make_box(content, self.sample_name)
}
}
pub struct SoundSampleEntry { pub struct SoundSampleEntry {
pub sample_name: [u8; 4],
pub dref_idx: u16, pub dref_idx: u16,
pub channels: u16, pub channels: u16,
pub sample_size: u16, pub sample_size: u16,
@ -476,11 +682,34 @@ pub struct SoundSampleEntry {
pub codec_config: CodecConfig, pub codec_config: CodecConfig,
} }
impl MP4Atom for SoundSampleEntry {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.append(&mut util::blank_vec(6));
content.extend_from_slice(&self.dref_idx.to_be_bytes());
content.append(&mut util::blank_vec(8));
content.extend_from_slice(&self.channels.to_be_bytes());
content.extend_from_slice(&self.sample_size.to_be_bytes());
content.append(&mut util::blank_vec(4));
content.extend_from_slice(&self.sample_rate.to_be_bytes());
content.append(&mut self.codec_config.marshall());
make_box(content, self.sample_name)
}
}
pub struct CodecConfig { pub struct CodecConfig {
pub atom_name: [u8; 4], pub atom_name: [u8; 4],
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl MP4Atom for CodecConfig {
fn marshall(&self) -> Vec<u8> {
let mut content = Vec::new();
content.extend_from_slice(&self.data.as_slice());
make_box(content, self.atom_name)
}
}
struct STTS { struct STTS {
version: u8, version: u8,
flags: u32, flags: u32,
@ -488,6 +717,20 @@ struct STTS {
entries: Vec<STTSEntry>, entries: Vec<STTSEntry>,
} }
impl MP4Atom for STTS {
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_entries.to_be_bytes());
for entry in &self.entries {
content.extend_from_slice(&entry.count_consec.to_be_bytes());
content.extend_from_slice(&entry.duration.to_be_bytes());
}
make_box(content, *b"stts")
}
}
impl Default for STTS { impl Default for STTS {
fn default() -> Self { fn default() -> Self {
STTS { STTS {
@ -511,6 +754,21 @@ struct STSC {
entries: Vec<STSCEntry>, entries: Vec<STSCEntry>,
} }
impl MP4Atom for STSC {
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_entries.to_be_bytes());
for entry in &self.entries {
content.extend_from_slice(&entry.chunk_idx.to_be_bytes());
content.extend_from_slice(&entry.samples_per.to_be_bytes());
content.extend_from_slice(&entry.data_ref_idx.to_be_bytes());
}
make_box(content, *b"stsc")
}
}
impl Default for STSC { impl Default for STSC {
fn default() -> Self { fn default() -> Self {
STSC { STSC {
@ -536,6 +794,20 @@ struct STSZ {
entries: Vec<u32>, entries: Vec<u32>,
} }
impl MP4Atom for STSZ {
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.common_size.to_be_bytes());
content.extend_from_slice(&self.num_entries.to_be_bytes());
for entry in &self.entries {
content.extend_from_slice(&entry.to_be_bytes());
}
make_box(content, *b"stsz")
}
}
impl Default for STSZ { impl Default for STSZ {
fn default() -> Self { fn default() -> Self {
STSZ { STSZ {
@ -555,6 +827,19 @@ struct STCO {
entries: Vec<u32>, entries: Vec<u32>,
} }
impl MP4Atom for STCO {
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_entries.to_be_bytes());
for entry in &self.entries {
content.extend_from_slice(&entry.to_be_bytes());
}
make_box(content, *b"stco")
}
}
impl Default for STCO { impl Default for STCO {
fn default() -> Self { fn default() -> Self {
STCO { STCO {
@ -674,7 +959,11 @@ fn new_mdia(stsd: STSD, metadata: &Arc<util::Metadata>) -> MDIA {
} }
} }
let minf = new_minf(stsd, metadata); let minf = new_minf(stsd, metadata);
todo!(); return MDIA {
mdhd: mdhd,
hdlr: hdlr,
minf: minf,
}
} }
fn new_minf(stsd: STSD, metadata: &Arc<util::Metadata>) -> MINF { fn new_minf(stsd: STSD, metadata: &Arc<util::Metadata>) -> MINF {

View file

@ -7,8 +7,8 @@ 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_v_cc()?;
let stsd_a = self.handle_v_cc()?; let stsd_a = self.handle_a_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)?; mp4::atoms::dump_init_tree(init_tree)?;
Ok(()) Ok(())
@ -47,6 +47,7 @@ fn get_av1_stsd(mut sample: Vec<u8>, metadata: &Arc<util::Metadata>) -> mp4::ato
dummy_mp4_cc_binding.append(&mut av1c); dummy_mp4_cc_binding.append(&mut av1c);
let cc = mp4::atoms::CodecConfig {atom_name: *b"av1C", data: dummy_mp4_cc_binding}; let cc = mp4::atoms::CodecConfig {atom_name: *b"av1C", data: dummy_mp4_cc_binding};
let v_sample_entry = mp4::atoms::VisualSampleEntry { let v_sample_entry = mp4::atoms::VisualSampleEntry {
sample_name: *b"av01",
dref_idx: 1, dref_idx: 1,
width: metadata.video.width as u16, width: metadata.video.width as u16,
height: metadata.video.height as u16, height: metadata.video.height as u16,
@ -73,11 +74,12 @@ fn get_opus_stsd(sample: Vec<u8>, metadata: &Arc<util::Metadata>) -> mp4::atoms:
let output_gain = u16::from_le_bytes(sample[16..18].try_into().unwrap()); let output_gain = u16::from_le_bytes(sample[16..18].try_into().unwrap());
opus_binding.splice(8..10, output_gain.to_be_bytes()); opus_binding.splice(8..10, output_gain.to_be_bytes());
opus_binding[10] = sample[18]; opus_binding[10] = sample[18];
if opus_binding[18] == 1 { if sample[18] == 1 {
opus_binding.append(&mut sample[19..].to_vec()); opus_binding.append(&mut sample[19..].to_vec());
} }
let a_sample_entry = mp4::atoms::SoundSampleEntry { let a_sample_entry = mp4::atoms::SoundSampleEntry {
sample_name: *b"Opus",
dref_idx: 1, dref_idx: 1,
channels: metadata.audio.channels as u16, channels: metadata.audio.channels as u16,
sample_size: 16, sample_size: 16,