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)]
59 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
61 fn read(br: &mut BitReader) -> DecoderResult<Self> {
62 let marker = br.read(2)?;
63 validate!(marker == 3);
64 let profile = br.read(2)? as u8;
65 validate!(profile == 0);
66 let _someval = br.read(4)?;
67 let ftypeid = br.read(2)? as usize;
68 let ftype = RV60_FRAME_TYPES[ftypeid];
69 let qp = br.read(6)? as u8;
70 let marker = br.read(1)?;
71 validate!(marker == 0);
72 let toolset = br.read(2)?;
73 validate!(toolset == 0);
74 let osvquant = br.read(2)? as u8;
75 let _some_flag = br.read_bool()?;
76 let _some_val = br.read(2)?;
77 let ts = br.read(24)?;
78 let width = ((br.read(11)? as usize) + 1) * 4;
79 let height = ((br.read(11)? as usize) + 0) * 4;
80 validate!(height > 0);
81 let _some_flag = br.read_bool()?;
83 if ftype == FrameType::I {
87 let flag = br.read_bool()?;
94 two_f_refs = br.read_bool()?;
96 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
97 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
98 let chroma_qp_diff = br.read(1)?;
99 validate!(chroma_qp_diff == 0);
100 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
101 let deblock = br.read_bool()?;
102 let deblock_chroma = deblock && !br.read_bool()?;
104 let custom_msg_hdr_len = br.read(2)? as usize;
105 if custom_msg_hdr_len != 0 {
106 for i in 0..custom_msg_hdr_len {
107 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
113 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
114 deblock, deblock_chroma,
117 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
118 let nslices = self.get_height_cu();
119 let nbits = (br.read(5)? as u8) + 1;
120 validate!(nbits < 32);
121 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
122 for _ in 0..nslices {
123 let sign = br.read_bool()?;
129 let first_size = br.read(nbits)? as usize;
130 validate!(first_size > 0);
132 let mut lastsize = first_size;
133 sizes.push(first_size);
134 for i in 1..nslices {
135 let diff = br.read(nbits)? as isize;
138 let sum = (lastsize as isize).checked_add(diff);
139 validate!(sum.is_some());
140 size = sum.unwrap() as usize;
142 let sum = (lastsize as isize).checked_sub(diff);
143 validate!(sum.is_some());
144 size = sum.unwrap() as usize;
151 if ((br.left() >> 3) as usize) != sum {
152 println!(" left {} / {}", br.left() >> 3, sum);
154 validate!((br.left() >> 3) >= (sum as isize));
157 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
158 match self.qp_off_type {
161 let val = br.read_code(UintCodeType::Unary012)?;
169 if br.read(1)? == 0 {
172 let val = br.read(2)? as i8;
182 fn get_width_cu(&self) -> usize {
183 (self.width + 63) >> 6
185 fn get_height_cu(&self) -> usize {
186 (self.height + 63) >> 6
188 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
189 if (ypos + dy) == 0 { return false; }
190 let xpos2 = xpos + dx;
191 if (xpos2 + size) > self.width { return false; }
194 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
195 if (ypos + dy) == 0 { return false; }
196 let xpos2 = xpos + dx;
197 if (xpos2 + size * 2) > self.width { return false; }
198 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
199 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
200 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
202 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
203 if (xpos + dx) == 0 { return false; }
204 let ypos2 = ypos + dy;
205 if (ypos2 + size) > self.height { return false; }
208 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
209 if (xpos + dx) == 0 { return false; }
210 let ypos2 = ypos + dy;
211 if (ypos2 + size * 2) > self.height { return false; }
212 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
213 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
214 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
218 const RV60_BLOCK_LOG2: [u8; 65] = [
220 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
225 const RV60_AVAIL_MASK: [u8; 64] = [
226 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0xF,
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
232 #[derive(Clone,Copy,PartialEq,Debug)]
240 impl Default for CUType {
241 fn default() -> Self { CUType::Intra }
244 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
246 #[derive(Clone,Copy,PartialEq,Debug)]
258 const RV60_PU_TYPES: [PUType; 8] = [
259 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
260 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
264 fn get_num_mvs(self) -> usize {
267 PUType::Quarters => 4,
271 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
272 let mv_size = size >> 2;
274 PUType::Full => (mv_size, mv_size),
275 PUType::N2Hor => (mv_size, mv_size >> 1),
276 PUType::N2Ver => (mv_size >> 1, mv_size),
277 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
280 (mv_size, mv_size >> 2)
282 (mv_size, (3 * mv_size) >> 2)
287 (mv_size, (3 * mv_size) >> 2)
289 (mv_size, mv_size >> 2)
294 ( mv_size >> 2, mv_size)
296 ((3 * mv_size) >> 2, mv_size)
301 ((3 * mv_size) >> 2, mv_size)
303 ( mv_size >> 2, mv_size)
308 fn has_hor_split(self) -> bool {
309 matches!(self, PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters)
311 fn has_ver_split(self) -> bool {
312 matches!(self, PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters)
316 impl Default for PUType {
317 fn default() -> Self { PUType::Full }
320 #[derive(Clone,Copy,Debug)]
328 #[derive(Clone,Copy,PartialEq,Debug)]
336 impl Default for TransformType {
337 fn default() -> Self { TransformType::None }
340 #[derive(Clone,Copy,PartialEq,Debug)]
353 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
356 fn get_skip_mv_num(self) -> usize {
364 fn is_ref0(self) -> bool {
365 matches!(self, MVRef::Ref0 | MVRef::Ref0AndBRef)
367 fn is_fwd(self) -> bool {
368 matches!(self, MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef)
370 fn is_bwd(self) -> bool {
371 matches!(self, MVRef::BRef | MVRef::Ref0AndBRef)
375 #[derive(Clone,Copy,PartialEq,Debug)]
383 fn is_some(&self) -> bool { self.mvref != MVRef::None }
384 fn matches_fwd(&self, mvref: MVRef) -> bool {
385 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
387 fn matches_bwd(&self, mvref: MVRef) -> bool {
388 self.mvref.is_bwd() && mvref.is_bwd()
390 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
391 if self.mvref != other.mvref { return true; }
393 if self.mvref.is_fwd() {
394 let diff = self.f_mv - other.f_mv;
395 mvdiff += diff.x.abs() + diff.y.abs();
397 if self.mvref.is_bwd() {
398 let diff = self.b_mv - other.b_mv;
399 mvdiff += diff.x.abs() + diff.y.abs();
405 impl Default for MVInfo {
406 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
409 #[derive(Clone,Copy,Debug)]
413 ttype: TransformType,
414 imode: [IntraMode; 4],
419 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
422 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
423 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
424 if ftype == FrameType::I {
425 cu_type = CUType::Intra;
427 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
431 if (size == 8) && br.read_bool()? {
432 pu_type = PUType::Quarters;
434 pu_type = PUType::Full;
436 if pu_type == PUType::Quarters {
438 imode[i] = CBHeader::read_intra_mode(br)?;
440 } else if size <= 32 {
441 imode[0] = CBHeader::read_intra_mode(br)?;
443 if !br.read_bool()? {
444 imode[0] = IntraMode::DC64;
446 imode[0] = IntraMode::Plane64;
451 let bits = if size == 8 { 2 } else { 3 };
452 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
453 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
456 pu_type = PUType::Full;
457 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
458 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
462 if cu_type == CUType::Skip {
463 ttype = TransformType::None;
464 } else if size >= 32 {
465 ttype = TransformType::T16X16;
466 } else if size == 16 {
467 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
468 ttype = TransformType::T16X16;
470 ttype = TransformType::T4X4;
473 if pu_type == PUType::Full {
474 ttype = TransformType::T8X8;
476 ttype = TransformType::T4X4;
480 cu_type, pu_type, ttype, imode, mv,
483 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
485 let idx = br.read_code(UintCodeType::Unary012)? as u8;
486 Ok(IntraMode::Index(idx))
488 let mode = br.read(5)? as u8;
489 Ok(IntraMode::Mode(mode))
492 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
493 let mv_count = pu_type.get_num_mvs();
494 for i in 0..mv_count {
495 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
499 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
500 let mut f_mv = ZERO_MV;
501 let mut b_mv = ZERO_MV;
503 if ftype != FrameType::B {
504 if two_f_refs && br.read_bool()? {
509 f_mv = CBHeader::read_mv(br)?;
510 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
512 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
513 if !br.read_bool()? {
515 f_mv = CBHeader::read_mv(br)?;
518 b_mv = CBHeader::read_mv(br)?;
521 mvref = MVRef::Ref0AndBRef;
522 f_mv = CBHeader::read_mv(br)?;
523 b_mv = CBHeader::read_mv(br)?;
525 Ok(MVInfo { f_mv, b_mv, mvref })
528 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
529 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
530 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
535 #[derive(Clone,Copy,Default)]
538 ttype: TransformType,
542 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
545 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
547 #[derive(Clone,Copy,Default)]
561 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
563 fn reinit(&mut self, w: usize, h: usize) {
564 self.left_str.clear();
565 self.top_str.clear();
566 self.stride = w >> 2;
567 let size = self.stride * (h >> 2);
568 self.left_str.resize(size, 0);
569 self.top_str.resize(size, 0);
571 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
572 let pos = self.get_pos(xpos, ypos);
573 let dsize = size >> 2;
574 let dval = (q << 2) | strength;
576 self.top_str[pos + x] = dval;
579 self.left_str[pos + y * self.stride] = dval;
582 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
583 (xpos >> 2) + (ypos >> 2) * self.stride
585 fn get_top_strength(&self, pos: usize) -> u8 {
586 self.top_str[pos] & 3
588 fn get_left_strength(&self, pos: usize) -> u8 {
589 self.left_str[pos] & 3
591 fn set_top_strength(&mut self, pos: usize, str: u8) {
592 self.top_str[pos] |= str;
594 fn set_left_strength(&mut self, pos: usize, str: u8) {
595 self.left_str[pos] |= str;
599 struct RealVideo60Decoder {
600 info: NACodecInfoRef,
604 ipred: IntraPredContext,
605 skip_mode: FrameSkipMode,
607 avg_buf: NAVideoBufferRef<u8>,
609 y_coeffs: [i16; 16 * 16],
610 u_coeffs: [i16; 8 * 8],
611 v_coeffs: [i16; 8 * 8],
615 cu_splits: Vec<bool>,
616 coded_blk: [bool; 64],
619 pu_info: Vec<PUInfo>,
623 blk_info: Vec<BlockInfo>,
637 impl RealVideo60Decoder {
639 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
640 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
641 let vb = vt.get_vbuf();
642 let avg_buf = vb.unwrap();
644 info: NACodecInfoRef::default(),
645 cbs: RV60Codebooks::init(),
646 ipbs: IPBShuffler::new(),
647 ipred: IntraPredContext::new(),
648 skip_mode: FrameSkipMode::default(),
651 y_coeffs: [0; 16 * 16],
652 u_coeffs: [0; 8 * 8],
653 v_coeffs: [0; 8 * 8],
656 cu_splits: Vec::with_capacity(24),
657 coded_blk: [false; 64],
658 dblk: DeblockInfo::new(),
662 blk_info: Vec::new(),
675 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
676 let mut br = BitReader::new(src, BitReaderMode::BE);
677 let cu_w = hdr.get_width_cu();
678 let dqp = hdr.read_line_qp_offset(&mut br)?;
679 let qps = (hdr.qp as i8) + dqp;
680 validate!((0..32).contains(&qps));
683 self.sel_qp = match hdr.osvquant {
703 for cu_x in 0..cu_w {
704 self.cu_splits.clear();
705 self.coded_blk = [false; 64];
706 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
708 self.cu_splits.reverse();
709 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
713 println!(" left {} bits", br.left());
717 #[allow(clippy::cognitive_complexity)]
718 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
719 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
721 let size = 1 << log_size;
722 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
723 self.cu_splits.push(split);
725 let hsize = size >> 1;
726 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
727 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
728 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
729 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
731 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
732 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
733 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
736 self.reconstruct_info(hdr, &cbh, size)?;
738 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
741 let itype = self.blk_info[self.blk_pos].imode;
743 let dstride = buf.stride[0];
744 let off = xpos + ypos * dstride;
745 let dst = &mut buf.data;
746 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
747 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
750 let dstride = buf.stride[comp];
751 let soff = buf.offset[comp];
752 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
753 let dst = &mut buf.data;
754 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
755 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
759 let mut mv_x = xpos >> 2;
760 let mut mv_y = ypos >> 2;
761 let mut mv_pos = mv_x + mv_y * self.blk_stride;
762 for part_no in 0..cbh.pu_type.get_num_mvs() {
763 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
764 let mv = self.blk_info[mv_pos].mv;
771 if hdr.ftype != FrameType::B {
772 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
773 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
776 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
777 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
782 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
783 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
787 validate!(hdr.ftype == FrameType::B);
788 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
789 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
792 MVRef::Ref0AndBRef => {
793 validate!(hdr.ftype == FrameType::B);
794 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
795 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
797 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
798 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
800 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
805 if cbh.pu_type == PUType::Quarters {
810 mv_pos += mv_h * self.blk_stride - mv_w;
814 } else if cbh.pu_type.has_hor_split() {
815 mv_pos += mv_h * self.blk_stride;
817 } else if cbh.pu_type.has_ver_split() {
824 if cbh.ttype != TransformType::None {
825 self.y_coeffs = [0; 16 * 16];
826 self.u_coeffs = [0; 8 * 8];
827 self.v_coeffs = [0; 8 * 8];
829 let is_intra = cbh.cu_type == CUType::Intra;
830 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
832 TransformType::T4X4 => {
833 let subset = if is_intra { 0 } else { 2 };
837 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
842 self.coded_blk[cb_pos + 0] = true;
843 self.coded_blk[cb_pos + 1] = true;
844 self.coded_blk[cb_pos + 8] = true;
845 self.coded_blk[cb_pos + 9] = true;
846 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)?;
850 if ((cbp16 >> i) & 1) != 0 {
851 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
852 let dstride = buf.stride[0];
853 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
854 let dst = &mut buf.data;
855 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
862 let xoff = (xpos >> 1) + x * 4;
863 let yoff = (ypos >> 1) + y * 4;
864 if ((cbp16 >> (16 + i)) & 1) != 0 {
865 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
866 let dstride = buf.stride[1];
867 let off = buf.offset[1] + xoff + yoff * dstride;
868 let dst = &mut buf.data;
869 self.dsp.add_block(dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
871 if ((cbp16 >> (20 + i)) & 1) != 0 {
872 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
873 let dstride = buf.stride[2];
874 let off = buf.offset[2] + xoff + yoff * dstride;
875 let dst = &mut buf.data;
876 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
882 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
884 self.coded_blk[cb_pos] = true;
885 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)?;
888 let xoff = (i & 1) * 4;
889 let yoff = (i & 2) * 2;
891 let dstride = buf.stride[0];
892 let off = xpos + xoff + (ypos + yoff) * dstride;
893 let dst = &mut buf.data;
894 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
895 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
896 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, false);
898 if ((cbp8 >> i) & 1) != 0 {
899 let blk = &mut self.y_coeffs[i * 16..][..16];
900 self.dsp.transform4x4(blk);
901 let dstride = buf.stride[0];
902 let soff = buf.offset[0];
903 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
904 self.dsp.add_block(buf.data, off, dstride, blk, 4);
907 if ((cbp8 >> 4) & 1) != 0 {
908 self.dsp.transform4x4(&mut self.u_coeffs);
909 let dstride = buf.stride[1];
910 let soff = buf.offset[1];
911 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
912 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
914 if ((cbp8 >> 5) & 1) != 0 {
915 self.dsp.transform4x4(&mut self.v_coeffs);
916 let dstride = buf.stride[2];
917 let soff = buf.offset[2];
918 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
919 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
923 TransformType::T8X8 => {
924 let subset = if is_intra { 1 } else { 3 };
925 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
927 self.coded_blk[cb_pos] = true;
928 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)?;
929 if (cbp8 & 0xF) != 0 {
930 self.dsp.transform8x8(&mut self.y_coeffs);
931 let dstride = buf.stride[0];
932 let off = xpos + ypos * dstride;
933 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
935 if ((cbp8 >> 4) & 1) != 0 {
936 self.dsp.transform4x4(&mut self.u_coeffs);
937 let dstride = buf.stride[1];
938 let soff = buf.offset[1];
939 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
940 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
942 if ((cbp8 >> 5) & 1) != 0 {
943 self.dsp.transform4x4(&mut self.v_coeffs);
944 let dstride = buf.stride[2];
945 let soff = buf.offset[2];
946 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
947 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
951 TransformType::T16X16 => {
952 let subset = if is_intra { 1 } else { 3 };
953 let num_clusters = size >> 4;
954 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
955 for y in 0..num_clusters {
956 for x in 0..num_clusters {
957 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
958 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
959 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
960 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
961 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
962 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
964 self.y_coeffs = [0; 16 * 16];
965 self.u_coeffs = [0; 8 * 8];
966 self.v_coeffs = [0; 8 * 8];
967 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)?;
968 if (super_cbp & 0xFFFF) != 0 {
969 self.dsp.transform16x16(&mut self.y_coeffs);
970 let dstride = buf.stride[0];
971 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
972 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
974 if ((super_cbp >> 16) & 0xF) != 0 {
975 self.dsp.transform8x8(&mut self.u_coeffs);
976 let dstride = buf.stride[1];
977 let soff = buf.offset[1];
978 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
979 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
981 if ((super_cbp >> 20) & 0xF) != 0 {
982 self.dsp.transform8x8(&mut self.v_coeffs);
983 let dstride = buf.stride[2];
984 let soff = buf.offset[2];
985 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
986 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
997 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
998 let mut pui = PUInfo::default();
999 let pu_size = size >> 3;
1000 pui.cu_type = cbh.cu_type;
1001 pui.ttype = cbh.ttype;
1002 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1003 self.pu_info[self.pu_pos] = pui;
1006 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1007 validate!(imode <= MAX_IMODE);
1008 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1009 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1016 self.pu_info[self.pu_pos] = pui;
1017 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1018 validate!(imode <= MAX_IMODE);
1019 for y in 0..(size >> 2) {
1020 for x in 0..(size >> 2) {
1021 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1025 CUType::InterMV => {
1026 let mut mv_x = self.xpos >> 2;
1027 let mut mv_y = self.ypos >> 2;
1028 let mut mv_pos = self.blk_pos;
1029 let pu_type = cbh.pu_type;
1030 for part_no in 0..pu_type.get_num_mvs() {
1031 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1032 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1035 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1038 if pu_type == PUType::Quarters {
1043 mv_pos += mv_h * self.blk_stride - mv_w;
1047 } else if pu_type.has_hor_split() {
1048 mv_pos += mv_h * self.blk_stride;
1050 } else if pu_type.has_ver_split() {
1057 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1058 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1059 self.fill_skip_cand(hdr, &mut skip_cand, size);
1060 let mv = skip_cand.list[skip_idx];
1062 let mv_size = size >> 2;
1063 for y in 0..mv_size {
1064 for x in 0..mv_size {
1065 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1070 for y in 0..pu_size {
1071 for x in 0..pu_size {
1072 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1077 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1078 match cbh.imode[0] {
1079 IntraMode::DC64 => { return 1; },
1080 IntraMode::Plane64 => { return 0; },
1083 // form list of predictors
1084 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1085 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1086 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1087 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1089 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1092 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1093 let pu = &self.pu_info[self.pu_pos - 1];
1095 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1098 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1099 let tl_y = self.ypos + (sub & 2) * 4;
1100 if (tl_x > 0) && (tl_y > 0) {
1101 let pu = match sub {
1102 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1103 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1104 2 => &self.pu_info[self.pu_pos - 1],
1105 _ => &self.pu_info[self.pu_pos - 1],
1109 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1111 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1115 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1118 // actually decode prediction mode
1119 match cbh.imode[sub] {
1120 IntraMode::Index(idx) => {
1121 ipm_cand.list[idx as usize]
1123 IntraMode::Mode(mode) => {
1124 let mut imode = mode;
1125 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1127 for ic in ipm_cs.iter() {
1134 _ => unreachable!(),
1137 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1138 let src_off = if is_luma {
1139 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1141 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1143 self.ipred = IntraPredContext::new();
1144 if (self.ypos + yoff) > 0 {
1145 self.ipred.has_t = true;
1147 self.ipred.t[x + 1] = src[src_off - stride + x];
1149 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1150 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1151 self.ipred.has_tr = true;
1152 for x in size..size*2 {
1153 self.ipred.t[x + 1] = src[src_off - stride + x];
1157 self.ipred.t[size + i + 1] = self.ipred.t[size];
1160 if (self.xpos + xoff) > 0 {
1161 self.ipred.t[0] = src[src_off - stride - 1];
1164 if (self.xpos + xoff) > 0 {
1165 self.ipred.has_l = true;
1167 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1169 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1170 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1171 self.ipred.has_ld = true;
1172 for y in size..size*2 {
1173 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1177 self.ipred.l[size + i + 1] = self.ipred.l[size];
1180 if (self.ypos + yoff) > 0 {
1181 self.ipred.l[0] = src[src_off - stride - 1];
1185 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1186 let mv_pos = mv_x + mv_y * self.blk_stride;
1189 if mvi.mvref.is_fwd() {
1190 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1191 let mut mv_cand_size: usize = 0;
1193 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1194 if ref_mv.matches_fwd(mvi.mvref) {
1195 mv_cand[mv_cand_size] = ref_mv.f_mv;
1200 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1206 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1213 f_mv = match mv_cand_size {
1215 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1216 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1217 if mv_cand_size == 1 {
1220 MV { x: x >> 1, y: y >> 1 }
1223 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1229 if mvi.mvref.is_bwd() {
1230 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1231 let mut mv_cand_size: usize = 0;
1233 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1234 if ref_mv.matches_bwd(mvi.mvref) {
1235 mv_cand[mv_cand_size] = ref_mv.b_mv;
1240 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1246 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1253 b_mv = match mv_cand_size {
1255 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1256 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1257 if mv_cand_size == 1 {
1260 MV { x: x >> 1, y: y >> 1 }
1263 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1270 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1272 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1273 let mv_size = size >> 2;
1276 let mv = &self.blk_info[self.blk_pos - 1].mv;
1282 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1287 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1288 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1293 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1294 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1299 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1300 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1305 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1306 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1311 if (self.xpos > 0) && (self.ypos > 0) {
1312 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1317 for i in skip_cand.fill..4 {
1318 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1321 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1322 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1323 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1325 let hsize = 1 << (log_size - 1);
1326 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1327 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1328 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1329 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1331 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1332 let cu_type = self.pu_info[pu_pos].cu_type;
1333 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1334 let ntiles = 1 << (log_size - tsize);
1335 let dparams = RV60DeblockParams {
1336 deblock_chroma: hdr.deblock_chroma,
1339 dblkstride: self.dblk.stride,
1341 for ty in 0..ntiles {
1342 for tx in 0..ntiles {
1343 let x = xpos + (tx << tsize);
1344 let y = ypos + (ty << tsize);
1345 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1346 if cu_type == CUType::Intra {
1347 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1348 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1349 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1351 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1352 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1354 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1355 self.dblk.top_str.as_slice(),
1356 self.dblk.left_str.as_slice(),
1357 self.dblk.get_pos(x, y));
1362 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1363 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1364 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1366 let top_blk_pos = blk_pos - self.blk_stride;
1368 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1369 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1370 self.dblk.set_top_strength(dblk_pos + i, 1);
1377 if self.dblk.get_left_strength(dblk_pos) == 0 {
1378 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1379 self.dblk.set_left_strength(dblk_pos, 1);
1382 dblk_pos += self.dblk.stride;
1388 impl NADecoder for RealVideo60Decoder {
1389 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1390 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1391 let fmt = YUV420_FORMAT;
1392 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1393 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1395 let edata = info.get_extradata().unwrap();
1396 let src: &[u8] = &edata;
1398 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1399 let mut mr = MemoryReader::new_read(src);
1400 let mut br = ByteReader::new(&mut mr);
1401 let _flags = br.read_u32be()?;
1402 let version = br.read_u32be()?;
1403 let _unk = br.read_u16be()?;
1404 validate!((version >> 28) == 4);
1405 // then width and height again as 16be
1407 //self.bd.width = vinfo.get_width();
1408 //self.bd.height = vinfo.get_height();
1409 //self.frmmgr.clear();
1411 supp.pool_u8.set_dec_bufs(3);
1412 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1417 Err(DecoderError::InvalidData)
1420 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1421 let src = pkt.get_buffer();
1423 validate!(src.len() > 9);
1424 let hsize = (src[0] as usize) * 8 + 9;
1425 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1426 let hdr = FrameHeader::read(&mut br)?;
1427 match self.skip_mode {
1428 FrameSkipMode::None => {},
1429 FrameSkipMode::KeyframesOnly => {
1430 if hdr.ftype == FrameType::B {
1431 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1432 frm.set_frame_type(FrameType::Skip);
1433 return Ok(frm.into_ref());
1436 FrameSkipMode::IntraOnly => {
1437 if hdr.ftype != FrameType::I {
1438 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1439 frm.set_frame_type(FrameType::Skip);
1440 return Ok(frm.into_ref());
1445 let mut slices: Vec<usize> = Vec::new();
1446 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1449 if self.ipbs.get_lastref().is_none() {
1450 return Err(DecoderError::MissingReference);
1454 if self.ipbs.get_lastref().is_none() {
1455 return Err(DecoderError::MissingReference);
1457 if self.ipbs.get_nextref().is_none() {
1458 return Err(DecoderError::MissingReference);
1464 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1465 let ret = supp.pool_u8.get_free();
1467 return Err(DecoderError::AllocError);
1469 let mut buf = ret.unwrap();
1470 if buf.get_info() != tmp_vinfo {
1472 supp.pool_u8.reset();
1473 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1474 let ret = supp.pool_u8.get_free();
1476 return Err(DecoderError::AllocError);
1481 let cu_w = hdr.get_width_cu();
1482 let cu_h = hdr.get_height_cu();
1483 self.pu_stride = cu_w << 3;
1484 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1485 self.blk_stride = cu_w << 4;
1486 self.blk_info.clear();
1487 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1489 self.dblk.reinit(hdr.width, hdr.height);
1491 let mut off = hsize + ((br.tell() >> 3) as usize);
1492 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1493 for (cu_y, size) in slices.into_iter().enumerate() {
1494 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1497 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1498 self.ipbs.add_frame(buf.clone());
1501 if hdr.ftype != FrameType::B {
1502 self.ref0_pts = self.ref1_pts;
1503 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1504 self.ref0_ts = self.ref1_ts;
1505 self.ref1_ts = hdr.ts as u64;
1506 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1507 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1510 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1511 frm.set_keyframe(hdr.ftype == FrameType::I);
1512 if hdr.ftype == FrameType::B {
1513 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1514 frm.set_pts(Some(pts));
1516 frm.set_frame_type(hdr.ftype);
1519 fn flush(&mut self) {
1524 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1525 NAOptionDefinition {
1526 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1527 opt_type: NAOptionDefinitionType::String(Some(&[
1528 FRAME_SKIP_OPTION_VAL_NONE,
1529 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1530 FRAME_SKIP_OPTION_VAL_INTRA
1534 impl NAOptionHandler for RealVideo60Decoder {
1535 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1536 fn set_options(&mut self, options: &[NAOption]) {
1537 for option in options.iter() {
1538 for opt_def in DECODER_OPTIONS.iter() {
1539 if opt_def.check(option).is_ok() {
1540 match (option.name, &option.value) {
1541 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1542 if let Ok(smode) = FrameSkipMode::from_str(str) {
1543 self.skip_mode = smode;
1552 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1554 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1560 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1561 Box::new(RealVideo60Decoder::new())
1566 use nihav_core::codecs::RegisteredDecoders;
1567 use nihav_core::demuxers::RegisteredDemuxers;
1568 use nihav_codec_support::test::dec_video::*;
1569 use crate::realmedia_register_all_decoders;
1570 use crate::realmedia_register_all_demuxers;
1573 let mut dmx_reg = RegisteredDemuxers::new();
1574 realmedia_register_all_demuxers(&mut dmx_reg);
1575 let mut dec_reg = RegisteredDecoders::new();
1576 realmedia_register_all_decoders(&mut dec_reg);
1578 // sample from a private collection
1579 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1580 ExpectedTestResult::MD5Frames(vec![
1581 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1582 [0xea406850, 0x400802b8, 0xac106fb6, 0xe1e2e766],
1583 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1584 [0xb04e2626, 0x976e16f5, 0xc41a7a78, 0x2d8765da],
1585 [0xf4f30d97, 0x7f2876eb, 0x265ffad4, 0x3542a7c4],
1586 [0xa5082524, 0x38a86952, 0x35bf1fee, 0xfc830d3f],
1587 [0x75eab1a2, 0x62e2222f, 0xe96a20d9, 0x652140b4],
1588 [0x7590fa49, 0x78c83490, 0x239eeff9, 0x64282ac7],
1589 [0x70b19e9f, 0x66c1f866, 0xb8d7142a, 0xf3e424b2],
1590 [0xc2934123, 0x3bf72fc4, 0x12d8d123, 0x1f39525b],
1591 [0x13344919, 0xecd01190, 0x2f69079b, 0xbf4d7026],
1592 [0xcefb3284, 0xa9b36d4d, 0xf1aa6752, 0xaae17d44],
1593 [0x57f01275, 0xf8e883ea, 0x4865752e, 0xc760a777]]));