use codec::frame::ColorMetadata;
use crate::mux::{
build_audio_stsd, build_av01, write_unity_matrix, BoxBuilder,
};
use crate::AudioInfo;
use super::{brand, SampleFlags};
pub fn build_mehd(fragment_duration: u64) -> Vec<u8> {
let mut b = BoxBuilder::new(b"mehd");
b.u8(1); b.extend(&[0, 0, 0]); b.u64(fragment_duration);
b.finish()
}
pub fn build_trex(track_id: u32, default_sample_flags: u32) -> Vec<u8> {
let mut b = BoxBuilder::new(b"trex");
b.u8(0); b.extend(&[0, 0, 0]); b.u32(track_id);
b.u32(1); b.u32(0); b.u32(0); b.u32(default_sample_flags);
b.finish()
}
pub fn build_mvex(mehd: &[u8], trexes: &[Vec<u8>]) -> Vec<u8> {
let mut b = BoxBuilder::new(b"mvex");
b.extend(mehd);
for trex in trexes {
b.extend(trex);
}
b.finish()
}
pub fn build_init_segment_video(
width: u32,
height: u32,
timescale: u32,
config_obus: &[u8],
color_metadata: &ColorMetadata,
) -> Vec<u8> {
let av01 = build_av01(width, height, config_obus, color_metadata);
build_init_segment_video_with_entry(width, height, timescale, &av01, b"av01")
}
pub fn build_init_segment_video_with_entry(
width: u32,
height: u32,
timescale: u32,
sample_entry: &[u8],
codec_brand: &[u8; 4],
) -> Vec<u8> {
let track_id = 1u32;
let ftyp = build_ftyp_video(codec_brand);
let mvhd = build_mvhd(timescale, 0, 2);
let trak = build_video_trak(width, height, timescale, track_id, sample_entry);
let mvex_blob = {
let mehd = build_mehd(0);
let trex = build_trex(track_id, SampleFlags::delta_frame().pack());
build_mvex(&mehd, &[trex])
};
let mut moov = BoxBuilder::new(b"moov");
moov.extend(&mvhd);
moov.extend(&trak);
moov.extend(&mvex_blob);
let moov = moov.finish();
let mut out = Vec::with_capacity(ftyp.len() + moov.len());
out.extend_from_slice(&ftyp);
out.extend_from_slice(&moov);
out
}
pub fn build_init_segment_audio(audio_info: &AudioInfo) -> Vec<u8> {
let track_id = 1u32;
let ftyp = build_ftyp_audio();
let mvhd = build_mvhd(
audio_info.timescale,
0,
2,
);
let trak = build_audio_trak(audio_info, track_id);
let mvex_blob = {
let mehd = build_mehd(0);
let trex = build_trex(track_id, SampleFlags::keyframe().pack());
build_mvex(&mehd, &[trex])
};
let mut moov = BoxBuilder::new(b"moov");
moov.extend(&mvhd);
moov.extend(&trak);
moov.extend(&mvex_blob);
let moov = moov.finish();
let mut out = Vec::with_capacity(ftyp.len() + moov.len());
out.extend_from_slice(&ftyp);
out.extend_from_slice(&moov);
out
}
fn build_ftyp_video(codec_brand: &[u8; 4]) -> Vec<u8> {
let mut b = BoxBuilder::new(b"ftyp");
b.extend(b"iso6"); b.u32(0); b.extend(b"iso6");
b.extend(b"iso2");
b.extend(b"mp42");
b.extend(brand::CMFC);
b.extend(codec_brand);
b.finish()
}
fn build_ftyp_audio() -> Vec<u8> {
let mut b = BoxBuilder::new(b"ftyp");
b.extend(b"iso6"); b.u32(0); b.extend(b"iso6");
b.extend(b"iso2");
b.extend(b"mp42");
b.extend(brand::CMFA);
b.finish()
}
fn build_mvhd(timescale: u32, duration: u64, next_track_id: u32) -> Vec<u8> {
let mut b = BoxBuilder::new(b"mvhd");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0); b.u32(0); b.u32(timescale);
b.u32(duration as u32);
b.u32(0x00010000); b.u16(0x0100); b.u16(0); b.u32(0);
b.u32(0);
write_unity_matrix(&mut b);
for _ in 0..6 {
b.u32(0);
} b.u32(next_track_id);
b.finish()
}
fn build_video_trak(
width: u32,
height: u32,
timescale: u32,
track_id: u32,
sample_entry: &[u8],
) -> Vec<u8> {
let tkhd = build_video_tkhd(width, height, track_id);
let mdia = build_video_mdia(timescale, sample_entry);
let mut b = BoxBuilder::new(b"trak");
b.extend(&tkhd);
b.extend(&mdia);
b.finish()
}
fn build_video_tkhd(width: u32, height: u32, track_id: u32) -> Vec<u8> {
let mut b = BoxBuilder::new(b"tkhd");
b.u8(0);
b.extend(&[0, 0, 0x03]);
b.u32(0); b.u32(0); b.u32(track_id);
b.u32(0); b.u32(0); b.u32(0);
b.u32(0);
b.u16(0); b.u16(0); b.u16(0); b.u16(0); write_unity_matrix(&mut b);
b.u32(width << 16); b.u32(height << 16);
b.finish()
}
fn build_video_mdia(timescale: u32, sample_entry: &[u8]) -> Vec<u8> {
let mdhd = build_mdhd(timescale, 0);
let hdlr = build_hdlr(b"vide", "VideoHandler\0");
let minf = build_video_minf(sample_entry);
let mut b = BoxBuilder::new(b"mdia");
b.extend(&mdhd);
b.extend(&hdlr);
b.extend(&minf);
b.finish()
}
fn build_video_minf(sample_entry: &[u8]) -> Vec<u8> {
let vmhd = build_vmhd();
let dinf = build_dinf();
let stbl = build_video_stbl_empty(sample_entry);
let mut b = BoxBuilder::new(b"minf");
b.extend(&vmhd);
b.extend(&dinf);
b.extend(&stbl);
b.finish()
}
fn build_video_stbl_empty(sample_entry: &[u8]) -> Vec<u8> {
let stsd = {
let mut b = BoxBuilder::new(b"stsd");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(1); b.extend(sample_entry);
b.finish()
};
let stts = build_empty_full_box(b"stts");
let stsc = build_empty_full_box(b"stsc");
let stsz = {
let mut b = BoxBuilder::new(b"stsz");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0); b.u32(0); b.finish()
};
let stco = build_empty_full_box(b"stco");
let mut b = BoxBuilder::new(b"stbl");
b.extend(&stsd);
b.extend(&stts);
b.extend(&stsc);
b.extend(&stsz);
b.extend(&stco);
b.finish()
}
fn build_audio_trak(info: &AudioInfo, track_id: u32) -> Vec<u8> {
let tkhd = build_audio_tkhd(track_id);
let mdia = build_audio_mdia(info);
let mut b = BoxBuilder::new(b"trak");
b.extend(&tkhd);
b.extend(&mdia);
b.finish()
}
fn build_audio_tkhd(track_id: u32) -> Vec<u8> {
let mut b = BoxBuilder::new(b"tkhd");
b.u8(0);
b.extend(&[0, 0, 0x03]);
b.u32(0);
b.u32(0);
b.u32(track_id);
b.u32(0);
b.u32(0);
b.u32(0);
b.u32(0);
b.u16(0); b.u16(0); b.u16(0x0100); b.u16(0); write_unity_matrix(&mut b);
b.u32(0);
b.u32(0); b.finish()
}
fn build_audio_mdia(info: &AudioInfo) -> Vec<u8> {
let mdhd = build_mdhd(info.timescale, 0);
let hdlr = build_hdlr(b"soun", "SoundHandler\0");
let minf = build_audio_minf(info);
let mut b = BoxBuilder::new(b"mdia");
b.extend(&mdhd);
b.extend(&hdlr);
b.extend(&minf);
b.finish()
}
fn build_audio_minf(info: &AudioInfo) -> Vec<u8> {
let smhd = build_smhd();
let dinf = build_dinf();
let stbl = build_audio_stbl_empty(info);
let mut b = BoxBuilder::new(b"minf");
b.extend(&smhd);
b.extend(&dinf);
b.extend(&stbl);
b.finish()
}
fn build_audio_stbl_empty(info: &AudioInfo) -> Vec<u8> {
let stsd = build_audio_stsd(info);
let stts = build_empty_full_box(b"stts");
let stsc = build_empty_full_box(b"stsc");
let stsz = {
let mut b = BoxBuilder::new(b"stsz");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0);
b.u32(0);
b.finish()
};
let stco = build_empty_full_box(b"stco");
let mut b = BoxBuilder::new(b"stbl");
b.extend(&stsd);
b.extend(&stts);
b.extend(&stsc);
b.extend(&stsz);
b.extend(&stco);
b.finish()
}
fn build_mdhd(timescale: u32, duration: u64) -> Vec<u8> {
let mut b = BoxBuilder::new(b"mdhd");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0); b.u32(0); b.u32(timescale);
b.u32(duration as u32);
b.u16(0x55c4); b.u16(0); b.finish()
}
fn build_hdlr(handler_type: &[u8; 4], name: &str) -> Vec<u8> {
let mut b = BoxBuilder::new(b"hdlr");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0); b.extend(handler_type);
b.u32(0);
b.u32(0);
b.u32(0); b.extend(name.as_bytes());
b.finish()
}
fn build_vmhd() -> Vec<u8> {
let mut b = BoxBuilder::new(b"vmhd");
b.u8(0);
b.extend(&[0, 0, 0x01]); b.u16(0); b.u16(0);
b.u16(0);
b.u16(0); b.finish()
}
fn build_smhd() -> Vec<u8> {
let mut b = BoxBuilder::new(b"smhd");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u16(0); b.u16(0); b.finish()
}
fn build_dinf() -> Vec<u8> {
let url = {
let mut b = BoxBuilder::new(b"url ");
b.u8(0); b.extend(&[0, 0, 0x01]); b.finish()
};
let dref = {
let mut b = BoxBuilder::new(b"dref");
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(1); b.extend(&url);
b.finish()
};
let mut b = BoxBuilder::new(b"dinf");
b.extend(&dref);
b.finish()
}
fn build_empty_full_box(box_type: &[u8; 4]) -> Vec<u8> {
let mut b = BoxBuilder::new(box_type);
b.u8(0);
b.extend(&[0, 0, 0]);
b.u32(0);
b.finish()
}