tracks: Vec<(u32, u64, u64)>,
}
+#[allow(dead_code)]
+enum TrackCompression {
+ None,
+ Deflate,
+ BZ2,
+ LZO,
+ Strip(Vec<u8>),
+ Unknown(u8),
+}
+
#[allow(dead_code)]
struct Track {
id: u32,
codec: String,
lacing: bool,
+ compr: TrackCompression,
+}
+
+impl Track {
+ fn read_packet(&self, br: &mut dyn ByteIO, stream: NAStreamRef, ts: NATimeInfo, keyframe: bool, pkt_size: usize) -> DemuxerResult<NAPacket> {
+ let buf = match self.compr {
+ TrackCompression::None => return br.read_packet(stream, ts, keyframe, pkt_size),
+ TrackCompression::Strip(ref hdr) => {
+ let mut buf = vec![0; hdr.len() + pkt_size];
+ let (header, body) = buf.split_at_mut(hdr.len());
+ header.copy_from_slice(hdr);
+ br.read_buf(body)?;
+ buf
+ },
+ _ => return Err(DemuxerError::NotImplemented),
+ };
+ Ok(NAPacket::new(stream, ts, keyframe, buf))
+ }
}
struct Segment {
impl std::convert::From<TrackInfo> for Track {
fn from(trk: TrackInfo) -> Self {
+ let compr = match trk.calgo {
+ None => TrackCompression::None,
+ Some(0) => TrackCompression::Deflate,
+ Some(1) => TrackCompression::BZ2,
+ Some(2) => TrackCompression::LZO,
+ Some(3) => TrackCompression::Strip(trk.csettings.unwrap()),
+ Some(id) => TrackCompression::Unknown(id),
+ };
Self {
id: trk.number.unwrap() as u32,
lacing: trk.lacing.unwrap_or(true),
codec: trk.codec_id.unwrap(),
+ compr,
}
}
}
if trk_id > U32_MAX { return Err(DemuxerError::NotImplemented); }
let trk_id = trk_id as u32;
validate!(self.src.tell() < end);
- if let Some(stream) = strmgr.get_stream_by_id(trk_id) {
+ 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 {
- if let Some(trk) = self.segments[self.cur_seg].tracks.iter().find(|x| x.id == trk_id) {
- validate!(trk.lacing);
- }
+ 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 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 = self.src.read_packet(stream.clone(), ts, keyframe, pkt_size)?;
+ let pkt = trk.read_packet(self.src, stream.clone(), ts, keyframe, pkt_size)?;
keyframe = false;
ts.pts = None;
self.queue.push_back(pkt);
} 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 self.src.read_packet(stream, ts, keyframe, pkt_size);
+ return trk.read_packet(self.src, stream, ts, keyframe, pkt_size);
}
}
},
pub real_rate: Option<f64>,
pub channels: Option<u8>,
pub adepth: Option<u8>,
+ pub ctype: Option<u8>,
+ pub calgo: Option<u8>,
+ pub csettings: Option<Vec<u8>>,
}
static PARSE_TRACK: &[ParseEntry<TrackInfo>] = &[
ParseEntry { id: 0x63A2, parse: TrackInfo::parse_edata },
ParseEntry { id: 0xE0, parse: TrackInfo::parse_video_elem },
ParseEntry { id: 0xE1, parse: TrackInfo::parse_audio_elem },
+ ParseEntry { id: 0x6D80, parse: TrackInfo::parse_content_encodings },
];
static PARSE_TRACK_VIDEO_ELEM: &[ParseEntry<TrackInfo>] = &[
ParseEntry { id: 0x6264, parse: TrackInfo::parse_adepth },
];
+static PARSE_TRACK_CONTENT_ENCODING: &[ParseEntry<TrackInfo>] = &[
+ ParseEntry { id: 0x5033, parse: TrackInfo::parse_content_enc_type },
+ ParseEntry { id: 0x5034, parse: TrackInfo::parse_content_compr },
+];
+
+static PARSE_TRACK_CONTENT_ENC_COMPR: &[ParseEntry<TrackInfo>] = &[
+ ParseEntry { id: 0x4254, parse: TrackInfo::parse_comp_algo },
+ ParseEntry { id: 0x4255, parse: TrackInfo::parse_comp_settings },
+];
+
impl TrackInfo {
pub fn validate(&self) -> DemuxerResult<()> {
validate!(self.number.is_some());
},
_ => {},
}
+ if let Some(calgo) = self.calgo {
+ validate!(self.ctype.unwrap_or(0) == 0);
+ if calgo == 3 {
+ validate!(self.csettings.is_some());
+ }
+ }
Ok(())
}
parse_entries(self, if self.debug { Some(3) } else { None }, br, PARSE_TRACK_AUDIO_ELEM, cur_end, ParseMode::Ignore)?;
Ok(())
}
+ fn parse_content_encodings(&mut self, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<()> {
+ let end = br.tell() + size;
+ while br.tell() + 2 <= end {
+ let off = br.tell();
+ let id = br.read_ebml_id()?;
+ let size = br.read_vint()?;
+ let cur_end = br.tell() + size;
+ if self.debug {
+ print_entry(3, off, id, size);
+ }
+ validate!(cur_end <= end);
+ if id == 0x6240 {
+ if self.debug {
+ println!(" content encoding");
+ }
+ parse_entries(self, if self.debug { Some(4) } else { None }, br, PARSE_TRACK_CONTENT_ENCODING, cur_end, ParseMode::Ignore)?;
+ }
+ validate!(br.tell() <= cur_end);
+ br.seek(SeekFrom::Start(cur_end))?;
+ }
+ Ok(())
+ }
+ read_field!(byte; parse_content_enc_type, ctype);
+ fn parse_content_compr(&mut self, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<()> {
+ let cur_end = br.tell() + size;
+ parse_entries(self, if self.debug { Some(5) } else { None }, br, PARSE_TRACK_CONTENT_ENC_COMPR, cur_end, ParseMode::Ignore)?;
+ Ok(())
+ }
+ read_field!(byte; parse_comp_algo, calgo);
+ fn parse_comp_settings(&mut self, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<()> {
+ validate!(self.csettings.is_none() && (1..=U32_MAX).contains(&size));
+ let mut buf = vec![0; size as usize];
+ br.read_buf(&mut buf)?;
+ self.csettings = Some(buf);
+ Ok(())
+ }
}