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 {
|
trait MP4Atom {
|
||||||
fn size(&self) -> u32;
|
fn size(&self) -> u32;
|
||||||
|
|
||||||
|
@ -16,12 +20,38 @@ struct WindowMatrix {
|
||||||
w: u32,
|
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 {
|
struct Edits {
|
||||||
duration: u64,
|
duration: u64,
|
||||||
start: u64,
|
start: i64,
|
||||||
play_rate: u32,
|
play_rate: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Edits {
|
||||||
|
fn default() -> Self {
|
||||||
|
Edits {
|
||||||
|
duration: 0,
|
||||||
|
start: 0,
|
||||||
|
play_rate: 1 << 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MOOV {
|
pub struct MOOV {
|
||||||
mvhd: MVHD,
|
mvhd: MVHD,
|
||||||
traks: [TRAK; 2],
|
traks: [TRAK; 2],
|
||||||
|
@ -41,6 +71,23 @@ struct MVHD {
|
||||||
next_track_id: u32,
|
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 {
|
struct TRAK {
|
||||||
tkhd: TKHD,
|
tkhd: TKHD,
|
||||||
edts: EDTS,
|
edts: EDTS,
|
||||||
|
@ -53,7 +100,6 @@ struct TKHD {
|
||||||
create_time: u64,
|
create_time: u64,
|
||||||
modify_time: u64,
|
modify_time: u64,
|
||||||
track_id: u32,
|
track_id: u32,
|
||||||
time_scale: u32,
|
|
||||||
duration: u64,
|
duration: u64,
|
||||||
layer: u16,
|
layer: u16,
|
||||||
alt_group: u16,
|
alt_group: u16,
|
||||||
|
@ -63,10 +109,35 @@ struct TKHD {
|
||||||
height: u32,
|
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 {
|
struct EDTS {
|
||||||
elst: ELST,
|
elst: ELST,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for EDTS {
|
||||||
|
fn default() -> Self {
|
||||||
|
EDTS {elst: ELST {..Default::default()}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ELST {
|
struct ELST {
|
||||||
version: u8,
|
version: u8,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
@ -74,6 +145,17 @@ struct ELST {
|
||||||
edits: Vec<Edits>,
|
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 {
|
struct MDIA {
|
||||||
mdhd: MDHD,
|
mdhd: MDHD,
|
||||||
hdlr: HDLR,
|
hdlr: HDLR,
|
||||||
|
@ -90,6 +172,20 @@ struct MDHD {
|
||||||
language: u32,
|
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 {
|
struct HDLR {
|
||||||
version: u8,
|
version: u8,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
@ -97,6 +193,17 @@ struct HDLR {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for HDLR {
|
||||||
|
fn default() -> Self {
|
||||||
|
HDLR {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
handler: 0,
|
||||||
|
name: String::from(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum MINF {
|
enum MINF {
|
||||||
Video(MINF_V),
|
Video(MINF_V),
|
||||||
Audio(MINF_A),
|
Audio(MINF_A),
|
||||||
|
@ -115,6 +222,17 @@ struct VMHD {
|
||||||
opcolor: [u16; 3],
|
opcolor: [u16; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for VMHD {
|
||||||
|
fn default() -> Self {
|
||||||
|
VMHD {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
mode: 0,
|
||||||
|
opcolor: [0,0,0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MINF_A {
|
struct MINF_A {
|
||||||
smhd: SMHD,
|
smhd: SMHD,
|
||||||
dinf: DINF,
|
dinf: DINF,
|
||||||
|
@ -127,10 +245,28 @@ struct SMHD {
|
||||||
balance: u16,
|
balance: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for SMHD {
|
||||||
|
fn default() -> Self {
|
||||||
|
SMHD {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
balance: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct DINF {
|
struct DINF {
|
||||||
dref: DREF,
|
dref: DREF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for DINF {
|
||||||
|
fn default() -> Self {
|
||||||
|
DINF {
|
||||||
|
dref: DREF {..Default::default() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct DREF {
|
struct DREF {
|
||||||
version: u8,
|
version: u8,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
@ -138,6 +274,21 @@ struct DREF {
|
||||||
refs: Vec<Refs>
|
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 {
|
enum Refs {
|
||||||
RefURL(URL),
|
RefURL(URL),
|
||||||
RefURN(URN),
|
RefURN(URN),
|
||||||
|
@ -207,6 +358,17 @@ struct STTS {
|
||||||
entries: Vec<STTSEntry>,
|
entries: Vec<STTSEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for STTS {
|
||||||
|
fn default() -> Self {
|
||||||
|
STTS {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
num_entries: 0,
|
||||||
|
entries: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct STTSEntry {
|
struct STTSEntry {
|
||||||
count_consec: u32,
|
count_consec: u32,
|
||||||
duration: u32,
|
duration: u32,
|
||||||
|
@ -219,6 +381,17 @@ struct STSC {
|
||||||
entries: Vec<STSCEntry>,
|
entries: Vec<STSCEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for STSC {
|
||||||
|
fn default() -> Self {
|
||||||
|
STSC {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
num_entries: 0,
|
||||||
|
entries: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct STSCEntry {
|
struct STSCEntry {
|
||||||
chunk_idx: u32,
|
chunk_idx: u32,
|
||||||
samples_per: u32,
|
samples_per: u32,
|
||||||
|
@ -233,6 +406,18 @@ struct STSZ {
|
||||||
entries: Vec<u32>,
|
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 {
|
struct STCO {
|
||||||
version: u8,
|
version: u8,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
@ -240,10 +425,29 @@ struct STCO {
|
||||||
entries: Vec<u32>,
|
entries: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for STCO {
|
||||||
|
fn default() -> Self {
|
||||||
|
STCO {
|
||||||
|
version: 0,
|
||||||
|
flags: 0,
|
||||||
|
num_entries: 0,
|
||||||
|
entries: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MVEX {
|
struct MVEX {
|
||||||
trexs: [TREX; 2],
|
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 {
|
struct TREX {
|
||||||
version: u8,
|
version: u8,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
@ -254,3 +458,111 @@ struct TREX {
|
||||||
default_flags: u32,
|
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>> {
|
pub fn gen_init(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
let stsd_v = self.handle_a_cc()?;
|
let stsd_v = self.handle_a_cc()?;
|
||||||
let stsd_a = self.handle_v_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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +33,6 @@ impl mp4::MP4Muxer {
|
||||||
_ => Err(Box::new(util::MuxerError::InvalidCodec))
|
_ => 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 {
|
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.
|
// More complicated to parse than is worth doing.
|
||||||
let mut dummy_mp4_cc_binding = vec![0x81u8, 0x05, 0x0d, 0x00];
|
let mut dummy_mp4_cc_binding = vec![0x81u8, 0x05, 0x0d, 0x00];
|
||||||
dummy_mp4_cc_binding.append(&mut av1c);
|
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 {
|
let v_sample_entry = mp4::atoms::VisualSampleEntry {
|
||||||
dref_idx: 1,
|
dref_idx: 1,
|
||||||
width: metadata.video.width as u16,
|
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,
|
channels: metadata.audio.channels as u16,
|
||||||
sample_size: 16,
|
sample_size: 16,
|
||||||
sample_rate: metadata.audio.samplerate,
|
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 {
|
return mp4::atoms::STSD {
|
||||||
version: 0,
|
version: 0,
|
||||||
|
|
Loading…
Reference in a new issue