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 {
fn marshall(&self) -> Vec<u8> {
let content = Vec::new();
let mut content = Vec::new();
content.push(self.version);
content.extend_from_slice(&self.flags.to_be_bytes()[1..]);
if self.version == 1 {
@ -268,7 +268,7 @@ impl MP4Atom for ELST {
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 {
for edit in &self.edits {
content.append(&mut edit.marshall());
}
make_box(content, *b"elst")
@ -292,6 +292,15 @@ struct MDIA {
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 {
version: u8,
flags: u32,
@ -299,7 +308,31 @@ struct MDHD {
modify_time: u64,
time_scale: u32,
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 {
@ -323,6 +356,20 @@ struct HDLR {
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 {
fn default() -> Self {
HDLR {
@ -339,12 +386,30 @@ enum MINF {
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 {
vmhd: VMHD,
dinf: DINF,
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 {
version: u8,
flags: u32,
@ -352,6 +417,19 @@ struct VMHD {
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 {
fn default() -> Self {
VMHD {
@ -369,12 +447,32 @@ struct MINF_A {
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 {
version: u8,
flags: u32,
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 {
fn default() -> Self {
SMHD {
@ -389,6 +487,12 @@ struct DINF {
dref: DREF,
}
impl MP4Atom for DINF {
fn marshall(&self) -> Vec<u8> {
make_box(self.dref.marshall(), *b"dinf")
}
}
impl Default for DINF {
fn default() -> Self {
DINF {
@ -404,6 +508,19 @@ struct DREF {
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 {
fn default() -> Self {
DREF {
@ -424,18 +541,49 @@ enum Refs {
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 {
version: u8,
flags: u32,
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 {
version: u8,
flags: u32,
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 {
stsd: STSD,
stts: STTS,
@ -445,6 +593,20 @@ struct STBL {
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 version: u8,
pub flags: u32,
@ -452,12 +614,33 @@ pub struct STSD {
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 {
Visual(VisualSampleEntry),
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 sample_name: [u8; 4],
pub dref_idx: u16,
pub width: u16,
pub height: u16,
@ -468,7 +651,30 @@ pub struct VisualSampleEntry {
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 sample_name: [u8; 4],
pub dref_idx: u16,
pub channels: u16,
pub sample_size: u16,
@ -476,11 +682,34 @@ pub struct SoundSampleEntry {
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 atom_name: [u8; 4],
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 {
version: u8,
flags: u32,
@ -488,6 +717,20 @@ struct STTS {
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 {
fn default() -> Self {
STTS {
@ -511,6 +754,21 @@ struct STSC {
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 {
fn default() -> Self {
STSC {
@ -536,6 +794,20 @@ struct STSZ {
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 {
fn default() -> Self {
STSZ {
@ -555,6 +827,19 @@ struct STCO {
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 {
fn default() -> Self {
STCO {
@ -674,7 +959,11 @@ fn new_mdia(stsd: STSD, metadata: &Arc<util::Metadata>) -> MDIA {
}
}
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 {

View file

@ -7,8 +7,8 @@ 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 stsd_v = self.handle_v_cc()?;
let stsd_a = self.handle_a_cc()?;
let init_tree = mp4::atoms::construct_moov(stsd_v, stsd_a, &self.metadata);
mp4::atoms::dump_init_tree(init_tree)?;
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);
let cc = mp4::atoms::CodecConfig {atom_name: *b"av1C", data: dummy_mp4_cc_binding};
let v_sample_entry = mp4::atoms::VisualSampleEntry {
sample_name: *b"av01",
dref_idx: 1,
width: metadata.video.width 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());
opus_binding.splice(8..10, output_gain.to_be_bytes());
opus_binding[10] = sample[18];
if opus_binding[18] == 1 {
if sample[18] == 1 {
opus_binding.append(&mut sample[19..].to_vec());
}
let a_sample_entry = mp4::atoms::SoundSampleEntry {
sample_name: *b"Opus",
dref_idx: 1,
channels: metadata.audio.channels as u16,
sample_size: 16,