Skip to content

Commit

Permalink
Don't merge tmcd track
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianEddy committed Mar 24, 2023
1 parent e407b1c commit d243955
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 44 additions & 37 deletions src/desc_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct TrackDesc {
pub stsz_count: u32,
pub stsc: Vec<(u32, u32, u32)>, // first_chunk, samples_per_chunk, sample_description_index
pub co64_final_position: u64,
pub skip: bool,
}

#[derive(Default, Clone, Debug)]
Expand All @@ -33,14 +34,13 @@ pub struct Desc {
pub mdat_final_position: u64,
}

pub fn read_desc<R: Read + Seek>(d: &mut R, desc: &mut Desc, track: usize, max_read: u64) -> Result<()> {
let mut total_read_size = 0;
pub fn read_desc<R: Read + Seek>(d: &mut R, desc: &mut Desc, track: usize, max_read: u64, file_index: usize) -> Result<()> {
let mut tl_track = track;
let start_offs = d.stream_position()?;
while let Ok((typ, offs, size, header_size)) = read_box(d) {
if size == 0 || typ == 0 { break; }
total_read_size += size;
if crate::has_children(typ) {
read_desc(d, desc, tl_track, size - header_size as u64)?;
if size == 0 || typ == 0 { continue; }
if crate::has_children(typ, true) {
read_desc(d, desc, tl_track, size - header_size as u64, file_index)?;

if typ == fourcc("trak") {
tl_track += 1;
Expand Down Expand Up @@ -72,44 +72,51 @@ pub fn read_desc<R: Read + Seek>(d: &mut R, desc: &mut Desc, track: usize, max_r
if typ == fourcc("elst") || typ == fourcc("stts") || typ == fourcc("stsz") || typ == fourcc("stss") ||
typ == fourcc("stco") || typ == fourcc("co64") || typ == fourcc("sdtp") || typ == fourcc("stsc") {
let track_desc = desc.moov_tracks.get_mut(tl_track).unwrap();
let (v, _flags) = (d.read_u8()?, d.read_u24::<BigEndian>()?);
if !(track_desc.skip && file_index > 0) {
let (v, _flags) = (d.read_u8()?, d.read_u24::<BigEndian>()?);

if typ == fourcc("elst") {
d.seek(SeekFrom::Current(4))?; // Skip fields
track_desc.elst_segment_duration += if v == 1 { d.read_u64::<BigEndian>()? } else { d.read_u32::<BigEndian>()? as u64 };
}
if typ == fourcc("stsz") {
track_desc.stsz_sample_size = d.read_u32::<BigEndian>()?;
let count = d.read_u32::<BigEndian>()?;
if track_desc.stsz_sample_size == 0 {
for _ in 0..count { track_desc.stsz.push(d.read_u32::<BigEndian>()?); }
if typ == fourcc("elst") {
d.seek(SeekFrom::Current(4))?; // Skip fields
track_desc.elst_segment_duration += if v == 1 { d.read_u64::<BigEndian>()? } else { d.read_u32::<BigEndian>()? as u64 };
}
track_desc.stsz_count += count;
}
if typ == fourcc("sdtp") {
let count = size - header_size as u64 - 4;
for _ in 0..count { track_desc.sdtp.push(d.read_u8()?); }
}
if typ == fourcc("stss") || typ == fourcc("stco") || typ == fourcc("co64") || typ == fourcc("stts") || typ == fourcc("stsc") {
let count = d.read_u32::<BigEndian>()?;
let current_file_mdat_position = desc.mdat_position.last().unwrap().1;
let mdat_offset = desc.mdat_offset as i64 - current_file_mdat_position as i64;
for _ in 0..count {
if typ == fourcc("stss") { track_desc.stss.push(d.read_u32::<BigEndian>()? + track_desc.sample_offset); }
if typ == fourcc("stco") { track_desc.stco.push((d.read_u32::<BigEndian>()? as i64 + mdat_offset) as u64); }
if typ == fourcc("co64") { track_desc.stco.push((d.read_u64::<BigEndian>()? as i64 + mdat_offset) as u64); }
if typ == fourcc("stts") { track_desc.stts.push((d.read_u32::<BigEndian>()?, d.read_u32::<BigEndian>()?)); }
if typ == fourcc("stsc") { track_desc.stsc.push((
d.read_u32::<BigEndian>()? + track_desc.chunk_offset,
d.read_u32::<BigEndian>()?,
d.read_u32::<BigEndian>()?
)); }
if typ == fourcc("stsz") {
track_desc.stsz_sample_size = d.read_u32::<BigEndian>()?;
let count = d.read_u32::<BigEndian>()?;
if track_desc.stsz_sample_size == 0 {
for _ in 0..count { track_desc.stsz.push(d.read_u32::<BigEndian>()?); }
}
track_desc.stsz_count += count;
}
if typ == fourcc("sdtp") {
let count = size - header_size as u64 - 4;
for _ in 0..count { track_desc.sdtp.push(d.read_u8()?); }
}
if typ == fourcc("stss") || typ == fourcc("stco") || typ == fourcc("co64") || typ == fourcc("stts") || typ == fourcc("stsc") {
let count = d.read_u32::<BigEndian>()?;
let current_file_mdat_position = desc.mdat_position.last().unwrap().1;
let mdat_offset = desc.mdat_offset as i64 - current_file_mdat_position as i64;
for _ in 0..count {
if typ == fourcc("stss") { track_desc.stss.push(d.read_u32::<BigEndian>()? + track_desc.sample_offset); }
if typ == fourcc("stco") { track_desc.stco.push((d.read_u32::<BigEndian>()? as i64 + mdat_offset) as u64); }
if typ == fourcc("co64") { track_desc.stco.push((d.read_u64::<BigEndian>()? as i64 + mdat_offset) as u64); }
if typ == fourcc("stts") { track_desc.stts.push((d.read_u32::<BigEndian>()?, d.read_u32::<BigEndian>()?)); }
if typ == fourcc("stsc") { track_desc.stsc.push((
d.read_u32::<BigEndian>()? + track_desc.chunk_offset,
d.read_u32::<BigEndian>()?,
d.read_u32::<BigEndian>()?
)); }
}
}
}
}
if typ == fourcc("tmcd") {
// Timecode shouldn't be merged
let track_desc = desc.moov_tracks.get_mut(tl_track).unwrap();
track_desc.skip = true;
}
d.seek(SeekFrom::Start(org_pos + size - header_size as u64))?;
}
if total_read_size >= max_read {
if d.stream_position()? - start_offs >= max_read {
break;
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ const fn fourcc(s: &str) -> u32 {
let s = s.as_bytes();
(s[3] as u32) | ((s[2] as u32) << 8) | ((s[1] as u32) << 16) | ((s[0] as u32) << 24)
}
const fn has_children(typ: u32) -> bool {
const fn has_children(typ: u32, is_read: bool) -> bool {
typ == fourcc("moov") || typ == fourcc("trak") || typ == fourcc("edts") ||
typ == fourcc("mdia") || typ == fourcc("minf") || typ == fourcc("stbl")
typ == fourcc("mdia") || typ == fourcc("minf") || typ == fourcc("stbl") ||
(typ == fourcc("stsd") && is_read)
}
fn typ_to_str(typ: u32) -> String {
unsafe { String::from_utf8_unchecked(vec![(typ >> 24) as u8, (typ >> 16) as u8, (typ >> 8) as u8, typ as u8 ]) }
Expand Down Expand Up @@ -70,7 +71,7 @@ pub fn join_files<P: AsRef<Path> + AsRef<std::ffi::OsStr>, F: Fn(f64)>(files: &[
fs.seek(std::io::SeekFrom::Start(0))?;
}

desc_reader::read_desc(&mut fs, &mut desc, 0, u64::MAX)?;
desc_reader::read_desc(&mut fs, &mut desc, 0, u64::MAX, i)?;

if let Some(mdat) = desc.mdat_position.last_mut() {
mdat.0 = Some(PathBuf::from(path));
Expand Down
4 changes: 2 additions & 2 deletions src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn rewrite_from_desc<R: Read + Seek, W: Write + Seek>(d: &mut R, output_file

total_read_size += size;
let mut new_size = size;
if crate::has_children(typ) {
if crate::has_children(typ, false) {
// Copy the header
d.seek(SeekFrom::Current(-header_size))?;
let out_pos = output_file.stream_position()?;
Expand Down Expand Up @@ -164,7 +164,7 @@ pub fn rewrite_from_desc<R: Read + Seek, W: Write + Seek>(d: &mut R, output_file
Ok(total_new_size)
}

fn patch_bytes<W: Write + Seek>(writer: &mut W, position: u64, bytes: &[u8]) -> Result<()> {
pub fn patch_bytes<W: Write + Seek>(writer: &mut W, position: u64, bytes: &[u8]) -> Result<()> {
let new_pos = writer.stream_position()?;
writer.seek(SeekFrom::Start(position))?;
writer.write(bytes)?;
Expand Down

0 comments on commit d243955

Please sign in to comment.