self.frame.resize(frame_size + self.hdr_size, 0);
self.frame[0] = (num_slices - 1) as u8;
self.frame_pos = 0;
- self.add_slice(1, data);
+ self.add_slice(1, data).unwrap();
}
- fn add_slice(&mut self, slice_no: usize, data: &[u8]) {
+ fn add_slice(&mut self, slice_no: usize, data: &[u8]) -> DemuxerResult<()> {
+ validate!(self.hdr_size + self.frame_pos + data.len() <= self.frame.len());
self.write_slice_info(slice_no);
let dslice = &mut self.frame[self.hdr_size + self.frame_pos..][..data.len()];
dslice.copy_from_slice(data);
self.frame_pos += data.len();
+ Ok(())
}
fn write_slice_info(&mut self, slice_no: usize) {
let off = 1 + (slice_no - 1) * 8;
self.sub_packet = 0;
if self.deint == Deinterleaver::Sipro {
- sipro_restore(&mut self.buf, factor, fsize);
+ sipro_restore(&mut self.buf, factor, iinfo.frame_size as usize);
}
let mut frames_iter = self.buf.chunks(fsize);
struct RMDemuxCommon {}
impl RMDemuxCommon {
- fn parse_stream_info(str_data: &mut CommonStreamData, strmgr: &mut StreamManager, stream_no: u32, edata: &Vec<u8>) -> DemuxerResult<bool> {
+ fn parse_stream_info(str_data: &mut CommonStreamData, strmgr: &mut StreamManager, stream_no: u32, edata: &[u8], duration: u32) -> DemuxerResult<bool> {
let mut is_mlti = false;
- let mut mr = MemoryReader::new_read(edata.as_slice());
+ let mut mr = MemoryReader::new_read(edata);
let mut src = ByteReader::new(&mut mr);
let tag = src.read_u32be()?;
let tag2 = src.peek_u32be()?;
//println!("tag1 {:X} tag2 {:X}", tag, tag2);
if tag == mktag!('.', 'r', 'a', 0xFD) {
- Self::parse_audio_stream(strmgr, &mut str_data.streams, stream_no, &mut src, edata.as_slice())?;
+ Self::parse_audio_stream(strmgr, &mut str_data.streams, stream_no, &mut src, edata, duration)?;
} else if ((tag2 == mktag!('V', 'I', 'D', 'O')) || (tag2 == mktag!('I', 'M', 'A', 'G'))) && ((tag as usize) <= edata.len()) {
- Self::parse_video_stream(strmgr, &mut str_data.streams, stream_no, &mut src, edata.as_slice(), tag2)?;
+ Self::parse_video_stream(strmgr, &mut str_data.streams, stream_no, &mut src, edata, tag2, duration)?;
} else if tag == mktag!(b"LSD:") {
let extradata = Some(edata.to_owned());
let soniton = NASoniton::new(samp_size as u8, SONITON_FLAG_SIGNED);
let ahdr = NAAudioInfo::new(sample_rate, channels as u8, soniton, 1);
let nainfo = NACodecInfo::new("ralf", NACodecTypeInfo::Audio(ahdr), extradata);
- let res = strmgr.add_stream(NAStream::new(StreamType::Audio, stream_no as u32, nainfo, 1, sample_rate));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Audio, stream_no as u32, nainfo, 1, 1000, u64::from(duration)));
if res.is_none() { return Err(MemoryError); }
let astr = RMAudioStream::new(None);
str_data.streams.push(RMStreamType::Audio(astr));
let stream_no = str_data.mlti_mapper.get_substream_no();
//todo check that all substreams are of the same type");
if tag == mktag!('.', 'r', 'a', 0xFD) {
- Self::parse_audio_stream(strmgr, &mut str_data.streams, stream_no, &mut hsrc, hdrsrc)?;
+ Self::parse_audio_stream(strmgr, &mut str_data.streams, stream_no, &mut hsrc, hdrsrc, duration)?;
} else if (tag2 == mktag!('V', 'I', 'D', 'O')) && ((tag as usize) <= hdr_size) {
- Self::parse_video_stream(strmgr, &mut str_data.streams, stream_no, &mut hsrc, hdrsrc, tag2)?;
+ Self::parse_video_stream(strmgr, &mut str_data.streams, stream_no, &mut hsrc, hdrsrc, tag2, duration)?;
} else {
println!("unknown MLTI substream {:08X} / {:08X}", tag, tag2);
return Err(DemuxerError::InvalidData);
}
Ok(is_mlti)
}
- fn parse_audio_stream(strmgr: &mut StreamManager, streams: &mut Vec<RMStreamType>, stream_no: u32, src: &mut ByteReader, edata_: &[u8]) -> DemuxerResult<()> {
+ fn parse_audio_stream(strmgr: &mut StreamManager, streams: &mut Vec<RMStreamType>, stream_no: u32, src: &mut ByteReader, edata_: &[u8], duration: u32) -> DemuxerResult<()> {
let ver = src.read_u16be()?;
let ainfo = match ver {
3 => {
let eslice = &edata_[(src.tell() as usize)..];
Some(eslice.to_vec())
};
+ let duration = if duration == 0 { ainfo.get_duration(1000) } else { u64::from(duration) };
let nainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), extradata);
- let res = strmgr.add_stream(NAStream::new(StreamType::Audio, stream_no as u32, nainfo, 1, srate));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Audio, stream_no as u32, nainfo, 1, 1000, duration));
if res.is_none() { return Err(MemoryError); }
let astr = RMAudioStream::new(ainfo.ileave_info);
Ok(())
}
#[allow(unused_variables)]
- fn parse_video_stream(strmgr: &mut StreamManager, streams: &mut Vec<RMStreamType>, stream_no: u32, src: &mut ByteReader, edata_: &[u8], tag2: u32) -> DemuxerResult<()> {
+ fn parse_video_stream(strmgr: &mut StreamManager, streams: &mut Vec<RMStreamType>, stream_no: u32, src: &mut ByteReader, edata_: &[u8], tag2: u32, duration: u32) -> DemuxerResult<()> {
src.read_skip(4)?;
let fcc = src.read_u32be()?;
let width = src.read_u16be()? as usize;
let bpp = src.read_u16be()?;
let pad_w = src.read_u16be()?;
let pad_h = src.read_u16be()?;
- let fps;
+ let _fps;
if tag2 == mktag!('V', 'I', 'D', 'O') {
- fps = src.read_u32be()?;
+ _fps = src.read_u32be()?;
} else {
- fps = 0x10000;
+ _fps = 0x10000;
}
let extradata: Option<Vec<u8>>;
if src.left() > 0 {
let vhdr = NAVideoInfo::new(width, height, false, RGB24_FORMAT);
let vinfo = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), extradata);
- let res = strmgr.add_stream(NAStream::new(StreamType::Video, stream_no as u32, vinfo, 0x10000, fps));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Video, stream_no as u32, vinfo, 1, 1000, u64::from(duration)));
if res.is_none() { return Err(DemuxerError::MemoryError); }
let vstr = RMVideoStream::new();
if packet_num == 1 {
vstr.start_slice(num_pkts, frame_size as usize, slice_buf.as_slice());
} else {
- vstr.add_slice(packet_num as usize, slice_buf.as_slice());
+ vstr.add_slice(packet_num as usize, slice_buf.as_slice())?;
}
if (packet_num as usize) < num_pkts {
return Err(DemuxerError::TryAgain);
if packet_num == 1 && frame_size == tail_size {
vstr.start_slice(num_pkts, frame_size as usize, slice_buf.as_slice());
} else {
- vstr.add_slice(packet_num as usize, slice_buf.as_slice());
+ vstr.add_slice(packet_num as usize, slice_buf.as_slice())?;
}
while src.tell() < pos + (payload_size as u64) {
}
#[allow(unused_variables)]
- fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
+ fn seek(&mut self, time: NATimePoint, seek_idx: &SeekIndex) -> DemuxerResult<()> {
self.queued_pkts.clear();
let ret = seek_idx.find_pos(time);
if ret.is_none() {
}
Err(DemuxerError::SeekError)
}
+
+ fn get_duration(&self) -> u64 { 0 }
+}
+
+impl<'a> NAOptionHandler for RealMediaDemuxer<'a> {
+ fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
+ fn set_options(&mut self, _options: &[NAOption]) { }
+ fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
}
fn read_chunk(src: &mut ByteReader) -> DemuxerResult<(u32, u32, u16)> {
ileave_info: Option<InterleaveInfo>
}
+impl RealAudioInfo {
+ fn get_duration(&self, base: u32) -> u64 {
+ if self.bytes_per_minute != 0 {
+ u64::from(self.total_bytes) * 60 * u64::from(base) / u64::from(self.bytes_per_minute)
+ } else {
+ 0
+ }
+ }
+}
+
fn skip_ra_metadata(src: &mut ByteReader) -> DemuxerResult<()> {
let title_len = src.read_byte()? as usize;
src.read_skip(title_len)?;
Ok(last) => { if last { break; } },
Err(DemuxerError::IOError) => { break; },
Err(etype) => {
- if self.data_chunks.len() == 0 { // data is not found, report error
+ if self.data_chunks.is_empty() { // data is not found, report error
return Err(etype);
}
},
};
}
//println!("now @ {:X} / {}", self.src.tell(), self.data_pos);
- validate!(self.data_chunks.len() > 0);
+ validate!(!self.data_chunks.is_empty());
self.cur_data_chunk = 0;
let (pos, size, ver) = self.data_chunks[self.cur_data_chunk];
self.data_pos = pos;
let mut is_mlti = false;
if edata_size > 8 {
if let Some(edata_) = edata {
- is_mlti = RMDemuxCommon::parse_stream_info(&mut self.str_data, strmgr, stream_no, &edata_)?;
+ is_mlti = RMDemuxCommon::parse_stream_info(&mut self.str_data, strmgr, stream_no, &edata_, duration)?;
}
} else {
self.str_data.streams.push(RMStreamType::Unknown);
Ok(())
}
fn parse_index(&mut self, seek_idx: &mut SeekIndex, chunk_size: usize, ver: u16) -> DemuxerResult<()> {
- if ver != 0 { return Ok(()); }
+ if ver != 0 && ver != 2 { return Ok(()); }
let num_entries = self.src.read_u32be()? as usize;
let str_id = self.src.read_u16be()? as u32;
let _next_idx = self.src.read_u32be()?;
- validate!(chunk_size == num_entries * 14 + 10);
+ if ver == 2 {
+ self.src.read_u32be()?;
+ }
+ if ver == 0 {
+ validate!(chunk_size == num_entries * 14 + 10);
+ } else {
+ validate!(chunk_size == num_entries * 18 + 14);
+ }
if num_entries == 0 { return Ok(()); }
-
+
seek_idx.add_stream(str_id);
let idx = seek_idx.get_stream_index(str_id).unwrap();
for _ in 0..num_entries {
- let ver = self.src.read_u16be()? as u32;
- validate!(ver == 0);
+ let iver = self.src.read_u16be()?;
+ validate!(iver == ver);
let ts = self.src.read_u32be()? as u64;
+ if ver == 2 {
+ self.src.read_u32be()?;
+ }
let pos = self.src.read_u32be()? as u64;
let _pkt_no = self.src.read_u32be()?;
idx.add_entry(SeekEntry { time: ts, pts: 0, pos });
vec.push(c);
}
let str = String::from_utf8(vec);
- if str.is_ok() {
- Ok(str.unwrap())
+ if let Ok(res) = str {
+ Ok(res)
} else {
Ok(String::new())
}
Some(dta)
};
let nainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), extradata);
- let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, nainfo, 1, srate));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, nainfo, 1, srate, ainfo.get_duration(ainfo.sample_rate)));
if res.is_none() { return Err(MemoryError); }
let astr = RMAudioStream::new(ainfo.ileave_info);
}
#[allow(unused_variables)]
- fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
+ fn seek(&mut self, time: NATimePoint, seek_idx: &SeekIndex) -> DemuxerResult<()> {
Err(NotImplemented)
}
+
+ fn get_duration(&self) -> u64 { 0 }
+}
+
+impl<'a> NAOptionHandler for RealAudioDemuxer<'a> {
+ fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
+ fn set_options(&mut self, _options: &[NAOption]) { }
+ fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
}
impl<'a> RealAudioDemuxer<'a> {
cur_str_no += 1;
let mut parsed = false;
let mut real_stream_no = 0;
+ let mut duration = 0;
for _ in 0..num {
let rec = IVRRecord::read(src)?;
//println!(" strm property {}", rec);
if name == b"StreamNumber\0" {
real_stream_no = val;
}
+ if name == b"Duration\0" {
+ duration = 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)?;
+ let is_mlti = RMDemuxCommon::parse_stream_info(str_data, strmgr, stream_no, val, duration)?;
if !is_mlti {
str_data.str_ids.push(stream_no);
}
}
#[allow(unused_variables)]
- fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
+ fn seek(&mut self, time: NATimePoint, seek_idx: &SeekIndex) -> DemuxerResult<()> {
Err(NotImplemented)
}
+
+ fn get_duration(&self) -> u64 { 0 }
+}
+
+impl<'a> NAOptionHandler for RealIVRDemuxer<'a> {
+ fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
+ fn set_options(&mut self, _options: &[NAOption]) { }
+ fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
}
impl<'a> RealIVRDemuxer<'a> {
}
}
-static RM_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
+static RM_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
(b"RV10", "realvideo1"),
(b"RV20", "realvideo2"),
(b"RVTR", "realvideo2"),
(b"CLV1", "clearvideo_rm"),
];
-static RM_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
+static RM_AUDIO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
(b"lpcJ", "ra14.4"),
(b"28_8", "ra28.8"),
(b"cook", "cook"),
let mut br = ByteReader::new(&mut fr);
let mut dmx = RealMediaDemuxer::new(&mut br);
let mut sm = StreamManager::new();
- dmx.open(&mut sm).unwrap();
+ let mut si = SeekIndex::new();
+ dmx.open(&mut sm, &mut si).unwrap();
loop {
let pktres = dmx.get_frame(&mut sm);
let mut br = ByteReader::new(&mut fr);
let mut dmx = RealAudioDemuxer::new(&mut br);
let mut sm = StreamManager::new();
- dmx.open(&mut sm).unwrap();
+ let mut si = SeekIndex::new();
+ dmx.open(&mut sm, &mut si).unwrap();
loop {
let pktres = dmx.get_frame(&mut sm);
let mut br = ByteReader::new(&mut fr);
let mut dmx = RealIVRDemuxer::new(&mut br);
let mut sm = StreamManager::new();
- dmx.open(&mut sm).unwrap();
+ let mut si = SeekIndex::new();
+ dmx.open(&mut sm, &mut si).unwrap();
loop {
let pktres = dmx.get_frame(&mut sm);