1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult};
4 use nihav_core::options::*;
5 use nihav_codec_support::codecs::{MV, ZERO_MV, 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.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: NACodecInfoRef,
617 ipred: IntraPredContext,
619 avg_buf: NAVideoBufferRef<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>,
649 impl RealVideo60Decoder {
651 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
652 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
653 let vb = vt.get_vbuf();
654 let avg_buf = vb.unwrap();
656 info: NACodecInfoRef::default(),
657 cbs: RV60Codebooks::init(),
658 ipbs: IPBShuffler::new(),
659 ipred: IntraPredContext::new(),
662 y_coeffs: [0; 16 * 16],
663 u_coeffs: [0; 8 * 8],
664 v_coeffs: [0; 8 * 8],
667 cu_splits: Vec::with_capacity(24),
668 coded_blk: [false; 64],
669 dblk: DeblockInfo::new(),
673 blk_info: Vec::new(),
686 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
687 let mut br = BitReader::new(src, BitReaderMode::BE);
688 let cu_w = hdr.get_width_cu();
689 let dqp = hdr.read_line_qp_offset(&mut br)?;
690 let qps = (hdr.qp as i8) + dqp;
691 validate!((qps >= 0) && (qps < 32));
694 self.sel_qp = match hdr.osvquant {
714 for cu_x in 0..cu_w {
715 self.cu_splits.clear();
716 self.coded_blk = [false; 64];
717 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
719 self.cu_splits.reverse();
720 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
724 println!(" left {} bits", br.left());
728 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
729 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
731 let size = 1 << log_size;
732 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
733 self.cu_splits.push(split);
735 let hsize = size >> 1;
736 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
737 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
738 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
739 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
741 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
742 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
743 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
746 self.reconstruct_info(hdr, &cbh, size)?;
748 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
751 let itype = self.blk_info[self.blk_pos].imode;
753 let dstride = buf.stride[0];
754 let off = xpos + ypos * dstride;
755 let dst = &mut buf.data;
756 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
757 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
760 let dstride = buf.stride[comp];
761 let soff = buf.offset[comp];
762 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
763 let mut dst = &mut buf.data;
764 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
765 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
769 let mut mv_x = xpos >> 2;
770 let mut mv_y = ypos >> 2;
771 let mut mv_pos = mv_x + mv_y * self.blk_stride;
772 for part_no in 0..cbh.pu_type.get_num_mvs() {
773 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
774 let mv = self.blk_info[mv_pos].mv;
781 if hdr.ftype != FrameType::B {
782 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
783 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
786 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
787 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
792 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
793 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
797 validate!(hdr.ftype == FrameType::B);
798 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
799 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
802 MVRef::Ref0AndBRef => {
803 validate!(hdr.ftype == FrameType::B);
804 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
805 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
807 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
808 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
810 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
815 if cbh.pu_type == PUType::Quarters {
820 mv_pos += mv_h * self.blk_stride - mv_w;
824 } else if cbh.pu_type.has_hor_split() {
825 mv_pos += mv_h * self.blk_stride;
827 } else if cbh.pu_type.has_ver_split() {
834 if cbh.ttype != TransformType::None {
835 self.y_coeffs = [0; 16 * 16];
836 self.u_coeffs = [0; 8 * 8];
837 self.v_coeffs = [0; 8 * 8];
839 let is_intra = cbh.cu_type == CUType::Intra;
840 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
842 TransformType::T4X4 => {
843 let subset = if is_intra { 0 } else { 2 };
847 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
852 self.coded_blk[cb_pos + 0] = true;
853 self.coded_blk[cb_pos + 1] = true;
854 self.coded_blk[cb_pos + 8] = true;
855 self.coded_blk[cb_pos + 9] = true;
856 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)?;
860 if ((cbp16 >> i) & 1) != 0 {
861 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
862 let dstride = buf.stride[0];
863 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
864 let mut dst = &mut buf.data;
865 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
872 let xoff = (xpos >> 1) + x * 4;
873 let yoff = (ypos >> 1) + y * 4;
874 if ((cbp16 >> (16 + i)) & 1) != 0 {
875 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
876 let dstride = buf.stride[1];
877 let off = buf.offset[1] + xoff + yoff * dstride;
878 let mut dst = &mut buf.data;
879 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
881 if ((cbp16 >> (20 + i)) & 1) != 0 {
882 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
883 let dstride = buf.stride[2];
884 let off = buf.offset[2] + xoff + yoff * dstride;
885 let mut dst = &mut buf.data;
886 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
892 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
894 self.coded_blk[cb_pos] = true;
895 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)?;
898 let xoff = (i & 1) * 4;
899 let yoff = (i & 2) * 2;
901 let dstride = buf.stride[0];
902 let off = xpos + xoff + (ypos + yoff) * dstride;
903 let mut dst = &mut buf.data;
904 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
905 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
906 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
908 if ((cbp8 >> i) & 1) != 0 {
909 let blk = &mut self.y_coeffs[i * 16..][..16];
910 self.dsp.transform4x4(blk);
911 let dstride = buf.stride[0];
912 let soff = buf.offset[0];
913 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
914 let mut dst = &mut buf.data;
915 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
918 if ((cbp8 >> 4) & 1) != 0 {
919 self.dsp.transform4x4(&mut self.u_coeffs);
920 let dstride = buf.stride[1];
921 let soff = buf.offset[1];
922 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
923 let mut dst = &mut buf.data;
924 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
926 if ((cbp8 >> 5) & 1) != 0 {
927 self.dsp.transform4x4(&mut self.v_coeffs);
928 let dstride = buf.stride[2];
929 let soff = buf.offset[2];
930 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
931 let mut dst = &mut buf.data;
932 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
936 TransformType::T8X8 => {
937 let subset = if is_intra { 1 } else { 3 };
938 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
940 self.coded_blk[cb_pos] = true;
941 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)?;
942 if (cbp8 & 0xF) != 0 {
943 self.dsp.transform8x8(&mut self.y_coeffs);
944 let dstride = buf.stride[0];
945 let off = xpos + ypos * dstride;
946 let mut dst = &mut buf.data;
947 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
949 if ((cbp8 >> 4) & 1) != 0 {
950 self.dsp.transform4x4(&mut self.u_coeffs);
951 let dstride = buf.stride[1];
952 let soff = buf.offset[1];
953 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
954 let mut dst = &mut buf.data;
955 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
957 if ((cbp8 >> 5) & 1) != 0 {
958 self.dsp.transform4x4(&mut self.v_coeffs);
959 let dstride = buf.stride[2];
960 let soff = buf.offset[2];
961 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
962 let mut dst = &mut buf.data;
963 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
967 TransformType::T16X16 => {
968 let subset = if is_intra { 1 } else { 3 };
969 let num_clusters = size >> 4;
970 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
971 for y in 0..num_clusters {
972 for x in 0..num_clusters {
973 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
974 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
975 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
976 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
977 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
978 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
980 self.y_coeffs = [0; 16 * 16];
981 self.u_coeffs = [0; 8 * 8];
982 self.v_coeffs = [0; 8 * 8];
983 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)?;
984 if (super_cbp & 0xFFFF) != 0 {
985 self.dsp.transform16x16(&mut self.y_coeffs);
986 let dstride = buf.stride[0];
987 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
988 let mut dst = &mut buf.data;
989 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
991 if ((super_cbp >> 16) & 0xF) != 0 {
992 self.dsp.transform8x8(&mut self.u_coeffs);
993 let dstride = buf.stride[1];
994 let soff = buf.offset[1];
995 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
996 let mut dst = &mut buf.data;
997 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
999 if ((super_cbp >> 20) & 0xF) != 0 {
1000 self.dsp.transform8x8(&mut self.v_coeffs);
1001 let dstride = buf.stride[2];
1002 let soff = buf.offset[2];
1003 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
1004 let mut dst = &mut buf.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.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.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 NASimpleVideoFrame<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, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> 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 = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
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();
1430 supp.pool_u8.set_dec_bufs(3);
1431 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1436 Err(DecoderError::InvalidData)
1439 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1440 let src = pkt.get_buffer();
1442 validate!(src.len() > 9);
1443 let hsize = (src[0] as usize) * 8 + 9;
1444 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1445 let hdr = FrameHeader::read(&mut br)?;
1446 let mut slices: Vec<usize> = Vec::new();
1447 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1450 if self.ipbs.get_lastref().is_none() {
1451 return Err(DecoderError::MissingReference);
1455 if self.ipbs.get_lastref().is_none() {
1456 return Err(DecoderError::MissingReference);
1458 if self.ipbs.get_nextref().is_none() {
1459 return Err(DecoderError::MissingReference);
1465 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1466 let ret = supp.pool_u8.get_free();
1468 return Err(DecoderError::AllocError);
1470 let mut buf = ret.unwrap();
1471 if buf.get_info() != tmp_vinfo {
1473 supp.pool_u8.reset();
1474 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1475 let ret = supp.pool_u8.get_free();
1477 return Err(DecoderError::AllocError);
1482 let cu_w = hdr.get_width_cu();
1483 let cu_h = hdr.get_height_cu();
1484 self.pu_stride = cu_w << 3;
1485 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1486 self.blk_stride = cu_w << 4;
1487 self.blk_info.truncate(0);
1488 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1490 self.dblk.reinit(hdr.width, hdr.height);
1492 let mut off = hsize + ((br.tell() >> 3) as usize);
1493 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1494 for (cu_y, size) in slices.into_iter().enumerate() {
1495 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1498 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1499 self.ipbs.add_frame(buf.clone());
1502 if hdr.ftype != FrameType::B {
1503 self.ref0_pts = self.ref1_pts;
1504 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1505 self.ref0_ts = self.ref1_ts;
1506 self.ref1_ts = hdr.ts as u64;
1507 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1508 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1511 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1512 frm.set_keyframe(hdr.ftype == FrameType::I);
1513 if hdr.ftype == FrameType::B {
1514 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1515 frm.set_pts(Some(pts));
1517 frm.set_frame_type(hdr.ftype);
1520 fn flush(&mut self) {
1525 impl NAOptionHandler for RealVideo60Decoder {
1526 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
1527 fn set_options(&mut self, _options: &[NAOption]) { }
1528 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
1531 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1532 Box::new(RealVideo60Decoder::new())
1537 use nihav_core::codecs::RegisteredDecoders;
1538 use nihav_core::demuxers::RegisteredDemuxers;
1539 use nihav_codec_support::test::dec_video::*;
1540 use crate::realmedia_register_all_codecs;
1541 use crate::realmedia_register_all_demuxers;
1544 let mut dmx_reg = RegisteredDemuxers::new();
1545 realmedia_register_all_demuxers(&mut dmx_reg);
1546 let mut dec_reg = RegisteredDecoders::new();
1547 realmedia_register_all_codecs(&mut dec_reg);
1549 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);