use broadcast_common::{Parse, Serialize};
use transmux::{CompositionOffsetBox, EditListBox, SegmentIndexBox, TimeToSampleBox, box_iter};
fn enter_chain<'a>(data: &'a [u8], types: &[&[u8; 4]]) -> &'a [u8] {
let mut current = data;
for &ty in types {
let mut offset = 0usize;
loop {
if offset + 8 > current.len() {
panic!("box {:?} not found", std::str::from_utf8(ty).unwrap());
}
let size = u32::from_be_bytes([
current[offset],
current[offset + 1],
current[offset + 2],
current[offset + 3],
]) as usize;
let box_ty = ¤t[offset + 4..offset + 8];
if size == 0 || size < 8 {
panic!(
"box {:?} not found (bad size)",
std::str::from_utf8(ty).unwrap()
);
}
if box_ty == ty {
current = ¤t[offset + 8..offset + size];
break;
}
offset += size;
}
}
current
}
fn find_full_box<'a>(body: &'a [u8], four_cc: &[u8; 4]) -> &'a [u8] {
let mut offset = 0usize;
while offset + 8 <= body.len() {
let size = u32::from_be_bytes([
body[offset],
body[offset + 1],
body[offset + 2],
body[offset + 3],
]) as usize;
let ty = &body[offset + 4..offset + 8];
if size == 0 || size < 8 {
break;
}
if ty == four_cc {
return &body[offset..offset + size];
}
offset += size;
}
panic!("box {:?} not found", std::str::from_utf8(four_cc).unwrap());
}
#[test]
fn stts_real_fixture_round_trip() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_aac_prog.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let stbl = enter_chain(&data, &[b"moov", b"trak", b"mdia", b"minf", b"stbl"]);
let stts_box = find_full_box(stbl, b"stts");
let parsed = TimeToSampleBox::parse(stts_box).expect("should parse stts from real fixture");
assert_eq!(parsed.entries.len(), 1, "stts entry count");
assert_eq!(parsed.entries[0].sample_count, 50, "stts sample_count");
assert_eq!(parsed.entries[0].sample_delta, 512, "stts sample_delta");
let serialized = parsed.to_bytes();
assert_eq!(
serialized.len(),
stts_box.len(),
"stts serialized length matches original"
);
assert_eq!(
&serialized[..],
stts_box,
"stts round-trip must be byte-identical"
);
}
#[test]
fn ctts_real_fixture_round_trip() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_aac_prog.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let stbl = enter_chain(&data, &[b"moov", b"trak", b"mdia", b"minf", b"stbl"]);
let ctts_box = find_full_box(stbl, b"ctts");
let parsed =
CompositionOffsetBox::parse(ctts_box).expect("should parse ctts from real fixture");
assert_eq!(parsed.version, 0, "ctts version");
assert_eq!(parsed.entries.len(), 34, "ctts entry count");
assert_eq!(parsed.entries[0].sample_offset, 1024, "ctts[0] offset");
assert_eq!(parsed.entries[1].sample_offset, 2048, "ctts[1] offset");
assert_eq!(parsed.entries[2].sample_offset, 512, "ctts[2] offset");
assert_eq!(parsed.entries[33].sample_offset, 1024, "ctts[33] offset");
let serialized = parsed.to_bytes();
assert_eq!(
serialized.len(),
ctts_box.len(),
"ctts serialized length matches original"
);
assert_eq!(
&serialized[..],
ctts_box,
"ctts round-trip must be byte-identical"
);
}
#[test]
fn elst_real_fixture_round_trip() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_aac_prog.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let trak = enter_chain(&data, &[b"moov", b"trak"]);
let edts = find_full_box(trak, b"edts");
let elst_box = find_full_box(&edts[8..], b"elst");
let parsed = EditListBox::parse(elst_box).expect("should parse elst from real fixture");
assert_eq!(parsed.version, 0, "elst version");
assert_eq!(parsed.entries.len(), 1, "elst entry count");
assert_eq!(
parsed.entries[0].segment_duration, 2000,
"elst segment_duration"
);
assert_eq!(parsed.entries[0].media_time, 1024, "elst media_time");
assert_eq!(
parsed.entries[0].media_rate_integer, 1,
"elst media_rate_integer"
);
assert_eq!(
parsed.entries[0].media_rate_fraction, 0,
"elst media_rate_fraction"
);
let serialized = parsed.to_bytes();
assert_eq!(
serialized.len(),
elst_box.len(),
"elst serialized length matches original"
);
assert_eq!(
&serialized[..],
elst_box,
"elst round-trip must be byte-identical"
);
}
#[test]
fn elst_mutation_changes_bytes() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_aac_prog.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let trak = enter_chain(&data, &[b"moov", b"trak"]);
let edts = find_full_box(trak, b"edts");
let elst_box = find_full_box(&edts[8..], b"elst");
let mut parsed = EditListBox::parse(elst_box).expect("should parse elst");
let original = parsed.to_bytes();
parsed.entries[0].media_time = 512; let mutated = parsed.to_bytes();
assert_ne!(
mutated, original,
"mutating media_time must change serialized bytes"
);
let mt = u32::from_be_bytes(mutated[20..24].try_into().unwrap());
assert_eq!(mt, 512, "media_time should be 512 at bytes 20..23");
}
#[test]
fn sidx_real_fixture_round_trip() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_sidx.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let mut found = false;
for box_ref in box_iter(&data) {
let (br, _consumed) = box_ref.expect("valid box");
if br.header.box_type.is(b"sidx") {
let hdr_len = br.header.serialized_len();
let mut full_box = vec![0u8; hdr_len + br.body.len()];
br.header.serialize_into(&mut full_box[..hdr_len]).unwrap();
full_box[hdr_len..].copy_from_slice(br.body);
let parsed =
SegmentIndexBox::parse(&full_box).expect("should parse sidx from real fixture");
assert_eq!(parsed.version, 0, "sidx version");
assert_eq!(parsed.reference_id, 1, "sidx reference_id");
assert_eq!(parsed.timescale, 90000, "sidx timescale");
assert_eq!(parsed.earliest_presentation_time, 0, "sidx EPT");
assert_eq!(parsed.first_offset, 68, "sidx first_offset");
assert_eq!(parsed.references.len(), 2, "sidx reference_count");
assert_eq!(parsed.references[0].reference_type, 0);
assert_eq!(parsed.references[0].referenced_size, 1000);
assert_eq!(parsed.references[0].subsegment_duration, 180000);
assert_eq!(
parsed.references[0].starts_with_sap, 1,
"sidx[0].starts_with_sap"
);
assert_eq!(parsed.references[0].sap_type, 1, "sidx[0].sap_type");
assert_eq!(parsed.references[1].referenced_size, 1200);
let serialized = parsed.to_bytes();
assert_eq!(
serialized.len(),
full_box.len(),
"sidx serialized length matches original"
);
assert_eq!(
&serialized[..],
&full_box[..],
"sidx round-trip must be byte-identical"
);
found = true;
break;
}
}
assert!(found, "sidx box not found in fixture");
}
#[test]
fn sidx_mutation_changes_bytes() {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/transmux/h264_sidx.mp4"
);
let data = std::fs::read(path).expect("fixture file must exist");
let mut parsed = None;
for box_ref in box_iter(&data) {
let (br, _consumed) = box_ref.expect("valid box");
if br.header.box_type.is(b"sidx") {
let hdr_len = br.header.serialized_len();
let mut full_box = vec![0u8; hdr_len + br.body.len()];
br.header.serialize_into(&mut full_box[..hdr_len]).unwrap();
full_box[hdr_len..].copy_from_slice(br.body);
parsed = Some(SegmentIndexBox::parse(&full_box).expect("should parse"));
break;
}
}
let mut sidx = parsed.expect("sidx must exist");
let original = sidx.to_bytes();
sidx.references[0].referenced_size = 999;
let mutated = sidx.to_bytes();
assert_ne!(
mutated, original,
"mutating referenced_size must change serialized bytes"
);
}