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 NAVideoBuffer<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 NAVideoBuffer<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.get_stride(0);
742 let off = xpos + ypos * dstride;
743 let mut data = buf.get_data_mut().unwrap();
745 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
746 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
749 let dstride = buf.get_stride(comp);
750 let soff = buf.get_offset(comp);
751 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
752 let mut data = buf.get_data_mut().unwrap();
753 let mut dst = &mut data;
754 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
755 self.ipred.pred_angle(&mut 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);
796 self.dsp.do_mc(&mut self.avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
797 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
802 if cbh.pu_type == PUType::Quarters {
807 mv_pos += mv_h * self.blk_stride - mv_w;
811 } else if cbh.pu_type.has_hor_split() {
812 mv_pos += mv_h * self.blk_stride;
814 } else if cbh.pu_type.has_ver_split() {
821 if cbh.ttype != TransformType::None {
822 self.y_coeffs = [0; 16 * 16];
823 self.u_coeffs = [0; 8 * 8];
824 self.v_coeffs = [0; 8 * 8];
826 let is_intra = cbh.cu_type == CUType::Intra;
827 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
829 TransformType::T4X4 => {
830 let subset = if is_intra { 0 } else { 2 };
834 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
839 self.coded_blk[cb_pos + 0] = true;
840 self.coded_blk[cb_pos + 1] = true;
841 self.coded_blk[cb_pos + 8] = true;
842 self.coded_blk[cb_pos + 9] = true;
843 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)?;
847 if ((cbp16 >> i) & 1) != 0 {
848 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
849 let dstride = buf.get_stride(0);
850 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
851 let mut data = buf.get_data_mut().unwrap();
852 let mut dst = &mut 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.get_stride(1);
865 let off = buf.get_offset(1) + xoff + yoff * dstride;
866 let mut data = buf.get_data_mut().unwrap();
867 let mut dst = &mut data;
868 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
870 if ((cbp16 >> (20 + i)) & 1) != 0 {
871 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
872 let dstride = buf.get_stride(2);
873 let off = buf.get_offset(2) + xoff + yoff * dstride;
874 let mut data = buf.get_data_mut().unwrap();
875 let mut dst = &mut data;
876 self.dsp.add_block(&mut 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.get_stride(0);
892 let off = xpos + xoff + (ypos + yoff) * dstride;
893 let mut data = buf.get_data_mut().unwrap();
894 let mut dst = &mut data;
895 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
896 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
897 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
899 if ((cbp8 >> i) & 1) != 0 {
900 let blk = &mut self.y_coeffs[i * 16..][..16];
901 self.dsp.transform4x4(blk);
902 let dstride = buf.get_stride(0);
903 let soff = buf.get_offset(0);
904 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
905 let mut data = buf.get_data_mut().unwrap();
906 let mut dst = &mut data;
907 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
910 if ((cbp8 >> 4) & 1) != 0 {
911 self.dsp.transform4x4(&mut self.u_coeffs);
912 let dstride = buf.get_stride(1);
913 let soff = buf.get_offset(1);
914 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
915 let mut data = buf.get_data_mut().unwrap();
916 let mut dst = &mut data;
917 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
919 if ((cbp8 >> 5) & 1) != 0 {
920 self.dsp.transform4x4(&mut self.v_coeffs);
921 let dstride = buf.get_stride(2);
922 let soff = buf.get_offset(2);
923 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
924 let mut data = buf.get_data_mut().unwrap();
925 let mut dst = &mut data;
926 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
930 TransformType::T8X8 => {
931 let subset = if is_intra { 1 } else { 3 };
932 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
934 self.coded_blk[cb_pos] = true;
935 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)?;
936 if (cbp8 & 0xF) != 0 {
937 self.dsp.transform8x8(&mut self.y_coeffs);
938 let dstride = buf.get_stride(0);
939 let off = xpos + ypos * dstride;
940 let mut data = buf.get_data_mut().unwrap();
941 let mut dst = &mut data;
942 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
944 if ((cbp8 >> 4) & 1) != 0 {
945 self.dsp.transform4x4(&mut self.u_coeffs);
946 let dstride = buf.get_stride(1);
947 let soff = buf.get_offset(1);
948 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
949 let mut data = buf.get_data_mut().unwrap();
950 let mut dst = &mut data;
951 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
953 if ((cbp8 >> 5) & 1) != 0 {
954 self.dsp.transform4x4(&mut self.v_coeffs);
955 let dstride = buf.get_stride(2);
956 let soff = buf.get_offset(2);
957 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
958 let mut data = buf.get_data_mut().unwrap();
959 let mut dst = &mut data;
960 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
964 TransformType::T16X16 => {
965 let subset = if is_intra { 1 } else { 3 };
966 let num_clusters = size >> 4;
967 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
968 for y in 0..num_clusters {
969 for x in 0..num_clusters {
970 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
971 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
972 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
973 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
974 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
975 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
977 self.y_coeffs = [0; 16 * 16];
978 self.u_coeffs = [0; 8 * 8];
979 self.v_coeffs = [0; 8 * 8];
980 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)?;
981 if (super_cbp & 0xFFFF) != 0 {
982 self.dsp.transform16x16(&mut self.y_coeffs);
983 let dstride = buf.get_stride(0);
984 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
985 let mut data = buf.get_data_mut().unwrap();
986 let mut dst = &mut data;
987 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
989 if ((super_cbp >> 16) & 0xF) != 0 {
990 self.dsp.transform8x8(&mut self.u_coeffs);
991 let dstride = buf.get_stride(1);
992 let soff = buf.get_offset(1);
993 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
994 let mut data = buf.get_data_mut().unwrap();
995 let mut dst = &mut data;
996 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
998 if ((super_cbp >> 20) & 0xF) != 0 {
999 self.dsp.transform8x8(&mut self.v_coeffs);
1000 let dstride = buf.get_stride(2);
1001 let soff = buf.get_offset(2);
1002 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
1003 let mut data = buf.get_data_mut().unwrap();
1004 let mut dst = &mut data;
1005 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1016 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1017 let mut pui = PUInfo::default();
1018 let pu_size = size >> 3;
1019 pui.cu_type = cbh.cu_type;
1020 pui.ttype = cbh.ttype;
1021 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1022 self.pu_info[self.pu_pos] = pui;
1025 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1026 validate!(imode <= MAX_IMODE);
1027 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1028 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1035 self.pu_info[self.pu_pos] = pui;
1036 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1037 validate!(imode <= MAX_IMODE);
1038 for y in 0..(size >> 2) {
1039 for x in 0..(size >> 2) {
1040 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1044 CUType::InterMV => {
1045 let mut mv_x = self.xpos >> 2;
1046 let mut mv_y = self.ypos >> 2;
1047 let mut mv_pos = self.blk_pos;
1048 let pu_type = cbh.pu_type;
1049 for part_no in 0..pu_type.get_num_mvs() {
1050 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1051 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1054 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1057 if pu_type == PUType::Quarters {
1062 mv_pos += mv_h * self.blk_stride - mv_w;
1066 } else if pu_type.has_hor_split() {
1067 mv_pos += mv_h * self.blk_stride;
1069 } else if pu_type.has_ver_split() {
1076 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1077 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1078 self.fill_skip_cand(hdr, &mut skip_cand, size);
1079 let mv = skip_cand.list[skip_idx];
1081 let mv_size = size >> 2;
1082 for y in 0..mv_size {
1083 for x in 0..mv_size {
1084 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1089 for y in 0..pu_size {
1090 for x in 0..pu_size {
1091 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1096 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1097 match cbh.imode[0] {
1098 IntraMode::DC64 => { return 1; },
1099 IntraMode::Plane64 => { return 0; },
1102 // form list of predictors
1103 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1104 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1105 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1106 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1108 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1111 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1112 let pu = &self.pu_info[self.pu_pos - 1];
1114 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1117 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1118 let tl_y = self.ypos + (sub & 2) * 4;
1119 if (tl_x > 0) && (tl_y > 0) {
1120 let pu = match sub {
1121 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1122 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1123 2 => &self.pu_info[self.pu_pos - 1],
1124 _ => &self.pu_info[self.pu_pos - 1],
1128 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1130 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1134 for el in RV60_CANDIDATE_INTRA_ANGLES.into_iter() {
1137 // actually decode prediction mode
1138 match cbh.imode[sub] {
1139 IntraMode::Index(idx) => {
1140 ipm_cand.list[idx as usize]
1142 IntraMode::Mode(mode) => {
1143 let mut imode = mode;
1144 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1146 for ic in ipm_cs.into_iter() {
1153 _ => unreachable!(),
1156 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1157 let src_off = if is_luma {
1158 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1160 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1162 self.ipred = IntraPredContext::new();
1163 if (self.ypos + yoff) > 0 {
1164 self.ipred.has_t = true;
1166 self.ipred.t[x + 1] = src[src_off - stride + x];
1168 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1169 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1170 self.ipred.has_tr = true;
1171 for x in size..size*2 {
1172 self.ipred.t[x + 1] = src[src_off - stride + x];
1176 self.ipred.t[size + i + 1] = self.ipred.t[size];
1179 if (self.xpos + xoff) > 0 {
1180 self.ipred.t[0] = src[src_off - stride - 1];
1183 if (self.xpos + xoff) > 0 {
1184 self.ipred.has_l = true;
1186 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1188 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1189 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1190 self.ipred.has_ld = true;
1191 for y in size..size*2 {
1192 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1196 self.ipred.l[size + i + 1] = self.ipred.l[size];
1199 if (self.ypos + yoff) > 0 {
1200 self.ipred.l[0] = src[src_off - stride - 1];
1204 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1205 let mv_pos = mv_x + mv_y * self.blk_stride;
1208 if mvi.mvref.is_fwd() {
1209 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1210 let mut mv_cand_size: usize = 0;
1212 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1213 if ref_mv.matches_fwd(mvi.mvref) {
1214 mv_cand[mv_cand_size] = ref_mv.f_mv;
1219 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1220 if ref_mv.matches_fwd(mvi.mvref) {
1221 mv_cand[mv_cand_size] = ref_mv.f_mv;
1225 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1226 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1227 if ref_mv.matches_fwd(mvi.mvref) {
1228 mv_cand[mv_cand_size] = ref_mv.f_mv;
1232 f_mv = match mv_cand_size {
1234 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1235 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1236 if mv_cand_size == 1 {
1239 MV { x: x >> 1, y: y >> 1 }
1242 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1248 if mvi.mvref.is_bwd() {
1249 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1250 let mut mv_cand_size: usize = 0;
1252 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1253 if ref_mv.matches_bwd(mvi.mvref) {
1254 mv_cand[mv_cand_size] = ref_mv.b_mv;
1259 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1260 if ref_mv.matches_bwd(mvi.mvref) {
1261 mv_cand[mv_cand_size] = ref_mv.b_mv;
1265 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1266 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1267 if ref_mv.matches_bwd(mvi.mvref) {
1268 mv_cand[mv_cand_size] = ref_mv.b_mv;
1272 b_mv = match mv_cand_size {
1274 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1275 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1276 if mv_cand_size == 1 {
1279 MV { x: x >> 1, y: y >> 1 }
1282 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1289 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1291 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1292 let mv_size = size >> 2;
1295 let mv = &self.blk_info[self.blk_pos - 1].mv;
1301 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1306 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1307 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1312 if hdr.has_left_down_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 hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1319 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1324 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1325 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1330 if (self.xpos > 0) && (self.ypos > 0) {
1331 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1336 for i in skip_cand.fill..4 {
1337 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1340 fn deblock_cb_tree(&mut self, buf: &mut NAVideoBuffer<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1341 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1342 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1344 let hsize = 1 << (log_size - 1);
1345 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1346 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1347 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1348 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1350 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1351 let cu_type = self.pu_info[pu_pos].cu_type;
1352 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1353 let ntiles = 1 << (log_size - tsize);
1354 let dparams = RV60DeblockParams {
1355 deblock_chroma: hdr.deblock_chroma,
1358 dblkstride: self.dblk.stride,
1360 for ty in 0..ntiles {
1361 for tx in 0..ntiles {
1362 let x = xpos + (tx << tsize);
1363 let y = ypos + (ty << tsize);
1364 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1365 if cu_type == CUType::Intra {
1366 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1367 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1368 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1370 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1371 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1373 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1374 self.dblk.top_str.as_slice(),
1375 self.dblk.left_str.as_slice(),
1376 self.dblk.get_pos(x, y));
1381 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1382 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1383 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1385 let top_blk_pos = blk_pos - self.blk_stride;
1387 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1388 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1389 self.dblk.set_top_strength(dblk_pos + i, 1);
1396 if self.dblk.get_left_strength(dblk_pos) == 0 {
1397 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1398 self.dblk.set_left_strength(dblk_pos, 1);
1401 dblk_pos += self.dblk.stride;
1407 impl NADecoder for RealVideo60Decoder {
1408 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
1409 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
1410 let fmt = YUV420_FORMAT;
1411 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1412 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
1414 let edata = info.get_extradata().unwrap();
1415 let src: &[u8] = &edata;
1417 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1418 let mut mr = MemoryReader::new_read(src);
1419 let mut br = ByteReader::new(&mut mr);
1420 let _flags = br.read_u32be()?;
1421 let version = br.read_u32be()?;
1422 let _unk = br.read_u16be()?;
1423 validate!((version >> 28) == 4);
1424 // then width and height again as 16be
1426 //self.bd.width = vinfo.get_width();
1427 //self.bd.height = vinfo.get_height();
1428 //self.frmmgr.clear();
1432 Err(DecoderError::InvalidData)
1435 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1436 let src = pkt.get_buffer();
1438 validate!(src.len() > 9);
1439 let hsize = (src[0] as usize) * 8 + 9;
1440 let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
1441 let hdr = FrameHeader::read(&mut br)?;
1442 let mut slices: Vec<usize> = Vec::new();
1443 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1445 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1446 let res = alloc_video_buffer(tmp_vinfo, 6);
1447 if !res.is_ok() { return Err(DecoderError::InvalidData); }
1448 let bufinfo = res.unwrap();
1449 let mut buf = bufinfo.get_vbuf().unwrap();
1451 let cu_w = hdr.get_width_cu();
1452 let cu_h = hdr.get_height_cu();
1453 self.pu_stride = cu_w << 3;
1454 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1455 self.blk_stride = cu_w << 4;
1456 self.blk_info.truncate(0);
1457 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1459 self.dblk.reinit(hdr.width, hdr.height);
1461 let mut off = hsize + ((br.tell() >> 3) as usize);
1462 for (cu_y, size) in slices.into_iter().enumerate() {
1463 self.decode_cu_line(&mut buf, &hdr, &src[off..][..size], cu_y)?;
1466 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1467 self.ipbs.add_frame(buf);
1470 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1471 frm.set_keyframe(hdr.ftype == FrameType::I);
1472 frm.set_pts(Some(hdr.ts as u64));
1473 frm.set_frame_type(hdr.ftype);
1474 Ok(Rc::new(RefCell::new(frm)))
1478 pub fn get_decoder() -> Box<NADecoder> {
1479 Box::new(RealVideo60Decoder::new())
1484 use nihav_core::codecs::RegisteredDecoders;
1485 use nihav_core::demuxers::RegisteredDemuxers;
1486 use nihav_core::test::dec_video::*;
1487 use crate::codecs::realmedia_register_all_codecs;
1488 use crate::demuxers::realmedia_register_all_demuxers;
1491 let mut dmx_reg = RegisteredDemuxers::new();
1492 realmedia_register_all_demuxers(&mut dmx_reg);
1493 let mut dec_reg = RegisteredDecoders::new();
1494 realmedia_register_all_codecs(&mut dec_reg);
1496 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);