2 use std::cell::RefCell;
3 use nihav_core::formats::YUV420_FORMAT;
4 use nihav_core::frame::*;
5 use nihav_core::codecs::{NADecoder, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
6 use nihav_core::io::byteio::{MemoryReader,ByteReader};
7 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
8 use nihav_core::io::intcode::*;
10 use super::rv60codes::*;
11 use super::rv60dsp::*;
13 struct UniqueList<A> {
19 impl<A:Copy+Default+PartialEq> UniqueList<A> {
20 fn new(max_size: usize) -> Self {
21 Self { list: [A::default(); 4], fill: 0, max_size }
23 fn add(&mut self, cand: A) {
24 if self.fill == self.max_size { return; }
25 let mut unique = true;
26 for el in self.list.into_iter().take(self.fill) {
33 self.list[self.fill] = cand;
39 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
40 const MAX_IMODE: u8 = 34;
42 #[derive(Clone,Copy,Debug)]
57 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
59 fn read(br: &mut BitReader) -> DecoderResult<Self> {
60 let marker = br.read(2)?;
61 validate!(marker == 3);
62 let profile = br.read(2)? as u8;
63 validate!(profile == 0);
64 let _someval = br.read(4)?;
65 let ftypeid = br.read(2)? as usize;
66 let ftype = RV60_FRAME_TYPES[ftypeid];
67 let qp = br.read(6)? as u8;
68 let marker = br.read(1)?;
69 validate!(marker == 0);
70 let toolset = br.read(2)?;
71 validate!(toolset == 0);
72 let osvquant = br.read(2)? as u8;
73 let _some_flag = br.read_bool()?;
74 let _some_val = br.read(2)?;
75 let ts = br.read(24)?;
76 let width = ((br.read(11)? as usize) + 1) * 4;
77 let height = ((br.read(11)? as usize) + 0) * 4;
78 validate!(height > 0);
79 let _some_flag = br.read_bool()?;
81 if ftype == FrameType::I {
85 let flag = br.read_bool()?;
92 two_f_refs = br.read_bool()?;
94 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
95 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
96 let chroma_qp_diff = br.read(1)?;
97 validate!(chroma_qp_diff == 0);
98 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
99 let deblock = br.read_bool()?;
100 let deblock_chroma = deblock && !br.read_bool()?;
102 let custom_msg_hdr_len = br.read(2)? as usize;
103 if custom_msg_hdr_len != 0 {
104 for i in 0..custom_msg_hdr_len {
105 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
111 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
112 deblock, deblock_chroma,
115 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
116 let nslices = self.get_height_cu();
117 let nbits = (br.read(5)? as u8) + 1;
118 validate!(nbits < 32);
119 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
120 for _ in 0..nslices {
121 let sign = br.read_bool()?;
127 let first_size = br.read(nbits)? as usize;
128 validate!(first_size > 0);
130 let mut lastsize = first_size;
131 sizes.push(first_size);
132 for i in 1..nslices {
133 let diff = br.read(nbits)? as isize;
136 let sum = (lastsize as isize).checked_add(diff);
137 validate!(sum.is_some());
138 size = sum.unwrap() as usize;
140 let sum = (lastsize as isize).checked_sub(diff);
141 validate!(sum.is_some());
142 size = sum.unwrap() as usize;
149 if ((br.left() >> 3) as usize) != sum {
150 println!(" left {} / {}", br.left() >> 3, sum);
152 validate!((br.left() >> 3) >= (sum as isize));
155 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
156 match self.qp_off_type {
159 let val = br.read_code(UintCodeType::Unary012)?;
167 if br.read(1)? == 0 {
170 let val = br.read(2)? as i8;
180 fn get_width_cu(&self) -> usize {
181 (self.width + 63) >> 6
183 fn get_height_cu(&self) -> usize {
184 (self.height + 63) >> 6
186 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
187 if (ypos + dy) == 0 { return false; }
188 let xpos2 = xpos + dx;
189 if (xpos2 + size) > self.width { return false; }
192 fn has_top_right_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 * 2) > self.width { return false; }
196 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
197 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
198 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
200 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
201 if (xpos + dx) == 0 { return false; }
202 let ypos2 = ypos + dy;
203 if (ypos2 + size) > self.height { return false; }
206 fn has_left_down_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 * 2) > self.height { return false; }
210 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
211 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
212 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
216 const RV60_BLOCK_LOG2: [u8; 65] = [
218 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
223 const RV60_AVAIL_MASK: [u8; 64] = [
224 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 0
230 #[derive(Clone,Copy,PartialEq,Debug)]
238 impl Default for CUType {
239 fn default() -> Self { CUType::Intra }
242 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
244 #[derive(Clone,Copy,PartialEq,Debug)]
256 const RV60_PU_TYPES: [PUType; 8] = [
257 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
258 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
262 fn get_num_mvs(&self) -> usize {
265 PUType::Quarters => 4,
269 fn get_mv_size(&self, part_no: usize, size: usize) -> (usize, usize) {
270 let mv_size = size >> 2;
272 PUType::Full => (mv_size, mv_size),
273 PUType::N2Hor => (mv_size, mv_size >> 1),
274 PUType::N2Ver => (mv_size >> 1, mv_size),
275 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
278 (mv_size, mv_size >> 2)
280 (mv_size, 3 * mv_size >> 2)
285 (mv_size, 3 * mv_size >> 2)
287 (mv_size, mv_size >> 2)
292 ( mv_size >> 2, mv_size)
294 (3 * mv_size >> 2, mv_size)
299 (3 * mv_size >> 2, mv_size)
301 ( mv_size >> 2, mv_size)
306 fn has_hor_split(&self) -> bool {
308 PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
312 fn has_ver_split(&self) -> bool {
314 PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
320 impl Default for PUType {
321 fn default() -> Self { PUType::Full }
324 #[derive(Clone,Copy,Debug)]
332 #[derive(Clone,Copy,PartialEq,Debug)]
340 impl Default for TransformType {
341 fn default() -> Self { TransformType::None }
344 #[derive(Clone,Copy,PartialEq,Debug)]
357 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
360 fn get_skip_mv_num(&self) -> usize {
368 fn is_ref0(&self) -> bool {
370 MVRef::Ref0 | MVRef::Ref0AndBRef => true,
374 fn is_fwd(&self) -> bool {
376 MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
380 fn is_bwd(&self) -> bool {
382 MVRef::BRef | MVRef::Ref0AndBRef => true,
388 #[derive(Clone,Copy,PartialEq,Debug)]
396 fn is_some(&self) -> bool { self.mvref != MVRef::None }
397 fn matches_fwd(&self, mvref: MVRef) -> bool {
398 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
400 fn matches_bwd(&self, mvref: MVRef) -> bool {
401 self.mvref.is_bwd() && mvref.is_bwd()
403 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
404 if self.mvref != other.mvref { return true; }
406 if self.mvref.is_fwd() {
407 let diff = self.f_mv - other.f_mv;
408 mvdiff += diff.x.abs() + diff.y.abs();
410 if self.mvref.is_bwd() {
411 let diff = self.b_mv - other.b_mv;
412 mvdiff += diff.x.abs() + diff.y.abs();
418 impl Default for MVInfo {
419 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
422 #[derive(Clone,Copy,Debug)]
426 ttype: TransformType,
427 imode: [IntraMode; 4],
432 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
435 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
436 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
437 if ftype == FrameType::I {
438 cu_type = CUType::Intra;
440 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
444 if (size == 8) && br.read_bool()? {
445 pu_type = PUType::Quarters;
447 pu_type = PUType::Full;
449 if pu_type == PUType::Quarters {
451 imode[i] = CBHeader::read_intra_mode(br)?;
453 } else if size <= 32 {
454 imode[0] = CBHeader::read_intra_mode(br)?;
456 if !br.read_bool()? {
457 imode[0] = IntraMode::DC64;
459 imode[0] = IntraMode::Plane64;
464 let bits = if size == 8 { 2 } else { 3 };
465 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
466 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
469 pu_type = PUType::Full;
470 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
471 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
475 if cu_type == CUType::Skip {
476 ttype = TransformType::None;
477 } else if size >= 32 {
478 ttype = TransformType::T16X16;
479 } else if size == 16 {
480 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
481 ttype = TransformType::T16X16;
483 ttype = TransformType::T4X4;
486 if pu_type == PUType::Full {
487 ttype = TransformType::T8X8;
489 ttype = TransformType::T4X4;
493 cu_type, pu_type, ttype, imode, mv,
496 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
498 let idx = br.read_code(UintCodeType::Unary012)? as u8;
499 Ok(IntraMode::Index(idx))
501 let mode = br.read(5)? as u8;
502 Ok(IntraMode::Mode(mode))
505 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
506 let mv_count = pu_type.get_num_mvs();
507 for i in 0..mv_count {
508 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
512 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
513 let mut f_mv = ZERO_MV;
514 let mut b_mv = ZERO_MV;
516 if ftype != FrameType::B {
517 if two_f_refs && br.read_bool()? {
522 f_mv = CBHeader::read_mv(br)?;
523 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
525 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
526 if !br.read_bool()? {
528 f_mv = CBHeader::read_mv(br)?;
531 b_mv = CBHeader::read_mv(br)?;
534 mvref = MVRef::Ref0AndBRef;
535 f_mv = CBHeader::read_mv(br)?;
536 b_mv = CBHeader::read_mv(br)?;
538 Ok(MVInfo { f_mv, b_mv, mvref })
541 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
542 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
543 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
548 #[derive(Clone,Copy,Default)]
551 ttype: TransformType,
555 fn is_intra(&self) -> bool { self.cu_type == CUType::Intra }
558 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
560 #[derive(Clone,Copy,Default)]
574 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
576 fn reinit(&mut self, w: usize, h: usize) {
577 self.left_str.clear();
578 self.top_str.clear();
579 self.stride = w >> 2;
580 let size = self.stride * (h >> 2);
581 self.left_str.resize(size, 0);
582 self.top_str.resize(size, 0);
584 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
585 let pos = self.get_pos(xpos, ypos);
586 let dsize = size >> 2;
587 let dval = (q << 2) | strength;
589 self.top_str[pos + x] = dval;
592 self.left_str[pos + y * self.stride] = dval;
595 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
596 (xpos >> 2) + (ypos >> 2) * self.stride
598 fn get_top_strength(&self, pos: usize) -> u8 {
599 self.top_str[pos] & 3
601 fn get_left_strength(&self, pos: usize) -> u8 {
602 self.left_str[pos] & 3
604 fn set_top_strength(&mut self, pos: usize, str: u8) {
605 self.top_str[pos] |= str;
607 fn set_left_strength(&mut self, pos: usize, str: u8) {
608 self.left_str[pos] |= str;
612 struct RealVideo60Decoder {
613 info: Rc<NACodecInfo>,
617 ipred: IntraPredContext,
619 avg_buf: NAVideoBuffer<u8>,
621 y_coeffs: [i16; 16 * 16],
622 u_coeffs: [i16; 8 * 8],
623 v_coeffs: [i16; 8 * 8],
627 cu_splits: Vec<bool>,
628 coded_blk: [bool; 64],
631 pu_info: Vec<PUInfo>,
635 blk_info: Vec<BlockInfo>,
643 impl RealVideo60Decoder {
645 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
646 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
647 let vb = vt.get_vbuf();
648 let avg_buf = vb.unwrap();
650 info: Rc::new(DUMMY_CODEC_INFO),
651 cbs: RV60Codebooks::init(),
652 ipbs: IPBShuffler::new(),
653 ipred: IntraPredContext::new(),
656 y_coeffs: [0; 16 * 16],
657 u_coeffs: [0; 8 * 8],
658 v_coeffs: [0; 8 * 8],
661 cu_splits: Vec::with_capacity(24),
662 coded_blk: [false; 64],
663 dblk: DeblockInfo::new(),
667 blk_info: Vec::new(),
674 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
675 let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
676 let cu_w = hdr.get_width_cu();
677 let dqp = hdr.read_line_qp_offset(&mut br)?;
678 let qps = (hdr.qp as i8) + dqp;
679 validate!((qps >= 0) && (qps < 32));
682 self.sel_qp = match hdr.osvquant {
702 for cu_x in 0..cu_w {
703 self.cu_splits.clear();
704 self.coded_blk = [false; 64];
705 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
707 self.cu_splits.reverse();
708 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
712 println!(" left {} bits", br.left());
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.width) || (ypos >= hdr.height) { return Ok(()); }
719 let size = 1 << log_size;
720 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (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 mut dst = &mut buf.data;
752 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
753 self.ipred.pred_angle(&mut 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 self.coded_blk[cb_pos + 0] = true;
841 self.coded_blk[cb_pos + 1] = true;
842 self.coded_blk[cb_pos + 8] = true;
843 self.coded_blk[cb_pos + 9] = true;
844 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)?;
848 if ((cbp16 >> i) & 1) != 0 {
849 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
850 let dstride = buf.stride[0];
851 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
852 let mut dst = &mut buf.data;
853 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
860 let xoff = (xpos >> 1) + x * 4;
861 let yoff = (ypos >> 1) + y * 4;
862 if ((cbp16 >> (16 + i)) & 1) != 0 {
863 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
864 let dstride = buf.stride[1];
865 let off = buf.offset[1] + xoff + yoff * dstride;
866 let mut dst = &mut buf.data;
867 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
869 if ((cbp16 >> (20 + i)) & 1) != 0 {
870 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
871 let dstride = buf.stride[2];
872 let off = buf.offset[2] + xoff + yoff * dstride;
873 let mut dst = &mut buf.data;
874 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
880 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
882 self.coded_blk[cb_pos] = true;
883 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)?;
886 let xoff = (i & 1) * 4;
887 let yoff = (i & 2) * 2;
889 let dstride = buf.stride[0];
890 let off = xpos + xoff + (ypos + yoff) * dstride;
891 let mut dst = &mut buf.data;
892 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
893 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
894 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
896 if ((cbp8 >> i) & 1) != 0 {
897 let blk = &mut self.y_coeffs[i * 16..][..16];
898 self.dsp.transform4x4(blk);
899 let dstride = buf.stride[0];
900 let soff = buf.offset[0];
901 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
902 let mut dst = &mut buf.data;
903 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
906 if ((cbp8 >> 4) & 1) != 0 {
907 self.dsp.transform4x4(&mut self.u_coeffs);
908 let dstride = buf.stride[1];
909 let soff = buf.offset[1];
910 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
911 let mut dst = &mut buf.data;
912 self.dsp.add_block(&mut dst, 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 let mut dst = &mut buf.data;
920 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
924 TransformType::T8X8 => {
925 let subset = if is_intra { 1 } else { 3 };
926 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
928 self.coded_blk[cb_pos] = true;
929 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)?;
930 if (cbp8 & 0xF) != 0 {
931 self.dsp.transform8x8(&mut self.y_coeffs);
932 let dstride = buf.stride[0];
933 let off = xpos + ypos * dstride;
934 let mut dst = &mut buf.data;
935 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
937 if ((cbp8 >> 4) & 1) != 0 {
938 self.dsp.transform4x4(&mut self.u_coeffs);
939 let dstride = buf.stride[1];
940 let soff = buf.offset[1];
941 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
942 let mut dst = &mut buf.data;
943 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
945 if ((cbp8 >> 5) & 1) != 0 {
946 self.dsp.transform4x4(&mut self.v_coeffs);
947 let dstride = buf.stride[2];
948 let soff = buf.offset[2];
949 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
950 let mut dst = &mut buf.data;
951 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
955 TransformType::T16X16 => {
956 let subset = if is_intra { 1 } else { 3 };
957 let num_clusters = size >> 4;
958 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
959 for y in 0..num_clusters {
960 for x in 0..num_clusters {
961 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
962 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
963 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
964 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
965 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
966 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
968 self.y_coeffs = [0; 16 * 16];
969 self.u_coeffs = [0; 8 * 8];
970 self.v_coeffs = [0; 8 * 8];
971 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)?;
972 if (super_cbp & 0xFFFF) != 0 {
973 self.dsp.transform16x16(&mut self.y_coeffs);
974 let dstride = buf.stride[0];
975 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
976 let mut dst = &mut buf.data;
977 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
979 if ((super_cbp >> 16) & 0xF) != 0 {
980 self.dsp.transform8x8(&mut self.u_coeffs);
981 let dstride = buf.stride[1];
982 let soff = buf.offset[1];
983 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
984 let mut dst = &mut buf.data;
985 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
987 if ((super_cbp >> 20) & 0xF) != 0 {
988 self.dsp.transform8x8(&mut self.v_coeffs);
989 let dstride = buf.stride[2];
990 let soff = buf.offset[2];
991 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
992 let mut dst = &mut buf.data;
993 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1004 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1005 let mut pui = PUInfo::default();
1006 let pu_size = size >> 3;
1007 pui.cu_type = cbh.cu_type;
1008 pui.ttype = cbh.ttype;
1009 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1010 self.pu_info[self.pu_pos] = pui;
1013 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1014 validate!(imode <= MAX_IMODE);
1015 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1016 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1023 self.pu_info[self.pu_pos] = pui;
1024 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1025 validate!(imode <= MAX_IMODE);
1026 for y in 0..(size >> 2) {
1027 for x in 0..(size >> 2) {
1028 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1032 CUType::InterMV => {
1033 let mut mv_x = self.xpos >> 2;
1034 let mut mv_y = self.ypos >> 2;
1035 let mut mv_pos = self.blk_pos;
1036 let pu_type = cbh.pu_type;
1037 for part_no in 0..pu_type.get_num_mvs() {
1038 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1039 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1042 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1045 if pu_type == PUType::Quarters {
1050 mv_pos += mv_h * self.blk_stride - mv_w;
1054 } else if pu_type.has_hor_split() {
1055 mv_pos += mv_h * self.blk_stride;
1057 } else if pu_type.has_ver_split() {
1064 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1065 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1066 self.fill_skip_cand(hdr, &mut skip_cand, size);
1067 let mv = skip_cand.list[skip_idx];
1069 let mv_size = size >> 2;
1070 for y in 0..mv_size {
1071 for x in 0..mv_size {
1072 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1077 for y in 0..pu_size {
1078 for x in 0..pu_size {
1079 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1084 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1085 match cbh.imode[0] {
1086 IntraMode::DC64 => { return 1; },
1087 IntraMode::Plane64 => { return 0; },
1090 // form list of predictors
1091 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1092 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1093 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1094 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1096 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1099 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1100 let pu = &self.pu_info[self.pu_pos - 1];
1102 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1105 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1106 let tl_y = self.ypos + (sub & 2) * 4;
1107 if (tl_x > 0) && (tl_y > 0) {
1108 let pu = match sub {
1109 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1110 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1111 2 => &self.pu_info[self.pu_pos - 1],
1112 _ => &self.pu_info[self.pu_pos - 1],
1116 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1118 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1122 for el in RV60_CANDIDATE_INTRA_ANGLES.into_iter() {
1125 // actually decode prediction mode
1126 match cbh.imode[sub] {
1127 IntraMode::Index(idx) => {
1128 ipm_cand.list[idx as usize]
1130 IntraMode::Mode(mode) => {
1131 let mut imode = mode;
1132 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1134 for ic in ipm_cs.into_iter() {
1141 _ => unreachable!(),
1144 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1145 let src_off = if is_luma {
1146 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1148 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1150 self.ipred = IntraPredContext::new();
1151 if (self.ypos + yoff) > 0 {
1152 self.ipred.has_t = true;
1154 self.ipred.t[x + 1] = src[src_off - stride + x];
1156 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1157 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1158 self.ipred.has_tr = true;
1159 for x in size..size*2 {
1160 self.ipred.t[x + 1] = src[src_off - stride + x];
1164 self.ipred.t[size + i + 1] = self.ipred.t[size];
1167 if (self.xpos + xoff) > 0 {
1168 self.ipred.t[0] = src[src_off - stride - 1];
1171 if (self.xpos + xoff) > 0 {
1172 self.ipred.has_l = true;
1174 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1176 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1177 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1178 self.ipred.has_ld = true;
1179 for y in size..size*2 {
1180 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1184 self.ipred.l[size + i + 1] = self.ipred.l[size];
1187 if (self.ypos + yoff) > 0 {
1188 self.ipred.l[0] = src[src_off - stride - 1];
1192 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1193 let mv_pos = mv_x + mv_y * self.blk_stride;
1196 if mvi.mvref.is_fwd() {
1197 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1198 let mut mv_cand_size: usize = 0;
1200 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1213 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1214 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1215 if ref_mv.matches_fwd(mvi.mvref) {
1216 mv_cand[mv_cand_size] = ref_mv.f_mv;
1220 f_mv = match mv_cand_size {
1222 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1223 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1224 if mv_cand_size == 1 {
1227 MV { x: x >> 1, y: y >> 1 }
1230 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1236 if mvi.mvref.is_bwd() {
1237 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1238 let mut mv_cand_size: usize = 0;
1240 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1253 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1254 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1255 if ref_mv.matches_bwd(mvi.mvref) {
1256 mv_cand[mv_cand_size] = ref_mv.b_mv;
1260 b_mv = match mv_cand_size {
1262 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1263 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1264 if mv_cand_size == 1 {
1267 MV { x: x >> 1, y: y >> 1 }
1270 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1277 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1279 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1280 let mv_size = size >> 2;
1283 let mv = &self.blk_info[self.blk_pos - 1].mv;
1289 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1294 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1295 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1300 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1301 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1306 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1307 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1312 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1313 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1318 if (self.xpos > 0) && (self.ypos > 0) {
1319 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1324 for i in skip_cand.fill..4 {
1325 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1328 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1329 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1330 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1332 let hsize = 1 << (log_size - 1);
1333 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1334 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1335 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1336 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1338 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1339 let cu_type = self.pu_info[pu_pos].cu_type;
1340 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1341 let ntiles = 1 << (log_size - tsize);
1342 let dparams = RV60DeblockParams {
1343 deblock_chroma: hdr.deblock_chroma,
1346 dblkstride: self.dblk.stride,
1348 for ty in 0..ntiles {
1349 for tx in 0..ntiles {
1350 let x = xpos + (tx << tsize);
1351 let y = ypos + (ty << tsize);
1352 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1353 if cu_type == CUType::Intra {
1354 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1355 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1356 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1358 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1359 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1361 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1362 self.dblk.top_str.as_slice(),
1363 self.dblk.left_str.as_slice(),
1364 self.dblk.get_pos(x, y));
1369 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1370 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1371 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1373 let top_blk_pos = blk_pos - self.blk_stride;
1375 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1376 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1377 self.dblk.set_top_strength(dblk_pos + i, 1);
1384 if self.dblk.get_left_strength(dblk_pos) == 0 {
1385 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1386 self.dblk.set_left_strength(dblk_pos, 1);
1389 dblk_pos += self.dblk.stride;
1395 impl NADecoder for RealVideo60Decoder {
1396 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
1397 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
1398 let fmt = YUV420_FORMAT;
1399 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1400 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
1402 let edata = info.get_extradata().unwrap();
1403 let src: &[u8] = &edata;
1405 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1406 let mut mr = MemoryReader::new_read(src);
1407 let mut br = ByteReader::new(&mut mr);
1408 let _flags = br.read_u32be()?;
1409 let version = br.read_u32be()?;
1410 let _unk = br.read_u16be()?;
1411 validate!((version >> 28) == 4);
1412 // then width and height again as 16be
1414 //self.bd.width = vinfo.get_width();
1415 //self.bd.height = vinfo.get_height();
1416 //self.frmmgr.clear();
1420 Err(DecoderError::InvalidData)
1423 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1424 let src = pkt.get_buffer();
1426 validate!(src.len() > 9);
1427 let hsize = (src[0] as usize) * 8 + 9;
1428 let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
1429 let hdr = FrameHeader::read(&mut br)?;
1430 let mut slices: Vec<usize> = Vec::new();
1431 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1433 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1434 let res = alloc_video_buffer(tmp_vinfo, 6);
1435 if !res.is_ok() { return Err(DecoderError::InvalidData); }
1436 let bufinfo = res.unwrap();
1437 let mut buf = bufinfo.get_vbuf().unwrap();
1439 let cu_w = hdr.get_width_cu();
1440 let cu_h = hdr.get_height_cu();
1441 self.pu_stride = cu_w << 3;
1442 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1443 self.blk_stride = cu_w << 4;
1444 self.blk_info.truncate(0);
1445 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1447 self.dblk.reinit(hdr.width, hdr.height);
1449 let mut off = hsize + ((br.tell() >> 3) as usize);
1450 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1451 for (cu_y, size) in slices.into_iter().enumerate() {
1452 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1455 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1456 self.ipbs.add_frame(buf);
1459 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1460 frm.set_keyframe(hdr.ftype == FrameType::I);
1461 frm.set_pts(Some(hdr.ts as u64));
1462 frm.set_frame_type(hdr.ftype);
1463 Ok(Rc::new(RefCell::new(frm)))
1467 pub fn get_decoder() -> Box<NADecoder> {
1468 Box::new(RealVideo60Decoder::new())
1473 use nihav_core::codecs::RegisteredDecoders;
1474 use nihav_core::demuxers::RegisteredDemuxers;
1475 use nihav_core::test::dec_video::*;
1476 use crate::codecs::realmedia_register_all_codecs;
1477 use crate::demuxers::realmedia_register_all_demuxers;
1480 let mut dmx_reg = RegisteredDemuxers::new();
1481 realmedia_register_all_demuxers(&mut dmx_reg);
1482 let mut dec_reg = RegisteredDecoders::new();
1483 realmedia_register_all_codecs(&mut dec_reg);
1485 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);