11 intra_mcbpc_cb: Codebook<u8>,
12 inter_mcbpc_cb: Codebook<u8>,
13 cbpy_cb: Codebook<u8>,
14 rl_cb: Codebook<H263RLSym>,
15 aic_rl_cb: Codebook<H263RLSym>,
27 struct RealVideo20Decoder {
28 info: Rc<NACodecInfo>,
37 struct RealVideo20BR<'a> {
57 struct RV20SliceInfo {
68 fn new(ftype: Type, qscale: u8, mb_x: usize, mb_y: usize, mb_pos: usize, w: usize, h: usize) -> Self {
69 RV20SliceInfo { ftype: ftype, qscale: qscale, mb_x: mb_x, mb_y: mb_y, mb_pos: mb_pos, w: w, h: h }
73 impl<'a> RealVideo20BR<'a> {
74 fn new(src: &'a [u8], tables: &'a Tables, width: usize, height: usize, minor_ver: u8, rpr: RPRInfo) -> Self {
75 let nslices = (src[0] as usize) + 1;
76 let mut slice_offs = Vec::with_capacity(nslices);
78 let offs = &src[1..][..nslices * 8];
79 let mut br = BitReader::new(offs, offs.len(), BitReaderMode::BE);
82 let off = br.read(32).unwrap();
86 let soff = nslices * 8 + 1;
87 let mb_w = (width + 15) >> 4;
88 let mb_h = (height + 15) >> 4;
89 let max_pos = mb_w * mb_h - 1;
91 for i in 0..H263_MBB.len() {
92 if max_pos <= H263_MBB[i].blocks {
93 mbpb = H263_MBB[i].bits;
98 br: BitReader::new(&src[soff..], src.len() - soff, BitReaderMode::BE),
102 slice_off: slice_offs,
112 minor_ver: minor_ver,
118 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
119 let mut br = &mut self.br;
121 if !self.is_intra && intra {
122 let mut dc = br.read(8).unwrap() as i16;
123 if dc == 255 { dc = 128; }
127 if !coded { return Ok(()); }
129 let rl_cb = if self.is_intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
130 let q_add = if quant == 0 { 0i16 } else { ((quant - 1) | 1) as i16 };
131 let q = (quant * 2) as i16;
133 let code = br.read_cb(rl_cb).unwrap();
137 if !code.is_escape() {
138 run = code.get_run();
139 level = code.get_level();
140 last = code.is_last();
141 if br.read_bool().unwrap() { level = -level; }
142 level = (level * q) + q_add;
144 last = br.read_bool().unwrap();
145 run = br.read(6).unwrap() as u8;
146 level = br.read_s(8).unwrap() as i16;
148 let low = br.read(5).unwrap() as i16;
149 let top = br.read_s(6).unwrap() as i16;
150 level = (top << 5) | low;
152 level = (level * q) + q_add;
153 if level < -2048 { level = -2048; }
154 if level > 2047 { level = 2047; }
158 let oidx = H263_ZIGZAG[idx as usize];
167 fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
168 let code = br.read_cb(mv_cb).unwrap() as i16;
169 if code == 0 { return Ok(0) }
170 if !br.read_bool().unwrap() {
177 fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
178 let xval = decode_mv_component(br, mv_cb).unwrap();
179 let yval = decode_mv_component(br, mv_cb).unwrap();
180 //println!(" MV {},{} @ {}", xval, yval, br.tell());
181 Ok(MV::new(xval, yval))
184 impl<'a> BlockDecoder for RealVideo20BR<'a> {
186 #[allow(unused_variables)]
187 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
189 println!("decoding picture header size {}", if self.num_slices > 1 { self.slice_off[1] } else { ((self.br.tell() as u32) + (self.br.left() as u32))/8 });
192 self.mb_count = self.mb_w * self.mb_h;
193 let shdr = self.read_slice_header().unwrap();
194 println!("slice ends @ {}\n", self.br.tell());
196 validate!((shdr.mb_x == 0) && (shdr.mb_y == 0));
198 if self.slice_no < self.num_slices {
199 let pos = self.br.tell();
200 let shdr2 = self.read_slice_header().unwrap();
201 self.br.seek(pos as u32)?;
202 mb_count = shdr2.mb_pos - shdr.mb_pos;
204 mb_count = self.mb_w * self.mb_h;
207 self.mb_x = shdr.mb_x;
208 self.mb_y = shdr.mb_y;
209 self.mb_count = mb_count;
210 self.mb_end = shdr.mb_pos + mb_count;
211 self.is_intra = shdr.ftype == Type::I;
213 let picinfo = PicInfo::new(shdr.w, shdr.h, shdr.ftype, shdr.qscale, false, MVMode::Old, 0, None, true);
217 #[allow(unused_variables)]
218 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
219 //println!("read slice {} header", self.slice_no);
220 let shdr = self.read_slice_header().unwrap();
223 if self.slice_no < self.num_slices {
224 let shdr2 = self.read_slice_header().unwrap();
225 mb_count = shdr2.mb_pos - shdr.mb_pos;
227 mb_count = self.mb_w * self.mb_h - shdr.mb_pos;
229 let ret = Slice::new(shdr.mb_x, shdr.mb_y, shdr.qscale);
230 self.mb_x = shdr.mb_x;
231 self.mb_y = shdr.mb_y;
232 self.mb_count = mb_count;
233 self.mb_end = shdr.mb_pos + mb_count;
238 fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
239 let mut br = &mut self.br;
240 let mut q = slice.get_quant();
241 match info.get_mode() {
243 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap();
244 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap(); }
246 let acpred = br.read_bool()?;
247 println!(" acp {} @ {}", acpred, br.tell());
249 br.skip(1)?;//pred direction
252 let cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
253 let cbp = (cbpy << 2) | (cbpc & 3);
254 let dquant = (cbpc & 4) != 0;
256 let idx = br.read(2).unwrap() as usize;
257 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
259 println!(" MB {},{} CBP {:X} @ {}", self.mb_x, self.mb_y, cbp, br.tell());
261 if self.mb_x == self.mb_w {
265 Ok(BlockInfo::new(Type::I, cbp, q))
268 if br.read_bool().unwrap() {
270 if self.mb_x == self.mb_w {
274 return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant()));
276 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb).unwrap();
277 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb).unwrap(); }
278 let is_intra = (cbpc & 0x04) != 0;
279 let dquant = (cbpc & 0x08) != 0;
280 let is_4x4 = (cbpc & 0x10) != 0;
282 let cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
283 let cbp = (cbpy << 2) | (cbpc & 3);
285 let idx = br.read(2).unwrap() as usize;
286 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
288 let binfo = BlockInfo::new(Type::I, cbp, q);
290 if self.mb_x == self.mb_w {
297 let mut cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
298 // if /* !aiv && */(cbpc & 3) != 3 {
301 let cbp = (cbpy << 2) | (cbpc & 3);
303 let idx = br.read(2).unwrap() as usize;
304 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
306 println!(" MB {}.{} cbp = {:X}", self.mb_x, self.mb_y, cbp);
307 let mut binfo = BlockInfo::new(Type::P, cbp, q);
309 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb).unwrap()];
312 let mvec: [MV; 4] = [
313 decode_mv(br, &self.tables.mv_cb).unwrap(),
314 decode_mv(br, &self.tables.mv_cb).unwrap(),
315 decode_mv(br, &self.tables.mv_cb).unwrap(),
316 decode_mv(br, &self.tables.mv_cb).unwrap()
321 if self.mb_x == self.mb_w {
327 _ => { println!("wrong info mode"); Err(DecoderError::InvalidData) },
331 #[allow(unused_variables)]
332 fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
333 self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
336 #[allow(unused_variables)]
337 fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
338 self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
341 fn is_slice_end(&mut self) -> bool { self.mb_x + self.mb_y * self.mb_w >= self.mb_end }
343 fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
344 let stride = buf.get_stride(0);
345 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
346 for mb_x in 0..mb_w {
348 let coded0 = cbpi.is_coded(mb_x, 0);
349 let coded1 = cbpi.is_coded(mb_x, 1);
350 let q = cbpi.get_q(mb_w + mb_x);
352 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
353 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
355 let coff = off + 8 * stride;
356 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
357 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
360 let mut leftt = false;
361 let mut leftc = false;
362 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
363 for mb_x in 0..mb_w {
364 let ctop0 = cbpi.is_coded_top(mb_x, 0);
365 let ctop1 = cbpi.is_coded_top(mb_x, 0);
366 let ccur0 = cbpi.is_coded(mb_x, 0);
367 let ccur1 = cbpi.is_coded(mb_x, 1);
368 let q = cbpi.get_q(mb_w + mb_x);
370 let coff = off - 8 * stride;
371 let qtop = cbpi.get_q(mb_x);
372 if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
373 if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
375 if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
376 if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
381 let strideu = buf.get_stride(1);
382 let stridev = buf.get_stride(2);
383 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
384 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
386 for mb_x in 0..mb_w {
387 let ctu = cbpi.is_coded_top(mb_x, 4);
388 let ccu = cbpi.is_coded(mb_x, 4);
389 let ctv = cbpi.is_coded_top(mb_x, 5);
390 let ccv = cbpi.is_coded(mb_x, 5);
391 let q = cbpi.get_q(mb_w + mb_x);
392 if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
393 if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
395 let mut leftu = false;
396 let mut leftv = false;
397 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
398 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
399 for mb_x in 0..mb_w {
400 let ctu = cbpi.is_coded_top(mb_x, 4);
401 let ctv = cbpi.is_coded_top(mb_x, 5);
402 let qt = cbpi.get_q(mb_x);
403 if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
404 if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
412 fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
413 let stride = buf.get_stride(comp);
414 let mut dptr = buf.get_data_mut();
415 let mut buf = dptr.as_mut_slice();
417 let a = buf[off - 2 * stride + x] as i16;
418 let b = buf[off - 1 * stride + x] as i16;
419 let c = buf[off + 0 * stride + x] as i16;
420 let d = buf[off + 1 * stride + x] as i16;
421 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
422 if (diff != 0) && (diff >= -32) && (diff < 32) {
423 let d0 = diff.abs() * 2 - (q as i16);
424 let d1 = if d0 < 0 { 0 } else { d0 };
425 let d2 = diff.abs() - d1;
426 let d3 = if d2 < 0 { 0 } else { d2 };
428 let delta = if diff < 0 { -d3 } else { d3 };
431 if b1 < 0 { buf[off - 1 * stride + x] = 0; }
432 else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
433 else { buf[off - 1 * stride + x] = b1 as u8; }
435 if c1 < 0 { buf[off + x] = 0; }
436 else if c1 > 255 { buf[off + x] = 0xFF; }
437 else { buf[off + x] = c1 as u8; }
442 impl<'a> RealVideo20BR<'a> {
443 fn read_slice_header(&mut self) -> DecoderResult<RV20SliceInfo> {
444 validate!(self.slice_no < self.num_slices);
446 let mut br = &mut self.br;
447 br.seek(self.slice_off[self.slice_no] * 8).unwrap();
448 //println!(" slice at off {}", br.tell());
450 let frm_type = br.read(2).unwrap();
451 let ftype = match frm_type {
452 0 | 1 => { Type::I },
457 let marker = br.read(1).unwrap();
458 validate!(marker == 0);
459 let qscale = br.read(5).unwrap() as u8;
460 validate!(qscale > 0);
461 if self.minor_ver >= 2 {
462 br.skip(1).unwrap(); // loop filter
464 let seq = if self.minor_ver <= 1 {
465 br.read(8).unwrap() << 7
467 br.read(13).unwrap() << 2
471 if self.rpr.present {
472 let rpr = br.read(self.rpr.bits).unwrap() as usize;
477 w = self.rpr.widths[rpr];
478 h = self.rpr.heights[rpr];
479 validate!((w != 0) && (h != 0));
486 let mb_pos = br.read(self.mb_pos_bits).unwrap() as usize;
487 let mb_x = mb_pos % self.mb_w;
488 let mb_y = mb_pos / self.mb_w;
490 br.skip(1).unwrap(); // no rounding
492 if (self.minor_ver <= 1) && (frm_type == 3) {
495 println!("slice q {} mb {},{}", qscale, mb_x, mb_y);
497 Ok(RV20SliceInfo::new(ftype, qscale, mb_x, mb_y, mb_pos, w, h))
501 fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
502 let stride = buf.get_stride(comp);
503 let mut dptr = buf.get_data_mut();
504 let mut buf = dptr.as_mut_slice();
506 let a = buf[off - 2 + y * stride] as i16;
507 let b = buf[off - 1 + y * stride] as i16;
508 let c = buf[off + 0 + y * stride] as i16;
509 let d = buf[off + 1 + y * stride] as i16;
510 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
511 if (diff != 0) && (diff >= -32) && (diff < 32) {
512 let d0 = diff.abs() * 2 - (q as i16);
513 let d1 = if d0 < 0 { 0 } else { d0 };
514 let d2 = diff.abs() - d1;
515 let d3 = if d2 < 0 { 0 } else { d2 };
517 let delta = if diff < 0 { -d3 } else { d3 };
520 if b1 < 0 { buf[off - 1 + y * stride] = 0; }
521 else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
522 else { buf[off - 1 + y * stride] = b1 as u8; }
524 if c1 < 0 { buf[off + y * stride] = 0; }
525 else if c1 > 255 { buf[off + y * stride] = 0xFF; }
526 else { buf[off + y * stride] = c1 as u8; }
531 impl RealVideo20Decoder {
533 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
534 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
535 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
536 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
537 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
538 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
539 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
540 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
541 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
542 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
543 let mut coderead = H263ShortCodeReader::new(H263_MV);
544 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
546 let tables = Tables {
547 intra_mcbpc_cb: intra_mcbpc_cb,
548 inter_mcbpc_cb: inter_mcbpc_cb,
551 aic_rl_cb: aic_rl_cb,
556 info: Rc::new(DUMMY_CODEC_INFO),
557 dec: H263BaseDecoder::new(),
562 rpr: RPRInfo { present: false, bits: 0, widths: [0; 8], heights: [0; 8] },
567 impl NADecoder for RealVideo20Decoder {
568 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
569 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
570 let w = vinfo.get_width();
571 let h = vinfo.get_height();
572 let fmt = formats::YUV420_FORMAT;
573 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
574 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
578 let edata = info.get_extradata().unwrap();
579 let src: &[u8] = &edata;
580 let ver = ((src[4] as u32) << 12) | ((src[5] as u32) << 4) | ((src[6] as u32) >> 4);
581 let maj_ver = ver >> 16;
582 let min_ver = (ver >> 8) & 0xFF;
583 let mic_ver = ver & 0xFF;
584 println!("ver {:06X}", ver);
585 validate!(maj_ver == 2);
586 self.minor_ver = min_ver as u8;
587 let rprb = src[1] & 7;
589 self.rpr.present = false;
591 self.rpr.present = true;
592 self.rpr.bits = rprb as u8;
593 for i in 4..(src.len()/2) {
594 self.rpr.widths [i - 4] = (src[i * 2] as usize) * 4;
595 self.rpr.heights[i - 4] = (src[i * 2 + 1] as usize) * 4;
600 println!(".unwrap().unwrap().unwrap()");
601 Err(DecoderError::InvalidData)
604 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
605 let src = pkt.get_buffer();
607 println!(" decode frame size {}, {} slices", src.len(), src[0]+1);
608 let mut ibr = RealVideo20BR::new(&src, &self.tables, self.w, self.h, self.minor_ver, self.rpr);
610 let bufinfo = self.dec.parse_frame(&mut ibr).unwrap();
612 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
613 frm.set_keyframe(self.dec.is_intra());
614 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
615 Ok(Rc::new(RefCell::new(frm)))
619 struct MBB { blocks: usize, bits: u8 }
620 const H263_MBB: &[MBB; 7] = &[
621 MBB{ blocks: 47, bits: 6 },
622 MBB{ blocks: 98, bits: 7 },
623 MBB{ blocks: 395, bits: 9 },
624 MBB{ blocks: 1583, bits: 11 },
625 MBB{ blocks: 6335, bits: 13 },
626 MBB{ blocks: 9215, bits: 14 },
627 MBB{ blocks: 65536, bits: 14 },
630 pub fn get_decoder() -> Box<NADecoder> {
631 Box::new(RealVideo20Decoder::new())
636 use test::dec_video::test_file_decoding;
639 test_file_decoding("realmedia", "assets/RV/rv20_cook_640x352_realproducer_plus_8.51.rm", None/*Some(160)*/, true, false, Some("rv20"));