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.width { 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.width { 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.height { 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.height { 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,
546 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
549 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
551 #[derive(Clone,Copy,Default)]
565 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
567 fn reinit(&mut self, w: usize, h: usize) {
568 self.left_str.clear();
569 self.top_str.clear();
570 self.stride = w >> 2;
571 let size = self.stride * (h >> 2);
572 self.left_str.resize(size, 0);
573 self.top_str.resize(size, 0);
575 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
576 let pos = self.get_pos(xpos, ypos);
577 let dsize = size >> 2;
578 let dval = (q << 2) | strength;
580 self.top_str[pos + x] = dval;
583 self.left_str[pos + y * self.stride] = dval;
586 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
587 (xpos >> 2) + (ypos >> 2) * self.stride
589 fn get_top_strength(&self, pos: usize) -> u8 {
590 self.top_str[pos] & 3
592 fn get_left_strength(&self, pos: usize) -> u8 {
593 self.left_str[pos] & 3
595 fn set_top_strength(&mut self, pos: usize, str: u8) {
596 self.top_str[pos] |= str;
598 fn set_left_strength(&mut self, pos: usize, str: u8) {
599 self.left_str[pos] |= str;
603 struct RealVideo60Decoder {
604 info: NACodecInfoRef,
608 ipred: IntraPredContext,
609 skip_mode: FrameSkipMode,
611 avg_buf: NAVideoBufferRef<u8>,
613 y_coeffs: [i16; 16 * 16],
614 u_coeffs: [i16; 8 * 8],
615 v_coeffs: [i16; 8 * 8],
619 cu_splits: Vec<bool>,
620 coded_blk: [bool; 64],
623 pu_info: Vec<PUInfo>,
627 blk_info: Vec<BlockInfo>,
641 impl RealVideo60Decoder {
643 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
644 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
645 let vb = vt.get_vbuf();
646 let avg_buf = vb.unwrap();
648 info: NACodecInfoRef::default(),
649 cbs: RV60Codebooks::init(),
650 ipbs: IPBShuffler::new(),
651 ipred: IntraPredContext::new(),
652 skip_mode: FrameSkipMode::default(),
655 y_coeffs: [0; 16 * 16],
656 u_coeffs: [0; 8 * 8],
657 v_coeffs: [0; 8 * 8],
660 cu_splits: Vec::with_capacity(24),
661 coded_blk: [false; 64],
662 dblk: DeblockInfo::new(),
666 blk_info: Vec::new(),
679 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
680 let mut br = BitReader::new(src, BitReaderMode::BE);
681 let cu_w = hdr.get_width_cu();
682 let dqp = hdr.read_line_qp_offset(&mut br)?;
683 let qps = (hdr.qp as i8) + dqp;
684 validate!((0..32).contains(&qps));
687 self.sel_qp = match hdr.osvquant {
707 for cu_x in 0..cu_w {
708 self.cu_splits.clear();
709 self.coded_blk = [false; 64];
710 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
712 self.cu_splits.reverse();
713 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
717 println!(" left {} bits", br.left());
721 #[allow(clippy::cognitive_complexity)]
722 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
723 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return Ok(()); }
725 let size = 1 << log_size;
726 let split = (xpos + size > hdr.awidth) || (ypos + size > hdr.aheight) || (size > 8 && br.read_bool()?);
727 self.cu_splits.push(split);
729 let hsize = size >> 1;
730 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
731 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
732 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
733 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
735 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
736 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
737 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
740 self.reconstruct_info(hdr, &cbh, size)?;
742 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
745 let itype = self.blk_info[self.blk_pos].imode;
747 let dstride = buf.stride[0];
748 let off = xpos + ypos * dstride;
749 let dst = &mut buf.data;
750 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
751 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
754 let dstride = buf.stride[comp];
755 let soff = buf.offset[comp];
756 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
757 let dst = &mut buf.data;
758 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
759 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
763 let mut mv_x = xpos >> 2;
764 let mut mv_y = ypos >> 2;
765 let mut mv_pos = mv_x + mv_y * self.blk_stride;
766 for part_no in 0..cbh.pu_type.get_num_mvs() {
767 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
768 let mv = self.blk_info[mv_pos].mv;
775 if hdr.ftype != FrameType::B {
776 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
777 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
780 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
781 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
786 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
787 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
791 validate!(hdr.ftype == FrameType::B);
792 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
793 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
796 MVRef::Ref0AndBRef => {
797 validate!(hdr.ftype == FrameType::B);
798 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
799 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
801 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
802 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
804 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
809 if cbh.pu_type == PUType::Quarters {
814 mv_pos += mv_h * self.blk_stride - mv_w;
818 } else if cbh.pu_type.has_hor_split() {
819 mv_pos += mv_h * self.blk_stride;
821 } else if cbh.pu_type.has_ver_split() {
828 if cbh.ttype != TransformType::None {
829 self.y_coeffs = [0; 16 * 16];
830 self.u_coeffs = [0; 8 * 8];
831 self.v_coeffs = [0; 8 * 8];
833 let is_intra = cbh.cu_type == CUType::Intra;
834 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
836 TransformType::T4X4 => {
837 let subset = if is_intra { 0 } else { 2 };
841 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
846 self.coded_blk[cb_pos + 0] = true;
847 self.coded_blk[cb_pos + 1] = true;
848 self.coded_blk[cb_pos + 8] = true;
849 self.coded_blk[cb_pos + 9] = true;
850 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)?;
854 if ((cbp16 >> i) & 1) != 0 {
855 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
856 let dstride = buf.stride[0];
857 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
858 let dst = &mut buf.data;
859 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
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);
875 if ((cbp16 >> (20 + i)) & 1) != 0 {
876 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
877 let dstride = buf.stride[2];
878 let off = buf.offset[2] + xoff + yoff * dstride;
879 let dst = &mut buf.data;
880 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
886 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
888 self.coded_blk[cb_pos] = true;
889 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)?;
892 let xoff = (i & 1) * 4;
893 let yoff = (i & 2) * 2;
895 let dstride = buf.stride[0];
896 let off = xpos + xoff + (ypos + yoff) * dstride;
897 let dst = &mut buf.data;
898 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
899 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
900 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, false);
902 if ((cbp8 >> i) & 1) != 0 {
903 let blk = &mut self.y_coeffs[i * 16..][..16];
904 self.dsp.transform4x4(blk);
905 let dstride = buf.stride[0];
906 let soff = buf.offset[0];
907 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
908 self.dsp.add_block(buf.data, off, dstride, blk, 4);
911 if ((cbp8 >> 4) & 1) != 0 {
912 self.dsp.transform4x4(&mut self.u_coeffs);
913 let dstride = buf.stride[1];
914 let soff = buf.offset[1];
915 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
916 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
918 if ((cbp8 >> 5) & 1) != 0 {
919 self.dsp.transform4x4(&mut self.v_coeffs);
920 let dstride = buf.stride[2];
921 let soff = buf.offset[2];
922 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
923 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
927 TransformType::T8X8 => {
928 let subset = if is_intra { 1 } else { 3 };
929 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
931 self.coded_blk[cb_pos] = true;
932 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)?;
933 if (cbp8 & 0xF) != 0 {
934 self.dsp.transform8x8(&mut self.y_coeffs);
935 let dstride = buf.stride[0];
936 let off = xpos + ypos * dstride;
937 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
939 if ((cbp8 >> 4) & 1) != 0 {
940 self.dsp.transform4x4(&mut self.u_coeffs);
941 let dstride = buf.stride[1];
942 let soff = buf.offset[1];
943 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
944 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
946 if ((cbp8 >> 5) & 1) != 0 {
947 self.dsp.transform4x4(&mut self.v_coeffs);
948 let dstride = buf.stride[2];
949 let soff = buf.offset[2];
950 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
951 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
955 TransformType::T16X16 => {
956 let subset = if is_intra { 1 } else { 3 };
957 let num_clusters = size >> 4;
958 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
959 for y in 0..num_clusters {
960 for x in 0..num_clusters {
961 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
962 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
963 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
964 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
965 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
966 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
968 self.y_coeffs = [0; 16 * 16];
969 self.u_coeffs = [0; 8 * 8];
970 self.v_coeffs = [0; 8 * 8];
971 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)?;
972 if (super_cbp & 0xFFFF) != 0 {
973 self.dsp.transform16x16(&mut self.y_coeffs);
974 let dstride = buf.stride[0];
975 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
976 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
978 if ((super_cbp >> 16) & 0xF) != 0 {
979 self.dsp.transform8x8(&mut self.u_coeffs);
980 let dstride = buf.stride[1];
981 let soff = buf.offset[1];
982 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
983 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
985 if ((super_cbp >> 20) & 0xF) != 0 {
986 self.dsp.transform8x8(&mut self.v_coeffs);
987 let dstride = buf.stride[2];
988 let soff = buf.offset[2];
989 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
990 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
1001 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1002 let mut pui = PUInfo::default();
1003 let pu_size = size >> 3;
1004 pui.cu_type = cbh.cu_type;
1005 pui.ttype = cbh.ttype;
1006 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1007 self.pu_info[self.pu_pos] = pui;
1010 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1011 validate!(imode <= MAX_IMODE);
1012 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1013 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1020 self.pu_info[self.pu_pos] = pui;
1021 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1022 validate!(imode <= MAX_IMODE);
1023 for y in 0..(size >> 2) {
1024 for x in 0..(size >> 2) {
1025 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1029 CUType::InterMV => {
1030 let mut mv_x = self.xpos >> 2;
1031 let mut mv_y = self.ypos >> 2;
1032 let mut mv_pos = self.blk_pos;
1033 let pu_type = cbh.pu_type;
1034 for part_no in 0..pu_type.get_num_mvs() {
1035 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1036 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1039 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1042 if pu_type == PUType::Quarters {
1047 mv_pos += mv_h * self.blk_stride - mv_w;
1051 } else if pu_type.has_hor_split() {
1052 mv_pos += mv_h * self.blk_stride;
1054 } else if pu_type.has_ver_split() {
1061 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1062 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1063 self.fill_skip_cand(hdr, &mut skip_cand, size);
1064 let mv = skip_cand.list[skip_idx];
1066 let mv_size = size >> 2;
1067 for y in 0..mv_size {
1068 for x in 0..mv_size {
1069 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1074 for y in 0..pu_size {
1075 for x in 0..pu_size {
1076 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1081 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1082 match cbh.imode[0] {
1083 IntraMode::DC64 => { return 1; },
1084 IntraMode::Plane64 => { return 0; },
1087 // form list of predictors
1088 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1089 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1090 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1091 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1093 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1096 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1097 let pu = &self.pu_info[self.pu_pos - 1];
1099 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1102 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1103 let tl_y = self.ypos + (sub & 2) * 4;
1104 if (tl_x > 0) && (tl_y > 0) {
1105 let pu = match sub {
1106 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1107 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1108 2 => &self.pu_info[self.pu_pos - 1],
1109 _ => &self.pu_info[self.pu_pos - 1],
1113 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1115 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1119 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1122 // actually decode prediction mode
1123 match cbh.imode[sub] {
1124 IntraMode::Index(idx) => {
1125 ipm_cand.list[idx as usize]
1127 IntraMode::Mode(mode) => {
1128 let mut imode = mode;
1129 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1131 for ic in ipm_cs.iter() {
1138 _ => unreachable!(),
1141 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1142 let src_off = if is_luma {
1143 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1145 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1147 self.ipred = IntraPredContext::new();
1148 if (self.ypos + yoff) > 0 {
1149 self.ipred.has_t = true;
1151 self.ipred.t[x + 1] = src[src_off - stride + x];
1153 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1154 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1155 self.ipred.has_tr = true;
1156 for x in size..size*2 {
1157 self.ipred.t[x + 1] = src[src_off - stride + x];
1161 self.ipred.t[size + i + 1] = self.ipred.t[size];
1164 if (self.xpos + xoff) > 0 {
1165 self.ipred.t[0] = src[src_off - stride - 1];
1168 if (self.xpos + xoff) > 0 {
1169 self.ipred.has_l = true;
1171 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1173 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1174 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1175 self.ipred.has_ld = true;
1176 for y in size..size*2 {
1177 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1181 self.ipred.l[size + i + 1] = self.ipred.l[size];
1184 if (self.ypos + yoff) > 0 {
1185 self.ipred.l[0] = src[src_off - stride - 1];
1189 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1190 let mv_pos = mv_x + mv_y * self.blk_stride;
1193 if mvi.mvref.is_fwd() {
1194 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1195 let mut mv_cand_size: usize = 0;
1197 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1198 if ref_mv.matches_fwd(mvi.mvref) {
1199 mv_cand[mv_cand_size] = ref_mv.f_mv;
1204 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1205 if ref_mv.matches_fwd(mvi.mvref) {
1206 mv_cand[mv_cand_size] = ref_mv.f_mv;
1210 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1211 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1212 if ref_mv.matches_fwd(mvi.mvref) {
1213 mv_cand[mv_cand_size] = ref_mv.f_mv;
1217 f_mv = match mv_cand_size {
1219 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1220 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1221 if mv_cand_size == 1 {
1224 MV { x: x >> 1, y: y >> 1 }
1227 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1233 if mvi.mvref.is_bwd() {
1234 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1235 let mut mv_cand_size: usize = 0;
1237 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1238 if ref_mv.matches_bwd(mvi.mvref) {
1239 mv_cand[mv_cand_size] = ref_mv.b_mv;
1244 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1245 if ref_mv.matches_bwd(mvi.mvref) {
1246 mv_cand[mv_cand_size] = ref_mv.b_mv;
1250 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1251 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1252 if ref_mv.matches_bwd(mvi.mvref) {
1253 mv_cand[mv_cand_size] = ref_mv.b_mv;
1257 b_mv = match mv_cand_size {
1259 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1260 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1261 if mv_cand_size == 1 {
1264 MV { x: x >> 1, y: y >> 1 }
1267 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1274 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1276 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1277 let mv_size = size >> 2;
1280 let mv = &self.blk_info[self.blk_pos - 1].mv;
1286 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1291 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1292 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1297 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1298 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1303 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1304 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1309 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1310 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1315 if (self.xpos > 0) && (self.ypos > 0) {
1316 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1321 for i in skip_cand.fill..4 {
1322 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1325 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1326 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1327 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1329 let hsize = 1 << (log_size - 1);
1330 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1331 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1332 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1333 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1335 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1336 let cu_type = self.pu_info[pu_pos].cu_type;
1337 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1338 let ntiles = 1 << (log_size - tsize);
1339 let dparams = RV60DeblockParams {
1340 deblock_chroma: hdr.deblock_chroma,
1343 dblkstride: self.dblk.stride,
1345 for ty in 0..ntiles {
1346 for tx in 0..ntiles {
1347 let x = xpos + (tx << tsize);
1348 let y = ypos + (ty << tsize);
1349 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1350 if cu_type == CUType::Intra {
1351 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1352 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1353 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1355 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1356 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1358 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1359 self.dblk.top_str.as_slice(),
1360 self.dblk.left_str.as_slice(),
1361 self.dblk.get_pos(x, y));
1366 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1367 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1368 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1370 let top_blk_pos = blk_pos - self.blk_stride;
1372 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1373 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1374 self.dblk.set_top_strength(dblk_pos + i, 1);
1381 if self.dblk.get_left_strength(dblk_pos) == 0 {
1382 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1383 self.dblk.set_left_strength(dblk_pos, 1);
1386 dblk_pos += self.dblk.stride;
1392 impl NADecoder for RealVideo60Decoder {
1393 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1394 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1395 let fmt = YUV420_FORMAT;
1396 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1397 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1399 let edata = info.get_extradata().unwrap();
1400 let src: &[u8] = &edata;
1402 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1403 let mut mr = MemoryReader::new_read(src);
1404 let mut br = ByteReader::new(&mut mr);
1405 let _flags = br.read_u32be()?;
1406 let version = br.read_u32be()?;
1407 let _unk = br.read_u16be()?;
1408 validate!((version >> 28) == 4);
1409 // then width and height again as 16be
1411 //self.bd.width = vinfo.get_width();
1412 //self.bd.height = vinfo.get_height();
1413 //self.frmmgr.clear();
1415 supp.pool_u8.set_dec_bufs(3);
1416 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1421 Err(DecoderError::InvalidData)
1424 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1425 let src = pkt.get_buffer();
1427 validate!(src.len() > 9);
1428 let hsize = (src[0] as usize) * 8 + 9;
1429 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1430 let hdr = FrameHeader::read(&mut br)?;
1431 match self.skip_mode {
1432 FrameSkipMode::None => {},
1433 FrameSkipMode::KeyframesOnly => {
1434 if hdr.ftype == FrameType::B {
1435 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1436 frm.set_frame_type(FrameType::Skip);
1437 return Ok(frm.into_ref());
1440 FrameSkipMode::IntraOnly => {
1441 if hdr.ftype != FrameType::I {
1442 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1443 frm.set_frame_type(FrameType::Skip);
1444 return Ok(frm.into_ref());
1449 let mut slices: Vec<usize> = Vec::new();
1450 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1453 if self.ipbs.get_lastref().is_none() {
1454 return Err(DecoderError::MissingReference);
1458 if self.ipbs.get_lastref().is_none() {
1459 return Err(DecoderError::MissingReference);
1461 if self.ipbs.get_nextref().is_none() {
1462 return Err(DecoderError::MissingReference);
1468 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1469 let ret = supp.pool_u8.get_free();
1471 return Err(DecoderError::AllocError);
1473 let mut buf = ret.unwrap();
1474 if buf.get_info() != tmp_vinfo {
1476 supp.pool_u8.reset();
1477 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1478 let ret = supp.pool_u8.get_free();
1480 return Err(DecoderError::AllocError);
1485 let cu_w = hdr.get_width_cu();
1486 let cu_h = hdr.get_height_cu();
1487 self.pu_stride = cu_w << 3;
1488 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1489 self.blk_stride = cu_w << 4;
1490 self.blk_info.clear();
1491 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1493 self.dblk.reinit(hdr.awidth, hdr.aheight);
1495 let mut off = hsize + ((br.tell() >> 3) as usize);
1496 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1497 for (cu_y, size) in slices.into_iter().enumerate() {
1498 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1501 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1502 self.ipbs.add_frame(buf.clone());
1505 if hdr.ftype != FrameType::B {
1506 self.ref0_pts = self.ref1_pts;
1507 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1508 self.ref0_ts = self.ref1_ts;
1509 self.ref1_ts = hdr.ts as u64;
1510 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1511 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1514 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1515 frm.set_keyframe(hdr.ftype == FrameType::I);
1516 if hdr.ftype == FrameType::B {
1517 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1518 frm.set_pts(Some(pts));
1520 frm.set_frame_type(hdr.ftype);
1523 fn flush(&mut self) {
1528 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1529 NAOptionDefinition {
1530 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1531 opt_type: NAOptionDefinitionType::String(Some(&[
1532 FRAME_SKIP_OPTION_VAL_NONE,
1533 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1534 FRAME_SKIP_OPTION_VAL_INTRA
1538 impl NAOptionHandler for RealVideo60Decoder {
1539 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1540 fn set_options(&mut self, options: &[NAOption]) {
1541 for option in options.iter() {
1542 for opt_def in DECODER_OPTIONS.iter() {
1543 if opt_def.check(option).is_ok() {
1544 match (option.name, &option.value) {
1545 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1546 if let Ok(smode) = FrameSkipMode::from_str(str) {
1547 self.skip_mode = smode;
1556 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1558 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1564 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1565 Box::new(RealVideo60Decoder::new())
1570 use nihav_core::codecs::RegisteredDecoders;
1571 use nihav_core::demuxers::RegisteredDemuxers;
1572 use nihav_codec_support::test::dec_video::*;
1573 use crate::realmedia_register_all_decoders;
1574 use crate::realmedia_register_all_demuxers;
1577 let mut dmx_reg = RegisteredDemuxers::new();
1578 realmedia_register_all_demuxers(&mut dmx_reg);
1579 let mut dec_reg = RegisteredDecoders::new();
1580 realmedia_register_all_decoders(&mut dec_reg);
1582 // sample from a private collection
1583 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1584 ExpectedTestResult::MD5Frames(vec![
1585 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1586 [0xc7d45c3b, 0x6a82ff3a, 0xaf49a7ea, 0x7cf9a533],
1587 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1588 [0x3db0f7ea, 0xbbf24a80, 0x54c0dd7c, 0xbdea881a],
1589 [0x24134118, 0xeece4c59, 0x3f319c04, 0xd04951fd],
1590 [0xe5f1a7a5, 0x204ab47b, 0x678277b3, 0x179f3007],
1591 [0x61fb5e14, 0x47cce437, 0xaeeed91f, 0x03f727aa],
1592 [0x46c71f20, 0x8e6ee603, 0xb68965ee, 0xf5bf3c45],
1593 [0xf87589a4, 0xd9cc9120, 0xff27a8e6, 0xc1cc1dd5],
1594 [0x12ea3288, 0x810b766b, 0x9a83ac11, 0x88f9996a],
1595 [0xe1a8020f, 0x972fadbb, 0x771f0f7e, 0x7a3a3e41],
1596 [0xed041308, 0x3112b04e, 0xcb39b23b, 0x5f73798c],
1597 [0xb0a2db76, 0x56dd7f97, 0x87e4f6d4, 0xe69ecfd8]]));