X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=src%2Fdemuxers%2Frealmedia.rs;h=4fc3b81a6c43ec7d87bd2f848293c99fa708fe5b;hb=d4df9ee1ede2aafa2fee47f327683cbdf165bb6b;hp=d4cd30998dde00c1a460b18bbf1a9114bd531569;hpb=c19ce782830be53272ad3bade03d975fe377c8d0;p=nihav.git diff --git a/src/demuxers/realmedia.rs b/src/demuxers/realmedia.rs index d4cd309..4fc3b81 100644 --- a/src/demuxers/realmedia.rs +++ b/src/demuxers/realmedia.rs @@ -15,6 +15,20 @@ macro_rules! mktag { }); } +const RM_SIPRO_BLOCK_SIZES: [usize; 4] = [ 29, 19, 37, 20 ]; +const RM_SIPRO_SWAPS: [[u8; 2]; 38] = [ + [ 0, 63 ], [ 1, 22 ], [ 2, 44 ], [ 3, 90 ], + [ 5, 81 ], [ 7, 31 ], [ 8, 86 ], [ 9, 58 ], + [ 10, 36 ], [ 12, 68 ], [ 13, 39 ], [ 14, 73 ], + [ 15, 53 ], [ 16, 69 ], [ 17, 57 ], [ 19, 88 ], + [ 20, 34 ], [ 21, 71 ], [ 24, 46 ], [ 25, 94 ], + [ 26, 54 ], [ 28, 75 ], [ 29, 50 ], [ 32, 70 ], + [ 33, 92 ], [ 35, 74 ], [ 38, 85 ], [ 40, 56 ], + [ 42, 87 ], [ 43, 65 ], [ 45, 59 ], [ 48, 79 ], + [ 49, 93 ], [ 51, 89 ], [ 55, 95 ], [ 61, 76 ], + [ 67, 83 ], [ 77, 80 ] +]; + struct RMVideoStream { frame: Vec, hdr_size: usize, @@ -82,30 +96,219 @@ enum Deinterleaver { struct RMAudioStream { deint: Deinterleaver, iinfo: Option, + buf: Vec, + sub_packet: usize, } const RM_ILEAVE_INT0: u32 = mktag!(b"Int0"); const RM_ILEAVE_INT4: u32 = mktag!(b"Int4"); const RM_ILEAVE_GENR: u32 = mktag!(b"genr"); const RM_ILEAVE_SIPR: u32 = mktag!(b"sipr"); +const RM_ILEAVE_VBRF: u32 = mktag!(b"vbrf"); const RM_ILEAVE_VBRS: u32 = mktag!(b"vbrs"); impl RMAudioStream { fn new(iinfo: Option) -> Self { let deint; + let mut buf: Vec; if let Some(info) = iinfo { deint = match info.id { RM_ILEAVE_INT0 => Deinterleaver::None, RM_ILEAVE_INT4 => Deinterleaver::RA28_8, RM_ILEAVE_GENR => Deinterleaver::Generic, RM_ILEAVE_SIPR => Deinterleaver::Sipro, + RM_ILEAVE_VBRF => Deinterleaver::VBR, RM_ILEAVE_VBRS => Deinterleaver::VBR, _ => {println!("unknown deint {:X}", info.id); Deinterleaver::None }, }; + match deint { + Deinterleaver::None => { buf = Vec::new(); }, + Deinterleaver::RA28_8 | + Deinterleaver::Generic | + Deinterleaver::Sipro => { + let bsize = (info.frame_size as usize) * (info.factor as usize); + buf = Vec::with_capacity(bsize); + buf.resize(bsize, 0u8); + }, + Deinterleaver::VBR => { + buf = Vec::new(); + }, + }; } else { deint = Deinterleaver::None; + buf = Vec::new(); + } + RMAudioStream { deint: deint, iinfo: iinfo, buf: buf, sub_packet: 0 } + } + fn read_apackets(&mut self, queued_packets: &mut Vec, src: &mut ByteReader, stream: Rc, ts: u32, keyframe: bool, payload_size: usize) -> DemuxerResult { + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(ts as u64), None, None, tb_num, tb_den); + + if keyframe { + self.sub_packet = 0; + } + match self.deint { + Deinterleaver::None => { return src.read_packet(stream, ts, keyframe, payload_size); }, + Deinterleaver::RA28_8 => { + let iinfo = self.iinfo.unwrap(); + let factor = iinfo.factor as usize; + let halffact = factor >> 1; + let fsize = iinfo.frame_size as usize; + let bsize = iinfo.block_size as usize; + let ppos = self.sub_packet; + for sb in 0..halffact { + let mut dst = &mut self.buf[sb * 2 * fsize + ppos * bsize..][..bsize]; + src.read_buf(&mut dst)?; + } + self.sub_packet += 1; + if self.sub_packet == factor { + self.sub_packet = 0; + return Ok(NAPacket::new(stream, ts, true, self.buf.clone())); + } else { + return Err(DemuxerError::TryAgain); + } + }, + Deinterleaver::Generic => { + let iinfo = self.iinfo.unwrap(); + let factor = iinfo.factor as usize; + let fsize = iinfo.frame_size as usize; + let bsize = iinfo.block_size as usize; + let factor2 = fsize / bsize; + let ppos = self.sub_packet; + + for sb in 0..factor2 { + let sb_pos = factor * sb + ((factor + 1) >> 1) * (ppos & 1) + (ppos >> 1); + let mut dst = &mut self.buf[bsize * sb_pos..][..bsize]; + src.read_buf(&mut dst)?; + } + }, + Deinterleaver::Sipro => { + let iinfo = self.iinfo.unwrap(); + let fsize = iinfo.frame_size as usize; + let ppos = self.sub_packet; + + let mut dst = &mut self.buf[fsize * ppos..][..fsize]; + src.read_buf(&mut dst)?; + }, + Deinterleaver::VBR => { + validate!(payload_size >= 5); + let hdrsizesize = src.read_u16be()?; + let num_entries = (hdrsizesize / 16) as usize; + validate!(payload_size >= num_entries * 3 + 2); + let mut sizes: Vec = Vec::with_capacity(num_entries); + let mut tot_size = 0; + for _ in 0..num_entries { + let sz = src.read_u16be()? as usize; + tot_size += sz; + sizes.push(sz); + } + validate!(tot_size + num_entries * 2 + 2 == payload_size); + let pkt_ts = NATimeInfo::new(None, None, None, tb_num, tb_den); + let mut first = true; + for size in sizes.iter() { + let cur_ts = if first { ts } else { pkt_ts }; + first = false; + let pkt = src.read_packet(stream.clone(), cur_ts, true, *size)?; + queued_packets.push(pkt); + } + queued_packets.reverse(); + let pkt0 = queued_packets.pop().unwrap(); + return Ok(pkt0); + }, + }; + + let iinfo = self.iinfo.unwrap(); + let factor = iinfo.factor as usize; + let fsize = if iinfo.block_size != 0 { iinfo.block_size } else { iinfo.frame_size } as usize; + + self.sub_packet += 1; + if self.sub_packet < factor { + return Err(DemuxerError::TryAgain); + } + + self.sub_packet = 0; + + if self.deint == Deinterleaver::Sipro { + sipro_restore(&mut self.buf, factor, fsize); + } + + let mut frames_iter = self.buf.chunks(fsize); + let pkt0 = frames_iter.next().unwrap(); + + let pkt_ts = NATimeInfo::new(None, None, None, tb_num, tb_den); + for pkts in frames_iter { + let pkt = NAPacket::new(stream.clone(), pkt_ts, true, pkts.to_vec()); + queued_packets.push(pkt); + } + queued_packets.reverse(); + Ok(NAPacket::new(stream, ts, true, pkt0.to_vec())) + } +} + +fn sipro_restore(buf: &mut [u8], factor: usize, fsize: usize) { + let stride = factor * fsize * 2 / 96; + for i in 0..38 { + let mut sidx = (RM_SIPRO_SWAPS[i][0] as usize) * stride; + let mut didx = (RM_SIPRO_SWAPS[i][1] as usize) * stride; + for _ in 0..stride { + let in0 = buf[sidx >> 1]; + let in1 = buf[didx >> 1]; + let nib0 = (in0 >> ((sidx & 1) * 4)) & 0xF; + let nib1 = (in1 >> ((didx & 1) * 4)) & 0xF; + + buf[didx >> 1] = (nib0 << (4 * (didx & 1))) | (in1 & (0xF << (4 * (!didx & 1)))); + buf[sidx >> 1] = (nib1 << (4 * (sidx & 1))) | (in0 & (0xF << (4 * (!sidx & 1)))); + + sidx += 1; + didx += 1; } - RMAudioStream { deint: deint, iinfo: iinfo } + } +} + +struct SubstreamInfo { + id: u32, + map: Vec, + str_ids: Vec, +} + +struct MLTIMapper { + sub_info: Vec, +} + +impl MLTIMapper { + fn new() -> Self { + MLTIMapper { + sub_info: Vec::new(), + } + } + fn add_stream(&mut self, stream_no: u32) { + let ssinfo = SubstreamInfo { id: stream_no, map: Vec::new(), str_ids: Vec::new() }; + self.sub_info.push(ssinfo); + } + fn find_idx(&self, stream_no: u32) -> Option { + self.sub_info.iter().position(|x| x.id == stream_no) + } + fn add_map_rule(&mut self, stream_no: u32, map_ss: u16) { + let idx = self.find_idx(stream_no).unwrap(); + self.sub_info[idx].map.push(map_ss); + } + fn add_substream(&mut self, stream_no: u32, sstr_id: u32) { + let idx = self.find_idx(stream_no).unwrap(); + self.sub_info[idx].str_ids.push(sstr_id); + } + fn is_mlti_stream(&self, stream_no: u32) -> bool { + self.find_idx(stream_no).is_some() + } + fn find_substream(&self, stream_no: u32, grp: u16) -> Option { + if let Some(idx) = self.find_idx(stream_no) { + if (grp as usize) < self.sub_info[idx].map.len() { + let sub_id = self.sub_info[idx].map[grp as usize] as usize; + if sub_id < self.sub_info[idx].str_ids.len() { + return Some(self.sub_info[idx].str_ids[sub_id]); + } + } + } + None } } @@ -119,11 +322,16 @@ enum RMStreamType { struct RealMediaDemuxer<'a> { src: &'a mut ByteReader<'a>, data_pos: u64, + next_data: u64, + data_ver: u16, num_packets: u32, cur_packet: u32, + mlti_stream_no: u32, + mlti_mapper: MLTIMapper, + streams: Vec, - str_ids: Vec, + str_ids: Vec, queued_pkts: Vec, slice_buf: Vec, @@ -187,44 +395,67 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> { return Ok(pkt); } loop { - if self.cur_packet >= self.num_packets { return Err(DemuxerError::EOF); } + if self.cur_packet >= self.num_packets { + if (self.next_data != 0) && (self.next_data == self.src.tell()) { + let res = read_chunk(self.src); + if let Ok((id, size, ver)) = res { + self.data_pos = self.src.tell(); + self.data_ver = ver; + if self.parse_data_start().is_ok() { + continue; + } + } + } + return Err(DemuxerError::EOF); + } let pkt_start = self.src.tell(); - let ver = self.src.read_u16le()?; + let ver = self.src.read_u16be()?; validate!(ver <= 1); let len = self.src.read_u16be()? as usize; - let str_no = self.src.read_u16be()?; + let str_no = self.src.read_u16be()? as u32; let ts = self.src.read_u32be()?; - let _pkt_grp; + let pkt_grp; + let flags; if ver == 0 { - _pkt_grp = self.src.read_byte()?; + pkt_grp = self.src.read_byte()? as u16; + flags = self.src.read_byte()?; } else { - //asm_rule = self.src.read_u16le()?; + //asm_rule = self.src.read_u16be()?; + //asm_flags = self.src.read_byte()?; self.src.read_skip(2)?; - _pkt_grp = 0; + pkt_grp = 0; + self.src.read_skip(1)?; + flags = 0; } - let flags = self.src.read_byte()?; let hdr_size = self.src.tell() - pkt_start; //println!("packet @{:X} size {} for {} ts {} grp {} flags {:X}", pkt_start, len, str_no, ts, pkt_grp, flags); self.cur_packet += 1; let payload_size = len - (hdr_size as usize); - let sr = self.str_ids.iter().position(|x| *x == str_no); + let stream_id; + if !self.mlti_mapper.is_mlti_stream(str_no as u32) { + stream_id = str_no as u32; + } else { + stream_id = self.mlti_mapper.find_substream(str_no as u32, pkt_grp).unwrap(); + } + let sr = self.str_ids.iter().position(|x| *x == stream_id); if sr.is_none() { //println!("stream {} not found", str_no); self.src.read_skip(payload_size)?; return Err(DemuxerError::InvalidData); } let str_id = sr.unwrap(); - let streamres = strmgr.get_stream_by_id(str_no as u32); + + let streamres = strmgr.get_stream_by_id(stream_id); if streamres.is_none() { self.src.read_skip(payload_size)?; continue; } let stream = streamres.unwrap(); //println!(" stream {}", str_id); - if strmgr.is_ignored_id(str_no as u32) { + if strmgr.is_ignored_id(stream_id) { self.src.read_skip(payload_size)?; continue; } @@ -254,7 +485,7 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> { if packet_num == 1 { vstr.start_slice(num_pkts, frame_size as usize, self.slice_buf.as_slice()); } else { - vstr.add_slice(packet_num as usize, self.slice_buf.as_slice()); + vstr.add_slice(packet_num as usize, self.slice_buf.as_slice()); } if (packet_num as usize) < num_pkts { continue; @@ -268,7 +499,7 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> { 1 => { // whole frame let seq_no = self.src.read_byte()?; //println!(" mode 1 seq {}", seq_no); - read_video_buf(self.src, stream, ts, keyframe, payload_size - 1) + read_video_buf(self.src, stream, ts, keyframe, payload_size - 2) }, 2 => { // last partial frame let b1 = self.src.read_byte()?; @@ -281,7 +512,11 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> { //println!(" mode 2 pkt {}/{} tail {}/{} seq {}", packet_num, num_pkts, tail_size, frame_size, seq_no); self.slice_buf.resize(tail_size as usize, 0); self.src.read_buf(self.slice_buf.as_mut_slice())?; - vstr.add_slice(packet_num as usize, self.slice_buf.as_slice()); + if packet_num == 1 && frame_size == tail_size { + vstr.start_slice(num_pkts, frame_size as usize, self.slice_buf.as_slice()); + } else { + vstr.add_slice(packet_num as usize, self.slice_buf.as_slice()); + } while self.src.tell() < pos + (payload_size as u64) { let res = read_multiple_frame(self.src, stream.clone(), false, false); @@ -309,9 +544,11 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> { } }, RMStreamType::Audio(ref mut astr) => { - let (tb_num, tb_den) = stream.get_timebase(); - let ts = NATimeInfo::new(Some(ts as u64), None, None, tb_num, tb_den); - self.src.read_packet(stream, ts, keyframe, payload_size) + let ret = astr.read_apackets(&mut self.queued_pkts, &mut self.src, stream, ts, keyframe, payload_size); + if let Err(DemuxerError::TryAgain) = ret { + continue; + } + ret }, _ => { // self.src.read_skip(payload_size)?; @@ -332,9 +569,14 @@ fn read_chunk(src: &mut ByteReader) -> DemuxerResult<(u32, u32, u16)> { let id = src.read_u32be()?; if id == 0 { return Ok((0, 0, 0)); } let size = src.read_u32be()?; +if size == 0 { + let ver = src.read_u16be()?; + validate!(ver <= 2); + return Ok((id, 0x0FFFFFFF, ver)); +} validate!(size >= 10); let ver = src.read_u16be()?; - validate!(ver <= 1); + validate!(ver <= 2); Ok((id, size, ver)) } @@ -351,6 +593,7 @@ struct RealAudioInfo { fcc: u32, sample_rate: u32, sample_size: u16, + flavor: u16, channels: u16, channel_mask: u32, granularity: u32, @@ -393,7 +636,8 @@ fn parse_aformat3(src: &mut ByteReader) -> DemuxerResult { validate!(end - start <= (header_len as u64) + 2); Ok(RealAudioInfo { - fcc: fcc, sample_rate: 8000, sample_size: 16, channels: 1, channel_mask: 0, + fcc: fcc, flavor: flavor, + sample_rate: 8000, sample_size: 16, channels: 1, channel_mask: 0, granularity: granularity, bytes_per_minute: bytes_per_minute, total_bytes: total_bytes, edata_size: 0, ileave_info: None, @@ -409,7 +653,7 @@ fn parse_aformat4(src: &mut ByteReader) -> DemuxerResult { let data_size = src.read_u32be()?; let _ver4 = src.read_u16be()?; // should be 4 let header_size = src.read_u32be()?; - let _flavor = src.read_u16be()?; + let flavor = src.read_u16be()?; let granularity = src.read_u32be()?; let total_bytes = src.read_u32be()?; let bytes_per_minute = src.read_u32be()?; @@ -437,14 +681,16 @@ fn parse_aformat4(src: &mut ByteReader) -> DemuxerResult { let ileave_info = if is_interleaved != 0 { Some(InterleaveInfo { - id: interleaver_id, factor: ileave_factor, block_size: ileave_block_size, frame_size: 0, + id: interleaver_id, factor: ileave_factor, block_size: granularity as u16, + frame_size: ileave_block_size, }) } else { None }; Ok(RealAudioInfo { - fcc: fcc, sample_rate: sample_rate, sample_size: sample_size as u16, channels: channels, channel_mask: 0, + fcc: fcc, flavor: flavor, + sample_rate: sample_rate, sample_size: sample_size as u16, channels: channels, channel_mask: 0, granularity: granularity, bytes_per_minute: bytes_per_minute, total_bytes: total_bytes & 0xFFFFFF, edata_size: 0, ileave_info: ileave_info, @@ -456,18 +702,18 @@ fn parse_aformat5(src: &mut ByteReader) -> DemuxerResult { let start = src.tell(); src.read_skip(2)?; // zeroes let id = src.read_u32be()?; - validate!(id == mktag!(b".ra5")); + validate!((id == mktag!(b".ra5")) || (id == mktag!(b".ra4"))); let data_size = src.read_u32be()?; let _ver5 = src.read_u16be()?; // should be 5 let header_size = src.read_u32be()?; - let _flavor = src.read_u16be()?; + let flavor = src.read_u16be()?; let granularity = src.read_u32be()?; let total_bytes = src.read_u32be()?; let bytes_per_minute = src.read_u32be()?; let _bytes_per_minute2 = src.read_u32be()?; let ileave_factor = src.read_u16be()?; - let ileave_block_size = src.read_u16be()?; let frame_size = src.read_u16be()?; + let ileave_block_size = src.read_u16be()?; let user_data = src.read_u32be()?; let _sample_rate1 = src.read_u16be()?; let sample_rate = src.read_u32be()?; @@ -482,11 +728,14 @@ fn parse_aformat5(src: &mut ByteReader) -> DemuxerResult { if has_ileave_pattern != 0 { unimplemented!("ra5 interleave pattern"); } - let edata_size = src.read_u32be()?; - + let mut edata_size = src.read_u32be()?; let end = src.tell(); - validate!(end - start <= (header_size as u64) + 10); - src.read_skip((end as usize) - (header_size as usize))?; + if id == mktag!(b".ra5") { + validate!(end - start <= (header_size as u64) + 10); +// src.read_skip(((end - start) as usize) - (header_size as usize) - 10)?; + } else { + validate!(end - start <= (header_size as u64) + 15); + } let ileave_info = if is_interleaved != 0 { Some(InterleaveInfo { @@ -495,9 +744,15 @@ unimplemented!("ra5 interleave pattern"); } else { None }; + if (fcc == mktag!(b"raac")) || (fcc == mktag!(b"racp")) { + validate!(edata_size > 1); + edata_size -= 1; + src.read_skip(1)?; + } Ok(RealAudioInfo { - fcc: fcc, sample_rate: sample_rate, sample_size: sample_size as u16, channels: channels, channel_mask: 0, + fcc: fcc, flavor: flavor, + sample_rate: sample_rate, sample_size: sample_size as u16, channels: channels, channel_mask: 0, granularity: granularity, bytes_per_minute: bytes_per_minute, total_bytes: total_bytes & 0xFFFFFF, edata_size: edata_size, ileave_info: ileave_info, @@ -513,8 +768,12 @@ impl<'a> RealMediaDemuxer<'a> { RealMediaDemuxer { src: io, data_pos: 0, + next_data: 0, + data_ver: 0, num_packets: 0, cur_packet: 0, + mlti_stream_no: 0x10000, + mlti_mapper: MLTIMapper::new(), streams: Vec::new(), str_ids: Vec::new(), queued_pkts: Vec::new(), @@ -524,7 +783,7 @@ impl<'a> RealMediaDemuxer<'a> { #[allow(unused_variables)] fn read_header(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { let (id, size, ver) = read_chunk(self.src)?; - validate!(id == mktag!(b".RMF")); + validate!((id == mktag!(b".RMF")) || (id == mktag!(b".RMP"))); validate!(size >= RMVB_HDR_SIZE); let fver = self.src.read_u32be()?; validate!(fver <= 1); @@ -535,8 +794,9 @@ impl<'a> RealMediaDemuxer<'a> { } let (id, size, ver) = read_chunk(self.src)?; - validate!(size >= RMVB_PROP_SIZE); - validate!(ver == 0); + let prop_size = if ver == 0 { RMVB_PROP_SIZE } else { RMVB_PROP_SIZE + 4 }; + validate!(size >= prop_size); + validate!((ver == 0) || (ver == 2)); let maxbr = self.src.read_u32be()?; let avgbr = self.src.read_u32be()?; let maxps = self.src.read_u32be()?; @@ -544,12 +804,15 @@ impl<'a> RealMediaDemuxer<'a> { let num_pkt = self.src.read_u32be()? as usize; let duration = self.src.read_u32be()?; let preroll = self.src.read_u32be()?; + if ver == 2 { + self.src.read_skip(4)?; + } let idx_off = self.src.read_u32be()?; let data_off = self.src.read_u32be()?; let num_streams = self.src.read_u16be()? as usize; let flags = self.src.read_u16be()?; - if size > RMVB_PROP_SIZE { - self.src.read_skip((size - RMVB_PROP_SIZE) as usize)?; + if size > prop_size { + self.src.read_skip((size - prop_size) as usize)?; } for _ in 0..num_hdr { @@ -561,26 +824,38 @@ impl<'a> RealMediaDemuxer<'a> { match res { Ok(last) => { if last { break; } }, Err(DemuxerError::IOError) => { break; }, - Err(etype) => { return Err(etype); }, + Err(etype) => { + if self.data_pos == 0 { // data is not found, report error + return Err(etype); + } + }, }; } //println!("now @ {:X} / {}", self.src.tell(), self.data_pos); validate!(self.data_pos > 0); self.src.seek(SeekFrom::Start(self.data_pos))?; + self.parse_data_start()?; + Ok(()) + } + fn parse_data_start(&mut self) -> DemuxerResult<()> { let num_packets = self.src.read_u32be()?; + if self.data_ver == 2 { + self.src.read_skip(12)?; // zeroes? + } let next_data_hdr = self.src.read_u32be()?; - self.num_packets = num_packets; + self.num_packets = if num_packets > 0 { num_packets } else { 0xFFFFFF }; self.cur_packet = 0; + self.next_data = next_data_hdr as u64; Ok(()) } fn parse_chunk(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { let (id, size, ver) = read_chunk(self.src)?; let end_pos = self.src.tell() - 10 + (size as u64); - validate!(ver == 0); + validate!((ver == 0) || (ver == 2)); if id == mktag!(b"CONT") { self.parse_content_desc()?; } else if id == mktag!(b"MDPR") { self.parse_mdpr(strmgr)?; } - else if id == mktag!(b"DATA") { if self.data_pos == 0 { self.data_pos = self.src.tell(); } } + else if id == mktag!(b"DATA") { if self.data_pos == 0 { self.data_ver = ver; self.data_pos = self.src.tell(); } } else if id == mktag!(b"INDX") { /* do nothing for now */ } else if id == 0 { return Ok(true); } else { println!("unknown chunk type {:08X}", id); } @@ -605,7 +880,7 @@ impl<'a> RealMediaDemuxer<'a> { } #[allow(unused_variables)] fn parse_mdpr(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { - let stream_no = self.src.read_u16be()?; + let stream_no = self.src.read_u16be()? as u32; //todo check stream_no for duplicates let maxbr = self.src.read_u32be()?; let avgbr = self.src.read_u32be()?; @@ -627,7 +902,7 @@ impl<'a> RealMediaDemuxer<'a> { self.src.read_buf(&mut edvec)?; Some(edvec) }; - self.str_ids.push(stream_no); + let mut is_mlti = false; if edata_size > 8 { if let Some(edata_) = edata { let mut mr = MemoryReader::new_read(edata_.as_slice()); @@ -637,69 +912,9 @@ impl<'a> RealMediaDemuxer<'a> { let tag2 = src.peek_u32be()?; //println!("tag1 {:X} tag2 {:X}", tag, tag2); if tag == mktag!('.', 'r', 'a', 0xFD) { - let ver = src.read_u16be()?; - let ainfo = match ver { - 3 => { - parse_aformat3(&mut src)? - }, - 4 => { - parse_aformat4(&mut src)? - }, - 5 => { - parse_aformat5(&mut src)? - }, - _ => { - println!("unknown version {}", ver); - return Err(DemuxerError::InvalidData); - }, - }; -println!(" got ainfo {:?}", ainfo); - let cname = find_codec_name(RM_AUDIO_CODEC_REGISTER, ainfo.fcc); - let srate = ainfo.sample_rate; - let soniton = NASoniton::new(ainfo.sample_size as u8, SONITON_FLAG_SIGNED); - let ahdr = NAAudioInfo::new(srate, ainfo.channels as u8, soniton, 1); - let extradata = if ainfo.edata_size == 0 { - None - } else { - let eslice = &edata_[(src.tell() as usize)..]; - Some(eslice.to_vec()) - }; - 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)); - if res.is_none() { return Err(MemoryError); } - - let astr = RMAudioStream::new(ainfo.ileave_info); - self.streams.push(RMStreamType::Audio(astr)); + self.parse_audio_stream(strmgr, stream_no, &mut src, &edata_.as_slice())?; } else if ((tag2 == mktag!('V', 'I', 'D', 'O')) || (tag2 == mktag!('I', 'M', 'A', 'G'))) && ((tag as usize) <= edata_size) { - src.read_skip(4)?; - let fcc = src.read_u32be()?; - let width = src.read_u16be()? as usize; - let height = src.read_u16be()? as usize; - let bpp = src.read_u16be()?; - let pad_w = src.read_u16be()?; - let pad_h = src.read_u16be()?; - let fps; - if tag2 == mktag!('V', 'I', 'D', 'O') { - fps = src.read_u32be()?; - } else { - fps = 0x10000; - } - let extradata: Option>; - if src.left() > 0 { - let eslice = &edata_[(src.tell() as usize)..]; - extradata = Some(eslice.to_vec()); - } else { - extradata = None; - } - let cname = find_codec_name(RM_VIDEO_CODEC_REGISTER, fcc); - - 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)); - if res.is_none() { return Err(DemuxerError::MemoryError); } - - let vstr = RMVideoStream::new(); - self.streams.push(RMStreamType::Video(vstr)); + self.parse_video_stream(strmgr, stream_no, &mut src, &edata_.as_slice(), tag2)?; } else if tag == mktag!(b"LSD:") { let extradata = Some(edata_.to_vec()); @@ -716,6 +931,45 @@ println!(" got ainfo {:?}", ainfo); if res.is_none() { return Err(MemoryError); } let astr = RMAudioStream::new(None); self.streams.push(RMStreamType::Audio(astr)); + } else if tag == mktag!(b"MLTI") { + is_mlti = true; + let num_rules = src.read_u16be()? as usize; + let mut max_sub = 0; + self.mlti_mapper.add_stream(stream_no); + for i in 0..num_rules { + let substr = src.read_u16be()?; + max_sub = max_sub.max(substr); + self.mlti_mapper.add_map_rule(stream_no, substr); + } + let num_substreams = src.read_u16be()? as usize; + validate!(num_substreams > (max_sub as usize)); + for i in 0..num_substreams { + let hdr_size = src.read_u32be()? as usize; + validate!(hdr_size > 8); + let pos = src.tell() as usize; + src.read_skip(hdr_size)?; + self.mlti_mapper.add_substream(stream_no, self.mlti_stream_no); + { + let hdrsrc = &edata_[pos..][..hdr_size]; + let mut mr = MemoryReader::new_read(hdrsrc); + let mut hsrc = ByteReader::new(&mut mr); + + let tag = hsrc.read_u32be()?; + let tag2 = hsrc.peek_u32be()?; + let stream_no = self.mlti_stream_no; + self.mlti_stream_no += 1; +//todo check that all substreams are of the same type"); + if tag == mktag!('.', 'r', 'a', 0xFD) { + self.parse_audio_stream(strmgr, stream_no, &mut hsrc, hdrsrc)?; + } else if (tag2 == mktag!('V', 'I', 'D', 'O')) && ((tag as usize) <= hdr_size) { + self.parse_video_stream(strmgr, stream_no, &mut hsrc, hdrsrc, tag2)?; + } else { +println!("unknown MLTI substream {:08X} / {:08X}", tag, tag2); + return Err(DemuxerError::InvalidData); + } + self.str_ids.push(stream_no); + } + } } else { self.streams.push(RMStreamType::Logical); } @@ -723,7 +977,85 @@ println!(" got ainfo {:?}", ainfo); } else { self.streams.push(RMStreamType::Unknown); } + if !is_mlti { + self.str_ids.push(stream_no); + } + + Ok(()) + } + fn parse_audio_stream(&mut self, strmgr: &mut StreamManager, stream_no: u32, src: &mut ByteReader, edata_: &[u8]) -> DemuxerResult<()> { + let ver = src.read_u16be()?; + let ainfo = match ver { + 3 => { + parse_aformat3(src)? + }, + 4 => { + parse_aformat4(src)? + }, + 5 => { + parse_aformat5(src)? + }, + _ => { + println!("unknown version {}", ver); + return Err(DemuxerError::InvalidData); + }, + }; +println!(" got ainfo {:?}", ainfo); + let cname = find_codec_name(RM_AUDIO_CODEC_REGISTER, ainfo.fcc); + let blk_size = if ainfo.fcc != mktag!(b"sipr") { + ainfo.granularity as usize + } else { + validate!(ainfo.flavor <= 3); + RM_SIPRO_BLOCK_SIZES[ainfo.flavor as usize] + }; + let srate = ainfo.sample_rate; + let soniton = NASoniton::new(ainfo.sample_size as u8, SONITON_FLAG_SIGNED); + let ahdr = NAAudioInfo::new(srate, ainfo.channels as u8, soniton, blk_size); + let extradata = if ainfo.edata_size == 0 { + None + } else { + let eslice = &edata_[(src.tell() as usize)..]; + Some(eslice.to_vec()) + }; + 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)); + if res.is_none() { return Err(MemoryError); } + + let astr = RMAudioStream::new(ainfo.ileave_info); + self.streams.push(RMStreamType::Audio(astr)); + Ok(()) + } +#[allow(unused_variables)] + fn parse_video_stream(&mut self, strmgr: &mut StreamManager, stream_no: u32, src: &mut ByteReader, edata_: &[u8], tag2: u32) -> DemuxerResult<()> { + src.read_skip(4)?; + let fcc = src.read_u32be()?; + let width = src.read_u16be()? as usize; + let height = src.read_u16be()? as usize; + let bpp = src.read_u16be()?; + let pad_w = src.read_u16be()?; + let pad_h = src.read_u16be()?; + let fps; + if tag2 == mktag!('V', 'I', 'D', 'O') { + fps = src.read_u32be()?; + } else { + fps = 0x10000; + } + let extradata: Option>; + if src.left() > 0 { + let eslice = &edata_[(src.tell() as usize)..]; + extradata = Some(eslice.to_vec()); + } else { + extradata = None; + } + let cname = find_codec_name(RM_VIDEO_CODEC_REGISTER, fcc); + + 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)); + if res.is_none() { return Err(DemuxerError::MemoryError); } + let vstr = RMVideoStream::new(); + self.streams.push(RMStreamType::Video(vstr)); Ok(()) } /*#[allow(unused_variables)] @@ -777,43 +1109,125 @@ fn read_string_size(src: &mut ByteReader, size: usize) -> DemuxerResult fn parse_rm_stream(io: &mut ByteReader) -> DemuxerResult { let mimetype = read_string(io)?; let strname = read_string(io)?; - let strnum = io.read_u32le()?; - let maxbr = io.read_u32le()?; - let avgbr = io.read_u32le()?; - let maxsize = io.read_u32le()?; - let avgsize = io.read_u32le()?; - let duration = io.read_u32le()?; - let preroll = io.read_u32le()?; - let start = io.read_u32le()?; - let edatalen = io.read_u32le()? as usize; + let strnum = io.read_u32be()?; + let maxbr = io.read_u32be()?; + let avgbr = io.read_u32be()?; + let maxsize = io.read_u32be()?; + let avgsize = io.read_u32be()?; + let duration = io.read_u32be()?; + let preroll = io.read_u32be()?; + let start = io.read_u32be()?; + let edatalen = io.read_u32be()? as usize; let mut edata: Vec = Vec::with_capacity(edatalen); edata.resize(edatalen, 0); io.read_buf(&mut edata)?; - let numprops = io.read_u32le()? as usize; + let numprops = io.read_u32be()? as usize; //read properties unimplemented!(); } -#[allow(dead_code)] -#[allow(unused_variables)] -fn read_ra_vbr_stream(io: &mut ByteReader) -> DemuxerResult { - let hdrsizesize = io.read_u16le()?; - let num_entries = (hdrsizesize / 16) as usize; - let mut sizes: Vec = Vec::with_capacity(num_entries); - for _ in 0..num_entries { - let sz = io.read_u16le()? as usize; - sizes.push(sz); - } - for i in 0..num_entries { -//read packet of sizes[i] - } - unimplemented!(); +struct RealAudioDemuxer<'a> { + src: &'a mut ByteReader<'a>, + stream: Option, + data_start: u64, + data_end: u64, + blk_size: usize, + queued_pkts: Vec, } -//todo interleavers +impl<'a> DemuxCore<'a> for RealAudioDemuxer<'a> { + #[allow(unused_variables)] + fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { + let magic = self.src.read_u32be()?; + validate!(magic == mktag!(b".ra\xFD")); + let ver = self.src.read_u16be()?; + let ainfo = match ver { + 3 => { + parse_aformat3(&mut self.src)? + }, + 4 => { + parse_aformat4(&mut self.src)? + }, + 5 => { + parse_aformat5(&mut self.src)? + }, + _ => { + println!("unknown version {}", ver); + return Err(DemuxerError::InvalidData); + }, + }; +println!(" got ainfo {:?}", ainfo); + let cname = find_codec_name(RM_AUDIO_CODEC_REGISTER, ainfo.fcc); + let blk_size = if ainfo.fcc != mktag!(b"sipr") { + ainfo.granularity as usize + } else { + validate!(ainfo.flavor <= 3); + RM_SIPRO_BLOCK_SIZES[ainfo.flavor as usize] + }; + let srate = ainfo.sample_rate; + let soniton = NASoniton::new(ainfo.sample_size as u8, SONITON_FLAG_SIGNED); + let ahdr = NAAudioInfo::new(srate, ainfo.channels as u8, soniton, blk_size); + let extradata = if ainfo.edata_size == 0 { + None + } else { + let mut dta: Vec = Vec::with_capacity(ainfo.edata_size as usize); + dta.resize(ainfo.edata_size as usize, 0); + self.src.read_buf(dta.as_mut_slice())?; + Some(dta) + }; + let nainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), extradata); + let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, nainfo, 1, srate)); + if res.is_none() { return Err(MemoryError); } + + let astr = RMAudioStream::new(ainfo.ileave_info); + self.data_start = self.src.tell(); + self.data_end = if ainfo.total_bytes > 0 { self.src.tell() + (ainfo.total_bytes as u64) } else { 0 }; + self.blk_size = blk_size; + self.stream = Some(astr); + + Ok(()) + } + + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + if !self.queued_pkts.is_empty() { + let pkt = self.queued_pkts.pop().unwrap(); + return Ok(pkt); + } + if (self.data_end != 0) && (self.src.tell() >= self.data_end) { + return Err(DemuxerError::EOF); + } + let streamres = strmgr.get_stream_by_id(0); + let stream = streamres.unwrap(); + if let Some(ref mut astr) = self.stream { + loop { + let ret = astr.read_apackets(&mut self.queued_pkts, &mut self.src, stream.clone(), 0, false, self.blk_size); + if let Err(DemuxerError::TryAgain) = ret { + continue; + } + return ret; + } + } + Err(DemuxerError::NoSuchInput) + } -//todo opaque data + #[allow(unused_variables)] + fn seek(&mut self, time: u64) -> DemuxerResult<()> { + Err(NotImplemented) + } +} +impl<'a> RealAudioDemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + RealAudioDemuxer { + src: io, + data_start: 0, + data_end: 0, + blk_size: 0, + stream: None, + queued_pkts: Vec::new(), + } + } +} static RM_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[ (b"RV10", "realvideo1"), @@ -821,6 +1235,7 @@ static RM_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[ (b"RVTR", "realvideo2"), (b"RV30", "realvideo3"), (b"RV40", "realvideo4"), + (b"RV60", "realvideo6"), (b"CLV1", "clearvideo_rm"), ]; @@ -846,6 +1261,24 @@ impl DemuxerCreator for RealMediaDemuxerCreator { fn get_name(&self) -> &'static str { "realmedia" } } +pub struct RealAudioDemuxerCreator { } + +impl DemuxerCreator for RealAudioDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(RealAudioDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "realaudio" } +} + +/*pub struct RealIVRDemuxerCreator { } + +impl DemuxerCreator for RealIVRDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(RealIVRDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "real_ivr" } +}*/ + #[cfg(test)] mod test { use super::*; @@ -882,4 +1315,25 @@ mod test { } //panic!("the end"); } + #[test] + fn test_ra_demux() { + let mut file = +// File::open("assets/RV/welcome288.ra").unwrap(); + File::open("assets/RV/diemusik.ra").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = RealAudioDemuxer::new(&mut br); + let mut sm = StreamManager::new(); + dmx.open(&mut sm).unwrap(); + + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if e == DemuxerError::EOF { break; } + panic!("error"); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } }