barebones default tree for init segment
This commit is contained in:
parent
d57ccb2c9d
commit
f0b7a3504a
2 changed files with 317 additions and 9 deletions
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue