init.mp4 segment creation and writing finished
This commit is contained in:
parent
358b69f450
commit
28a43ecdaa
2 changed files with 298 additions and 7 deletions
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue