1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult};
4 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
5 use nihav_core::io::byteio::{MemoryReader,ByteReader};
6 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
7 use nihav_core::io::intcode::*;
9 use super::rv60codes::*;
10 use super::rv60dsp::*;
12 struct UniqueList<A> {
18 impl<A:Copy+Default+PartialEq> UniqueList<A> {
19 fn new(max_size: usize) -> Self {
20 Self { list: [A::default(); 4], fill: 0, max_size }
22 fn add(&mut self, cand: A) {
23 if self.fill == self.max_size { return; }
24 let mut unique = true;
25 for el in self.list.iter().take(self.fill) {
32 self.list[self.fill] = cand;
38 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
39 const MAX_IMODE: u8 = 34;
41 #[derive(Clone,Copy,Debug)]
56 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
58 fn read(br: &mut BitReader) -> DecoderResult<Self> {
59 let marker = br.read(2)?;
60 validate!(marker == 3);
61 let profile = br.read(2)? as u8;
62 validate!(profile == 0);
63 let _someval = br.read(4)?;
64 let ftypeid = br.read(2)? as usize;
65 let ftype = RV60_FRAME_TYPES[ftypeid];
66 let qp = br.read(6)? as u8;
67 let marker = br.read(1)?;
68 validate!(marker == 0);
69 let toolset = br.read(2)?;
70 validate!(toolset == 0);
71 let osvquant = br.read(2)? as u8;
72 let _some_flag = br.read_bool()?;
73 let _some_val = br.read(2)?;
74 let ts = br.read(24)?;
75 let width = ((br.read(11)? as usize) + 1) * 4;
76 let height = ((br.read(11)? as usize) + 0) * 4;
77 validate!(height > 0);
78 let _some_flag = br.read_bool()?;
80 if ftype == FrameType::I {
84 let flag = br.read_bool()?;
91 two_f_refs = br.read_bool()?;
93 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
94 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
95 let chroma_qp_diff = br.read(1)?;
96 validate!(chroma_qp_diff == 0);
97 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
98 let deblock = br.read_bool()?;
99 let deblock_chroma = deblock && !br.read_bool()?;
101 let custom_msg_hdr_len = br.read(2)? as usize;
102 if custom_msg_hdr_len != 0 {
103 for i in 0..custom_msg_hdr_len {
104 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
110 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
111 deblock, deblock_chroma,
114 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
115 let nslices = self.get_height_cu();
116 let nbits = (br.read(5)? as u8) + 1;
117 validate!(nbits < 32);
118 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
119 for _ in 0..nslices {
120 let sign = br.read_bool()?;
126 let first_size = br.read(nbits)? as usize;
127 validate!(first_size > 0);
129 let mut lastsize = first_size;
130 sizes.push(first_size);
131 for i in 1..nslices {
132 let diff = br.read(nbits)? as isize;
135 let sum = (lastsize as isize).checked_add(diff);
136 validate!(sum.is_some());
137 size = sum.unwrap() as usize;
139 let sum = (lastsize as isize).checked_sub(diff);
140 validate!(sum.is_some());
141 size = sum.unwrap() as usize;
148 if ((br.left() >> 3) as usize) != sum {
149 println!(" left {} / {}", br.left() >> 3, sum);
151 validate!((br.left() >> 3) >= (sum as isize));
154 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
155 match self.qp_off_type {
158 let val = br.read_code(UintCodeType::Unary012)?;
166 if br.read(1)? == 0 {
169 let val = br.read(2)? as i8;
179 fn get_width_cu(&self) -> usize {
180 (self.width + 63) >> 6
182 fn get_height_cu(&self) -> usize {
183 (self.height + 63) >> 6
185 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
186 if (ypos + dy) == 0 { return false; }
187 let xpos2 = xpos + dx;
188 if (xpos2 + size) > self.width { return false; }
191 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
192 if (ypos + dy) == 0 { return false; }
193 let xpos2 = xpos + dx;
194 if (xpos2 + size * 2) > self.width { return false; }
195 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
196 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
197 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
199 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
200 if (xpos + dx) == 0 { return false; }
201 let ypos2 = ypos + dy;
202 if (ypos2 + size) > self.height { return false; }
205 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
206 if (xpos + dx) == 0 { return false; }
207 let ypos2 = ypos + dy;
208 if (ypos2 + size * 2) > self.height { return false; }
209 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
210 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
211 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
215 const RV60_BLOCK_LOG2: [u8; 65] = [
217 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
222 const RV60_AVAIL_MASK: [u8; 64] = [
223 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 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,
226 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
229 #[derive(Clone,Copy,PartialEq,Debug)]
237 impl Default for CUType {
238 fn default() -> Self { CUType::Intra }
241 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
243 #[derive(Clone,Copy,PartialEq,Debug)]
255 const RV60_PU_TYPES: [PUType; 8] = [
256 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
257 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
261 fn get_num_mvs(self) -> usize {
264 PUType::Quarters => 4,
268 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
269 let mv_size = size >> 2;
271 PUType::Full => (mv_size, mv_size),
272 PUType::N2Hor => (mv_size, mv_size >> 1),
273 PUType::N2Ver => (mv_size >> 1, mv_size),
274 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
277 (mv_size, mv_size >> 2)
279 (mv_size, (3 * mv_size) >> 2)
284 (mv_size, (3 * mv_size) >> 2)
286 (mv_size, mv_size >> 2)
291 ( mv_size >> 2, mv_size)
293 ((3 * mv_size) >> 2, mv_size)
298 ((3 * mv_size) >> 2, mv_size)
300 ( mv_size >> 2, mv_size)
305 fn has_hor_split(self) -> bool {
307 PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
311 fn has_ver_split(self) -> bool {
313 PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
319 impl Default for PUType {
320 fn default() -> Self { PUType::Full }
323 #[derive(Clone,Copy,Debug)]
331 #[derive(Clone,Copy,PartialEq,Debug)]
339 impl Default for TransformType {
340 fn default() -> Self { TransformType::None }
343 #[derive(Clone,Copy,PartialEq,Debug)]
356 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
359 fn get_skip_mv_num(self) -> usize {
367 fn is_ref0(self) -> bool {
369 MVRef::Ref0 | MVRef::Ref0AndBRef => true,
373 fn is_fwd(self) -> bool {
375 MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
379 fn is_bwd(self) -> bool {
381 MVRef::BRef | MVRef::Ref0AndBRef => true,
387 #[derive(Clone,Copy,PartialEq,Debug)]
395 fn is_some(&self) -> bool { self.mvref != MVRef::None }
396 fn matches_fwd(&self, mvref: MVRef) -> bool {
397 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
399 fn matches_bwd(&self, mvref: MVRef) -> bool {
400 self.mvref.is_bwd() && mvref.is_bwd()
402 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
403 if self.mvref != other.mvref { return true; }
405 if self.mvref.is_fwd() {
406 let diff = self.f_mv - other.f_mv;
407 mvdiff += diff.x.abs() + diff.y.abs();
409 if self.mvref.is_bwd() {
410 let diff = self.b_mv - other.b_mv;
411 mvdiff += diff.x.abs() + diff.y.abs();
417 impl Default for MVInfo {
418 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
421 #[derive(Clone,Copy,Debug)]
425 ttype: TransformType,
426 imode: [IntraMode; 4],
431 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
434 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
435 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
436 if ftype == FrameType::I {
437 cu_type = CUType::Intra;
439 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
443 if (size == 8) && br.read_bool()? {
444 pu_type = PUType::Quarters;
446 pu_type = PUType::Full;
448 if pu_type == PUType::Quarters {
450 imode[i] = CBHeader::read_intra_mode(br)?;
452 } else if size <= 32 {
453 imode[0] = CBHeader::read_intra_mode(br)?;
455 if !br.read_bool()? {
456 imode[0] = IntraMode::DC64;
458 imode[0] = IntraMode::Plane64;
463 let bits = if size == 8 { 2 } else { 3 };
464 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
465 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
468 pu_type = PUType::Full;
469 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
470 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
474 if cu_type == CUType::Skip {
475 ttype = TransformType::None;
476 } else if size >= 32 {
477 ttype = TransformType::T16X16;
478 } else if size == 16 {
479 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
480 ttype = TransformType::T16X16;
482 ttype = TransformType::T4X4;
485 if pu_type == PUType::Full {
486 ttype = TransformType::T8X8;
488 ttype = TransformType::T4X4;
492 cu_type, pu_type, ttype, imode, mv,
495 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
497 let idx = br.read_code(UintCodeType::Unary012)? as u8;
498 Ok(IntraMode::Index(idx))
500 let mode = br.read(5)? as u8;
501 Ok(IntraMode::Mode(mode))
504 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
505 let mv_count = pu_type.get_num_mvs();
506 for i in 0..mv_count {
507 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
511 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
512 let mut f_mv = ZERO_MV;
513 let mut b_mv = ZERO_MV;
515 if ftype != FrameType::B {
516 if two_f_refs && br.read_bool()? {
521 f_mv = CBHeader::read_mv(br)?;
522 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
524 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
525 if !br.read_bool()? {
527 f_mv = CBHeader::read_mv(br)?;
530 b_mv = CBHeader::read_mv(br)?;
533 mvref = MVRef::Ref0AndBRef;
534 f_mv = CBHeader::read_mv(br)?;
535 b_mv = CBHeader::read_mv(br)?;
537 Ok(MVInfo { f_mv, b_mv, mvref })
540 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
541 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
542 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
547 #[derive(Clone,Copy,Default)]
550 ttype: TransformType,
554 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
557 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
559 #[derive(Clone,Copy,Default)]
573 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
575 fn reinit(&mut self, w: usize, h: usize) {
576 self.left_str.clear();
577 self.top_str.clear();
578 self.stride = w >> 2;
579 let size = self.stride * (h >> 2);
580 self.left_str.resize(size, 0);
581 self.top_str.resize(size, 0);
583 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
584 let pos = self.get_pos(xpos, ypos);
585 let dsize = size >> 2;
586 let dval = (q << 2) | strength;
588 self.top_str[pos + x] = dval;
591 self.left_str[pos + y * self.stride] = dval;
594 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
595 (xpos >> 2) + (ypos >> 2) * self.stride
597 fn get_top_strength(&self, pos: usize) -> u8 {
598 self.top_str[pos] & 3
600 fn get_left_strength(&self, pos: usize) -> u8 {
601 self.left_str[pos] & 3
603 fn set_top_strength(&mut self, pos: usize, str: u8) {
604 self.top_str[pos] |= str;
606 fn set_left_strength(&mut self, pos: usize, str: u8) {
607 self.left_str[pos] |= str;
611 struct RealVideo60Decoder {
612 info: NACodecInfoRef,
616 ipred: IntraPredContext,
618 avg_buf: NAVideoBufferRef<u8>,
620 y_coeffs: [i16; 16 * 16],
621 u_coeffs: [i16; 8 * 8],
622 v_coeffs: [i16; 8 * 8],
626 cu_splits: Vec<bool>,
627 coded_blk: [bool; 64],
630 pu_info: Vec<PUInfo>,
634 blk_info: Vec<BlockInfo>,
648 impl RealVideo60Decoder {
650 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
651 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
652 let vb = vt.get_vbuf();
653 let avg_buf = vb.unwrap();
655 info: NACodecInfoRef::default(),
656 cbs: RV60Codebooks::init(),
657 ipbs: IPBShuffler::new(),
658 ipred: IntraPredContext::new(),
661 y_coeffs: [0; 16 * 16],
662 u_coeffs: [0; 8 * 8],
663 v_coeffs: [0; 8 * 8],
666 cu_splits: Vec::with_capacity(24),
667 coded_blk: [false; 64],
668 dblk: DeblockInfo::new(),
672 blk_info: Vec::new(),
685 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
686 let mut br = BitReader::new(src, BitReaderMode::BE);
687 let cu_w = hdr.get_width_cu();
688 let dqp = hdr.read_line_qp_offset(&mut br)?;
689 let qps = (hdr.qp as i8) + dqp;
690 validate!((qps >= 0) && (qps < 32));
693 self.sel_qp = match hdr.osvquant {
713 for cu_x in 0..cu_w {
714 self.cu_splits.clear();
715 self.coded_blk = [false; 64];
716 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
718 self.cu_splits.reverse();
719 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
723 println!(" left {} bits", br.left());
727 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
728 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
730 let size = 1 << log_size;
731 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
732 self.cu_splits.push(split);
734 let hsize = size >> 1;
735 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
736 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
737 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
738 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
740 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
741 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
742 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
745 self.reconstruct_info(hdr, &cbh, size)?;
747 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
750 let itype = self.blk_info[self.blk_pos].imode;
752 let dstride = buf.stride[0];
753 let off = xpos + ypos * dstride;
754 let dst = &mut buf.data;
755 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
756 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
759 let dstride = buf.stride[comp];
760 let soff = buf.offset[comp];
761 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
762 let mut dst = &mut buf.data;
763 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
764 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
768 let mut mv_x = xpos >> 2;
769 let mut mv_y = ypos >> 2;
770 let mut mv_pos = mv_x + mv_y * self.blk_stride;
771 for part_no in 0..cbh.pu_type.get_num_mvs() {
772 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
773 let mv = self.blk_info[mv_pos].mv;
780 if hdr.ftype != FrameType::B {
781 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
782 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
785 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
786 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
791 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
792 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
796 validate!(hdr.ftype == FrameType::B);
797 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
798 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
801 MVRef::Ref0AndBRef => {
802 validate!(hdr.ftype == FrameType::B);
803 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
804 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
806 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
807 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
809 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
814 if cbh.pu_type == PUType::Quarters {
819 mv_pos += mv_h * self.blk_stride - mv_w;
823 } else if cbh.pu_type.has_hor_split() {
824 mv_pos += mv_h * self.blk_stride;
826 } else if cbh.pu_type.has_ver_split() {
833 if cbh.ttype != TransformType::None {
834 self.y_coeffs = [0; 16 * 16];
835 self.u_coeffs = [0; 8 * 8];
836 self.v_coeffs = [0; 8 * 8];
838 let is_intra = cbh.cu_type == CUType::Intra;
839 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
841 TransformType::T4X4 => {
842 let subset = if is_intra { 0 } else { 2 };
846 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
851 self.coded_blk[cb_pos + 0] = true;
852 self.coded_blk[cb_pos + 1] = true;
853 self.coded_blk[cb_pos + 8] = true;
854 self.coded_blk[cb_pos + 9] = true;
855 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)?;
859 if ((cbp16 >> i) & 1) != 0 {
860 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
861 let dstride = buf.stride[0];
862 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
863 let mut dst = &mut buf.data;
864 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
871 let xoff = (xpos >> 1) + x * 4;
872 let yoff = (ypos >> 1) + y * 4;
873 if ((cbp16 >> (16 + i)) & 1) != 0 {
874 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
875 let dstride = buf.stride[1];
876 let off = buf.offset[1] + xoff + yoff * dstride;
877 let mut dst = &mut buf.data;
878 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
880 if ((cbp16 >> (20 + i)) & 1) != 0 {
881 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
882 let dstride = buf.stride[2];
883 let off = buf.offset[2] + xoff + yoff * dstride;
884 let mut dst = &mut buf.data;
885 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
891 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
893 self.coded_blk[cb_pos] = true;
894 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)?;
897 let xoff = (i & 1) * 4;
898 let yoff = (i & 2) * 2;
900 let dstride = buf.stride[0];
901 let off = xpos + xoff + (ypos + yoff) * dstride;
902 let mut dst = &mut buf.data;
903 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
904 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
905 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
907 if ((cbp8 >> i) & 1) != 0 {
908 let blk = &mut self.y_coeffs[i * 16..][..16];
909 self.dsp.transform4x4(blk);
910 let dstride = buf.stride[0];
911 let soff = buf.offset[0];
912 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
913 let mut dst = &mut buf.data;
914 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
917 if ((cbp8 >> 4) & 1) != 0 {
918 self.dsp.transform4x4(&mut self.u_coeffs);
919 let dstride = buf.stride[1];
920 let soff = buf.offset[1];
921 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
922 let mut dst = &mut buf.data;
923 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
925 if ((cbp8 >> 5) & 1) != 0 {
926 self.dsp.transform4x4(&mut self.v_coeffs);
927 let dstride = buf.stride[2];
928 let soff = buf.offset[2];
929 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
930 let mut dst = &mut buf.data;
931 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
935 TransformType::T8X8 => {
936 let subset = if is_intra { 1 } else { 3 };
937 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
939 self.coded_blk[cb_pos] = true;
940 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)?;
941 if (cbp8 & 0xF) != 0 {
942 self.dsp.transform8x8(&mut self.y_coeffs);
943 let dstride = buf.stride[0];
944 let off = xpos + ypos * dstride;
945 let mut dst = &mut buf.data;
946 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
948 if ((cbp8 >> 4) & 1) != 0 {
949 self.dsp.transform4x4(&mut self.u_coeffs);
950 let dstride = buf.stride[1];
951 let soff = buf.offset[1];
952 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
953 let mut dst = &mut buf.data;
954 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
956 if ((cbp8 >> 5) & 1) != 0 {
957 self.dsp.transform4x4(&mut self.v_coeffs);
958 let dstride = buf.stride[2];
959 let soff = buf.offset[2];
960 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
961 let mut dst = &mut buf.data;
962 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
966 TransformType::T16X16 => {
967 let subset = if is_intra { 1 } else { 3 };
968 let num_clusters = size >> 4;
969 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
970 for y in 0..num_clusters {
971 for x in 0..num_clusters {
972 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
973 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
974 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
975 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
976 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
977 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
979 self.y_coeffs = [0; 16 * 16];
980 self.u_coeffs = [0; 8 * 8];
981 self.v_coeffs = [0; 8 * 8];
982 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)?;
983 if (super_cbp & 0xFFFF) != 0 {
984 self.dsp.transform16x16(&mut self.y_coeffs);
985 let dstride = buf.stride[0];
986 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
987 let mut dst = &mut buf.data;
988 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
990 if ((super_cbp >> 16) & 0xF) != 0 {
991 self.dsp.transform8x8(&mut self.u_coeffs);
992 let dstride = buf.stride[1];
993 let soff = buf.offset[1];
994 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
995 let mut dst = &mut buf.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.stride[2];
1001 let soff = buf.offset[2];
1002 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
1003 let mut dst = &mut buf.data;
1004 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1015 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1016 let mut pui = PUInfo::default();
1017 let pu_size = size >> 3;
1018 pui.cu_type = cbh.cu_type;
1019 pui.ttype = cbh.ttype;
1020 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1021 self.pu_info[self.pu_pos] = pui;
1024 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1025 validate!(imode <= MAX_IMODE);
1026 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1027 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1034 self.pu_info[self.pu_pos] = pui;
1035 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1036 validate!(imode <= MAX_IMODE);
1037 for y in 0..(size >> 2) {
1038 for x in 0..(size >> 2) {
1039 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1043 CUType::InterMV => {
1044 let mut mv_x = self.xpos >> 2;
1045 let mut mv_y = self.ypos >> 2;
1046 let mut mv_pos = self.blk_pos;
1047 let pu_type = cbh.pu_type;
1048 for part_no in 0..pu_type.get_num_mvs() {
1049 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1050 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1053 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1056 if pu_type == PUType::Quarters {
1061 mv_pos += mv_h * self.blk_stride - mv_w;
1065 } else if pu_type.has_hor_split() {
1066 mv_pos += mv_h * self.blk_stride;
1068 } else if pu_type.has_ver_split() {
1075 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1076 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1077 self.fill_skip_cand(hdr, &mut skip_cand, size);
1078 let mv = skip_cand.list[skip_idx];
1080 let mv_size = size >> 2;
1081 for y in 0..mv_size {
1082 for x in 0..mv_size {
1083 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1088 for y in 0..pu_size {
1089 for x in 0..pu_size {
1090 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1095 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1096 match cbh.imode[0] {
1097 IntraMode::DC64 => { return 1; },
1098 IntraMode::Plane64 => { return 0; },
1101 // form list of predictors
1102 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1103 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1104 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1105 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1107 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1110 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1111 let pu = &self.pu_info[self.pu_pos - 1];
1113 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1116 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1117 let tl_y = self.ypos + (sub & 2) * 4;
1118 if (tl_x > 0) && (tl_y > 0) {
1119 let pu = match sub {
1120 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1121 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1122 2 => &self.pu_info[self.pu_pos - 1],
1123 _ => &self.pu_info[self.pu_pos - 1],
1127 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1129 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1133 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1136 // actually decode prediction mode
1137 match cbh.imode[sub] {
1138 IntraMode::Index(idx) => {
1139 ipm_cand.list[idx as usize]
1141 IntraMode::Mode(mode) => {
1142 let mut imode = mode;
1143 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1145 for ic in ipm_cs.iter() {
1152 _ => unreachable!(),
1155 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1156 let src_off = if is_luma {
1157 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1159 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1161 self.ipred = IntraPredContext::new();
1162 if (self.ypos + yoff) > 0 {
1163 self.ipred.has_t = true;
1165 self.ipred.t[x + 1] = src[src_off - stride + x];
1167 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1168 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1169 self.ipred.has_tr = true;
1170 for x in size..size*2 {
1171 self.ipred.t[x + 1] = src[src_off - stride + x];
1175 self.ipred.t[size + i + 1] = self.ipred.t[size];
1178 if (self.xpos + xoff) > 0 {
1179 self.ipred.t[0] = src[src_off - stride - 1];
1182 if (self.xpos + xoff) > 0 {
1183 self.ipred.has_l = true;
1185 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1187 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1188 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1189 self.ipred.has_ld = true;
1190 for y in size..size*2 {
1191 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1195 self.ipred.l[size + i + 1] = self.ipred.l[size];
1198 if (self.ypos + yoff) > 0 {
1199 self.ipred.l[0] = src[src_off - stride - 1];
1203 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1204 let mv_pos = mv_x + mv_y * self.blk_stride;
1207 if mvi.mvref.is_fwd() {
1208 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1209 let mut mv_cand_size: usize = 0;
1211 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1212 if ref_mv.matches_fwd(mvi.mvref) {
1213 mv_cand[mv_cand_size] = ref_mv.f_mv;
1218 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1219 if ref_mv.matches_fwd(mvi.mvref) {
1220 mv_cand[mv_cand_size] = ref_mv.f_mv;
1224 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1225 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1226 if ref_mv.matches_fwd(mvi.mvref) {
1227 mv_cand[mv_cand_size] = ref_mv.f_mv;
1231 f_mv = match mv_cand_size {
1233 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1234 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1235 if mv_cand_size == 1 {
1238 MV { x: x >> 1, y: y >> 1 }
1241 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1247 if mvi.mvref.is_bwd() {
1248 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1249 let mut mv_cand_size: usize = 0;
1251 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1252 if ref_mv.matches_bwd(mvi.mvref) {
1253 mv_cand[mv_cand_size] = ref_mv.b_mv;
1258 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1259 if ref_mv.matches_bwd(mvi.mvref) {
1260 mv_cand[mv_cand_size] = ref_mv.b_mv;
1264 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1265 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1266 if ref_mv.matches_bwd(mvi.mvref) {
1267 mv_cand[mv_cand_size] = ref_mv.b_mv;
1271 b_mv = match mv_cand_size {
1273 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1274 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1275 if mv_cand_size == 1 {
1278 MV { x: x >> 1, y: y >> 1 }
1281 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1288 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1290 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1291 let mv_size = size >> 2;
1294 let mv = &self.blk_info[self.blk_pos - 1].mv;
1300 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1305 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1306 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1311 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1312 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1317 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1318 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1323 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1324 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1329 if (self.xpos > 0) && (self.ypos > 0) {
1330 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1335 for i in skip_cand.fill..4 {
1336 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1339 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1340 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1341 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1343 let hsize = 1 << (log_size - 1);
1344 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1345 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1346 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1347 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1349 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1350 let cu_type = self.pu_info[pu_pos].cu_type;
1351 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1352 let ntiles = 1 << (log_size - tsize);
1353 let dparams = RV60DeblockParams {
1354 deblock_chroma: hdr.deblock_chroma,
1357 dblkstride: self.dblk.stride,
1359 for ty in 0..ntiles {
1360 for tx in 0..ntiles {
1361 let x = xpos + (tx << tsize);
1362 let y = ypos + (ty << tsize);
1363 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1364 if cu_type == CUType::Intra {
1365 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1366 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1367 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1369 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1370 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1372 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1373 self.dblk.top_str.as_slice(),
1374 self.dblk.left_str.as_slice(),
1375 self.dblk.get_pos(x, y));
1380 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1381 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1382 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1384 let top_blk_pos = blk_pos - self.blk_stride;
1386 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1387 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1388 self.dblk.set_top_strength(dblk_pos + i, 1);
1395 if self.dblk.get_left_strength(dblk_pos) == 0 {
1396 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1397 self.dblk.set_left_strength(dblk_pos, 1);
1400 dblk_pos += self.dblk.stride;
1406 impl NADecoder for RealVideo60Decoder {
1407 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1408 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1409 let fmt = YUV420_FORMAT;
1410 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1411 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1413 let edata = info.get_extradata().unwrap();
1414 let src: &[u8] = &edata;
1416 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1417 let mut mr = MemoryReader::new_read(src);
1418 let mut br = ByteReader::new(&mut mr);
1419 let _flags = br.read_u32be()?;
1420 let version = br.read_u32be()?;
1421 let _unk = br.read_u16be()?;
1422 validate!((version >> 28) == 4);
1423 // then width and height again as 16be
1425 //self.bd.width = vinfo.get_width();
1426 //self.bd.height = vinfo.get_height();
1427 //self.frmmgr.clear();
1429 supp.pool_u8.set_dec_bufs(3);
1430 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1435 Err(DecoderError::InvalidData)
1438 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1439 let src = pkt.get_buffer();
1441 validate!(src.len() > 9);
1442 let hsize = (src[0] as usize) * 8 + 9;
1443 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1444 let hdr = FrameHeader::read(&mut br)?;
1445 let mut slices: Vec<usize> = Vec::new();
1446 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1449 if self.ipbs.get_lastref().is_none() {
1450 return Err(DecoderError::MissingReference);
1454 if self.ipbs.get_lastref().is_none() {
1455 return Err(DecoderError::MissingReference);
1457 if self.ipbs.get_nextref().is_none() {
1458 return Err(DecoderError::MissingReference);
1464 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1465 let ret = supp.pool_u8.get_free();
1467 return Err(DecoderError::AllocError);
1469 let mut buf = ret.unwrap();
1470 if buf.get_info() != tmp_vinfo {
1472 supp.pool_u8.reset();
1473 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1474 let ret = supp.pool_u8.get_free();
1476 return Err(DecoderError::AllocError);
1481 let cu_w = hdr.get_width_cu();
1482 let cu_h = hdr.get_height_cu();
1483 self.pu_stride = cu_w << 3;
1484 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1485 self.blk_stride = cu_w << 4;
1486 self.blk_info.truncate(0);
1487 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1489 self.dblk.reinit(hdr.width, hdr.height);
1491 let mut off = hsize + ((br.tell() >> 3) as usize);
1492 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1493 for (cu_y, size) in slices.into_iter().enumerate() {
1494 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1497 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1498 self.ipbs.add_frame(buf.clone());
1501 if hdr.ftype != FrameType::B {
1502 self.ref0_pts = self.ref1_pts;
1503 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1504 self.ref0_ts = self.ref1_ts;
1505 self.ref1_ts = hdr.ts as u64;
1506 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1507 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1510 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1511 frm.set_keyframe(hdr.ftype == FrameType::I);
1512 if hdr.ftype == FrameType::B {
1513 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1514 frm.set_pts(Some(pts));
1516 frm.set_frame_type(hdr.ftype);
1519 fn flush(&mut self) {
1524 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1525 Box::new(RealVideo60Decoder::new())
1530 use nihav_core::codecs::RegisteredDecoders;
1531 use nihav_core::demuxers::RegisteredDemuxers;
1532 use nihav_codec_support::test::dec_video::*;
1533 use crate::realmedia_register_all_codecs;
1534 use crate::realmedia_register_all_demuxers;
1537 let mut dmx_reg = RegisteredDemuxers::new();
1538 realmedia_register_all_demuxers(&mut dmx_reg);
1539 let mut dec_reg = RegisteredDecoders::new();
1540 realmedia_register_all_codecs(&mut dec_reg);
1542 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);