1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
4 use nihav_core::io::byteio::{MemoryReader,ByteReader};
5 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
6 use nihav_core::io::intcode::*;
8 use super::rv60codes::*;
11 struct UniqueList<A> {
17 impl<A:Copy+Default+PartialEq> UniqueList<A> {
18 fn new(max_size: usize) -> Self {
19 Self { list: [A::default(); 4], fill: 0, max_size }
21 fn add(&mut self, cand: A) {
22 if self.fill == self.max_size { return; }
23 let mut unique = true;
24 for el in self.list.into_iter().take(self.fill) {
31 self.list[self.fill] = cand;
37 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
38 const MAX_IMODE: u8 = 34;
40 #[derive(Clone,Copy,Debug)]
55 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
57 fn read(br: &mut BitReader) -> DecoderResult<Self> {
58 let marker = br.read(2)?;
59 validate!(marker == 3);
60 let profile = br.read(2)? as u8;
61 validate!(profile == 0);
62 let _someval = br.read(4)?;
63 let ftypeid = br.read(2)? as usize;
64 let ftype = RV60_FRAME_TYPES[ftypeid];
65 let qp = br.read(6)? as u8;
66 let marker = br.read(1)?;
67 validate!(marker == 0);
68 let toolset = br.read(2)?;
69 validate!(toolset == 0);
70 let osvquant = br.read(2)? as u8;
71 let _some_flag = br.read_bool()?;
72 let _some_val = br.read(2)?;
73 let ts = br.read(24)?;
74 let width = ((br.read(11)? as usize) + 1) * 4;
75 let height = ((br.read(11)? as usize) + 0) * 4;
76 validate!(height > 0);
77 let _some_flag = br.read_bool()?;
79 if ftype == FrameType::I {
83 let flag = br.read_bool()?;
90 two_f_refs = br.read_bool()?;
92 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
93 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
94 let chroma_qp_diff = br.read(1)?;
95 validate!(chroma_qp_diff == 0);
96 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
97 let deblock = br.read_bool()?;
98 let deblock_chroma = deblock && !br.read_bool()?;
100 let custom_msg_hdr_len = br.read(2)? as usize;
101 if custom_msg_hdr_len != 0 {
102 for i in 0..custom_msg_hdr_len {
103 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
109 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
110 deblock, deblock_chroma,
113 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
114 let nslices = self.get_height_cu();
115 let nbits = (br.read(5)? as u8) + 1;
116 validate!(nbits < 32);
117 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
118 for _ in 0..nslices {
119 let sign = br.read_bool()?;
125 let first_size = br.read(nbits)? as usize;
126 validate!(first_size > 0);
128 let mut lastsize = first_size;
129 sizes.push(first_size);
130 for i in 1..nslices {
131 let diff = br.read(nbits)? as isize;
134 let sum = (lastsize as isize).checked_add(diff);
135 validate!(sum.is_some());
136 size = sum.unwrap() as usize;
138 let sum = (lastsize as isize).checked_sub(diff);
139 validate!(sum.is_some());
140 size = sum.unwrap() as usize;
147 if ((br.left() >> 3) as usize) != sum {
148 println!(" left {} / {}", br.left() >> 3, sum);
150 validate!((br.left() >> 3) >= (sum as isize));
153 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
154 match self.qp_off_type {
157 let val = br.read_code(UintCodeType::Unary012)?;
165 if br.read(1)? == 0 {
168 let val = br.read(2)? as i8;
178 fn get_width_cu(&self) -> usize {
179 (self.width + 63) >> 6
181 fn get_height_cu(&self) -> usize {
182 (self.height + 63) >> 6
184 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
185 if (ypos + dy) == 0 { return false; }
186 let xpos2 = xpos + dx;
187 if (xpos2 + size) > self.width { return false; }
190 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
191 if (ypos + dy) == 0 { return false; }
192 let xpos2 = xpos + dx;
193 if (xpos2 + size * 2) > self.width { return false; }
194 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
195 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
196 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
198 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
199 if (xpos + dx) == 0 { return false; }
200 let ypos2 = ypos + dy;
201 if (ypos2 + size) > self.height { return false; }
204 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
205 if (xpos + dx) == 0 { return false; }
206 let ypos2 = ypos + dy;
207 if (ypos2 + size * 2) > self.height { return false; }
208 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
209 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
210 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
214 const RV60_BLOCK_LOG2: [u8; 65] = [
216 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
221 const RV60_AVAIL_MASK: [u8; 64] = [
222 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
228 #[derive(Clone,Copy,PartialEq,Debug)]
236 impl Default for CUType {
237 fn default() -> Self { CUType::Intra }
240 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
242 #[derive(Clone,Copy,PartialEq,Debug)]
254 const RV60_PU_TYPES: [PUType; 8] = [
255 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
256 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
260 fn get_num_mvs(&self) -> usize {
263 PUType::Quarters => 4,
267 fn get_mv_size(&self, part_no: usize, size: usize) -> (usize, usize) {
268 let mv_size = size >> 2;
270 PUType::Full => (mv_size, mv_size),
271 PUType::N2Hor => (mv_size, mv_size >> 1),
272 PUType::N2Ver => (mv_size >> 1, mv_size),
273 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
276 (mv_size, mv_size >> 2)
278 (mv_size, 3 * mv_size >> 2)
283 (mv_size, 3 * mv_size >> 2)
285 (mv_size, mv_size >> 2)
290 ( mv_size >> 2, mv_size)
292 (3 * mv_size >> 2, mv_size)
297 (3 * mv_size >> 2, mv_size)
299 ( mv_size >> 2, mv_size)
304 fn has_hor_split(&self) -> bool {
306 PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
310 fn has_ver_split(&self) -> bool {
312 PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
318 impl Default for PUType {
319 fn default() -> Self { PUType::Full }
322 #[derive(Clone,Copy,Debug)]
330 #[derive(Clone,Copy,PartialEq,Debug)]
338 impl Default for TransformType {
339 fn default() -> Self { TransformType::None }
342 #[derive(Clone,Copy,PartialEq,Debug)]
355 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
358 fn get_skip_mv_num(&self) -> usize {
366 fn is_ref0(&self) -> bool {
368 MVRef::Ref0 | MVRef::Ref0AndBRef => true,
372 fn is_fwd(&self) -> bool {
374 MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
378 fn is_bwd(&self) -> bool {
380 MVRef::BRef | MVRef::Ref0AndBRef => true,
386 #[derive(Clone,Copy,PartialEq,Debug)]
394 fn is_some(&self) -> bool { self.mvref != MVRef::None }
395 fn matches_fwd(&self, mvref: MVRef) -> bool {
396 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
398 fn matches_bwd(&self, mvref: MVRef) -> bool {
399 self.mvref.is_bwd() && mvref.is_bwd()
401 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
402 if self.mvref != other.mvref { return true; }
404 if self.mvref.is_fwd() {
405 let diff = self.f_mv - other.f_mv;
406 mvdiff += diff.x.abs() + diff.y.abs();
408 if self.mvref.is_bwd() {
409 let diff = self.b_mv - other.b_mv;
410 mvdiff += diff.x.abs() + diff.y.abs();
416 impl Default for MVInfo {
417 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
420 #[derive(Clone,Copy,Debug)]
424 ttype: TransformType,
425 imode: [IntraMode; 4],
430 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
433 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
434 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
435 if ftype == FrameType::I {
436 cu_type = CUType::Intra;
438 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
442 if (size == 8) && br.read_bool()? {
443 pu_type = PUType::Quarters;
445 pu_type = PUType::Full;
447 if pu_type == PUType::Quarters {
449 imode[i] = CBHeader::read_intra_mode(br)?;
451 } else if size <= 32 {
452 imode[0] = CBHeader::read_intra_mode(br)?;
454 if !br.read_bool()? {
455 imode[0] = IntraMode::DC64;
457 imode[0] = IntraMode::Plane64;
462 let bits = if size == 8 { 2 } else { 3 };
463 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
464 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
467 pu_type = PUType::Full;
468 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
469 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
473 if cu_type == CUType::Skip {
474 ttype = TransformType::None;
475 } else if size >= 32 {
476 ttype = TransformType::T16X16;
477 } else if size == 16 {
478 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
479 ttype = TransformType::T16X16;
481 ttype = TransformType::T4X4;
484 if pu_type == PUType::Full {
485 ttype = TransformType::T8X8;
487 ttype = TransformType::T4X4;
491 cu_type, pu_type, ttype, imode, mv,
494 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
496 let idx = br.read_code(UintCodeType::Unary012)? as u8;
497 Ok(IntraMode::Index(idx))
499 let mode = br.read(5)? as u8;
500 Ok(IntraMode::Mode(mode))
503 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
504 let mv_count = pu_type.get_num_mvs();
505 for i in 0..mv_count {
506 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
510 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
511 let mut f_mv = ZERO_MV;
512 let mut b_mv = ZERO_MV;
514 if ftype != FrameType::B {
515 if two_f_refs && br.read_bool()? {
520 f_mv = CBHeader::read_mv(br)?;
521 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
523 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
524 if !br.read_bool()? {
526 f_mv = CBHeader::read_mv(br)?;
529 b_mv = CBHeader::read_mv(br)?;
532 mvref = MVRef::Ref0AndBRef;
533 f_mv = CBHeader::read_mv(br)?;
534 b_mv = CBHeader::read_mv(br)?;
536 Ok(MVInfo { f_mv, b_mv, mvref })
539 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
540 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
541 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
546 #[derive(Clone,Copy,Default)]
549 ttype: TransformType,
553 fn is_intra(&self) -> bool { self.cu_type == CUType::Intra }
556 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
558 #[derive(Clone,Copy,Default)]
572 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
574 fn reinit(&mut self, w: usize, h: usize) {
575 self.left_str.clear();
576 self.top_str.clear();
577 self.stride = w >> 2;
578 let size = self.stride * (h >> 2);
579 self.left_str.resize(size, 0);
580 self.top_str.resize(size, 0);
582 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
583 let pos = self.get_pos(xpos, ypos);
584 let dsize = size >> 2;
585 let dval = (q << 2) | strength;
587 self.top_str[pos + x] = dval;
590 self.left_str[pos + y * self.stride] = dval;
593 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
594 (xpos >> 2) + (ypos >> 2) * self.stride
596 fn get_top_strength(&self, pos: usize) -> u8 {
597 self.top_str[pos] & 3
599 fn get_left_strength(&self, pos: usize) -> u8 {
600 self.left_str[pos] & 3
602 fn set_top_strength(&mut self, pos: usize, str: u8) {
603 self.top_str[pos] |= str;
605 fn set_left_strength(&mut self, pos: usize, str: u8) {
606 self.left_str[pos] |= str;
610 struct RealVideo60Decoder {
611 info: NACodecInfoRef,
615 ipred: IntraPredContext,
617 avg_buf: NAVideoBuffer<u8>,
619 y_coeffs: [i16; 16 * 16],
620 u_coeffs: [i16; 8 * 8],
621 v_coeffs: [i16; 8 * 8],
625 cu_splits: Vec<bool>,
626 coded_blk: [bool; 64],
629 pu_info: Vec<PUInfo>,
633 blk_info: Vec<BlockInfo>,
641 impl RealVideo60Decoder {
643 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
644 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
645 let vb = vt.get_vbuf();
646 let avg_buf = vb.unwrap();
648 info: NACodecInfoRef::default(),
649 cbs: RV60Codebooks::init(),
650 ipbs: IPBShuffler::new(),
651 ipred: IntraPredContext::new(),
654 y_coeffs: [0; 16 * 16],
655 u_coeffs: [0; 8 * 8],
656 v_coeffs: [0; 8 * 8],
659 cu_splits: Vec::with_capacity(24),
660 coded_blk: [false; 64],
661 dblk: DeblockInfo::new(),
665 blk_info: Vec::new(),
672 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
673 let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
674 let cu_w = hdr.get_width_cu();
675 let dqp = hdr.read_line_qp_offset(&mut br)?;
676 let qps = (hdr.qp as i8) + dqp;
677 validate!((qps >= 0) && (qps < 32));
680 self.sel_qp = match hdr.osvquant {
700 for cu_x in 0..cu_w {
701 self.cu_splits.clear();
702 self.coded_blk = [false; 64];
703 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
705 self.cu_splits.reverse();
706 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
710 println!(" left {} bits", br.left());
714 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
715 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
717 let size = 1 << log_size;
718 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
719 self.cu_splits.push(split);
721 let hsize = size >> 1;
722 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
723 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
724 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
725 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
727 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
728 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
729 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
732 self.reconstruct_info(hdr, &cbh, size)?;
734 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
737 let itype = self.blk_info[self.blk_pos].imode;
739 let dstride = buf.stride[0];
740 let off = xpos + ypos * dstride;
741 let dst = &mut buf.data;
742 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
743 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
746 let dstride = buf.stride[comp];
747 let soff = buf.offset[comp];
748 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
749 let mut dst = &mut buf.data;
750 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
751 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
755 let mut mv_x = xpos >> 2;
756 let mut mv_y = ypos >> 2;
757 let mut mv_pos = mv_x + mv_y * self.blk_stride;
758 for part_no in 0..cbh.pu_type.get_num_mvs() {
759 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
760 let mv = self.blk_info[mv_pos].mv;
767 if hdr.ftype != FrameType::B {
768 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
769 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
772 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
773 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
778 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
779 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
783 validate!(hdr.ftype == FrameType::B);
784 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
785 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
788 MVRef::Ref0AndBRef => {
789 validate!(hdr.ftype == FrameType::B);
790 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
791 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
793 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
794 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
796 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
801 if cbh.pu_type == PUType::Quarters {
806 mv_pos += mv_h * self.blk_stride - mv_w;
810 } else if cbh.pu_type.has_hor_split() {
811 mv_pos += mv_h * self.blk_stride;
813 } else if cbh.pu_type.has_ver_split() {
820 if cbh.ttype != TransformType::None {
821 self.y_coeffs = [0; 16 * 16];
822 self.u_coeffs = [0; 8 * 8];
823 self.v_coeffs = [0; 8 * 8];
825 let is_intra = cbh.cu_type == CUType::Intra;
826 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
828 TransformType::T4X4 => {
829 let subset = if is_intra { 0 } else { 2 };
833 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
838 self.coded_blk[cb_pos + 0] = true;
839 self.coded_blk[cb_pos + 1] = true;
840 self.coded_blk[cb_pos + 8] = true;
841 self.coded_blk[cb_pos + 9] = true;
842 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)?;
846 if ((cbp16 >> i) & 1) != 0 {
847 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
848 let dstride = buf.stride[0];
849 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
850 let mut dst = &mut buf.data;
851 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
858 let xoff = (xpos >> 1) + x * 4;
859 let yoff = (ypos >> 1) + y * 4;
860 if ((cbp16 >> (16 + i)) & 1) != 0 {
861 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
862 let dstride = buf.stride[1];
863 let off = buf.offset[1] + xoff + yoff * dstride;
864 let mut dst = &mut buf.data;
865 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
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 mut dst = &mut buf.data;
872 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
878 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
880 self.coded_blk[cb_pos] = true;
881 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)?;
884 let xoff = (i & 1) * 4;
885 let yoff = (i & 2) * 2;
887 let dstride = buf.stride[0];
888 let off = xpos + xoff + (ypos + yoff) * dstride;
889 let mut dst = &mut buf.data;
890 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
891 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
892 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
894 if ((cbp8 >> i) & 1) != 0 {
895 let blk = &mut self.y_coeffs[i * 16..][..16];
896 self.dsp.transform4x4(blk);
897 let dstride = buf.stride[0];
898 let soff = buf.offset[0];
899 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
900 let mut dst = &mut buf.data;
901 self.dsp.add_block(&mut dst, 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 let mut dst = &mut buf.data;
910 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
912 if ((cbp8 >> 5) & 1) != 0 {
913 self.dsp.transform4x4(&mut self.v_coeffs);
914 let dstride = buf.stride[2];
915 let soff = buf.offset[2];
916 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
917 let mut dst = &mut buf.data;
918 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
922 TransformType::T8X8 => {
923 let subset = if is_intra { 1 } else { 3 };
924 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
926 self.coded_blk[cb_pos] = true;
927 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)?;
928 if (cbp8 & 0xF) != 0 {
929 self.dsp.transform8x8(&mut self.y_coeffs);
930 let dstride = buf.stride[0];
931 let off = xpos + ypos * dstride;
932 let mut dst = &mut buf.data;
933 self.dsp.add_block(&mut dst, 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 let mut dst = &mut buf.data;
941 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
943 if ((cbp8 >> 5) & 1) != 0 {
944 self.dsp.transform4x4(&mut self.v_coeffs);
945 let dstride = buf.stride[2];
946 let soff = buf.offset[2];
947 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
948 let mut dst = &mut buf.data;
949 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
953 TransformType::T16X16 => {
954 let subset = if is_intra { 1 } else { 3 };
955 let num_clusters = size >> 4;
956 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
957 for y in 0..num_clusters {
958 for x in 0..num_clusters {
959 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
960 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
961 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
962 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
963 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
964 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
966 self.y_coeffs = [0; 16 * 16];
967 self.u_coeffs = [0; 8 * 8];
968 self.v_coeffs = [0; 8 * 8];
969 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)?;
970 if (super_cbp & 0xFFFF) != 0 {
971 self.dsp.transform16x16(&mut self.y_coeffs);
972 let dstride = buf.stride[0];
973 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
974 let mut dst = &mut buf.data;
975 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
977 if ((super_cbp >> 16) & 0xF) != 0 {
978 self.dsp.transform8x8(&mut self.u_coeffs);
979 let dstride = buf.stride[1];
980 let soff = buf.offset[1];
981 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
982 let mut dst = &mut buf.data;
983 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
985 if ((super_cbp >> 20) & 0xF) != 0 {
986 self.dsp.transform8x8(&mut self.v_coeffs);
987 let dstride = buf.stride[2];
988 let soff = buf.offset[2];
989 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
990 let mut dst = &mut buf.data;
991 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1002 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1003 let mut pui = PUInfo::default();
1004 let pu_size = size >> 3;
1005 pui.cu_type = cbh.cu_type;
1006 pui.ttype = cbh.ttype;
1007 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1008 self.pu_info[self.pu_pos] = pui;
1011 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1012 validate!(imode <= MAX_IMODE);
1013 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1014 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1021 self.pu_info[self.pu_pos] = pui;
1022 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1023 validate!(imode <= MAX_IMODE);
1024 for y in 0..(size >> 2) {
1025 for x in 0..(size >> 2) {
1026 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1030 CUType::InterMV => {
1031 let mut mv_x = self.xpos >> 2;
1032 let mut mv_y = self.ypos >> 2;
1033 let mut mv_pos = self.blk_pos;
1034 let pu_type = cbh.pu_type;
1035 for part_no in 0..pu_type.get_num_mvs() {
1036 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1037 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1040 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1043 if pu_type == PUType::Quarters {
1048 mv_pos += mv_h * self.blk_stride - mv_w;
1052 } else if pu_type.has_hor_split() {
1053 mv_pos += mv_h * self.blk_stride;
1055 } else if pu_type.has_ver_split() {
1062 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1063 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1064 self.fill_skip_cand(hdr, &mut skip_cand, size);
1065 let mv = skip_cand.list[skip_idx];
1067 let mv_size = size >> 2;
1068 for y in 0..mv_size {
1069 for x in 0..mv_size {
1070 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1075 for y in 0..pu_size {
1076 for x in 0..pu_size {
1077 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1082 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1083 match cbh.imode[0] {
1084 IntraMode::DC64 => { return 1; },
1085 IntraMode::Plane64 => { return 0; },
1088 // form list of predictors
1089 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1090 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1091 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1092 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1094 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1097 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1098 let pu = &self.pu_info[self.pu_pos - 1];
1100 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1103 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1104 let tl_y = self.ypos + (sub & 2) * 4;
1105 if (tl_x > 0) && (tl_y > 0) {
1106 let pu = match sub {
1107 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1108 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1109 2 => &self.pu_info[self.pu_pos - 1],
1110 _ => &self.pu_info[self.pu_pos - 1],
1114 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1116 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1120 for el in RV60_CANDIDATE_INTRA_ANGLES.into_iter() {
1123 // actually decode prediction mode
1124 match cbh.imode[sub] {
1125 IntraMode::Index(idx) => {
1126 ipm_cand.list[idx as usize]
1128 IntraMode::Mode(mode) => {
1129 let mut imode = mode;
1130 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1132 for ic in ipm_cs.into_iter() {
1139 _ => unreachable!(),
1142 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1143 let src_off = if is_luma {
1144 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1146 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1148 self.ipred = IntraPredContext::new();
1149 if (self.ypos + yoff) > 0 {
1150 self.ipred.has_t = true;
1152 self.ipred.t[x + 1] = src[src_off - stride + x];
1154 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1155 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1156 self.ipred.has_tr = true;
1157 for x in size..size*2 {
1158 self.ipred.t[x + 1] = src[src_off - stride + x];
1162 self.ipred.t[size + i + 1] = self.ipred.t[size];
1165 if (self.xpos + xoff) > 0 {
1166 self.ipred.t[0] = src[src_off - stride - 1];
1169 if (self.xpos + xoff) > 0 {
1170 self.ipred.has_l = true;
1172 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1174 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1175 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1176 self.ipred.has_ld = true;
1177 for y in size..size*2 {
1178 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1182 self.ipred.l[size + i + 1] = self.ipred.l[size];
1185 if (self.ypos + yoff) > 0 {
1186 self.ipred.l[0] = src[src_off - stride - 1];
1190 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1191 let mv_pos = mv_x + mv_y * self.blk_stride;
1194 if mvi.mvref.is_fwd() {
1195 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1196 let mut mv_cand_size: usize = 0;
1198 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1199 if ref_mv.matches_fwd(mvi.mvref) {
1200 mv_cand[mv_cand_size] = ref_mv.f_mv;
1205 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1206 if ref_mv.matches_fwd(mvi.mvref) {
1207 mv_cand[mv_cand_size] = ref_mv.f_mv;
1211 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1212 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1213 if ref_mv.matches_fwd(mvi.mvref) {
1214 mv_cand[mv_cand_size] = ref_mv.f_mv;
1218 f_mv = match mv_cand_size {
1220 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1221 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1222 if mv_cand_size == 1 {
1225 MV { x: x >> 1, y: y >> 1 }
1228 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1234 if mvi.mvref.is_bwd() {
1235 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1236 let mut mv_cand_size: usize = 0;
1238 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1239 if ref_mv.matches_bwd(mvi.mvref) {
1240 mv_cand[mv_cand_size] = ref_mv.b_mv;
1245 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1246 if ref_mv.matches_bwd(mvi.mvref) {
1247 mv_cand[mv_cand_size] = ref_mv.b_mv;
1251 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1252 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1253 if ref_mv.matches_bwd(mvi.mvref) {
1254 mv_cand[mv_cand_size] = ref_mv.b_mv;
1258 b_mv = match mv_cand_size {
1260 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1261 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1262 if mv_cand_size == 1 {
1265 MV { x: x >> 1, y: y >> 1 }
1268 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1275 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1277 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1278 let mv_size = size >> 2;
1281 let mv = &self.blk_info[self.blk_pos - 1].mv;
1287 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1292 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1293 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1298 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1299 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1304 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1305 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1310 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1311 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1316 if (self.xpos > 0) && (self.ypos > 0) {
1317 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1322 for i in skip_cand.fill..4 {
1323 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1326 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1327 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1328 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1330 let hsize = 1 << (log_size - 1);
1331 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1332 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1333 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1334 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1336 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1337 let cu_type = self.pu_info[pu_pos].cu_type;
1338 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1339 let ntiles = 1 << (log_size - tsize);
1340 let dparams = RV60DeblockParams {
1341 deblock_chroma: hdr.deblock_chroma,
1344 dblkstride: self.dblk.stride,
1346 for ty in 0..ntiles {
1347 for tx in 0..ntiles {
1348 let x = xpos + (tx << tsize);
1349 let y = ypos + (ty << tsize);
1350 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1351 if cu_type == CUType::Intra {
1352 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1353 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1354 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1356 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1357 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1359 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1360 self.dblk.top_str.as_slice(),
1361 self.dblk.left_str.as_slice(),
1362 self.dblk.get_pos(x, y));
1367 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1368 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1369 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1371 let top_blk_pos = blk_pos - self.blk_stride;
1373 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1374 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1375 self.dblk.set_top_strength(dblk_pos + i, 1);
1382 if self.dblk.get_left_strength(dblk_pos) == 0 {
1383 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1384 self.dblk.set_left_strength(dblk_pos, 1);
1387 dblk_pos += self.dblk.stride;
1393 impl NADecoder for RealVideo60Decoder {
1394 fn init(&mut self, info: NACodecInfoRef) -> DecoderResult<()> {
1395 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
1396 let fmt = YUV420_FORMAT;
1397 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1398 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1400 let edata = info.get_extradata().unwrap();
1401 let src: &[u8] = &edata;
1403 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1404 let mut mr = MemoryReader::new_read(src);
1405 let mut br = ByteReader::new(&mut mr);
1406 let _flags = br.read_u32be()?;
1407 let version = br.read_u32be()?;
1408 let _unk = br.read_u16be()?;
1409 validate!((version >> 28) == 4);
1410 // then width and height again as 16be
1412 //self.bd.width = vinfo.get_width();
1413 //self.bd.height = vinfo.get_height();
1414 //self.frmmgr.clear();
1418 Err(DecoderError::InvalidData)
1421 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1422 let src = pkt.get_buffer();
1424 validate!(src.len() > 9);
1425 let hsize = (src[0] as usize) * 8 + 9;
1426 let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
1427 let hdr = FrameHeader::read(&mut br)?;
1428 let mut slices: Vec<usize> = Vec::new();
1429 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1431 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1432 let res = alloc_video_buffer(tmp_vinfo, 6);
1433 if !res.is_ok() { return Err(DecoderError::InvalidData); }
1434 let bufinfo = res.unwrap();
1435 let mut buf = bufinfo.get_vbuf().unwrap();
1437 let cu_w = hdr.get_width_cu();
1438 let cu_h = hdr.get_height_cu();
1439 self.pu_stride = cu_w << 3;
1440 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1441 self.blk_stride = cu_w << 4;
1442 self.blk_info.truncate(0);
1443 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1445 self.dblk.reinit(hdr.width, hdr.height);
1447 let mut off = hsize + ((br.tell() >> 3) as usize);
1448 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1449 for (cu_y, size) in slices.into_iter().enumerate() {
1450 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1453 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1454 self.ipbs.add_frame(buf);
1457 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1458 frm.set_keyframe(hdr.ftype == FrameType::I);
1459 frm.set_pts(Some(hdr.ts as u64));
1460 frm.set_frame_type(hdr.ftype);
1465 pub fn get_decoder() -> Box<NADecoder> {
1466 Box::new(RealVideo60Decoder::new())
1471 use nihav_core::codecs::RegisteredDecoders;
1472 use nihav_core::demuxers::RegisteredDemuxers;
1473 use nihav_core::test::dec_video::*;
1474 use crate::codecs::realmedia_register_all_codecs;
1475 use crate::demuxers::realmedia_register_all_demuxers;
1478 let mut dmx_reg = RegisteredDemuxers::new();
1479 realmedia_register_all_demuxers(&mut dmx_reg);
1480 let mut dec_reg = RegisteredDecoders::new();
1481 realmedia_register_all_codecs(&mut dec_reg);
1483 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);