1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult, FrameSkipMode};
4 use nihav_core::options::*;
5 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
6 use nihav_core::io::byteio::{MemoryReader,ByteReader};
7 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
8 use nihav_core::io::intcode::*;
11 use super::rv60codes::*;
12 use super::rv60dsp::*;
14 struct UniqueList<A> {
20 impl<A:Copy+Default+PartialEq> UniqueList<A> {
21 fn new(max_size: usize) -> Self {
22 Self { list: [A::default(); 4], fill: 0, max_size }
24 fn add(&mut self, cand: A) {
25 if self.fill == self.max_size { return; }
26 let mut unique = true;
27 for el in self.list.iter().take(self.fill) {
34 self.list[self.fill] = cand;
40 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
41 const MAX_IMODE: u8 = 34;
43 #[derive(Clone,Copy,Debug)]
61 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
63 fn read(br: &mut BitReader) -> DecoderResult<Self> {
64 let marker = br.read(2)?;
65 validate!(marker == 3);
66 let profile = br.read(2)? as u8;
67 validate!(profile == 0);
68 let _someval = br.read(4)?;
69 let ftypeid = br.read(2)? as usize;
70 let ftype = RV60_FRAME_TYPES[ftypeid];
71 let qp = br.read(6)? as u8;
72 let marker = br.read(1)?;
73 validate!(marker == 0);
74 let toolset = br.read(2)?;
75 validate!(toolset == 0);
76 let osvquant = br.read(2)? as u8;
77 let _some_flag = br.read_bool()?;
78 let _some_val = br.read(2)?;
79 let ts = br.read(24)?;
80 let width = ((br.read(11)? as usize) + 1) * 4;
81 let height = ((br.read(11)? as usize) + 0) * 4;
82 validate!(height > 0);
83 let awidth = (width + 15) & !15;
84 let aheight = (height + 15) & !15;
85 let _some_flag = br.read_bool()?;
87 if ftype == FrameType::I {
91 let flag = br.read_bool()?;
98 two_f_refs = br.read_bool()?;
100 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
101 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
102 let chroma_qp_diff = br.read(1)?;
103 validate!(chroma_qp_diff == 0);
104 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
105 let deblock = br.read_bool()?;
106 let deblock_chroma = deblock && !br.read_bool()?;
108 let custom_msg_hdr_len = br.read(2)? as usize;
109 if custom_msg_hdr_len != 0 {
110 for i in 0..custom_msg_hdr_len {
111 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
117 profile, ftype, qp, osvquant, ts, width, height, awidth, aheight,
118 two_f_refs, qp_off_type, deblock, deblock_chroma,
121 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
122 let nslices = self.get_height_cu();
123 let nbits = (br.read(5)? as u8) + 1;
124 validate!(nbits < 32);
125 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
126 for _ in 0..nslices {
127 let sign = br.read_bool()?;
133 let first_size = br.read(nbits)? as usize;
134 validate!(first_size > 0);
136 let mut lastsize = first_size;
137 sizes.push(first_size);
138 for i in 1..nslices {
139 let diff = br.read(nbits)? as isize;
142 let sum = (lastsize as isize).checked_add(diff);
143 validate!(sum.is_some());
144 size = sum.unwrap() as usize;
146 let sum = (lastsize as isize).checked_sub(diff);
147 validate!(sum.is_some());
148 size = sum.unwrap() as usize;
155 if ((br.left() >> 3) as usize) != sum {
156 println!(" left {} / {}", br.left() >> 3, sum);
158 validate!((br.left() >> 3) >= (sum as isize));
161 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
162 match self.qp_off_type {
165 let val = br.read_code(UintCodeType::Unary012)?;
173 if br.read(1)? == 0 {
176 let val = br.read(2)? as i8;
186 fn get_width_cu(&self) -> usize {
187 (self.width + 63) >> 6
189 fn get_height_cu(&self) -> usize {
190 (self.height + 63) >> 6
192 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
193 if (ypos + dy) == 0 { return false; }
194 let xpos2 = xpos + dx;
195 if (xpos2 + size) > self.awidth { return false; }
198 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
199 if (ypos + dy) == 0 { return false; }
200 let xpos2 = xpos + dx;
201 if (xpos2 + size * 2) > self.awidth { return false; }
202 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
203 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
204 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
206 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
207 if (xpos + dx) == 0 { return false; }
208 let ypos2 = ypos + dy;
209 if (ypos2 + size) > self.aheight { return false; }
212 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
213 if (xpos + dx) == 0 { return false; }
214 let ypos2 = ypos + dy;
215 if (ypos2 + size * 2) > self.aheight { return false; }
216 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
217 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
218 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
222 const RV60_BLOCK_LOG2: [u8; 65] = [
224 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
226 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
229 const RV60_AVAIL_MASK: [u8; 64] = [
230 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0xF,
231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
236 #[derive(Clone,Copy,PartialEq,Debug,Default)]
245 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
247 #[derive(Clone,Copy,PartialEq,Debug,Default)]
260 const RV60_PU_TYPES: [PUType; 8] = [
261 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
262 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
266 fn get_num_mvs(self) -> usize {
269 PUType::Quarters => 4,
273 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
274 let mv_size = size >> 2;
276 PUType::Full => (mv_size, mv_size),
277 PUType::N2Hor => (mv_size, mv_size >> 1),
278 PUType::N2Ver => (mv_size >> 1, mv_size),
279 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
282 (mv_size, mv_size >> 2)
284 (mv_size, (3 * mv_size) >> 2)
289 (mv_size, (3 * mv_size) >> 2)
291 (mv_size, mv_size >> 2)
296 ( mv_size >> 2, mv_size)
298 ((3 * mv_size) >> 2, mv_size)
303 ((3 * mv_size) >> 2, mv_size)
305 ( mv_size >> 2, mv_size)
310 fn has_hor_split(self) -> bool {
311 matches!(self, PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters)
313 fn has_ver_split(self) -> bool {
314 matches!(self, PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters)
318 #[derive(Clone,Copy,Debug)]
326 #[derive(Clone,Copy,PartialEq,Debug,Default)]
335 #[derive(Clone,Copy,PartialEq,Debug)]
348 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
351 fn get_skip_mv_num(self) -> usize {
359 fn is_ref0(self) -> bool {
360 matches!(self, MVRef::Ref0 | MVRef::Ref0AndBRef)
362 fn is_fwd(self) -> bool {
363 matches!(self, MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef)
365 fn is_bwd(self) -> bool {
366 matches!(self, MVRef::BRef | MVRef::Ref0AndBRef)
370 #[derive(Clone,Copy,PartialEq,Debug)]
378 fn is_some(&self) -> bool { self.mvref != MVRef::None }
379 fn matches_fwd(&self, mvref: MVRef) -> bool {
380 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
382 fn matches_bwd(&self, mvref: MVRef) -> bool {
383 self.mvref.is_bwd() && mvref.is_bwd()
385 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
386 if self.mvref != other.mvref { return true; }
388 if self.mvref.is_fwd() {
389 let diff = self.f_mv - other.f_mv;
390 mvdiff += diff.x.abs() + diff.y.abs();
392 if self.mvref.is_bwd() {
393 let diff = self.b_mv - other.b_mv;
394 mvdiff += diff.x.abs() + diff.y.abs();
400 impl Default for MVInfo {
401 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
404 #[derive(Clone,Copy,Debug)]
408 ttype: TransformType,
409 imode: [IntraMode; 4],
414 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
417 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
418 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
419 if ftype == FrameType::I {
420 cu_type = CUType::Intra;
422 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
426 if (size == 8) && br.read_bool()? {
427 pu_type = PUType::Quarters;
429 pu_type = PUType::Full;
431 if pu_type == PUType::Quarters {
433 imode[i] = CBHeader::read_intra_mode(br)?;
435 } else if size <= 32 {
436 imode[0] = CBHeader::read_intra_mode(br)?;
438 if !br.read_bool()? {
439 imode[0] = IntraMode::DC64;
441 imode[0] = IntraMode::Plane64;
446 let bits = if size == 8 { 2 } else { 3 };
447 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
448 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
451 pu_type = PUType::Full;
452 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
453 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
457 if cu_type == CUType::Skip {
458 ttype = TransformType::None;
459 } else if size >= 32 {
460 ttype = TransformType::T16X16;
461 } else if size == 16 {
462 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
463 ttype = TransformType::T16X16;
465 ttype = TransformType::T4X4;
468 if pu_type == PUType::Full {
469 ttype = TransformType::T8X8;
471 ttype = TransformType::T4X4;
475 cu_type, pu_type, ttype, imode, mv,
478 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
480 let idx = br.read_code(UintCodeType::Unary012)? as u8;
481 Ok(IntraMode::Index(idx))
483 let mode = br.read(5)? as u8;
484 Ok(IntraMode::Mode(mode))
487 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
488 let mv_count = pu_type.get_num_mvs();
489 for i in 0..mv_count {
490 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
494 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
495 let mut f_mv = ZERO_MV;
496 let mut b_mv = ZERO_MV;
498 if ftype != FrameType::B {
499 if two_f_refs && br.read_bool()? {
504 f_mv = CBHeader::read_mv(br)?;
505 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
507 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
508 if !br.read_bool()? {
510 f_mv = CBHeader::read_mv(br)?;
513 b_mv = CBHeader::read_mv(br)?;
516 mvref = MVRef::Ref0AndBRef;
517 f_mv = CBHeader::read_mv(br)?;
518 b_mv = CBHeader::read_mv(br)?;
520 Ok(MVInfo { f_mv, b_mv, mvref })
523 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
524 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
525 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
530 #[derive(Clone,Copy,Default)]
533 ttype: TransformType,
538 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
541 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
543 #[derive(Clone,Copy,Default)]
557 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
559 fn reinit(&mut self, w: usize, h: usize) {
560 self.left_str.clear();
561 self.top_str.clear();
562 self.stride = w >> 2;
563 let size = self.stride * (h >> 2);
564 self.left_str.resize(size, 0);
565 self.top_str.resize(size, 0);
567 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
568 let pos = self.get_pos(xpos, ypos);
569 let dsize = size >> 2;
570 let dval = (q << 2) | strength;
572 self.top_str[pos + x] = dval;
573 self.top_str[pos + (dsize - 1) * self.stride + x] = dval;
576 self.left_str[pos + y * self.stride] = dval;
577 self.left_str[pos + y * self.stride + dsize - 1] = dval;
580 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
581 (xpos >> 2) + (ypos >> 2) * self.stride
583 fn get_top_strength(&self, pos: usize) -> u8 {
584 self.top_str[pos] & 3
586 fn get_left_strength(&self, pos: usize) -> u8 {
587 self.left_str[pos] & 3
589 fn set_top_strength(&mut self, pos: usize, strength: u8) {
590 self.top_str[pos] |= strength;
592 fn set_left_strength(&mut self, pos: usize, strength: u8) {
593 self.left_str[pos] |= strength;
597 struct RealVideo60Decoder {
598 info: NACodecInfoRef,
602 ipred: IntraPredContext,
603 skip_mode: FrameSkipMode,
605 avg_buf: NAVideoBufferRef<u8>,
607 y_coeffs: [i16; 16 * 16],
608 u_coeffs: [i16; 8 * 8],
609 v_coeffs: [i16; 8 * 8],
613 cu_splits: Vec<bool>,
614 coded_blk: [bool; 64],
617 pu_info: Vec<PUInfo>,
621 blk_info: Vec<BlockInfo>,
635 impl RealVideo60Decoder {
637 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
638 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
639 let vb = vt.get_vbuf();
640 let avg_buf = vb.unwrap();
642 info: NACodecInfoRef::default(),
643 cbs: RV60Codebooks::init(),
644 ipbs: IPBShuffler::new(),
645 ipred: IntraPredContext::new(),
646 skip_mode: FrameSkipMode::default(),
649 y_coeffs: [0; 16 * 16],
650 u_coeffs: [0; 8 * 8],
651 v_coeffs: [0; 8 * 8],
654 cu_splits: Vec::with_capacity(24),
655 coded_blk: [false; 64],
656 dblk: DeblockInfo::new(),
660 blk_info: Vec::new(),
673 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
674 let mut br = BitReader::new(src, BitReaderMode::BE);
675 let cu_w = hdr.get_width_cu();
676 for cu_x in 0..cu_w {
677 let dqp = hdr.read_line_qp_offset(&mut br)?;
678 let qps = (hdr.qp as i8) + dqp;
679 validate!((0..32).contains(&qps));
682 self.sel_qp = match hdr.osvquant {
702 self.cu_splits.clear();
703 self.coded_blk = [false; 64];
704 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
706 self.cu_splits.reverse();
707 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
711 println!(" left {} bits", br.left());
715 #[allow(clippy::cognitive_complexity)]
716 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
717 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return Ok(()); }
719 let size = 1 << log_size;
720 let split = (xpos + size > hdr.awidth) || (ypos + size > hdr.aheight) || (size > 8 && br.read_bool()?);
721 self.cu_splits.push(split);
723 let hsize = size >> 1;
724 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
725 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
726 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
727 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
729 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
730 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
731 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
734 self.reconstruct_info(hdr, &cbh, size)?;
736 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
739 let itype = self.blk_info[self.blk_pos].imode;
741 let dstride = buf.stride[0];
742 let off = xpos + ypos * dstride;
743 let dst = &mut buf.data;
744 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
745 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
748 let dstride = buf.stride[comp];
749 let soff = buf.offset[comp];
750 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
751 let dst = &mut buf.data;
752 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
753 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
757 let mut mv_x = xpos >> 2;
758 let mut mv_y = ypos >> 2;
759 let mut mv_pos = mv_x + mv_y * self.blk_stride;
760 for part_no in 0..cbh.pu_type.get_num_mvs() {
761 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
762 let mv = self.blk_info[mv_pos].mv;
769 if hdr.ftype != FrameType::B {
770 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
771 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
774 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
775 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
780 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
781 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
785 validate!(hdr.ftype == FrameType::B);
786 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
787 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
790 MVRef::Ref0AndBRef => {
791 validate!(hdr.ftype == FrameType::B);
792 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
793 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
795 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
796 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
798 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
803 if cbh.pu_type == PUType::Quarters {
808 mv_pos += mv_h * self.blk_stride - mv_w;
812 } else if cbh.pu_type.has_hor_split() {
813 mv_pos += mv_h * self.blk_stride;
815 } else if cbh.pu_type.has_ver_split() {
822 if cbh.ttype != TransformType::None {
823 self.y_coeffs = [0; 16 * 16];
824 self.u_coeffs = [0; 8 * 8];
825 self.v_coeffs = [0; 8 * 8];
827 let is_intra = cbh.cu_type == CUType::Intra;
828 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
830 TransformType::T4X4 => {
831 let subset = if is_intra { 0 } else { 2 };
835 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
840 rv6_decode_cu_4x4in16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp16)?;
844 if ((cbp16 >> i) & 1) != 0 {
845 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
846 let dstride = buf.stride[0];
847 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
848 let dst = &mut buf.data;
849 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
850 self.coded_blk[cb_pos + (y / 2) * 8 + (x / 2)] = true;
857 let xoff = (xpos >> 1) + x * 4;
858 let yoff = (ypos >> 1) + y * 4;
859 if ((cbp16 >> (16 + i)) & 1) != 0 {
860 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
861 let dstride = buf.stride[1];
862 let off = buf.offset[1] + xoff + yoff * dstride;
863 let dst = &mut buf.data;
864 self.dsp.add_block(dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
865 self.coded_blk[cb_pos + y * 8 + x] = true;
867 if ((cbp16 >> (20 + i)) & 1) != 0 {
868 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
869 let dstride = buf.stride[2];
870 let off = buf.offset[2] + xoff + yoff * dstride;
871 let dst = &mut buf.data;
872 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
873 self.coded_blk[cb_pos + y * 8 + x] = true;
879 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
881 self.coded_blk[cb_pos] = true;
882 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, true)?;
885 let xoff = (i & 1) * 4;
886 let yoff = (i & 2) * 2;
888 let dstride = buf.stride[0];
889 let off = xpos + xoff + (ypos + yoff) * dstride;
890 let dst = &mut buf.data;
891 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
892 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
893 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, true);
895 if ((cbp8 >> i) & 1) != 0 {
896 let blk = &mut self.y_coeffs[i * 16..][..16];
897 self.dsp.transform4x4(blk);
898 let dstride = buf.stride[0];
899 let soff = buf.offset[0];
900 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
901 self.dsp.add_block(buf.data, off, dstride, blk, 4);
904 if ((cbp8 >> 4) & 1) != 0 {
905 self.dsp.transform4x4(&mut self.u_coeffs);
906 let dstride = buf.stride[1];
907 let soff = buf.offset[1];
908 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
909 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
911 if ((cbp8 >> 5) & 1) != 0 {
912 self.dsp.transform4x4(&mut self.v_coeffs);
913 let dstride = buf.stride[2];
914 let soff = buf.offset[2];
915 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
916 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
920 TransformType::T8X8 => {
921 let subset = if is_intra { 1 } else { 3 };
922 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
924 self.coded_blk[cb_pos] = true;
925 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, false)?;
926 if (cbp8 & 0xF) != 0 {
927 self.dsp.transform8x8(&mut self.y_coeffs);
928 let dstride = buf.stride[0];
929 let off = xpos + ypos * dstride;
930 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
932 if ((cbp8 >> 4) & 1) != 0 {
933 self.dsp.transform4x4(&mut self.u_coeffs);
934 let dstride = buf.stride[1];
935 let soff = buf.offset[1];
936 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
937 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
939 if ((cbp8 >> 5) & 1) != 0 {
940 self.dsp.transform4x4(&mut self.v_coeffs);
941 let dstride = buf.stride[2];
942 let soff = buf.offset[2];
943 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
944 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
948 TransformType::T16X16 => {
949 let subset = if is_intra { 1 } else { 3 };
950 let num_clusters = size >> 4;
951 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
952 for y in 0..num_clusters {
953 for x in 0..num_clusters {
954 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
955 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
956 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
957 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
958 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
959 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
961 self.y_coeffs = [0; 16 * 16];
962 self.u_coeffs = [0; 8 * 8];
963 self.v_coeffs = [0; 8 * 8];
964 rv6_decode_cu_16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, super_cbp)?;
965 if (super_cbp & 0xFFFF) != 0 {
966 self.dsp.transform16x16(&mut self.y_coeffs);
967 let dstride = buf.stride[0];
968 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
969 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
971 if ((super_cbp >> 16) & 0xF) != 0 {
972 self.dsp.transform8x8(&mut self.u_coeffs);
973 let dstride = buf.stride[1];
974 let soff = buf.offset[1];
975 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
976 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
978 if ((super_cbp >> 20) & 0xF) != 0 {
979 self.dsp.transform8x8(&mut self.v_coeffs);
980 let dstride = buf.stride[2];
981 let soff = buf.offset[2];
982 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
983 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
994 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
995 let mut pui = PUInfo::default();
996 let pu_size = size >> 3;
997 pui.cu_type = cbh.cu_type;
998 pui.ttype = cbh.ttype;
999 pui.pu_type = cbh.pu_type;
1000 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1001 self.pu_info[self.pu_pos] = pui;
1004 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1005 validate!(imode <= MAX_IMODE);
1006 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1007 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1014 self.pu_info[self.pu_pos] = pui;
1015 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1016 validate!(imode <= MAX_IMODE);
1017 for y in 0..(size >> 2) {
1018 for x in 0..(size >> 2) {
1019 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1023 CUType::InterMV => {
1024 let mut mv_x = self.xpos >> 2;
1025 let mut mv_y = self.ypos >> 2;
1026 let mut mv_pos = self.blk_pos;
1027 let pu_type = cbh.pu_type;
1028 for part_no in 0..pu_type.get_num_mvs() {
1029 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1030 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1033 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1036 if pu_type == PUType::Quarters {
1041 mv_pos += mv_h * self.blk_stride - mv_w;
1045 } else if pu_type.has_hor_split() {
1046 mv_pos += mv_h * self.blk_stride;
1048 } else if pu_type.has_ver_split() {
1055 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1056 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1057 self.fill_skip_cand(hdr, &mut skip_cand, size);
1058 let mv = skip_cand.list[skip_idx];
1060 let mv_size = size >> 2;
1061 for y in 0..mv_size {
1062 for x in 0..mv_size {
1063 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1068 for y in 0..pu_size {
1069 for x in 0..pu_size {
1070 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1075 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1076 match cbh.imode[0] {
1077 IntraMode::DC64 => { return 1; },
1078 IntraMode::Plane64 => { return 0; },
1081 // form list of predictors
1082 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1083 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1084 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1085 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1087 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1090 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1091 let pu = &self.pu_info[self.pu_pos - 1];
1093 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1096 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1097 let tl_y = self.ypos + (sub & 2) * 4;
1098 if (tl_x > 0) && (tl_y > 0) {
1099 let pu = match sub {
1100 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1101 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1102 2 => &self.pu_info[self.pu_pos - 1],
1103 _ => &self.pu_info[self.pu_pos - 1],
1107 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1109 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1113 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1116 // actually decode prediction mode
1117 match cbh.imode[sub] {
1118 IntraMode::Index(idx) => {
1119 ipm_cand.list[idx as usize]
1121 IntraMode::Mode(mode) => {
1122 let mut imode = mode;
1123 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1125 for ic in ipm_cs.iter() {
1132 _ => unreachable!(),
1135 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1136 let src_off = if is_luma {
1137 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1139 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1141 self.ipred = IntraPredContext::new();
1142 if (self.ypos + yoff) > 0 {
1143 self.ipred.has_t = true;
1145 self.ipred.t[x + 1] = src[src_off - stride + x];
1147 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1148 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1149 self.ipred.has_tr = true;
1150 for x in size..size*2 {
1151 self.ipred.t[x + 1] = src[src_off - stride + x];
1155 self.ipred.t[size + i + 1] = self.ipred.t[size];
1158 if (self.xpos + xoff) > 0 {
1159 self.ipred.t[0] = src[src_off - stride - 1];
1162 if (self.xpos + xoff) > 0 {
1163 self.ipred.has_l = true;
1165 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1167 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1168 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1169 self.ipred.has_ld = true;
1170 for y in size..size*2 {
1171 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1175 self.ipred.l[size + i + 1] = self.ipred.l[size];
1178 if (self.ypos + yoff) > 0 {
1179 self.ipred.l[0] = src[src_off - stride - 1];
1183 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1184 let mv_pos = mv_x + mv_y * self.blk_stride;
1187 if mvi.mvref.is_fwd() {
1188 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1189 let mut mv_cand_size: usize = 0;
1191 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1192 if ref_mv.matches_fwd(mvi.mvref) {
1193 mv_cand[mv_cand_size] = ref_mv.f_mv;
1198 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1199 if ref_mv.matches_fwd(mvi.mvref) {
1200 mv_cand[mv_cand_size] = ref_mv.f_mv;
1204 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1205 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1206 if ref_mv.matches_fwd(mvi.mvref) {
1207 mv_cand[mv_cand_size] = ref_mv.f_mv;
1211 f_mv = match mv_cand_size {
1213 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1214 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1215 if mv_cand_size == 1 {
1218 MV { x: x >> 1, y: y >> 1 }
1221 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1227 if mvi.mvref.is_bwd() {
1228 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1229 let mut mv_cand_size: usize = 0;
1231 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1232 if ref_mv.matches_bwd(mvi.mvref) {
1233 mv_cand[mv_cand_size] = ref_mv.b_mv;
1238 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1239 if ref_mv.matches_bwd(mvi.mvref) {
1240 mv_cand[mv_cand_size] = ref_mv.b_mv;
1244 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1245 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1246 if ref_mv.matches_bwd(mvi.mvref) {
1247 mv_cand[mv_cand_size] = ref_mv.b_mv;
1251 b_mv = match mv_cand_size {
1253 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1254 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1255 if mv_cand_size == 1 {
1258 MV { x: x >> 1, y: y >> 1 }
1261 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1268 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1270 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1271 let mv_size = size >> 2;
1274 let mv = &self.blk_info[self.blk_pos - 1].mv;
1280 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1285 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1286 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1291 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1292 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1297 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1298 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1303 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1304 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1309 if (self.xpos > 0) && (self.ypos > 0) {
1310 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1315 for i in skip_cand.fill..4 {
1316 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1319 fn calc_tile_size(&self, pu_pos: usize, cu_type: CUType, log_size: u8) -> u8 {
1322 4 if (cu_type != CUType::Intra) && (self.pu_info[pu_pos].pu_type != PUType::Full) => 3,
1324 _ => unreachable!(),
1327 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1328 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return; }
1329 let split = self.cu_splits.pop().unwrap();
1331 let hsize = 1 << (log_size - 1);
1332 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1333 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1334 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1335 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1337 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1338 let cu_type = self.pu_info[pu_pos].cu_type;
1339 let tsize = self.calc_tile_size(pu_pos, cu_type, log_size);
1340 let ntiles = 1 << (log_size - tsize);
1341 let dparams = RV60DeblockParams {
1342 deblock_chroma: hdr.deblock_chroma,
1344 height: hdr.aheight,
1345 dblkstride: self.dblk.stride,
1347 for ty in 0..ntiles {
1348 for tx in 0..ntiles {
1349 let x = xpos + (tx << tsize);
1350 let y = ypos + (ty << tsize);
1351 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1352 if cu_type == CUType::Intra {
1353 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1354 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1355 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1357 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1358 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1360 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1361 self.dblk.top_str.as_slice(),
1362 self.dblk.left_str.as_slice(),
1363 self.dblk.get_pos(x, y));
1368 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1369 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1370 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1372 let top_blk_pos = blk_pos - self.blk_stride;
1374 if self.dblk.get_top_strength(dblk_pos - self.dblk.stride + i) == 0 {
1375 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1376 self.dblk.set_top_strength(dblk_pos + i, 1);
1383 if self.dblk.get_left_strength(dblk_pos - 1) == 0 {
1384 if self.blk_info[blk_pos + i * self.blk_stride].mv.is_deblock_cand(&self.blk_info[blk_pos + i * self.blk_stride - 1].mv) {
1385 self.dblk.set_left_strength(dblk_pos, 1);
1388 dblk_pos += self.dblk.stride;
1394 impl NADecoder for RealVideo60Decoder {
1395 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1396 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1397 let fmt = YUV420_FORMAT;
1398 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1399 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1401 let edata = info.get_extradata().unwrap();
1402 let src: &[u8] = &edata;
1404 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1405 let mut mr = MemoryReader::new_read(src);
1406 let mut br = ByteReader::new(&mut mr);
1407 let _flags = br.read_u32be()?;
1408 let version = br.read_u32be()?;
1409 let _unk = br.read_u16be()?;
1410 validate!((version >> 28) == 4);
1411 // then width and height again as 16be
1413 //self.bd.width = vinfo.get_width();
1414 //self.bd.height = vinfo.get_height();
1415 //self.frmmgr.clear();
1417 supp.pool_u8.set_dec_bufs(3);
1418 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1422 Err(DecoderError::InvalidData)
1425 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1426 let src = pkt.get_buffer();
1428 validate!(src.len() > 9);
1429 let hsize = (src[0] as usize) * 8 + 9;
1430 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1431 let hdr = FrameHeader::read(&mut br)?;
1432 match self.skip_mode {
1433 FrameSkipMode::None => {},
1434 FrameSkipMode::KeyframesOnly => {
1435 if hdr.ftype == FrameType::B {
1436 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1437 frm.set_frame_type(FrameType::Skip);
1438 return Ok(frm.into_ref());
1441 FrameSkipMode::IntraOnly => {
1442 if hdr.ftype != FrameType::I {
1443 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1444 frm.set_frame_type(FrameType::Skip);
1445 return Ok(frm.into_ref());
1450 let mut slices: Vec<usize> = Vec::new();
1451 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1454 if self.ipbs.get_lastref().is_none() {
1455 return Err(DecoderError::MissingReference);
1459 if self.ipbs.get_lastref().is_none() {
1460 return Err(DecoderError::MissingReference);
1462 if self.ipbs.get_nextref().is_none() {
1463 return Err(DecoderError::MissingReference);
1469 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1470 let ret = supp.pool_u8.get_free();
1472 return Err(DecoderError::AllocError);
1474 let mut buf = ret.unwrap();
1475 if buf.get_info() != tmp_vinfo {
1477 supp.pool_u8.reset();
1478 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1479 let ret = supp.pool_u8.get_free();
1481 return Err(DecoderError::AllocError);
1486 let cu_w = hdr.get_width_cu();
1487 let cu_h = hdr.get_height_cu();
1488 self.pu_stride = cu_w << 3;
1489 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1490 self.blk_stride = cu_w << 4;
1491 self.blk_info.clear();
1492 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1494 self.dblk.reinit(hdr.awidth, hdr.aheight);
1496 let mut off = hsize + (br.tell() >> 3);
1497 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1498 for (cu_y, size) in slices.into_iter().enumerate() {
1499 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1502 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1503 self.ipbs.add_frame(buf.clone());
1506 if hdr.ftype != FrameType::B {
1507 self.ref0_pts = self.ref1_pts;
1508 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1509 self.ref0_ts = self.ref1_ts;
1510 self.ref1_ts = hdr.ts as u64;
1511 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1512 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1515 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1516 frm.set_keyframe(hdr.ftype == FrameType::I);
1517 if hdr.ftype == FrameType::B {
1518 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1519 frm.set_pts(Some(pts));
1521 frm.set_frame_type(hdr.ftype);
1524 fn flush(&mut self) {
1529 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1530 NAOptionDefinition {
1531 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1532 opt_type: NAOptionDefinitionType::String(Some(&[
1533 FRAME_SKIP_OPTION_VAL_NONE,
1534 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1535 FRAME_SKIP_OPTION_VAL_INTRA
1539 impl NAOptionHandler for RealVideo60Decoder {
1540 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1541 fn set_options(&mut self, options: &[NAOption]) {
1542 for option in options.iter() {
1543 for opt_def in DECODER_OPTIONS.iter() {
1544 if opt_def.check(option).is_ok() {
1545 match (option.name, &option.value) {
1546 (FRAME_SKIP_OPTION, NAValue::String(ref strval)) => {
1547 if let Ok(smode) = FrameSkipMode::from_str(strval) {
1548 self.skip_mode = smode;
1557 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1559 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1565 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1566 Box::new(RealVideo60Decoder::new())
1571 use nihav_core::codecs::RegisteredDecoders;
1572 use nihav_core::demuxers::RegisteredDemuxers;
1573 use nihav_codec_support::test::dec_video::*;
1574 use crate::realmedia_register_all_decoders;
1575 use crate::realmedia_register_all_demuxers;
1578 let mut dmx_reg = RegisteredDemuxers::new();
1579 realmedia_register_all_demuxers(&mut dmx_reg);
1580 let mut dec_reg = RegisteredDecoders::new();
1581 realmedia_register_all_decoders(&mut dec_reg);
1583 // sample from a private collection
1584 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1585 ExpectedTestResult::MD5Frames(vec![
1586 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1587 [0x76743a3b, 0x7dd4f196, 0x0193fe5a, 0x4f78c7cb],
1588 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1589 [0xfee70206, 0x626f3bea, 0x7677ad4b, 0x1228f3b6],
1590 [0x7156cbc2, 0xf381bcb6, 0xe86531f2, 0xb311c3ea],
1591 [0x1742b5a1, 0x66252580, 0x242753de, 0x5215d732],
1592 [0xd357ebda, 0x6460dba6, 0xa93eb616, 0x63ee6d60],
1593 [0x4cd72275, 0x28e1e439, 0xad17dfca, 0x3fd7253f],
1594 [0xe389ce4f, 0x8f0891b3, 0x88639b23, 0x21ed114f],
1595 [0x5b2b2f1b, 0x17a7518b, 0x53806e6a, 0x4538bb00],
1596 [0xdca03c9a, 0x1a45d80c, 0x86141211, 0x79912ed4],
1597 [0x0bf66bf4, 0x46385620, 0xc6fa4796, 0xd8e16d56],
1598 [0x4671a7f0, 0x46f50649, 0x268df27b, 0x70b71ab3]]));
1601 fn test_rv60_dqp() {
1602 let mut dmx_reg = RegisteredDemuxers::new();
1603 realmedia_register_all_demuxers(&mut dmx_reg);
1604 let mut dec_reg = RegisteredDecoders::new();
1605 realmedia_register_all_decoders(&mut dec_reg);
1607 // sample provided by Peter Ross
1608 test_decoding("realmedia", "realvideo6", "assets/RV/qp-offset-type-2.rmhd", Some(500), &dmx_reg, &dec_reg,
1609 ExpectedTestResult::MD5Frames(vec![
1610 [0x3dc2f19e, 0x0f8c66bd, 0x8e81ceda, 0xa1bf8f58],
1611 [0xbd9c0f89, 0x67b780b0, 0xa4afe443, 0x9f17221a],
1612 [0xf3e0a7ba, 0xe620ace9, 0x03857219, 0x8c3bd1fb],
1613 [0xc4eedc8c, 0x81d2dd0f, 0xa6443847, 0x09c8cec9],
1614 [0x565fc952, 0x4d5dc166, 0xf64b7b0d, 0x1570de50],
1615 [0x0e50786a, 0xaf058ff3, 0xa3f71eba, 0x370c197a],
1616 [0x1b92667b, 0x9cab9e24, 0x1bf48cb2, 0x368db124],
1617 [0xefcc0ab4, 0x6efceb20, 0xb2501ee8, 0xb449b7b6],
1618 [0xbbc2ca23, 0x6a7a8da2, 0xeadc1ff7, 0x2ff0a7f3],
1619 [0x6d14a2b4, 0x0d2642fb, 0x78fcad10, 0xba571ec1],
1620 [0xbdf889fd, 0x5f15838a, 0x8fedd13f, 0xc26a2e50],
1621 [0x886f03b6, 0xc46ba7c3, 0xae6aa971, 0x90cf94b6],
1622 [0x951693e7, 0xa77f68f3, 0x765990c9, 0x4a4d57fa],
1623 [0x3c25f4eb, 0x5c113c41, 0x4d73f498, 0xd7e210b0]]));