1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
4 use nihav_core::io::byteio::{MemoryReader,ByteReader};
5 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
6 use nihav_core::io::intcode::*;
8 use super::rv60codes::*;
11 struct UniqueList<A> {
17 impl<A:Copy+Default+PartialEq> UniqueList<A> {
18 fn new(max_size: usize) -> Self {
19 Self { list: [A::default(); 4], fill: 0, max_size }
21 fn add(&mut self, cand: A) {
22 if self.fill == self.max_size { return; }
23 let mut unique = true;
24 for el in self.list.iter().take(self.fill) {
31 self.list[self.fill] = cand;
37 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
38 const MAX_IMODE: u8 = 34;
40 #[derive(Clone,Copy,Debug)]
55 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
57 fn read(br: &mut BitReader) -> DecoderResult<Self> {
58 let marker = br.read(2)?;
59 validate!(marker == 3);
60 let profile = br.read(2)? as u8;
61 validate!(profile == 0);
62 let _someval = br.read(4)?;
63 let ftypeid = br.read(2)? as usize;
64 let ftype = RV60_FRAME_TYPES[ftypeid];
65 let qp = br.read(6)? as u8;
66 let marker = br.read(1)?;
67 validate!(marker == 0);
68 let toolset = br.read(2)?;
69 validate!(toolset == 0);
70 let osvquant = br.read(2)? as u8;
71 let _some_flag = br.read_bool()?;
72 let _some_val = br.read(2)?;
73 let ts = br.read(24)?;
74 let width = ((br.read(11)? as usize) + 1) * 4;
75 let height = ((br.read(11)? as usize) + 0) * 4;
76 validate!(height > 0);
77 let _some_flag = br.read_bool()?;
79 if ftype == FrameType::I {
83 let flag = br.read_bool()?;
90 two_f_refs = br.read_bool()?;
92 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
93 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
94 let chroma_qp_diff = br.read(1)?;
95 validate!(chroma_qp_diff == 0);
96 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
97 let deblock = br.read_bool()?;
98 let deblock_chroma = deblock && !br.read_bool()?;
100 let custom_msg_hdr_len = br.read(2)? as usize;
101 if custom_msg_hdr_len != 0 {
102 for i in 0..custom_msg_hdr_len {
103 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
109 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
110 deblock, deblock_chroma,
113 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
114 let nslices = self.get_height_cu();
115 let nbits = (br.read(5)? as u8) + 1;
116 validate!(nbits < 32);
117 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
118 for _ in 0..nslices {
119 let sign = br.read_bool()?;
125 let first_size = br.read(nbits)? as usize;
126 validate!(first_size > 0);
128 let mut lastsize = first_size;
129 sizes.push(first_size);
130 for i in 1..nslices {
131 let diff = br.read(nbits)? as isize;
134 let sum = (lastsize as isize).checked_add(diff);
135 validate!(sum.is_some());
136 size = sum.unwrap() as usize;
138 let sum = (lastsize as isize).checked_sub(diff);
139 validate!(sum.is_some());
140 size = sum.unwrap() as usize;
147 if ((br.left() >> 3) as usize) != sum {
148 println!(" left {} / {}", br.left() >> 3, sum);
150 validate!((br.left() >> 3) >= (sum as isize));
153 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
154 match self.qp_off_type {
157 let val = br.read_code(UintCodeType::Unary012)?;
165 if br.read(1)? == 0 {
168 let val = br.read(2)? as i8;
178 fn get_width_cu(&self) -> usize {
179 (self.width + 63) >> 6
181 fn get_height_cu(&self) -> usize {
182 (self.height + 63) >> 6
184 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
185 if (ypos + dy) == 0 { return false; }
186 let xpos2 = xpos + dx;
187 if (xpos2 + size) > self.width { return false; }
190 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
191 if (ypos + dy) == 0 { return false; }
192 let xpos2 = xpos + dx;
193 if (xpos2 + size * 2) > self.width { return false; }
194 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
195 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
196 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
198 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
199 if (xpos + dx) == 0 { return false; }
200 let ypos2 = ypos + dy;
201 if (ypos2 + size) > self.height { return false; }
204 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
205 if (xpos + dx) == 0 { return false; }
206 let ypos2 = ypos + dy;
207 if (ypos2 + size * 2) > self.height { return false; }
208 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
209 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
210 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
214 const RV60_BLOCK_LOG2: [u8; 65] = [
216 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
221 const RV60_AVAIL_MASK: [u8; 64] = [
222 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
228 #[derive(Clone,Copy,PartialEq,Debug)]
236 impl Default for CUType {
237 fn default() -> Self { CUType::Intra }
240 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
242 #[derive(Clone,Copy,PartialEq,Debug)]
254 const RV60_PU_TYPES: [PUType; 8] = [
255 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
256 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
260 fn get_num_mvs(self) -> usize {
263 PUType::Quarters => 4,
267 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
268 let mv_size = size >> 2;
270 PUType::Full => (mv_size, mv_size),
271 PUType::N2Hor => (mv_size, mv_size >> 1),
272 PUType::N2Ver => (mv_size >> 1, mv_size),
273 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
276 (mv_size, mv_size >> 2)
278 (mv_size, (3 * mv_size) >> 2)
283 (mv_size, (3 * mv_size) >> 2)
285 (mv_size, mv_size >> 2)
290 ( mv_size >> 2, mv_size)
292 ((3 * mv_size) >> 2, mv_size)
297 ((3 * mv_size) >> 2, mv_size)
299 ( mv_size >> 2, mv_size)
304 fn has_hor_split(self) -> bool {
306 PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
310 fn has_ver_split(self) -> bool {
312 PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
318 impl Default for PUType {
319 fn default() -> Self { PUType::Full }
322 #[derive(Clone,Copy,Debug)]
330 #[derive(Clone,Copy,PartialEq,Debug)]
338 impl Default for TransformType {
339 fn default() -> Self { TransformType::None }
342 #[derive(Clone,Copy,PartialEq,Debug)]
355 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
358 fn get_skip_mv_num(self) -> usize {
366 fn is_ref0(self) -> bool {
368 MVRef::Ref0 | MVRef::Ref0AndBRef => true,
372 fn is_fwd(self) -> bool {
374 MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
378 fn is_bwd(self) -> bool {
380 MVRef::BRef | MVRef::Ref0AndBRef => true,
386 #[derive(Clone,Copy,PartialEq,Debug)]
394 fn is_some(&self) -> bool { self.mvref != MVRef::None }
395 fn matches_fwd(&self, mvref: MVRef) -> bool {
396 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
398 fn matches_bwd(&self, mvref: MVRef) -> bool {
399 self.mvref.is_bwd() && mvref.is_bwd()
401 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
402 if self.mvref != other.mvref { return true; }
404 if self.mvref.is_fwd() {
405 let diff = self.f_mv - other.f_mv;
406 mvdiff += diff.x.abs() + diff.y.abs();
408 if self.mvref.is_bwd() {
409 let diff = self.b_mv - other.b_mv;
410 mvdiff += diff.x.abs() + diff.y.abs();
416 impl Default for MVInfo {
417 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
420 #[derive(Clone,Copy,Debug)]
424 ttype: TransformType,
425 imode: [IntraMode; 4],
430 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
433 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
434 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
435 if ftype == FrameType::I {
436 cu_type = CUType::Intra;
438 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
442 if (size == 8) && br.read_bool()? {
443 pu_type = PUType::Quarters;
445 pu_type = PUType::Full;
447 if pu_type == PUType::Quarters {
449 imode[i] = CBHeader::read_intra_mode(br)?;
451 } else if size <= 32 {
452 imode[0] = CBHeader::read_intra_mode(br)?;
454 if !br.read_bool()? {
455 imode[0] = IntraMode::DC64;
457 imode[0] = IntraMode::Plane64;
462 let bits = if size == 8 { 2 } else { 3 };
463 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
464 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
467 pu_type = PUType::Full;
468 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
469 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
473 if cu_type == CUType::Skip {
474 ttype = TransformType::None;
475 } else if size >= 32 {
476 ttype = TransformType::T16X16;
477 } else if size == 16 {
478 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
479 ttype = TransformType::T16X16;
481 ttype = TransformType::T4X4;
484 if pu_type == PUType::Full {
485 ttype = TransformType::T8X8;
487 ttype = TransformType::T4X4;
491 cu_type, pu_type, ttype, imode, mv,
494 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
496 let idx = br.read_code(UintCodeType::Unary012)? as u8;
497 Ok(IntraMode::Index(idx))
499 let mode = br.read(5)? as u8;
500 Ok(IntraMode::Mode(mode))
503 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
504 let mv_count = pu_type.get_num_mvs();
505 for i in 0..mv_count {
506 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
510 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
511 let mut f_mv = ZERO_MV;
512 let mut b_mv = ZERO_MV;
514 if ftype != FrameType::B {
515 if two_f_refs && br.read_bool()? {
520 f_mv = CBHeader::read_mv(br)?;
521 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
523 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
524 if !br.read_bool()? {
526 f_mv = CBHeader::read_mv(br)?;
529 b_mv = CBHeader::read_mv(br)?;
532 mvref = MVRef::Ref0AndBRef;
533 f_mv = CBHeader::read_mv(br)?;
534 b_mv = CBHeader::read_mv(br)?;
536 Ok(MVInfo { f_mv, b_mv, mvref })
539 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
540 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
541 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
546 #[derive(Clone,Copy,Default)]
549 ttype: TransformType,
553 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
556 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
558 #[derive(Clone,Copy,Default)]
572 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
574 fn reinit(&mut self, w: usize, h: usize) {
575 self.left_str.clear();
576 self.top_str.clear();
577 self.stride = w >> 2;
578 let size = self.stride * (h >> 2);
579 self.left_str.resize(size, 0);
580 self.top_str.resize(size, 0);
582 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
583 let pos = self.get_pos(xpos, ypos);
584 let dsize = size >> 2;
585 let dval = (q << 2) | strength;
587 self.top_str[pos + x] = dval;
590 self.left_str[pos + y * self.stride] = dval;
593 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
594 (xpos >> 2) + (ypos >> 2) * self.stride
596 fn get_top_strength(&self, pos: usize) -> u8 {
597 self.top_str[pos] & 3
599 fn get_left_strength(&self, pos: usize) -> u8 {
600 self.left_str[pos] & 3
602 fn set_top_strength(&mut self, pos: usize, str: u8) {
603 self.top_str[pos] |= str;
605 fn set_left_strength(&mut self, pos: usize, str: u8) {
606 self.left_str[pos] |= str;
610 struct RealVideo60Decoder {
611 info: NACodecInfoRef,
615 ipred: IntraPredContext,
617 avg_buf: NAVideoBufferRef<u8>,
619 y_coeffs: [i16; 16 * 16],
620 u_coeffs: [i16; 8 * 8],
621 v_coeffs: [i16; 8 * 8],
625 cu_splits: Vec<bool>,
626 coded_blk: [bool; 64],
629 pu_info: Vec<PUInfo>,
633 blk_info: Vec<BlockInfo>,
647 impl RealVideo60Decoder {
649 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
650 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
651 let vb = vt.get_vbuf();
652 let avg_buf = vb.unwrap();
654 info: NACodecInfoRef::default(),
655 cbs: RV60Codebooks::init(),
656 ipbs: IPBShuffler::new(),
657 ipred: IntraPredContext::new(),
660 y_coeffs: [0; 16 * 16],
661 u_coeffs: [0; 8 * 8],
662 v_coeffs: [0; 8 * 8],
665 cu_splits: Vec::with_capacity(24),
666 coded_blk: [false; 64],
667 dblk: DeblockInfo::new(),
671 blk_info: Vec::new(),
684 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
685 let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
686 let cu_w = hdr.get_width_cu();
687 let dqp = hdr.read_line_qp_offset(&mut br)?;
688 let qps = (hdr.qp as i8) + dqp;
689 validate!((qps >= 0) && (qps < 32));
692 self.sel_qp = match hdr.osvquant {
712 for cu_x in 0..cu_w {
713 self.cu_splits.clear();
714 self.coded_blk = [false; 64];
715 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
717 self.cu_splits.reverse();
718 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
722 println!(" left {} bits", br.left());
726 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
727 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
729 let size = 1 << log_size;
730 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
731 self.cu_splits.push(split);
733 let hsize = size >> 1;
734 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
735 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
736 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
737 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
739 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
740 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
741 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
744 self.reconstruct_info(hdr, &cbh, size)?;
746 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
749 let itype = self.blk_info[self.blk_pos].imode;
751 let dstride = buf.stride[0];
752 let off = xpos + ypos * dstride;
753 let dst = &mut buf.data;
754 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
755 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
758 let dstride = buf.stride[comp];
759 let soff = buf.offset[comp];
760 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
761 let mut dst = &mut buf.data;
762 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
763 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
767 let mut mv_x = xpos >> 2;
768 let mut mv_y = ypos >> 2;
769 let mut mv_pos = mv_x + mv_y * self.blk_stride;
770 for part_no in 0..cbh.pu_type.get_num_mvs() {
771 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
772 let mv = self.blk_info[mv_pos].mv;
779 if hdr.ftype != FrameType::B {
780 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
781 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
784 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
785 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
790 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
791 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
795 validate!(hdr.ftype == FrameType::B);
796 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
797 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
800 MVRef::Ref0AndBRef => {
801 validate!(hdr.ftype == FrameType::B);
802 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
803 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
805 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
806 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
808 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
813 if cbh.pu_type == PUType::Quarters {
818 mv_pos += mv_h * self.blk_stride - mv_w;
822 } else if cbh.pu_type.has_hor_split() {
823 mv_pos += mv_h * self.blk_stride;
825 } else if cbh.pu_type.has_ver_split() {
832 if cbh.ttype != TransformType::None {
833 self.y_coeffs = [0; 16 * 16];
834 self.u_coeffs = [0; 8 * 8];
835 self.v_coeffs = [0; 8 * 8];
837 let is_intra = cbh.cu_type == CUType::Intra;
838 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
840 TransformType::T4X4 => {
841 let subset = if is_intra { 0 } else { 2 };
845 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
850 self.coded_blk[cb_pos + 0] = true;
851 self.coded_blk[cb_pos + 1] = true;
852 self.coded_blk[cb_pos + 8] = true;
853 self.coded_blk[cb_pos + 9] = true;
854 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)?;
858 if ((cbp16 >> i) & 1) != 0 {
859 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
860 let dstride = buf.stride[0];
861 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
862 let mut dst = &mut buf.data;
863 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
870 let xoff = (xpos >> 1) + x * 4;
871 let yoff = (ypos >> 1) + y * 4;
872 if ((cbp16 >> (16 + i)) & 1) != 0 {
873 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
874 let dstride = buf.stride[1];
875 let off = buf.offset[1] + xoff + yoff * dstride;
876 let mut dst = &mut buf.data;
877 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
879 if ((cbp16 >> (20 + i)) & 1) != 0 {
880 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
881 let dstride = buf.stride[2];
882 let off = buf.offset[2] + xoff + yoff * dstride;
883 let mut dst = &mut buf.data;
884 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
890 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
892 self.coded_blk[cb_pos] = true;
893 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)?;
896 let xoff = (i & 1) * 4;
897 let yoff = (i & 2) * 2;
899 let dstride = buf.stride[0];
900 let off = xpos + xoff + (ypos + yoff) * dstride;
901 let mut dst = &mut buf.data;
902 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
903 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
904 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
906 if ((cbp8 >> i) & 1) != 0 {
907 let blk = &mut self.y_coeffs[i * 16..][..16];
908 self.dsp.transform4x4(blk);
909 let dstride = buf.stride[0];
910 let soff = buf.offset[0];
911 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
912 let mut dst = &mut buf.data;
913 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
916 if ((cbp8 >> 4) & 1) != 0 {
917 self.dsp.transform4x4(&mut self.u_coeffs);
918 let dstride = buf.stride[1];
919 let soff = buf.offset[1];
920 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
921 let mut dst = &mut buf.data;
922 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
924 if ((cbp8 >> 5) & 1) != 0 {
925 self.dsp.transform4x4(&mut self.v_coeffs);
926 let dstride = buf.stride[2];
927 let soff = buf.offset[2];
928 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
929 let mut dst = &mut buf.data;
930 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
934 TransformType::T8X8 => {
935 let subset = if is_intra { 1 } else { 3 };
936 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
938 self.coded_blk[cb_pos] = true;
939 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)?;
940 if (cbp8 & 0xF) != 0 {
941 self.dsp.transform8x8(&mut self.y_coeffs);
942 let dstride = buf.stride[0];
943 let off = xpos + ypos * dstride;
944 let mut dst = &mut buf.data;
945 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
947 if ((cbp8 >> 4) & 1) != 0 {
948 self.dsp.transform4x4(&mut self.u_coeffs);
949 let dstride = buf.stride[1];
950 let soff = buf.offset[1];
951 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
952 let mut dst = &mut buf.data;
953 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
955 if ((cbp8 >> 5) & 1) != 0 {
956 self.dsp.transform4x4(&mut self.v_coeffs);
957 let dstride = buf.stride[2];
958 let soff = buf.offset[2];
959 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
960 let mut dst = &mut buf.data;
961 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
965 TransformType::T16X16 => {
966 let subset = if is_intra { 1 } else { 3 };
967 let num_clusters = size >> 4;
968 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
969 for y in 0..num_clusters {
970 for x in 0..num_clusters {
971 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
972 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
973 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
974 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
975 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
976 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
978 self.y_coeffs = [0; 16 * 16];
979 self.u_coeffs = [0; 8 * 8];
980 self.v_coeffs = [0; 8 * 8];
981 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)?;
982 if (super_cbp & 0xFFFF) != 0 {
983 self.dsp.transform16x16(&mut self.y_coeffs);
984 let dstride = buf.stride[0];
985 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
986 let mut dst = &mut buf.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.stride[1];
992 let soff = buf.offset[1];
993 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
994 let mut dst = &mut buf.data;
995 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
997 if ((super_cbp >> 20) & 0xF) != 0 {
998 self.dsp.transform8x8(&mut self.v_coeffs);
999 let dstride = buf.stride[2];
1000 let soff = buf.offset[2];
1001 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
1002 let mut dst = &mut buf.data;
1003 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1014 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1015 let mut pui = PUInfo::default();
1016 let pu_size = size >> 3;
1017 pui.cu_type = cbh.cu_type;
1018 pui.ttype = cbh.ttype;
1019 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1020 self.pu_info[self.pu_pos] = pui;
1023 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1024 validate!(imode <= MAX_IMODE);
1025 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1026 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1033 self.pu_info[self.pu_pos] = pui;
1034 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1035 validate!(imode <= MAX_IMODE);
1036 for y in 0..(size >> 2) {
1037 for x in 0..(size >> 2) {
1038 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1042 CUType::InterMV => {
1043 let mut mv_x = self.xpos >> 2;
1044 let mut mv_y = self.ypos >> 2;
1045 let mut mv_pos = self.blk_pos;
1046 let pu_type = cbh.pu_type;
1047 for part_no in 0..pu_type.get_num_mvs() {
1048 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1049 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1052 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1055 if pu_type == PUType::Quarters {
1060 mv_pos += mv_h * self.blk_stride - mv_w;
1064 } else if pu_type.has_hor_split() {
1065 mv_pos += mv_h * self.blk_stride;
1067 } else if pu_type.has_ver_split() {
1074 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1075 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1076 self.fill_skip_cand(hdr, &mut skip_cand, size);
1077 let mv = skip_cand.list[skip_idx];
1079 let mv_size = size >> 2;
1080 for y in 0..mv_size {
1081 for x in 0..mv_size {
1082 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1087 for y in 0..pu_size {
1088 for x in 0..pu_size {
1089 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1094 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1095 match cbh.imode[0] {
1096 IntraMode::DC64 => { return 1; },
1097 IntraMode::Plane64 => { return 0; },
1100 // form list of predictors
1101 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1102 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1103 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1104 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1106 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1109 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1110 let pu = &self.pu_info[self.pu_pos - 1];
1112 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1115 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1116 let tl_y = self.ypos + (sub & 2) * 4;
1117 if (tl_x > 0) && (tl_y > 0) {
1118 let pu = match sub {
1119 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1120 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1121 2 => &self.pu_info[self.pu_pos - 1],
1122 _ => &self.pu_info[self.pu_pos - 1],
1126 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1128 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1132 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1135 // actually decode prediction mode
1136 match cbh.imode[sub] {
1137 IntraMode::Index(idx) => {
1138 ipm_cand.list[idx as usize]
1140 IntraMode::Mode(mode) => {
1141 let mut imode = mode;
1142 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1144 for ic in ipm_cs.iter() {
1151 _ => unreachable!(),
1154 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1155 let src_off = if is_luma {
1156 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1158 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1160 self.ipred = IntraPredContext::new();
1161 if (self.ypos + yoff) > 0 {
1162 self.ipred.has_t = true;
1164 self.ipred.t[x + 1] = src[src_off - stride + x];
1166 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1167 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1168 self.ipred.has_tr = true;
1169 for x in size..size*2 {
1170 self.ipred.t[x + 1] = src[src_off - stride + x];
1174 self.ipred.t[size + i + 1] = self.ipred.t[size];
1177 if (self.xpos + xoff) > 0 {
1178 self.ipred.t[0] = src[src_off - stride - 1];
1181 if (self.xpos + xoff) > 0 {
1182 self.ipred.has_l = true;
1184 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1186 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1187 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1188 self.ipred.has_ld = true;
1189 for y in size..size*2 {
1190 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1194 self.ipred.l[size + i + 1] = self.ipred.l[size];
1197 if (self.ypos + yoff) > 0 {
1198 self.ipred.l[0] = src[src_off - stride - 1];
1202 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1203 let mv_pos = mv_x + mv_y * self.blk_stride;
1206 if mvi.mvref.is_fwd() {
1207 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1208 let mut mv_cand_size: usize = 0;
1210 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1211 if ref_mv.matches_fwd(mvi.mvref) {
1212 mv_cand[mv_cand_size] = ref_mv.f_mv;
1217 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1218 if ref_mv.matches_fwd(mvi.mvref) {
1219 mv_cand[mv_cand_size] = ref_mv.f_mv;
1223 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1224 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1225 if ref_mv.matches_fwd(mvi.mvref) {
1226 mv_cand[mv_cand_size] = ref_mv.f_mv;
1230 f_mv = match mv_cand_size {
1232 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1233 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1234 if mv_cand_size == 1 {
1237 MV { x: x >> 1, y: y >> 1 }
1240 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1246 if mvi.mvref.is_bwd() {
1247 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1248 let mut mv_cand_size: usize = 0;
1250 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1251 if ref_mv.matches_bwd(mvi.mvref) {
1252 mv_cand[mv_cand_size] = ref_mv.b_mv;
1257 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1258 if ref_mv.matches_bwd(mvi.mvref) {
1259 mv_cand[mv_cand_size] = ref_mv.b_mv;
1263 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1264 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1265 if ref_mv.matches_bwd(mvi.mvref) {
1266 mv_cand[mv_cand_size] = ref_mv.b_mv;
1270 b_mv = match mv_cand_size {
1272 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1273 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1274 if mv_cand_size == 1 {
1277 MV { x: x >> 1, y: y >> 1 }
1280 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1287 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1289 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1290 let mv_size = size >> 2;
1293 let mv = &self.blk_info[self.blk_pos - 1].mv;
1299 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1304 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1305 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1310 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1311 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1316 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1317 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1322 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1323 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1328 if (self.xpos > 0) && (self.ypos > 0) {
1329 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1334 for i in skip_cand.fill..4 {
1335 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1338 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1339 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1340 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1342 let hsize = 1 << (log_size - 1);
1343 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1344 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1345 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1346 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1348 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1349 let cu_type = self.pu_info[pu_pos].cu_type;
1350 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1351 let ntiles = 1 << (log_size - tsize);
1352 let dparams = RV60DeblockParams {
1353 deblock_chroma: hdr.deblock_chroma,
1356 dblkstride: self.dblk.stride,
1358 for ty in 0..ntiles {
1359 for tx in 0..ntiles {
1360 let x = xpos + (tx << tsize);
1361 let y = ypos + (ty << tsize);
1362 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1363 if cu_type == CUType::Intra {
1364 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1365 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1366 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1368 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1369 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1371 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1372 self.dblk.top_str.as_slice(),
1373 self.dblk.left_str.as_slice(),
1374 self.dblk.get_pos(x, y));
1379 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1380 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1381 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1383 let top_blk_pos = blk_pos - self.blk_stride;
1385 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1386 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1387 self.dblk.set_top_strength(dblk_pos + i, 1);
1394 if self.dblk.get_left_strength(dblk_pos) == 0 {
1395 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1396 self.dblk.set_left_strength(dblk_pos, 1);
1399 dblk_pos += self.dblk.stride;
1405 impl NADecoder for RealVideo60Decoder {
1406 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1407 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1408 let fmt = YUV420_FORMAT;
1409 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1410 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1412 let edata = info.get_extradata().unwrap();
1413 let src: &[u8] = &edata;
1415 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1416 let mut mr = MemoryReader::new_read(src);
1417 let mut br = ByteReader::new(&mut mr);
1418 let _flags = br.read_u32be()?;
1419 let version = br.read_u32be()?;
1420 let _unk = br.read_u16be()?;
1421 validate!((version >> 28) == 4);
1422 // then width and height again as 16be
1424 //self.bd.width = vinfo.get_width();
1425 //self.bd.height = vinfo.get_height();
1426 //self.frmmgr.clear();
1428 supp.pool_u8.set_dec_bufs(3);
1429 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1434 Err(DecoderError::InvalidData)
1437 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1438 let src = pkt.get_buffer();
1440 validate!(src.len() > 9);
1441 let hsize = (src[0] as usize) * 8 + 9;
1442 let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
1443 let hdr = FrameHeader::read(&mut br)?;
1444 let mut slices: Vec<usize> = Vec::new();
1445 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1448 if self.ipbs.get_lastref().is_none() {
1449 return Err(DecoderError::MissingReference);
1453 if self.ipbs.get_lastref().is_none() {
1454 return Err(DecoderError::MissingReference);
1456 if self.ipbs.get_nextref().is_none() {
1457 return Err(DecoderError::MissingReference);
1463 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1464 let ret = supp.pool_u8.get_free();
1466 return Err(DecoderError::AllocError);
1468 let mut buf = ret.unwrap();
1469 if buf.get_info() != tmp_vinfo {
1471 supp.pool_u8.reset();
1472 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1473 let ret = supp.pool_u8.get_free();
1475 return Err(DecoderError::AllocError);
1480 let cu_w = hdr.get_width_cu();
1481 let cu_h = hdr.get_height_cu();
1482 self.pu_stride = cu_w << 3;
1483 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1484 self.blk_stride = cu_w << 4;
1485 self.blk_info.truncate(0);
1486 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1488 self.dblk.reinit(hdr.width, hdr.height);
1490 let mut off = hsize + ((br.tell() >> 3) as usize);
1491 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1492 for (cu_y, size) in slices.into_iter().enumerate() {
1493 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1496 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1497 self.ipbs.add_frame(buf.clone());
1500 if hdr.ftype != FrameType::B {
1501 self.ref0_pts = self.ref1_pts;
1502 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1503 self.ref0_ts = self.ref1_ts;
1504 self.ref1_ts = hdr.ts as u64;
1505 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1506 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1509 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1510 frm.set_keyframe(hdr.ftype == FrameType::I);
1511 if hdr.ftype == FrameType::B {
1512 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1513 frm.set_pts(Some(pts));
1515 frm.set_frame_type(hdr.ftype);
1518 fn flush(&mut self) {
1523 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1524 Box::new(RealVideo60Decoder::new())
1529 use nihav_core::codecs::RegisteredDecoders;
1530 use nihav_core::demuxers::RegisteredDemuxers;
1531 use nihav_core::test::dec_video::*;
1532 use crate::codecs::realmedia_register_all_codecs;
1533 use crate::demuxers::realmedia_register_all_demuxers;
1536 let mut dmx_reg = RegisteredDemuxers::new();
1537 realmedia_register_all_demuxers(&mut dmx_reg);
1538 let mut dec_reg = RegisteredDecoders::new();
1539 realmedia_register_all_codecs(&mut dec_reg);
1541 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);