+enum IVRRecord {
+ Invalid(u8),
+ StreamProperties(usize),
+ Packet { ts: u32, str: u32, flags: u32, len: usize, checksum: u32 },
+ IntValue(Vec<u8>, u32),
+ BinaryData(Vec<u8>, Vec<u8>),
+ StringData(Vec<u8>, Vec<u8>),
+ HeaderEnd,
+ DataStart,
+ DataEnd,
+}
+
+impl IVRRecord {
+ fn read_string(src: &mut ByteReader) -> DemuxerResult<Vec<u8>> {
+ let len = src.read_u32be()? as usize;
+ let mut val = Vec::with_capacity(len);
+ val.resize(len, 0);
+ src.read_buf(val.as_mut_slice())?;
+ Ok(val)
+ }
+
+ fn read(src: &mut ByteReader) -> DemuxerResult<Self> {
+ let code = src.read_byte()?;
+ match code {
+ 1 => {
+ let val = src.read_u32be()? as usize;
+ Ok(IVRRecord::StreamProperties(val))
+ },
+ 2 => {
+ let ts = src.read_u32be()?;
+ let str = src.read_u16be()? as u32;
+ let flags = src.read_u32be()?;
+ let len = src.read_u32be()? as usize;
+ let chk = src.read_u32be()?;
+ Ok(IVRRecord::Packet { ts, str, flags, len, checksum: chk })
+ },
+ 3 => {
+ let name = Self::read_string(src)?;
+ let len = src.read_u32be()?;
+ validate!(len == 4);
+ let val = src.read_u32be()?;
+ Ok(IVRRecord::IntValue(name, val))
+ },
+ 4 => {
+ let name = Self::read_string(src)?;
+ let len = src.read_u32be()? as usize;
+ let mut val = Vec::with_capacity(len);
+ val.resize(len, 0);
+ src.read_buf(val.as_mut_slice())?;
+ Ok(IVRRecord::BinaryData(name, val))
+ },
+ 5 => {
+ let name = Self::read_string(src)?;
+ let val = Self::read_string(src)?;
+ Ok(IVRRecord::StringData(name, val))
+ },
+ 6 => Ok(IVRRecord::HeaderEnd),
+ 7 => {
+ src.read_skip(8)?; // always zero?
+ Ok(IVRRecord::DataEnd)
+ },
+ 8 => {
+ src.read_skip(8)?; // always zero?
+ Ok(IVRRecord::DataStart)
+ },
+ _ => Ok(IVRRecord::Invalid(code)),
+ }
+ }
+ fn is_data_start(&self) -> bool {
+ match *self {
+ IVRRecord::DataStart => true,
+ _ => false,
+ }
+ }
+}
+
+impl fmt::Display for IVRRecord {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ IVRRecord::Invalid(typ) => write!(f, "Invalid({:02X})", typ),
+ IVRRecord::StreamProperties(num) =>
+ write!(f, "({} stream properties)", num),
+ IVRRecord::Packet { ts, str, flags, len, checksum } =>
+ write!(f, "paket({}, {}, {:X}, {}, {})", ts, str, flags, len, checksum),
+ IVRRecord::IntValue(ref name, val) =>
+ write!(f, "({} = {})", String::from_utf8_lossy(name), val),
+ IVRRecord::BinaryData(ref name, ref val) =>
+ write!(f, "({} = {} bytes)", String::from_utf8_lossy(name), val.len()),
+ IVRRecord::StringData(ref name, ref val) =>
+ write!(f, "({} = {})", String::from_utf8_lossy(name), String::from_utf8_lossy(val)),
+ IVRRecord::HeaderEnd => write!(f, "header end"),
+ IVRRecord::DataEnd => write!(f, "data end"),
+ IVRRecord::DataStart => write!(f, "data start"),
+ }
+ }
+}
+
+struct RecordDemuxer {
+ start_pos: u64,
+ cur_pos: u64,
+ start_str: u32,
+ remap_ids: Vec<u32>,
+}
+
+impl RecordDemuxer {
+ fn new(pos: u64, start_str: u32) -> Self {
+ RecordDemuxer {
+ start_pos: pos,
+ cur_pos: pos,
+ start_str: start_str,
+ remap_ids: Vec::new(),
+ }
+ }
+ fn parse_header(&mut self, src: &mut ByteReader, strmgr: &mut StreamManager, str_data: &mut CommonStreamData) -> DemuxerResult<()> {
+ src.seek(SeekFrom::Start(self.cur_pos))?;
+ let magic = src.read_u32be()?;
+ validate!(magic == mktag!(b".REC"));
+ let _smth = src.read_byte()?;
+ let num_entries = src.read_u32be()? as usize;
+ for _ in 0..num_entries {
+ let _rec = IVRRecord::read(src)?;
+//println!(" header rec {}", _rec);
+ }
+ let mut has_seek_table = false;
+ let mut cur_str_no = 0;
+ loop {
+ let rec = IVRRecord::read(src)?;
+ match rec {
+ IVRRecord::HeaderEnd => { break; },
+ IVRRecord::StreamProperties(num) => {
+ let stream_no = cur_str_no + self.start_str;
+ cur_str_no += 1;
+ let mut parsed = false;
+ let mut real_stream_no = 0;
+ for _ in 0..num {
+ let rec = IVRRecord::read(src)?;
+//println!(" strm property {}", rec);
+ match rec {
+ IVRRecord::IntValue(ref name, val) => {
+ if name == b"StreamNumber\0" {
+ real_stream_no = val;
+ }
+ },
+ IVRRecord::BinaryData(ref name, ref val) => {
+ if name == b"OpaqueData\0" {
+ validate!(!parsed);
+ let is_mlti = RMDemuxCommon::parse_stream_info(str_data, strmgr, stream_no, val)?;
+ if !is_mlti {
+ str_data.str_ids.push(stream_no);
+ }
+ parsed = true;
+ }
+ },
+ IVRRecord::StringData(ref name, ref val) => {
+ if (name == b"SeekType\0") && (val != b"None\0") {
+ has_seek_table = true;
+ }
+ },
+ _ => { return Err(DemuxerError::InvalidData); }
+ };
+ }
+ if !parsed {
+ str_data.streams.push(RMStreamType::Unknown);
+ str_data.str_ids.push(stream_no);
+ }
+ self.remap_ids.push(real_stream_no);
+ },
+ _ => {println!(" unexpected {}", rec); return Err(DemuxerError::InvalidData); }
+ };
+ }
+ println!(" now @ {:X}", src.tell());
+ let off0 = src.read_u32be()? as u64;
+ let _off1 = src.read_u32be()?;
+ let _off2 = src.read_u32be()?;
+ validate!(off0 + self.start_pos == src.tell());
+ println!(" has seek tab: {}", has_seek_table);
+ if has_seek_table {
+ src.read_skip(4)?;
+ let data_off = src.read_u32be()? as u64;
+ println!(" new off {:X}", data_off);
+ let pos = src.tell();
+ validate!(data_off + self.start_pos > pos);
+ src.read_skip((data_off + self.start_pos - pos) as usize)?;
+ let rec = IVRRecord::read(src)?;
+ validate!(rec.is_data_start());
+ } else {
+ let ntype = src.peek_byte()?;
+ validate!((ntype == 2) || (ntype == 7)); // packet or data end, no start
+ }
+
+ self.cur_pos = src.tell();
+
+ Ok(())
+ }
+ fn get_packet(&mut self, src: &mut ByteReader, str_data: &mut CommonStreamData, strmgr: &StreamManager, queued_pkts: &mut Vec<NAPacket>, slice_buf: &mut Vec<u8>) -> DemuxerResult<NAPacket> {
+ src.seek(SeekFrom::Start(self.cur_pos))?;
+ loop {
+ let rec = IVRRecord::read(src)?;
+ match rec {
+ IVRRecord::Packet { ts, str, flags: _, len, checksum: _ } => {
+ let payload_size = len;
+ let sr = self.remap_ids.iter().position(|x| *x == str);
+ validate!(sr.is_some());
+ let str_no = self.start_str + (sr.unwrap() as u32);
+ let stream_id = str_data.get_stream_id(str_no as u32, 0/*pkt_grp*/);
+ let sr = str_data.find_stream(stream_id);
+ if sr.is_none() {
+ src.read_skip(payload_size)?;
+ return Err(DemuxerError::InvalidData);
+ }
+ let str_id = sr.unwrap();
+
+ let streamres = strmgr.get_stream_by_id(stream_id);
+ if streamres.is_none() {
+ src.read_skip(payload_size)?;
+ continue;
+ }
+ let stream = streamres.unwrap();
+ if strmgr.is_ignored_id(stream_id) {
+ src.read_skip(payload_size)?;
+ continue;
+ }
+ let keyframe = false;
+ let ret = RMDemuxCommon::parse_packet_payload(src, &mut str_data.streams[str_id], stream, slice_buf, queued_pkts, keyframe, ts, payload_size);
+ if let Err(DemuxerError::TryAgain) = ret {
+ continue;
+ } else {
+ self.cur_pos = src.tell();
+ return ret;
+ }
+ },
+ IVRRecord::DataEnd => return Err(DemuxerError::EOF),
+ _ => return Err(DemuxerError::InvalidData),
+ }
+ }
+ }
+}
+
+struct RealIVRDemuxer<'a> {
+ src: &'a mut ByteReader<'a>,
+ recs: Vec<RecordDemuxer>,
+ cur_rec: usize,
+ queued_pkts: Vec<NAPacket>,
+ slice_buf: Vec<u8>,
+ str_data: CommonStreamData,
+}
+
+impl<'a> DemuxCore<'a> for RealIVRDemuxer<'a> {
+ #[allow(unused_variables)]
+ fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+ let magic = self.src.peek_u32be()?;
+ if magic == mktag!(b".REC") {
+ let mut rec = RecordDemuxer::new(0, 0);
+ rec.parse_header(&mut self.src, strmgr, &mut self.str_data)?;
+ self.recs.push(rec);
+ } else if magic == mktag!(b".R1M") {
+println!("R1M kind");
+ self.src.read_skip(4)?; // magic
+ self.src.read_skip(3)?; // always 0, 1, 1 ?
+ let _name = IVRRecord::read_string(&mut self.src)?;
+ self.src.read_skip(1)?; // always 0?
+ let len1 = self.src.read_u32be()? as u64;
+ let off1 = self.src.read_u64be()?;
+ let cpos = self.src.tell();
+ validate!(off1 == len1 + cpos - 8);
+ self.src.read_skip((off1 - cpos) as usize)?;
+ loop {
+ let typ = self.src.read_byte()?;
+ println!(" at {:X} type {:02X}", self.src.tell(), typ);
+ match typ {
+ 1 => {
+ let len = self.src.read_u32be()?;
+ self.src.read_skip(len as usize)?;
+ },
+ 2 => {
+ let len = self.src.read_u32be()? as u64;
+ let pos = self.src.tell();
+ let num_streams = self.str_data.streams.len() as u32;
+ let mut rec = RecordDemuxer::new(pos + 12, num_streams);
+ rec.parse_header(&mut self.src, strmgr, &mut self.str_data)?;
+ self.recs.push(rec);
+ self.src.seek(SeekFrom::Start(pos + len))?;
+ },
+ b'R' => {
+ let mut buf: [u8; 2] = [0; 2];
+ self.src.peek_buf(&mut buf)?;
+ if (buf[0] == b'J') && (buf[1] == b'M') { // RJMx markers at the end of file
+ break;
+ } else {
+ return Err(DemuxerError::InvalidData);
+ }
+ },
+ _ => { return Err(DemuxerError::InvalidData); },
+ };
+ }
+ } else {
+ return Err(DemuxerError::InvalidData);
+ }
+
+ Ok(())
+ }
+
+ fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
+ if !self.queued_pkts.is_empty() {
+ let pkt = self.queued_pkts.pop().unwrap();
+ return Ok(pkt);
+ }
+ loop {
+ if self.cur_rec >= self.recs.len() { return Err(DemuxerError::EOF); }
+ let res = self.recs[self.cur_rec].get_packet(&mut self.src, &mut self.str_data, strmgr, &mut self.queued_pkts, &mut self.slice_buf);
+ if let Err(DemuxerError::EOF) = res {
+ self.cur_rec += 1;
+ } else {
+ return res;
+ }
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+ Err(NotImplemented)
+ }
+}
+
+impl<'a> RealIVRDemuxer<'a> {
+ fn new(io: &'a mut ByteReader<'a>) -> Self {
+ RealIVRDemuxer {
+ src: io,
+ recs: Vec::new(),
+ cur_rec: 0,
+ queued_pkts: Vec::new(),
+ slice_buf: Vec::new(),
+ str_data: CommonStreamData::new(),
+ }
+ }
+}
+