1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult, FrameSkipMode};
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::*;
11 use super::rv60codes::*;
12 use super::rv60dsp::*;
14 struct UniqueList<A> {
20 impl<A:Copy+Default+PartialEq> UniqueList<A> {
21 fn new(max_size: usize) -> Self {
22 Self { list: [A::default(); 4], fill: 0, max_size }
24 fn add(&mut self, cand: A) {
25 if self.fill == self.max_size { return; }
26 let mut unique = true;
27 for el in self.list.iter().take(self.fill) {
34 self.list[self.fill] = cand;
40 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
41 const MAX_IMODE: u8 = 34;
43 #[derive(Clone,Copy,Debug)]
61 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
63 fn read(br: &mut BitReader) -> DecoderResult<Self> {
64 let marker = br.read(2)?;
65 validate!(marker == 3);
66 let profile = br.read(2)? as u8;
67 validate!(profile == 0);
68 let _someval = br.read(4)?;
69 let ftypeid = br.read(2)? as usize;
70 let ftype = RV60_FRAME_TYPES[ftypeid];
71 let qp = br.read(6)? as u8;
72 let marker = br.read(1)?;
73 validate!(marker == 0);
74 let toolset = br.read(2)?;
75 validate!(toolset == 0);
76 let osvquant = br.read(2)? as u8;
77 let _some_flag = br.read_bool()?;
78 let _some_val = br.read(2)?;
79 let ts = br.read(24)?;
80 let width = ((br.read(11)? as usize) + 1) * 4;
81 let height = ((br.read(11)? as usize) + 0) * 4;
82 validate!(height > 0);
83 let awidth = (width + 15) & !15;
84 let aheight = (height + 15) & !15;
85 let _some_flag = br.read_bool()?;
87 if ftype == FrameType::I {
91 let flag = br.read_bool()?;
98 two_f_refs = br.read_bool()?;
100 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
101 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
102 let chroma_qp_diff = br.read(1)?;
103 validate!(chroma_qp_diff == 0);
104 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
105 let deblock = br.read_bool()?;
106 let deblock_chroma = deblock && !br.read_bool()?;
108 let custom_msg_hdr_len = br.read(2)? as usize;
109 if custom_msg_hdr_len != 0 {
110 for i in 0..custom_msg_hdr_len {
111 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
117 profile, ftype, qp, osvquant, ts, width, height, awidth, aheight,
118 two_f_refs, qp_off_type, deblock, deblock_chroma,
121 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
122 let nslices = self.get_height_cu();
123 let nbits = (br.read(5)? as u8) + 1;
124 validate!(nbits < 32);
125 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
126 for _ in 0..nslices {
127 let sign = br.read_bool()?;
133 let first_size = br.read(nbits)? as usize;
134 validate!(first_size > 0);
136 let mut lastsize = first_size;
137 sizes.push(first_size);
138 for i in 1..nslices {
139 let diff = br.read(nbits)? as isize;
142 let sum = (lastsize as isize).checked_add(diff);
143 validate!(sum.is_some());
144 size = sum.unwrap() as usize;
146 let sum = (lastsize as isize).checked_sub(diff);
147 validate!(sum.is_some());
148 size = sum.unwrap() as usize;
155 if ((br.left() >> 3) as usize) != sum {
156 println!(" left {} / {}", br.left() >> 3, sum);
158 validate!((br.left() >> 3) >= (sum as isize));
161 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
162 match self.qp_off_type {
165 let val = br.read_code(UintCodeType::Unary012)?;
173 if br.read(1)? == 0 {
176 let val = br.read(2)? as i8;
186 fn get_width_cu(&self) -> usize {
187 (self.width + 63) >> 6
189 fn get_height_cu(&self) -> usize {
190 (self.height + 63) >> 6
192 fn has_top_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) > self.awidth { return false; }
198 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
199 if (ypos + dy) == 0 { return false; }
200 let xpos2 = xpos + dx;
201 if (xpos2 + size * 2) > self.awidth { return false; }
202 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
203 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
204 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
206 fn has_left_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) > self.aheight { return false; }
212 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
213 if (xpos + dx) == 0 { return false; }
214 let ypos2 = ypos + dy;
215 if (ypos2 + size * 2) > self.aheight { return false; }
216 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
217 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
218 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
222 const RV60_BLOCK_LOG2: [u8; 65] = [
224 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
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, 6
229 const RV60_AVAIL_MASK: [u8; 64] = [
230 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0xF,
231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
236 #[derive(Clone,Copy,PartialEq,Debug)]
244 impl Default for CUType {
245 fn default() -> Self { CUType::Intra }
248 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
250 #[derive(Clone,Copy,PartialEq,Debug)]
262 const RV60_PU_TYPES: [PUType; 8] = [
263 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
264 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
268 fn get_num_mvs(self) -> usize {
271 PUType::Quarters => 4,
275 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
276 let mv_size = size >> 2;
278 PUType::Full => (mv_size, mv_size),
279 PUType::N2Hor => (mv_size, mv_size >> 1),
280 PUType::N2Ver => (mv_size >> 1, mv_size),
281 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
284 (mv_size, mv_size >> 2)
286 (mv_size, (3 * mv_size) >> 2)
291 (mv_size, (3 * mv_size) >> 2)
293 (mv_size, mv_size >> 2)
298 ( mv_size >> 2, mv_size)
300 ((3 * mv_size) >> 2, mv_size)
305 ((3 * mv_size) >> 2, mv_size)
307 ( mv_size >> 2, mv_size)
312 fn has_hor_split(self) -> bool {
313 matches!(self, PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters)
315 fn has_ver_split(self) -> bool {
316 matches!(self, PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters)
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 {
369 matches!(self, MVRef::Ref0 | MVRef::Ref0AndBRef)
371 fn is_fwd(self) -> bool {
372 matches!(self, MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef)
374 fn is_bwd(self) -> bool {
375 matches!(self, MVRef::BRef | MVRef::Ref0AndBRef)
379 #[derive(Clone,Copy,PartialEq,Debug)]
387 fn is_some(&self) -> bool { self.mvref != MVRef::None }
388 fn matches_fwd(&self, mvref: MVRef) -> bool {
389 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
391 fn matches_bwd(&self, mvref: MVRef) -> bool {
392 self.mvref.is_bwd() && mvref.is_bwd()
394 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
395 if self.mvref != other.mvref { return true; }
397 if self.mvref.is_fwd() {
398 let diff = self.f_mv - other.f_mv;
399 mvdiff += diff.x.abs() + diff.y.abs();
401 if self.mvref.is_bwd() {
402 let diff = self.b_mv - other.b_mv;
403 mvdiff += diff.x.abs() + diff.y.abs();
409 impl Default for MVInfo {
410 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
413 #[derive(Clone,Copy,Debug)]
417 ttype: TransformType,
418 imode: [IntraMode; 4],
423 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
426 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
427 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
428 if ftype == FrameType::I {
429 cu_type = CUType::Intra;
431 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
435 if (size == 8) && br.read_bool()? {
436 pu_type = PUType::Quarters;
438 pu_type = PUType::Full;
440 if pu_type == PUType::Quarters {
442 imode[i] = CBHeader::read_intra_mode(br)?;
444 } else if size <= 32 {
445 imode[0] = CBHeader::read_intra_mode(br)?;
447 if !br.read_bool()? {
448 imode[0] = IntraMode::DC64;
450 imode[0] = IntraMode::Plane64;
455 let bits = if size == 8 { 2 } else { 3 };
456 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
457 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
460 pu_type = PUType::Full;
461 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
462 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
466 if cu_type == CUType::Skip {
467 ttype = TransformType::None;
468 } else if size >= 32 {
469 ttype = TransformType::T16X16;
470 } else if size == 16 {
471 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
472 ttype = TransformType::T16X16;
474 ttype = TransformType::T4X4;
477 if pu_type == PUType::Full {
478 ttype = TransformType::T8X8;
480 ttype = TransformType::T4X4;
484 cu_type, pu_type, ttype, imode, mv,
487 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
489 let idx = br.read_code(UintCodeType::Unary012)? as u8;
490 Ok(IntraMode::Index(idx))
492 let mode = br.read(5)? as u8;
493 Ok(IntraMode::Mode(mode))
496 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
497 let mv_count = pu_type.get_num_mvs();
498 for i in 0..mv_count {
499 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
503 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
504 let mut f_mv = ZERO_MV;
505 let mut b_mv = ZERO_MV;
507 if ftype != FrameType::B {
508 if two_f_refs && br.read_bool()? {
513 f_mv = CBHeader::read_mv(br)?;
514 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
516 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
517 if !br.read_bool()? {
519 f_mv = CBHeader::read_mv(br)?;
522 b_mv = CBHeader::read_mv(br)?;
525 mvref = MVRef::Ref0AndBRef;
526 f_mv = CBHeader::read_mv(br)?;
527 b_mv = CBHeader::read_mv(br)?;
529 Ok(MVInfo { f_mv, b_mv, mvref })
532 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
533 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
534 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
539 #[derive(Clone,Copy,Default)]
542 ttype: TransformType,
547 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
550 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
552 #[derive(Clone,Copy,Default)]
566 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
568 fn reinit(&mut self, w: usize, h: usize) {
569 self.left_str.clear();
570 self.top_str.clear();
571 self.stride = w >> 2;
572 let size = self.stride * (h >> 2);
573 self.left_str.resize(size, 0);
574 self.top_str.resize(size, 0);
576 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
577 let pos = self.get_pos(xpos, ypos);
578 let dsize = size >> 2;
579 let dval = (q << 2) | strength;
581 self.top_str[pos + x] = dval;
582 self.top_str[pos + (dsize - 1) * self.stride + x] = dval;
585 self.left_str[pos + y * self.stride] = dval;
586 self.left_str[pos + y * self.stride + dsize - 1] = dval;
589 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
590 (xpos >> 2) + (ypos >> 2) * self.stride
592 fn get_top_strength(&self, pos: usize) -> u8 {
593 self.top_str[pos] & 3
595 fn get_left_strength(&self, pos: usize) -> u8 {
596 self.left_str[pos] & 3
598 fn set_top_strength(&mut self, pos: usize, str: u8) {
599 self.top_str[pos] |= str;
601 fn set_left_strength(&mut self, pos: usize, str: u8) {
602 self.left_str[pos] |= str;
606 struct RealVideo60Decoder {
607 info: NACodecInfoRef,
611 ipred: IntraPredContext,
612 skip_mode: FrameSkipMode,
614 avg_buf: NAVideoBufferRef<u8>,
616 y_coeffs: [i16; 16 * 16],
617 u_coeffs: [i16; 8 * 8],
618 v_coeffs: [i16; 8 * 8],
622 cu_splits: Vec<bool>,
623 coded_blk: [bool; 64],
626 pu_info: Vec<PUInfo>,
630 blk_info: Vec<BlockInfo>,
644 impl RealVideo60Decoder {
646 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
647 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
648 let vb = vt.get_vbuf();
649 let avg_buf = vb.unwrap();
651 info: NACodecInfoRef::default(),
652 cbs: RV60Codebooks::init(),
653 ipbs: IPBShuffler::new(),
654 ipred: IntraPredContext::new(),
655 skip_mode: FrameSkipMode::default(),
658 y_coeffs: [0; 16 * 16],
659 u_coeffs: [0; 8 * 8],
660 v_coeffs: [0; 8 * 8],
663 cu_splits: Vec::with_capacity(24),
664 coded_blk: [false; 64],
665 dblk: DeblockInfo::new(),
669 blk_info: Vec::new(),
682 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
683 let mut br = BitReader::new(src, BitReaderMode::BE);
684 let cu_w = hdr.get_width_cu();
685 for cu_x in 0..cu_w {
686 let dqp = hdr.read_line_qp_offset(&mut br)?;
687 let qps = (hdr.qp as i8) + dqp;
688 validate!((0..32).contains(&qps));
691 self.sel_qp = match hdr.osvquant {
711 self.cu_splits.clear();
712 self.coded_blk = [false; 64];
713 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
715 self.cu_splits.reverse();
716 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
720 println!(" left {} bits", br.left());
724 #[allow(clippy::cognitive_complexity)]
725 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
726 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return Ok(()); }
728 let size = 1 << log_size;
729 let split = (xpos + size > hdr.awidth) || (ypos + size > hdr.aheight) || (size > 8 && br.read_bool()?);
730 self.cu_splits.push(split);
732 let hsize = size >> 1;
733 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
734 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
735 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
736 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
738 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
739 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
740 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
743 self.reconstruct_info(hdr, &cbh, size)?;
745 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
748 let itype = self.blk_info[self.blk_pos].imode;
750 let dstride = buf.stride[0];
751 let off = xpos + ypos * dstride;
752 let dst = &mut buf.data;
753 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
754 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
757 let dstride = buf.stride[comp];
758 let soff = buf.offset[comp];
759 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
760 let dst = &mut buf.data;
761 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
762 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
766 let mut mv_x = xpos >> 2;
767 let mut mv_y = ypos >> 2;
768 let mut mv_pos = mv_x + mv_y * self.blk_stride;
769 for part_no in 0..cbh.pu_type.get_num_mvs() {
770 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
771 let mv = self.blk_info[mv_pos].mv;
778 if hdr.ftype != FrameType::B {
779 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
780 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
783 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
784 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
789 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
790 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
794 validate!(hdr.ftype == FrameType::B);
795 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
796 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
799 MVRef::Ref0AndBRef => {
800 validate!(hdr.ftype == FrameType::B);
801 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
802 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
804 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
805 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
807 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
812 if cbh.pu_type == PUType::Quarters {
817 mv_pos += mv_h * self.blk_stride - mv_w;
821 } else if cbh.pu_type.has_hor_split() {
822 mv_pos += mv_h * self.blk_stride;
824 } else if cbh.pu_type.has_ver_split() {
831 if cbh.ttype != TransformType::None {
832 self.y_coeffs = [0; 16 * 16];
833 self.u_coeffs = [0; 8 * 8];
834 self.v_coeffs = [0; 8 * 8];
836 let is_intra = cbh.cu_type == CUType::Intra;
837 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
839 TransformType::T4X4 => {
840 let subset = if is_intra { 0 } else { 2 };
844 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
849 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)?;
853 if ((cbp16 >> i) & 1) != 0 {
854 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
855 let dstride = buf.stride[0];
856 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
857 let dst = &mut buf.data;
858 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
859 self.coded_blk[cb_pos + (y / 2) * 8 + (x / 2)] = true;
866 let xoff = (xpos >> 1) + x * 4;
867 let yoff = (ypos >> 1) + y * 4;
868 if ((cbp16 >> (16 + i)) & 1) != 0 {
869 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
870 let dstride = buf.stride[1];
871 let off = buf.offset[1] + xoff + yoff * dstride;
872 let dst = &mut buf.data;
873 self.dsp.add_block(dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
874 self.coded_blk[cb_pos + y * 8 + x] = true;
876 if ((cbp16 >> (20 + i)) & 1) != 0 {
877 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
878 let dstride = buf.stride[2];
879 let off = buf.offset[2] + xoff + yoff * dstride;
880 let dst = &mut buf.data;
881 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
882 self.coded_blk[cb_pos + y * 8 + x] = true;
888 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
890 self.coded_blk[cb_pos] = true;
891 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)?;
894 let xoff = (i & 1) * 4;
895 let yoff = (i & 2) * 2;
897 let dstride = buf.stride[0];
898 let off = xpos + xoff + (ypos + yoff) * dstride;
899 let dst = &mut buf.data;
900 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
901 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
902 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, true);
904 if ((cbp8 >> i) & 1) != 0 {
905 let blk = &mut self.y_coeffs[i * 16..][..16];
906 self.dsp.transform4x4(blk);
907 let dstride = buf.stride[0];
908 let soff = buf.offset[0];
909 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
910 self.dsp.add_block(buf.data, off, dstride, blk, 4);
913 if ((cbp8 >> 4) & 1) != 0 {
914 self.dsp.transform4x4(&mut self.u_coeffs);
915 let dstride = buf.stride[1];
916 let soff = buf.offset[1];
917 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
918 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
920 if ((cbp8 >> 5) & 1) != 0 {
921 self.dsp.transform4x4(&mut self.v_coeffs);
922 let dstride = buf.stride[2];
923 let soff = buf.offset[2];
924 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
925 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
929 TransformType::T8X8 => {
930 let subset = if is_intra { 1 } else { 3 };
931 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
933 self.coded_blk[cb_pos] = true;
934 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)?;
935 if (cbp8 & 0xF) != 0 {
936 self.dsp.transform8x8(&mut self.y_coeffs);
937 let dstride = buf.stride[0];
938 let off = xpos + ypos * dstride;
939 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
941 if ((cbp8 >> 4) & 1) != 0 {
942 self.dsp.transform4x4(&mut self.u_coeffs);
943 let dstride = buf.stride[1];
944 let soff = buf.offset[1];
945 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
946 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
948 if ((cbp8 >> 5) & 1) != 0 {
949 self.dsp.transform4x4(&mut self.v_coeffs);
950 let dstride = buf.stride[2];
951 let soff = buf.offset[2];
952 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
953 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
957 TransformType::T16X16 => {
958 let subset = if is_intra { 1 } else { 3 };
959 let num_clusters = size >> 4;
960 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
961 for y in 0..num_clusters {
962 for x in 0..num_clusters {
963 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
964 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
965 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
966 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
967 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
968 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
970 self.y_coeffs = [0; 16 * 16];
971 self.u_coeffs = [0; 8 * 8];
972 self.v_coeffs = [0; 8 * 8];
973 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)?;
974 if (super_cbp & 0xFFFF) != 0 {
975 self.dsp.transform16x16(&mut self.y_coeffs);
976 let dstride = buf.stride[0];
977 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
978 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
980 if ((super_cbp >> 16) & 0xF) != 0 {
981 self.dsp.transform8x8(&mut self.u_coeffs);
982 let dstride = buf.stride[1];
983 let soff = buf.offset[1];
984 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
985 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
987 if ((super_cbp >> 20) & 0xF) != 0 {
988 self.dsp.transform8x8(&mut self.v_coeffs);
989 let dstride = buf.stride[2];
990 let soff = buf.offset[2];
991 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
992 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
1003 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1004 let mut pui = PUInfo::default();
1005 let pu_size = size >> 3;
1006 pui.cu_type = cbh.cu_type;
1007 pui.ttype = cbh.ttype;
1008 pui.pu_type = cbh.pu_type;
1009 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1010 self.pu_info[self.pu_pos] = pui;
1013 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1014 validate!(imode <= MAX_IMODE);
1015 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1016 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1023 self.pu_info[self.pu_pos] = pui;
1024 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1025 validate!(imode <= MAX_IMODE);
1026 for y in 0..(size >> 2) {
1027 for x in 0..(size >> 2) {
1028 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1032 CUType::InterMV => {
1033 let mut mv_x = self.xpos >> 2;
1034 let mut mv_y = self.ypos >> 2;
1035 let mut mv_pos = self.blk_pos;
1036 let pu_type = cbh.pu_type;
1037 for part_no in 0..pu_type.get_num_mvs() {
1038 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1039 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1042 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1045 if pu_type == PUType::Quarters {
1050 mv_pos += mv_h * self.blk_stride - mv_w;
1054 } else if pu_type.has_hor_split() {
1055 mv_pos += mv_h * self.blk_stride;
1057 } else if pu_type.has_ver_split() {
1064 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1065 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1066 self.fill_skip_cand(hdr, &mut skip_cand, size);
1067 let mv = skip_cand.list[skip_idx];
1069 let mv_size = size >> 2;
1070 for y in 0..mv_size {
1071 for x in 0..mv_size {
1072 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1077 for y in 0..pu_size {
1078 for x in 0..pu_size {
1079 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1084 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1085 match cbh.imode[0] {
1086 IntraMode::DC64 => { return 1; },
1087 IntraMode::Plane64 => { return 0; },
1090 // form list of predictors
1091 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1092 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1093 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1094 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1096 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1099 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1100 let pu = &self.pu_info[self.pu_pos - 1];
1102 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1105 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1106 let tl_y = self.ypos + (sub & 2) * 4;
1107 if (tl_x > 0) && (tl_y > 0) {
1108 let pu = match sub {
1109 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1110 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1111 2 => &self.pu_info[self.pu_pos - 1],
1112 _ => &self.pu_info[self.pu_pos - 1],
1116 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1118 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1122 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1125 // actually decode prediction mode
1126 match cbh.imode[sub] {
1127 IntraMode::Index(idx) => {
1128 ipm_cand.list[idx as usize]
1130 IntraMode::Mode(mode) => {
1131 let mut imode = mode;
1132 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1134 for ic in ipm_cs.iter() {
1141 _ => unreachable!(),
1144 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1145 let src_off = if is_luma {
1146 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1148 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1150 self.ipred = IntraPredContext::new();
1151 if (self.ypos + yoff) > 0 {
1152 self.ipred.has_t = true;
1154 self.ipred.t[x + 1] = src[src_off - stride + x];
1156 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1157 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1158 self.ipred.has_tr = true;
1159 for x in size..size*2 {
1160 self.ipred.t[x + 1] = src[src_off - stride + x];
1164 self.ipred.t[size + i + 1] = self.ipred.t[size];
1167 if (self.xpos + xoff) > 0 {
1168 self.ipred.t[0] = src[src_off - stride - 1];
1171 if (self.xpos + xoff) > 0 {
1172 self.ipred.has_l = true;
1174 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1176 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1177 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1178 self.ipred.has_ld = true;
1179 for y in size..size*2 {
1180 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1184 self.ipred.l[size + i + 1] = self.ipred.l[size];
1187 if (self.ypos + yoff) > 0 {
1188 self.ipred.l[0] = src[src_off - stride - 1];
1192 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1193 let mv_pos = mv_x + mv_y * self.blk_stride;
1196 if mvi.mvref.is_fwd() {
1197 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1198 let mut mv_cand_size: usize = 0;
1200 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1213 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1214 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1215 if ref_mv.matches_fwd(mvi.mvref) {
1216 mv_cand[mv_cand_size] = ref_mv.f_mv;
1220 f_mv = match mv_cand_size {
1222 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1223 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1224 if mv_cand_size == 1 {
1227 MV { x: x >> 1, y: y >> 1 }
1230 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1236 if mvi.mvref.is_bwd() {
1237 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1238 let mut mv_cand_size: usize = 0;
1240 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1253 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1254 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1255 if ref_mv.matches_bwd(mvi.mvref) {
1256 mv_cand[mv_cand_size] = ref_mv.b_mv;
1260 b_mv = match mv_cand_size {
1262 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1263 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1264 if mv_cand_size == 1 {
1267 MV { x: x >> 1, y: y >> 1 }
1270 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1277 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1279 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1280 let mv_size = size >> 2;
1283 let mv = &self.blk_info[self.blk_pos - 1].mv;
1289 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1294 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1295 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1300 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1301 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1306 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1307 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1312 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1313 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1318 if (self.xpos > 0) && (self.ypos > 0) {
1319 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1324 for i in skip_cand.fill..4 {
1325 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1328 fn calc_tile_size(&self, pu_pos: usize, cu_type: CUType, log_size: u8) -> u8 {
1331 4 if (cu_type != CUType::Intra) && (self.pu_info[pu_pos].pu_type != PUType::Full) => 3,
1333 _ => unreachable!(),
1336 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1337 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return; }
1338 let split = self.cu_splits.pop().unwrap();
1340 let hsize = 1 << (log_size - 1);
1341 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1342 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1343 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1344 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1346 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1347 let cu_type = self.pu_info[pu_pos].cu_type;
1348 let tsize = self.calc_tile_size(pu_pos, cu_type, log_size);
1349 let ntiles = 1 << (log_size - tsize);
1350 let dparams = RV60DeblockParams {
1351 deblock_chroma: hdr.deblock_chroma,
1353 height: hdr.aheight,
1354 dblkstride: self.dblk.stride,
1356 for ty in 0..ntiles {
1357 for tx in 0..ntiles {
1358 let x = xpos + (tx << tsize);
1359 let y = ypos + (ty << tsize);
1360 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1361 if cu_type == CUType::Intra {
1362 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1363 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1364 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1366 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1367 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1369 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1370 self.dblk.top_str.as_slice(),
1371 self.dblk.left_str.as_slice(),
1372 self.dblk.get_pos(x, y));
1377 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1378 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1379 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1381 let top_blk_pos = blk_pos - self.blk_stride;
1383 if self.dblk.get_top_strength(dblk_pos - self.dblk.stride + i) == 0 {
1384 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1385 self.dblk.set_top_strength(dblk_pos + i, 1);
1392 if self.dblk.get_left_strength(dblk_pos - 1) == 0 {
1393 if self.blk_info[blk_pos + i * self.blk_stride].mv.is_deblock_cand(&self.blk_info[blk_pos + i * self.blk_stride - 1].mv) {
1394 self.dblk.set_left_strength(dblk_pos, 1);
1397 dblk_pos += self.dblk.stride;
1403 impl NADecoder for RealVideo60Decoder {
1404 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1405 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1406 let fmt = YUV420_FORMAT;
1407 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1408 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1410 let edata = info.get_extradata().unwrap();
1411 let src: &[u8] = &edata;
1413 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1414 let mut mr = MemoryReader::new_read(src);
1415 let mut br = ByteReader::new(&mut mr);
1416 let _flags = br.read_u32be()?;
1417 let version = br.read_u32be()?;
1418 let _unk = br.read_u16be()?;
1419 validate!((version >> 28) == 4);
1420 // then width and height again as 16be
1422 //self.bd.width = vinfo.get_width();
1423 //self.bd.height = vinfo.get_height();
1424 //self.frmmgr.clear();
1426 supp.pool_u8.set_dec_bufs(3);
1427 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1432 Err(DecoderError::InvalidData)
1435 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1436 let src = pkt.get_buffer();
1438 validate!(src.len() > 9);
1439 let hsize = (src[0] as usize) * 8 + 9;
1440 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1441 let hdr = FrameHeader::read(&mut br)?;
1442 match self.skip_mode {
1443 FrameSkipMode::None => {},
1444 FrameSkipMode::KeyframesOnly => {
1445 if hdr.ftype == FrameType::B {
1446 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1447 frm.set_frame_type(FrameType::Skip);
1448 return Ok(frm.into_ref());
1451 FrameSkipMode::IntraOnly => {
1452 if hdr.ftype != FrameType::I {
1453 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1454 frm.set_frame_type(FrameType::Skip);
1455 return Ok(frm.into_ref());
1460 let mut slices: Vec<usize> = Vec::new();
1461 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1464 if self.ipbs.get_lastref().is_none() {
1465 return Err(DecoderError::MissingReference);
1469 if self.ipbs.get_lastref().is_none() {
1470 return Err(DecoderError::MissingReference);
1472 if self.ipbs.get_nextref().is_none() {
1473 return Err(DecoderError::MissingReference);
1479 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1480 let ret = supp.pool_u8.get_free();
1482 return Err(DecoderError::AllocError);
1484 let mut buf = ret.unwrap();
1485 if buf.get_info() != tmp_vinfo {
1487 supp.pool_u8.reset();
1488 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1489 let ret = supp.pool_u8.get_free();
1491 return Err(DecoderError::AllocError);
1496 let cu_w = hdr.get_width_cu();
1497 let cu_h = hdr.get_height_cu();
1498 self.pu_stride = cu_w << 3;
1499 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1500 self.blk_stride = cu_w << 4;
1501 self.blk_info.clear();
1502 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1504 self.dblk.reinit(hdr.awidth, hdr.aheight);
1506 let mut off = hsize + ((br.tell() >> 3) as usize);
1507 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1508 for (cu_y, size) in slices.into_iter().enumerate() {
1509 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1512 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1513 self.ipbs.add_frame(buf.clone());
1516 if hdr.ftype != FrameType::B {
1517 self.ref0_pts = self.ref1_pts;
1518 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1519 self.ref0_ts = self.ref1_ts;
1520 self.ref1_ts = hdr.ts as u64;
1521 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1522 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1525 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1526 frm.set_keyframe(hdr.ftype == FrameType::I);
1527 if hdr.ftype == FrameType::B {
1528 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1529 frm.set_pts(Some(pts));
1531 frm.set_frame_type(hdr.ftype);
1534 fn flush(&mut self) {
1539 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1540 NAOptionDefinition {
1541 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1542 opt_type: NAOptionDefinitionType::String(Some(&[
1543 FRAME_SKIP_OPTION_VAL_NONE,
1544 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1545 FRAME_SKIP_OPTION_VAL_INTRA
1549 impl NAOptionHandler for RealVideo60Decoder {
1550 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1551 fn set_options(&mut self, options: &[NAOption]) {
1552 for option in options.iter() {
1553 for opt_def in DECODER_OPTIONS.iter() {
1554 if opt_def.check(option).is_ok() {
1555 match (option.name, &option.value) {
1556 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1557 if let Ok(smode) = FrameSkipMode::from_str(str) {
1558 self.skip_mode = smode;
1567 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1569 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1575 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1576 Box::new(RealVideo60Decoder::new())
1581 use nihav_core::codecs::RegisteredDecoders;
1582 use nihav_core::demuxers::RegisteredDemuxers;
1583 use nihav_codec_support::test::dec_video::*;
1584 use crate::realmedia_register_all_decoders;
1585 use crate::realmedia_register_all_demuxers;
1588 let mut dmx_reg = RegisteredDemuxers::new();
1589 realmedia_register_all_demuxers(&mut dmx_reg);
1590 let mut dec_reg = RegisteredDecoders::new();
1591 realmedia_register_all_decoders(&mut dec_reg);
1593 // sample from a private collection
1594 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1595 ExpectedTestResult::MD5Frames(vec![
1596 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1597 [0x76743a3b, 0x7dd4f196, 0x0193fe5a, 0x4f78c7cb],
1598 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1599 [0xfee70206, 0x626f3bea, 0x7677ad4b, 0x1228f3b6],
1600 [0x7156cbc2, 0xf381bcb6, 0xe86531f2, 0xb311c3ea],
1601 [0x1742b5a1, 0x66252580, 0x242753de, 0x5215d732],
1602 [0xd357ebda, 0x6460dba6, 0xa93eb616, 0x63ee6d60],
1603 [0x4cd72275, 0x28e1e439, 0xad17dfca, 0x3fd7253f],
1604 [0xe389ce4f, 0x8f0891b3, 0x88639b23, 0x21ed114f],
1605 [0x5b2b2f1b, 0x17a7518b, 0x53806e6a, 0x4538bb00],
1606 [0xdca03c9a, 0x1a45d80c, 0x86141211, 0x79912ed4],
1607 [0x0bf66bf4, 0x46385620, 0xc6fa4796, 0xd8e16d56],
1608 [0x4671a7f0, 0x46f50649, 0x268df27b, 0x70b71ab3]]));
1611 fn test_rv60_dqp() {
1612 let mut dmx_reg = RegisteredDemuxers::new();
1613 realmedia_register_all_demuxers(&mut dmx_reg);
1614 let mut dec_reg = RegisteredDecoders::new();
1615 realmedia_register_all_decoders(&mut dec_reg);
1617 // sample provided by Peter Ross
1618 test_decoding("realmedia", "realvideo6", "assets/RV/qp-offset-type-2.rmhd", Some(500), &dmx_reg, &dec_reg,
1619 ExpectedTestResult::MD5Frames(vec![
1620 [0x3dc2f19e, 0x0f8c66bd, 0x8e81ceda, 0xa1bf8f58],
1621 [0xbd9c0f89, 0x67b780b0, 0xa4afe443, 0x9f17221a],
1622 [0xf3e0a7ba, 0xe620ace9, 0x03857219, 0x8c3bd1fb],
1623 [0xc4eedc8c, 0x81d2dd0f, 0xa6443847, 0x09c8cec9],
1624 [0x565fc952, 0x4d5dc166, 0xf64b7b0d, 0x1570de50],
1625 [0x0e50786a, 0xaf058ff3, 0xa3f71eba, 0x370c197a],
1626 [0x1b92667b, 0x9cab9e24, 0x1bf48cb2, 0x368db124],
1627 [0xefcc0ab4, 0x6efceb20, 0xb2501ee8, 0xb449b7b6],
1628 [0xbbc2ca23, 0x6a7a8da2, 0xeadc1ff7, 0x2ff0a7f3],
1629 [0x6d14a2b4, 0x0d2642fb, 0x78fcad10, 0xba571ec1],
1630 [0xbdf889fd, 0x5f15838a, 0x8fedd13f, 0xc26a2e50],
1631 [0x886f03b6, 0xc46ba7c3, 0xae6aa971, 0x90cf94b6],
1632 [0x951693e7, 0xa77f68f3, 0x765990c9, 0x4a4d57fa],
1633 [0x3c25f4eb, 0x5c113c41, 0x4d73f498, 0xd7e210b0]]));