+const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
+ TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
+ TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
+ TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
+ TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
+];
+
+fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
+ validate!(size >= 8);
+ let start = br.tell();
+ let _version = br.read_byte()?;
+ let flags = br.read_u24be()?;
+ let _track_id = br.read_u32be()?;
+ if (flags & 0x000001) != 0 {
+ let base_offset = br.read_u64be()?;
+ track.moof_off = base_offset;
+ }
+ if (flags & 0x000002) != 0 {
+ let _sample_description_index = br.read_u32be()?;
+ }
+ if (flags & 0x000008) != 0 {
+ let default_sample_duration = br.read_u32be()?;
+ if track.tb_div == 1 {
+ track.rescale(default_sample_duration);
+ }
+ }
+ if (flags & 0x000010) != 0 {
+ let _default_sample_size = br.read_u32be()?;
+ }
+ if (flags & 0x000020) != 0 {
+ let _default_sample_flags = br.read_u32be()?;
+ }
+ if (flags & 0x010000) != 0 {
+ }
+ /*if (flags & 0x020000) != 0 { // base offset is moof start
+ }*/
+ Ok(br.tell() - start)
+}
+
+fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
+ validate!(size >= 8);
+ let version = br.read_byte()?;
+ let flags = br.read_u24be()?;
+ let data_off_present = (flags & 0x000001) != 0;
+ let first_sample_flags = (flags & 0x000004) != 0;
+ let sample_duration_present = (flags & 0x000100) != 0;
+ let sample_size_present = (flags & 0x000200) != 0;
+ let sample_flags_present = (flags & 0x000400) != 0;
+ let sample_ct_off_present = (flags & 0x000800) != 0;
+
+ let sample_count = br.read_u32be()? as usize;
+
+ let mut hdr_size = 8;
+ let mut arr_size = 0;
+ if data_off_present {
+ hdr_size += 4;
+ }
+ if first_sample_flags {
+ hdr_size += 4;
+ }
+ if sample_duration_present {
+ arr_size += 4;
+ }
+ if sample_size_present {
+ arr_size += 4;
+ }
+ if sample_flags_present {
+ arr_size += 4;
+ }
+ if sample_ct_off_present {
+ arr_size += 4;
+ }
+ validate!(size == hdr_size + arr_size * (sample_count as u64));
+
+ let mut data_off = if data_off_present {
+ let off = br.read_u32be()? as i32;
+ let new_off = (track.moof_off as i64) + i64::from(off);
+ validate!(new_off > 0);
+ new_off as u64
+ } else {
+ track.moof_off
+ };
+ if first_sample_flags {
+ let _flags = br.read_u32be()?;
+ }
+
+ if sample_size_present {
+ track.chunk_sizes.reserve(sample_count);
+ track.chunk_offsets.reserve(sample_count);
+ }
+
+ if sample_ct_off_present {
+ if track.ctts_version != version {
+ track.ctts_version = version;
+ }
+ track.ctts_map.reserve(sample_count);
+ }
+
+ for _ in 0..sample_count {
+ if sample_duration_present {
+ let _duration = br.read_u32be()?;
+ }
+ if sample_size_present {
+ let ssize = br.read_u32be()?;
+ track.chunk_sizes.push(ssize);
+ track.chunk_offsets.push(data_off);
+ data_off += u64::from(ssize);
+ }
+ if sample_flags_present {
+ let _flags = br.read_u32be()?;
+ }
+ if sample_ct_off_present {
+ let samp_offset = br.read_u32be()?;
+ if version == 0 {
+ track.ctts_map.add(1, samp_offset / track.tb_div);
+ } else {
+ track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
+ }
+ }
+ }
+
+ Ok(size)
+}
+