barebones default tree for init segment

This commit is contained in:
Muaz Ahmad 2023-10-19 15:02:16 +05:00
parent d57ccb2c9d
commit f0b7a3504a
2 changed files with 317 additions and 9 deletions

View file

@ -1,3 +1,7 @@
use std::sync::Arc;
use crate::util;
trait MP4Atom {
fn size(&self) -> u32;
@ -16,12 +20,38 @@ struct WindowMatrix {
w: u32,
}
impl Default for WindowMatrix {
fn default() -> Self {
WindowMatrix {
a: 1 << 16,
b: 0,
u: 0,
c: 0,
d: 1 << 16,
v: 0,
x: 0,
y: 0,
w: 1 << 30,
}
}
}
struct Edits {
duration: u64,
start: u64,
start: i64,
play_rate: u32,
}
impl Default for Edits {
fn default() -> Self {
Edits {
duration: 0,
start: 0,
play_rate: 1 << 16,
}
}
}
pub struct MOOV {
mvhd: MVHD,
traks: [TRAK; 2],
@ -41,6 +71,23 @@ struct MVHD {
next_track_id: u32,
}
impl Default for MVHD {
fn default() -> Self {
MVHD {
version: 0,
flags: 0,
create_time: 0,
modify_time: 0,
time_scale: 1000,
duration: 0,
playrate: 1 << 16,
volume: 1 << 8,
matrix: WindowMatrix {..Default::default()},
next_track_id: 2,
}
}
}
struct TRAK {
tkhd: TKHD,
edts: EDTS,
@ -53,7 +100,6 @@ struct TKHD {
create_time: u64,
modify_time: u64,
track_id: u32,
time_scale: u32,
duration: u64,
layer: u16,
alt_group: u16,
@ -63,10 +109,35 @@ struct TKHD {
height: u32,
}
impl Default for TKHD {
fn default() -> Self {
TKHD {
version: 0,
flags: 1,
create_time: 0,
modify_time: 0,
track_id: 0,
duration: 0,
layer: 0,
alt_group: 0,
volume: 0,
matrix: WindowMatrix {..Default::default()},
width: 0,
height: 0,
}
}
}
struct EDTS {
elst: ELST,
}
impl Default for EDTS {
fn default() -> Self {
EDTS {elst: ELST {..Default::default()}}
}
}
struct ELST {
version: u8,
flags: u32,
@ -74,6 +145,17 @@ struct ELST {
edits: Vec<Edits>,
}
impl Default for ELST {
fn default() -> Self {
ELST {
version: 0,
flags: 0,
num_edits: 1,
edits: vec![Edits {..Default::default() }],
}
}
}
struct MDIA {
mdhd: MDHD,
hdlr: HDLR,
@ -90,6 +172,20 @@ struct MDHD {
language: u32,
}
impl Default for MDHD {
fn default() -> Self {
MDHD {
version: 0,
flags: 0,
create_time: 0,
modify_time: 0,
time_scale: 0,
duration: 0,
language: 21956,
}
}
}
struct HDLR {
version: u8,
flags: u32,
@ -97,6 +193,17 @@ struct HDLR {
name: String,
}
impl Default for HDLR {
fn default() -> Self {
HDLR {
version: 0,
flags: 0,
handler: 0,
name: String::from(""),
}
}
}
enum MINF {
Video(MINF_V),
Audio(MINF_A),
@ -115,6 +222,17 @@ struct VMHD {
opcolor: [u16; 3],
}
impl Default for VMHD {
fn default() -> Self {
VMHD {
version: 0,
flags: 0,
mode: 0,
opcolor: [0,0,0],
}
}
}
struct MINF_A {
smhd: SMHD,
dinf: DINF,
@ -127,10 +245,28 @@ struct SMHD {
balance: u16,
}
impl Default for SMHD {
fn default() -> Self {
SMHD {
version: 0,
flags: 0,
balance: 0,
}
}
}
struct DINF {
dref: DREF,
}
impl Default for DINF {
fn default() -> Self {
DINF {
dref: DREF {..Default::default() },
}
}
}
struct DREF {
version: u8,
flags: u32,
@ -138,6 +274,21 @@ struct DREF {
refs: Vec<Refs>
}
impl Default for DREF {
fn default() -> Self {
DREF {
version: 0,
flags: 0,
num_refs: 1,
refs: vec![Refs::RefURL(URL {
version: 0,
flags: 1,
url: String::from(""),
})],
}
}
}
enum Refs {
RefURL(URL),
RefURN(URN),
@ -207,6 +358,17 @@ struct STTS {
entries: Vec<STTSEntry>,
}
impl Default for STTS {
fn default() -> Self {
STTS {
version: 0,
flags: 0,
num_entries: 0,
entries: Vec::new(),
}
}
}
struct STTSEntry {
count_consec: u32,
duration: u32,
@ -219,6 +381,17 @@ struct STSC {
entries: Vec<STSCEntry>,
}
impl Default for STSC {
fn default() -> Self {
STSC {
version: 0,
flags: 0,
num_entries: 0,
entries: Vec::new(),
}
}
}
struct STSCEntry {
chunk_idx: u32,
samples_per: u32,
@ -233,6 +406,18 @@ struct STSZ {
entries: Vec<u32>,
}
impl Default for STSZ {
fn default() -> Self {
STSZ {
version: 0,
flags: 0,
common_size: 0,
num_entries: 0,
entries: Vec::new(),
}
}
}
struct STCO {
version: u8,
flags: u32,
@ -240,10 +425,29 @@ struct STCO {
entries: Vec<u32>,
}
impl Default for STCO {
fn default() -> Self {
STCO {
version: 0,
flags: 0,
num_entries: 0,
entries: Vec::new(),
}
}
}
struct MVEX {
trexs: [TREX; 2],
}
impl Default for MVEX {
fn default() -> Self {
MVEX {
trexs: [TREX {track_id: 1, ..Default::default()}, TREX{track_id: 2, ..Default::default()}],
}
}
}
struct TREX {
version: u8,
flags: u32,
@ -254,3 +458,111 @@ struct TREX {
default_flags: u32,
}
impl Default for TREX {
fn default() -> Self {
TREX {
version: 0,
flags: 0,
track_id: 0,
default_desc_idx: 1,
default_duration: 0,
default_size: 0,
default_flags: 0,
}
}
}
pub fn construct_moov(stsd_v: STSD, stsd_a: STSD, metadata: &Arc<util::Metadata>) -> MOOV {
let mvhd = MVHD {..Default::default() };
let traks = [new_trak(stsd_v, &metadata), new_trak(stsd_a, &metadata)];
let mvex = MVEX {..Default::default() };
return MOOV {
mvhd: mvhd,
traks: traks,
mvex: mvex,
}
}
fn new_trak(stsd: STSD, metadata: &Arc<util::Metadata>) -> TRAK {
let mut tkhd = TKHD {..Default::default() };
match stsd.entry {
SampleEntry::Visual(_) => {
tkhd.width = metadata.video.width << 16;
tkhd.height = metadata.video.height << 16;
tkhd.track_id = 1;
},
SampleEntry::Sound(_) => {
tkhd.alt_group = 1;
tkhd.volume = 1 << 8;
tkhd.track_id = 2;
}
}
let edts = EDTS { ..Default::default()};
let mdia = new_mdia(stsd, metadata);
return TRAK {
tkhd: tkhd,
edts: edts,
mdia: mdia,
}
}
fn new_mdia(stsd: STSD, metadata: &Arc<util::Metadata>) -> MDIA {
let mut mdhd = MDHD {..Default::default() };
let mut hdlr = HDLR {..Default::default() };
match stsd.entry {
SampleEntry::Visual(_) => {
mdhd.time_scale = (metadata.video.framerate * 1000.0) as u32;
hdlr.handler = u32::from_be_bytes(*b"vide");
hdlr.name = String::from("VideoHandler");
},
SampleEntry::Sound(_) => {
mdhd.time_scale = metadata.audio.samplerate;
hdlr.handler = u32::from_be_bytes(*b"soun");
hdlr.name = String::from("SoundHandler");
}
}
let minf = new_minf(stsd, metadata);
todo!();
}
fn new_minf(stsd: STSD, metadata: &Arc<util::Metadata>) -> MINF {
match stsd.entry {
SampleEntry::Visual(_) => MINF::Video(new_minf_v(stsd, metadata)),
SampleEntry::Sound(_) => MINF::Audio(new_minf_a(stsd, metadata))
}
}
fn new_minf_v(stsd: STSD, metadata: &Arc<util::Metadata>) -> MINF_V {
let vmhd = VMHD {..Default::default() };
let dinf = DINF {..Default::default() };
let stbl = new_stbl(stsd, metadata);
return MINF_V {
vmhd: vmhd,
dinf: dinf,
stbl: stbl,
}
}
fn new_minf_a(stsd: STSD, metadata: &Arc<util::Metadata>) -> MINF_A {
let smhd = SMHD {..Default::default() };
let dinf = DINF {..Default::default() };
let stbl = new_stbl(stsd, metadata);
return MINF_A {
smhd: smhd,
dinf: dinf,
stbl: stbl,
}
}
fn new_stbl(stsd: STSD, metadata: &Arc<util::Metadata>) -> STBL {
STBL {
stsd: stsd,
stts: STTS{..Default::default()},
stsc: STSC{..Default::default()},
stsz: STSZ{..Default::default()},
stco: STCO{..Default::default()},
opts: Vec::new(),
}
}

View file

@ -8,7 +8,7 @@ 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 init_tree = self.construct_moov(stsd_v, stsd_a);
let init_tree = mp4::atoms::construct_moov(stsd_v, stsd_a, &self.metadata);
Ok(())
}
@ -33,10 +33,6 @@ impl mp4::MP4Muxer {
_ => Err(Box::new(util::MuxerError::InvalidCodec))
}
}
fn construct_moov(&self, stsd_v: mp4::atoms::STSD, stsd_a: mp4::atoms::STSD) -> mp4::atoms::MOOV {
todo!();
}
}
fn get_av1_stsd(mut sample: Vec<u8>, metadata: &Arc<util::Metadata>) -> mp4::atoms::STSD {
@ -47,7 +43,7 @@ fn get_av1_stsd(mut sample: Vec<u8>, metadata: &Arc<util::Metadata>) -> mp4::ato
// More complicated to parse than is worth doing.
let mut dummy_mp4_cc_binding = vec![0x81u8, 0x05, 0x0d, 0x00];
dummy_mp4_cc_binding.append(&mut av1c);
let cc = mp4::atoms::CodecConfig {atom_name: "av1C".as_bytes().try_into().unwrap(), 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 {
dref_idx: 1,
width: metadata.video.width as u16,
@ -84,7 +80,7 @@ fn get_opus_stsd(sample: Vec<u8>, metadata: &Arc<util::Metadata>) -> mp4::atoms:
channels: metadata.audio.channels as u16,
sample_size: 16,
sample_rate: metadata.audio.samplerate,
codec_config: mp4::atoms::CodecConfig { atom_name: "dOps".as_bytes().try_into().unwrap(), data: opus_binding}
codec_config: mp4::atoms::CodecConfig { atom_name: *b"dOps", data: opus_binding}
};
return mp4::atoms::STSD {
version: 0,