}
}
+#[allow(dead_code)]
+struct BlockHeader {
+ full_ts: u64,
+ keyframe: bool,
+ invisible: bool,
+ lacing: u8,
+}
+
struct MatroskaDemuxer<'a> {
src: &'a mut dyn ByteIO,
segments: Vec<Segment>,
}
self.clu_ts = Some(ts);
},
- 0xA0 => return Err(DemuxerError::NotImplemented), // BlockGroup
+ 0xA0 => {
+ validate!(self.clu_ts.is_some());
+
+ let blk_end = end;
+ let mut has_block = false;
+ while self.src.tell() < blk_end {
+ let off = self.src.tell();
+ let id = self.src.read_ebml_id()?;
+ let size = self.src.read_vint()?;
+ let end = self.src.tell() + size;
+ if self.print_chunks {
+ print_entry(3, off, id, size);
+ }
+ validate!(end <= blk_end);
+ if id == 0xA1 {
+ validate!(!has_block);
+ has_block = true;
+
+ let trk_id = self.src.read_vint()?;
+ let timestamp = self.src.read_u16be()?;
+ let flags = self.src.read_byte()?;
+ let mut full_ts = self.clu_ts.unwrap() + u64::from(timestamp);
+ if (timestamp & 0x8000) != 0 {
+ full_ts = full_ts.wrapping_sub(0x10000);
+ }
+ validate!((flags & 0xF0) == 0);
+ let invisible = (flags & 0x08) != 0;
+ let lacing = (flags >> 1) & 3;
+ if self.print_chunks {
+ println!(" block - track {trk_id} ts {full_ts} ({timestamp}) {}{}", if invisible { " invisible" } else {""}, if lacing != 0 { " laced" } else {""});
+ }
+ if trk_id > U32_MAX { return Err(DemuxerError::NotImplemented); }
+ let trk_id = trk_id as u32;
+ validate!(self.src.tell() < end);
+ let tfind = self.segments[self.cur_seg].tracks.iter().find(|x| x.id == trk_id);
+ if let (Some(trk), Some(stream)) = (tfind, strmgr.get_stream_by_id(trk_id)) {
+ let blk_hdr = BlockHeader { full_ts, keyframe: false, lacing, invisible };
+ let first_pkt = Self::read_block(trk, stream, self.src, &blk_hdr, end, &mut self.queue)?;
+ self.queue.push_front(first_pkt);
+ }
+ }
+ validate!(self.src.tell() <= end);
+ self.src.seek(SeekFrom::Start(end))?;
+ }
+ if let Some(pkt) = self.queue.pop_front() {
+ return Ok(pkt);
+ }
+ },
0xA3 => {
validate!(self.clu_ts.is_some());
let trk_id = self.src.read_vint()?;
validate!(self.src.tell() < end);
let tfind = self.segments[self.cur_seg].tracks.iter().find(|x| x.id == trk_id);
if let (Some(trk), Some(stream)) = (tfind, strmgr.get_stream_by_id(trk_id)) {
- if lacing != 0 {
- validate!(trk.lacing);
- let nframes = usize::from(self.src.read_byte()?) + 1;
- validate!(nframes > 1 && self.src.tell() < end);
- let mut sizes = [0; 256];
- let mut tot_size = 0;
- match lacing {
- 1 => { // Xiph lacing
- for dsize in sizes[..nframes - 1].iter_mut() {
- let mut b = self.src.read_byte()?;
- let mut size = usize::from(b);
- while b == 255 {
- b = self.src.read_byte()?;
- size += usize::from(b);
- }
- *dsize = size;
- tot_size += size;
- }
- validate!(self.src.tell() + (tot_size as u64) < end);
- sizes[nframes - 1] = (end - self.src.tell()) as usize - tot_size;
- },
- 3 => { // EBML lacing
- let first_size = self.src.read_vint()?;
- let mut prev = first_size as i64;
- let fsize = first_size as usize;
- sizes[0] = fsize;
- tot_size += fsize;
- for dsize in sizes[..nframes - 1].iter_mut().skip(1) {
- let diff = self.src.read_vint_s()?;
- let size = prev + diff;
- validate!((1..=(U32_MAX as i64)).contains(&size));
- prev = size;
- let size = size as usize;
- *dsize = size;
- tot_size += size;
- }
- validate!(self.src.tell() + (tot_size as u64) < end);
- sizes[nframes - 1] = (end - self.src.tell()) as usize - tot_size;
- },
- 2 => { // fixed-size lacing
- let rest_size = (end - self.src.tell()) as usize;
- validate!((rest_size > 0) && (rest_size % nframes == 0));
- let pkt_size = rest_size / nframes;
- for el in sizes.iter_mut().take(nframes) {
- *el = pkt_size;
- }
- },
- _ => unreachable!()
- }
- let mut ts = NATimeInfo::new(Some(full_ts), None, None, stream.tb_num, stream.tb_den);
- let mut keyframe = keyframe;
- for &pkt_size in sizes[..nframes].iter() {
- let pkt = trk.read_packet(self.src, stream.clone(), ts, keyframe, pkt_size)?;
- keyframe = false;
- ts.pts = None;
- self.queue.push_back(pkt);
- }
- validate!(self.src.tell() == end);
- return Ok(self.queue.pop_front().unwrap());
- } else {
- let pkt_size = (end - self.src.tell()) as usize;
- let ts = NATimeInfo::new(Some(full_ts), None, None, stream.tb_num, stream.tb_den);
- return trk.read_packet(self.src, stream, ts, keyframe, pkt_size);
- }
+ let blk_hdr = BlockHeader { full_ts, keyframe, lacing, invisible };
+ return Self::read_block(trk, stream, self.src, &blk_hdr, end, &mut self.queue);
}
},
_ => {},
queue: VecDeque::new(),
}
}
+ fn read_block(trk: &Track, stream: NAStreamRef, br: &mut dyn ByteIO, blk_hdr: &BlockHeader, end: u64, queue: &mut VecDeque<NAPacket>) -> DemuxerResult<NAPacket> {
+ if blk_hdr.lacing != 0 {
+ validate!(trk.lacing);
+ let nframes = usize::from(br.read_byte()?) + 1;
+ validate!(nframes > 1 && br.tell() < end);
+ let mut sizes = [0; 256];
+ let mut tot_size = 0;
+ match blk_hdr.lacing {
+ 1 => { // Xiph lacing
+ for dsize in sizes[..nframes - 1].iter_mut() {
+ let mut b = br.read_byte()?;
+ let mut size = usize::from(b);
+ while b == 255 {
+ b = br.read_byte()?;
+ size += usize::from(b);
+ }
+ *dsize = size;
+ tot_size += size;
+ }
+ validate!(br.tell() + (tot_size as u64) < end);
+ sizes[nframes - 1] = (end - br.tell()) as usize - tot_size;
+ },
+ 3 => { // EBML lacing
+ let first_size = br.read_vint()?;
+ let mut prev = first_size as i64;
+ let fsize = first_size as usize;
+ sizes[0] = fsize;
+ tot_size += fsize;
+ for dsize in sizes[..nframes - 1].iter_mut().skip(1) {
+ let diff = br.read_vint_s()?;
+ let size = prev + diff;
+ validate!((1..=(U32_MAX as i64)).contains(&size));
+ prev = size;
+ let size = size as usize;
+ *dsize = size;
+ tot_size += size;
+ }
+ validate!(br.tell() + (tot_size as u64) < end);
+ sizes[nframes - 1] = (end - br.tell()) as usize - tot_size;
+ },
+ 2 => { // fixed-size lacing
+ let rest_size = (end - br.tell()) as usize;
+ validate!((rest_size > 0) && (rest_size % nframes == 0));
+ let pkt_size = rest_size / nframes;
+ for el in sizes.iter_mut().take(nframes) {
+ *el = pkt_size;
+ }
+ },
+ _ => unreachable!()
+ }
+ let mut ts = NATimeInfo::new(Some(blk_hdr.full_ts), None, None, stream.tb_num, stream.tb_den);
+ let mut keyframe = blk_hdr.keyframe;
+ for &pkt_size in sizes[..nframes].iter() {
+ let pkt = trk.read_packet(br, stream.clone(), ts, keyframe, pkt_size)?;
+ keyframe = false;
+ ts.pts = None;
+ queue.push_back(pkt);
+ }
+ validate!(br.tell() == end);
+ Ok(queue.pop_front().unwrap())
+ } else {
+ let pkt_size = (end - br.tell()) as usize;
+ let ts = NATimeInfo::new(Some(blk_hdr.full_ts), None, None, stream.tb_num, stream.tb_den);
+ trk.read_packet(br, stream, ts, blk_hdr.keyframe, pkt_size)
+ }
+ }
}
pub struct MatroskaDemuxerCreator { }