From 52aad9fed3d4cfb4243fdd54522aa28d40068fad Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 13 Nov 2018 19:35:36 +0100 Subject: [PATCH] RealVideo 6 decoder (mostly working) --- Cargo.toml | 3 +- src/codecs/mod.rs | 2 +- src/codecs/real/mod.rs | 4 + src/codecs/real/rv60.rs | 1490 ++++++++++++++++++++++++++++++++++ src/codecs/real/rv60codes.rs | 1437 ++++++++++++++++++++++++++++++++ src/codecs/real/rv60dsp.rs | 928 +++++++++++++++++++++ 6 files changed, 3862 insertions(+), 2 deletions(-) create mode 100644 src/codecs/real/rv60.rs create mode 100644 src/codecs/real/rv60codes.rs create mode 100644 src/codecs/real/rv60dsp.rs diff --git a/Cargo.toml b/Cargo.toml index a243794..df405a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ dsp_window = ["dsp"] all_decoders = ["all_video_decoders", "all_audio_decoders"] -all_video_decoders = ["decoder_clearvideo", "decoder_gdvvid", "decoder_indeo2", "decoder_indeo3", "decoder_indeo4", "decoder_indeo5", "decoder_intel263", "decoder_realvideo1", "decoder_realvideo2", "decoder_realvideo3", "decoder_realvideo4"] +all_video_decoders = ["decoder_clearvideo", "decoder_gdvvid", "decoder_indeo2", "decoder_indeo3", "decoder_indeo4", "decoder_indeo5", "decoder_intel263", "decoder_realvideo1", "decoder_realvideo2", "decoder_realvideo3", "decoder_realvideo4", "decoder_realvideo6"] decoder_clearvideo = ["decoders"] decoder_gdvvid = ["decoders"] decoder_indeo2 = ["decoders"] @@ -33,6 +33,7 @@ decoder_realvideo1 = ["h263", "decoders"] decoder_realvideo2 = ["h263", "decoders"] decoder_realvideo3 = ["decoders"] decoder_realvideo4 = ["decoders"] +decoder_realvideo6 = ["decoders"] all_audio_decoders = ["decoder_pcm", "decoder_imc", "decoders_real"] decoder_pcm = ["decoders"] diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index daf53fa..5f6009a 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -156,7 +156,7 @@ impl IPBShuffler { } } -#[derive(Debug,Clone,Copy)] +#[derive(Debug,Clone,Copy,PartialEq)] pub struct MV { pub x: i16, pub y: i16, diff --git a/src/codecs/real/mod.rs b/src/codecs/real/mod.rs index da15819..244b901 100644 --- a/src/codecs/real/mod.rs +++ b/src/codecs/real/mod.rs @@ -15,6 +15,10 @@ pub mod rv40; pub mod rv40dsp; #[cfg(feature="decoder_realvideo6")] pub mod rv60; +#[cfg(feature="decoder_realvideo6")] +pub mod rv60codes; +#[cfg(feature="decoder_realvideo6")] +pub mod rv60dsp; #[cfg(feature="decoder_realaudio144")] pub mod ra144; diff --git a/src/codecs/real/rv60.rs b/src/codecs/real/rv60.rs new file mode 100644 index 0000000..bc1a149 --- /dev/null +++ b/src/codecs/real/rv60.rs @@ -0,0 +1,1490 @@ +use std::rc::Rc; +use std::cell::RefCell; +use formats::YUV420_FORMAT; +use frame::*; +use codecs::{NADecoder, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler}; +use io::byteio::{MemoryReader,ByteReader}; +use io::bitreader::{BitReader,BitReaderMode}; +use io::intcode::*; + +use super::rv60codes::*; +use super::rv60dsp::*; + +struct UniqueList { + list: [A; 4], + fill: usize, + max_size: usize, +} + +impl UniqueList { + fn new(max_size: usize) -> Self { + Self { list: [A::default(); 4], fill: 0, max_size } + } + fn add(&mut self, cand: A) { + if self.fill == self.max_size { return; } + let mut unique = true; + for el in self.list.into_iter().take(self.fill) { + if *el == cand { + unique = false; + break; + } + } + if unique { + self.list[self.fill] = cand; + self.fill += 1; + } + } +} + +const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ]; +const MAX_IMODE: u8 = 34; + +#[derive(Clone,Copy,Debug)] +struct FrameHeader { + profile: u8, + ftype: FrameType, + qp: u8, + osvquant: u8, + ts: u32, + width: usize, + height: usize, + two_f_refs: bool, + qp_off_type: u8, + deblock: bool, + deblock_chroma: bool, +} + +const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ]; +impl FrameHeader { + fn read(br: &mut BitReader) -> DecoderResult { + let marker = br.read(2)?; + validate!(marker == 3); + let profile = br.read(2)? as u8; + validate!(profile == 0); + let _someval = br.read(4)?; + let ftypeid = br.read(2)? as usize; + let ftype = RV60_FRAME_TYPES[ftypeid]; + let qp = br.read(6)? as u8; + let marker = br.read(1)?; + validate!(marker == 0); + let toolset = br.read(2)?; + validate!(toolset == 0); + let osvquant = br.read(2)? as u8; + let _some_flag = br.read_bool()?; + let _some_val = br.read(2)?; + let ts = br.read(24)?; + let width = ((br.read(11)? as usize) + 1) * 4; + let height = ((br.read(11)? as usize) + 0) * 4; + validate!(height > 0); + let _some_flag = br.read_bool()?; + let two_f_refs; + if ftype == FrameType::I { +//byte17 = 0 + two_f_refs = false; + } else { + let flag = br.read_bool()?; + if flag { // untested + br.skip(1)?; + br.skip(1)?; + br.skip(1)?; + } +//byte17 = flag? + two_f_refs = br.read_bool()?; + } +// if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; } + let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff? + let chroma_qp_diff = br.read(1)?; + validate!(chroma_qp_diff == 0); + let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8; + let deblock = br.read_bool()?; + let deblock_chroma = deblock && !br.read_bool()?; + if br.read_bool()? { + let custom_msg_hdr_len = br.read(2)? as usize; + if custom_msg_hdr_len != 0 { + for i in 0..custom_msg_hdr_len { + br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?; + } + } + } + + Ok(FrameHeader { + profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type, + deblock, deblock_chroma, + }) + } + fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec) -> DecoderResult<()> { + let nslices = self.get_height_cu(); + let nbits = (br.read(5)? as u8) + 1; + validate!(nbits < 32); + let mut signs: Vec = Vec::with_capacity(nslices); + for _ in 0..nslices { + let sign = br.read_bool()?; + signs.push(sign); + } + validate!(signs[0]); + sizes.truncate(0); + let mut sum = 0; + let first_size = br.read(nbits)? as usize; + validate!(first_size > 0); + sum += first_size; + let mut lastsize = first_size; + sizes.push(first_size); + for i in 1..nslices { + let diff = br.read(nbits)? as isize; + let size; + if signs[i] { + let sum = (lastsize as isize).checked_add(diff); + validate!(sum.is_some()); + size = sum.unwrap() as usize; + } else { + let sum = (lastsize as isize).checked_sub(diff); + validate!(sum.is_some()); + size = sum.unwrap() as usize; + } + sizes.push(size); + sum += size; + lastsize = size; + } + br.align(); +if ((br.left() >> 3) as usize) != sum { +println!(" left {} / {}", br.left() >> 3, sum); +} + validate!((br.left() >> 3) >= (sum as isize)); + Ok(()) + } + fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult { + match self.qp_off_type { + 0 => Ok(0), + 1 => { + let val = br.read_code(UintCodeType::Unary012)?; + if val != 2 { + Ok(val as i8) + } else { + Ok(-1) + } + }, + _ => { + if br.read(1)? == 0 { + Ok(0) + } else { + let val = br.read(2)? as i8; + if (val & 2) == 0 { + Ok(val + 1) + } else { + Ok(-((val & 1) + 1)) + } + } + }, + } + } + fn get_width_cu(&self) -> usize { + (self.width + 63) >> 6 + } + fn get_height_cu(&self) -> usize { + (self.height + 63) >> 6 + } + fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool { + if (ypos + dy) == 0 { return false; } + let xpos2 = xpos + dx; + if (xpos2 + size) > self.width { return false; } + true + } + fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool { + if (ypos + dy) == 0 { return false; } + let xpos2 = xpos + dx; + if (xpos2 + size * 2) > self.width { return false; } + let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size]; + let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size]; + ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0 + } + fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool { + if (xpos + dx) == 0 { return false; } + let ypos2 = ypos + dy; + if (ypos2 + size) > self.height { return false; } + true + } + fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool { + if (xpos + dx) == 0 { return false; } + let ypos2 = ypos + dy; + if (ypos2 + size * 2) > self.height { return false; } + let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size]; + let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size]; + ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1 + } +} + +const RV60_BLOCK_LOG2: [u8; 65] = [ + 0, + 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 +]; +const RV60_AVAIL_MASK: [u8; 64] = [ + 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +]; + +#[derive(Clone,Copy,PartialEq,Debug)] +enum CUType { + Intra, + InterMV, + Skip, + InterNoMV, +} + +impl Default for CUType { + fn default() -> Self { CUType::Intra } +} + +const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ]; + +#[derive(Clone,Copy,PartialEq,Debug)] +enum PUType { + Full, + N2Hor, + N2Ver, + Quarters, + N4Hor, + N34Hor, + N4Ver, + N34Ver, +} + +const RV60_PU_TYPES: [PUType; 8] = [ + PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters, + PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver, +]; + +impl PUType { + fn get_num_mvs(&self) -> usize { + match *self { + PUType::Full => 1, + PUType::Quarters => 4, + _ => 2, + } + } + fn get_mv_size(&self, part_no: usize, size: usize) -> (usize, usize) { + let mv_size = size >> 2; + match *self { + PUType::Full => (mv_size, mv_size), + PUType::N2Hor => (mv_size, mv_size >> 1), + PUType::N2Ver => (mv_size >> 1, mv_size), + PUType::Quarters => (mv_size >> 1, mv_size >> 1), + PUType::N4Hor => { + if part_no == 0 { + (mv_size, mv_size >> 2) + } else { + (mv_size, 3 * mv_size >> 2) + } + }, + PUType::N34Hor => { + if part_no == 0 { + (mv_size, 3 * mv_size >> 2) + } else { + (mv_size, mv_size >> 2) + } + }, + PUType::N4Ver => { + if part_no == 0 { + ( mv_size >> 2, mv_size) + } else { + (3 * mv_size >> 2, mv_size) + } + }, + PUType::N34Ver => { + if part_no == 0 { + (3 * mv_size >> 2, mv_size) + } else { + ( mv_size >> 2, mv_size) + } + }, + } + } + fn has_hor_split(&self) -> bool { + match *self { + PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true, + _ => false, + } + } + fn has_ver_split(&self) -> bool { + match *self { + PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true, + _ => false, + } + } +} + +impl Default for PUType { + fn default() -> Self { PUType::Full } +} + +#[derive(Clone,Copy,Debug)] +enum IntraMode { + Index(u8), + Mode(u8), + DC64, + Plane64, +} + +#[derive(Clone,Copy,PartialEq,Debug)] +enum TransformType { + None, + T4X4, + T8X8, + T16X16, +} + +impl Default for TransformType { + fn default() -> Self { TransformType::None } +} + +#[derive(Clone,Copy,PartialEq,Debug)] +enum MVRef { + None, + Ref0, + Ref1, + BRef, + Ref0AndBRef, + Skip0, + Skip1, + Skip2, + Skip3, +} + +const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ]; + +impl MVRef { + fn get_skip_mv_num(&self) -> usize { + match *self { + MVRef::Skip1 => 1, + MVRef::Skip2 => 2, + MVRef::Skip3 => 3, + _ => 0, + } + } + fn is_ref0(&self) -> bool { + match *self { + MVRef::Ref0 | MVRef::Ref0AndBRef => true, + _ => false, + } + } + fn is_fwd(&self) -> bool { + match *self { + MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true, + _ => false, + } + } + fn is_bwd(&self) -> bool { + match *self { + MVRef::BRef | MVRef::Ref0AndBRef => true, + _ => false, + } + } +} + +#[derive(Clone,Copy,PartialEq,Debug)] +struct MVInfo { + f_mv: MV, + b_mv: MV, + mvref: MVRef, +} + +impl MVInfo { + fn is_some(&self) -> bool { self.mvref != MVRef::None } + fn matches_fwd(&self, mvref: MVRef) -> bool { + (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0()) + } + fn matches_bwd(&self, mvref: MVRef) -> bool { + self.mvref.is_bwd() && mvref.is_bwd() + } + fn is_deblock_cand(&self, other: &MVInfo) -> bool { + if self.mvref != other.mvref { return true; } + let mut mvdiff = 0; + if self.mvref.is_fwd() { + let diff = self.f_mv - other.f_mv; + mvdiff += diff.x.abs() + diff.y.abs(); + } + if self.mvref.is_bwd() { + let diff = self.b_mv - other.b_mv; + mvdiff += diff.x.abs() + diff.y.abs(); + } + mvdiff > 4 + } +} + +impl Default for MVInfo { + fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } } +} + +#[derive(Clone,Copy,Debug)] +struct CBHeader { + cu_type: CUType, + pu_type: PUType, + ttype: TransformType, + imode: [IntraMode; 4], + mv: [MVInfo; 4], +} + +impl CBHeader { + fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult { + let cu_type; + let pu_type; + let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4]; + let mut mv: [MVInfo; 4] = [MVInfo::default(); 4]; + if ftype == FrameType::I { + cu_type = CUType::Intra; + } else { + cu_type = RV60_CU_TYPES[br.read(2)? as usize]; + } + match cu_type { + CUType::Intra => { + if (size == 8) && br.read_bool()? { + pu_type = PUType::Quarters; + } else { + pu_type = PUType::Full; + } + if pu_type == PUType::Quarters { + for i in 0..4 { + imode[i] = CBHeader::read_intra_mode(br)?; + } + } else if size <= 32 { + imode[0] = CBHeader::read_intra_mode(br)?; + } else { + if !br.read_bool()? { + imode[0] = IntraMode::DC64; + } else { + imode[0] = IntraMode::Plane64; + } + } + }, + CUType::InterMV => { + let bits = if size == 8 { 2 } else { 3 }; + pu_type = RV60_PU_TYPES[br.read(bits)? as usize]; + CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?; + }, + _ => { + pu_type = PUType::Full; + let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?; + mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize]; + }, + }; + let ttype; + if cu_type == CUType::Skip { + ttype = TransformType::None; + } else if size >= 32 { + ttype = TransformType::T16X16; + } else if size == 16 { + if (cu_type == CUType::Intra) || (pu_type == PUType::Full) { + ttype = TransformType::T16X16; + } else { + ttype = TransformType::T4X4; + } + } else { + if pu_type == PUType::Full { + ttype = TransformType::T8X8; + } else { + ttype = TransformType::T4X4; + } + } + Ok(Self { + cu_type, pu_type, ttype, imode, mv, + }) + } + fn read_intra_mode(br: &mut BitReader) -> DecoderResult { + if br.read_bool()? { + let idx = br.read_code(UintCodeType::Unary012)? as u8; + Ok(IntraMode::Index(idx)) + } else { + let mode = br.read(5)? as u8; + Ok(IntraMode::Mode(mode)) + } + } + fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> { + let mv_count = pu_type.get_num_mvs(); + for i in 0..mv_count { + mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?; + } + Ok(()) + } + fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult { + let mut f_mv = ZERO_MV; + let mut b_mv = ZERO_MV; + let mvref; + if ftype != FrameType::B { + if two_f_refs && br.read_bool()? { + mvref = MVRef::Ref1; + } else { + mvref = MVRef::Ref0; + } + f_mv = CBHeader::read_mv(br)?; + Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref }) + } else { + if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? { + if !br.read_bool()? { + mvref = MVRef::Ref0; + f_mv = CBHeader::read_mv(br)?; + } else { + mvref = MVRef::BRef; + b_mv = CBHeader::read_mv(br)?; + } + } else { + mvref = MVRef::Ref0AndBRef; + f_mv = CBHeader::read_mv(br)?; + b_mv = CBHeader::read_mv(br)?; + } + Ok(MVInfo { f_mv, b_mv, mvref }) + } + } + fn read_mv(br: &mut BitReader) -> DecoderResult { + let x = br.read_code_signed(IntCodeType::Gamma)? as i16; + let y = br.read_code_signed(IntCodeType::Gamma)? as i16; + Ok(MV { x, y }) + } +} + +#[derive(Clone,Copy,Default)] +struct PUInfo { + cu_type: CUType, + ttype: TransformType, +} + +impl PUInfo { + fn is_intra(&self) -> bool { self.cu_type == CUType::Intra } +} + +const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ]; + +#[derive(Clone,Copy,Default)] +struct BlockInfo { + mv: MVInfo, + imode: u8, +} + +struct DeblockInfo { + left_str: Vec, + top_str: Vec, + stride: usize, +} + +impl DeblockInfo { + fn new() -> Self { + Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 } + } + fn reinit(&mut self, w: usize, h: usize) { + self.left_str.clear(); + self.top_str.clear(); + self.stride = w >> 2; + let size = self.stride * (h >> 2); + self.left_str.resize(size, 0); + self.top_str.resize(size, 0); + } + fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) { + let pos = self.get_pos(xpos, ypos); + let dsize = size >> 2; + let dval = (q << 2) | strength; + for x in 0..dsize { + self.top_str[pos + x] = dval; + } + for y in 0..dsize { + self.left_str[pos + y * self.stride] = dval; + } + } + fn get_pos(&self, xpos: usize, ypos: usize) -> usize { + (xpos >> 2) + (ypos >> 2) * self.stride + } + fn get_top_strength(&self, pos: usize) -> u8 { + self.top_str[pos] & 3 + } + fn get_left_strength(&self, pos: usize) -> u8 { + self.left_str[pos] & 3 + } + fn set_top_strength(&mut self, pos: usize, str: u8) { + self.top_str[pos] |= str; + } + fn set_left_strength(&mut self, pos: usize, str: u8) { + self.left_str[pos] |= str; + } +} + +struct RealVideo60Decoder { + info: Rc, + cbs: RV60Codebooks, + ipbs: IPBShuffler, + dsp: RV60DSP, + ipred: IntraPredContext, + + avg_buf: NAVideoBuffer, + + y_coeffs: [i16; 16 * 16], + u_coeffs: [i16; 8 * 8], + v_coeffs: [i16; 8 * 8], + qp: u8, + sel_qp: u8, + + cu_splits: Vec, + coded_blk: [bool; 64], + dblk: DeblockInfo, + + pu_info: Vec, + pu_stride: usize, + pu_pos: usize, + + blk_info: Vec, + blk_stride: usize, + blk_pos: usize, + + xpos: usize, + ypos: usize, +} + +impl RealVideo60Decoder { + fn new() -> Self { + let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT); + let mut vt = alloc_video_buffer(tmp_vinfo, 4).unwrap(); + let vb = vt.get_vbuf(); + let avg_buf = vb.unwrap(); + RealVideo60Decoder{ + info: Rc::new(DUMMY_CODEC_INFO), + cbs: RV60Codebooks::init(), + ipbs: IPBShuffler::new(), + ipred: IntraPredContext::new(), + dsp: RV60DSP::new(), + avg_buf: avg_buf, + y_coeffs: [0; 16 * 16], + u_coeffs: [0; 8 * 8], + v_coeffs: [0; 8 * 8], + qp: 0, + sel_qp: 0, + cu_splits: Vec::with_capacity(24), + coded_blk: [false; 64], + dblk: DeblockInfo::new(), + pu_info: Vec::new(), + pu_stride: 0, + pu_pos: 0, + blk_info: Vec::new(), + blk_stride: 0, + blk_pos: 0, + xpos: 0, + ypos: 0, + } + } + fn decode_cu_line(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> { + let mut br = BitReader::new(src, src.len(), BitReaderMode::BE); + let cu_w = hdr.get_width_cu(); + let dqp = hdr.read_line_qp_offset(&mut br)?; + let qps = (hdr.qp as i8) + dqp; + validate!((qps >= 0) && (qps < 32)); + let qp = qps as u8; + self.qp = qp; + self.sel_qp = match hdr.osvquant { + 0 => qp, + 1 => { + if qp <= 25 { + qp + 5 + } else { + qp + } + }, + _ => { + if qp <= 18 { + qp + 10 + } else if qp <= 25 { + qp + 5 + } else { + qp + } + }, + }; + + for cu_x in 0..cu_w { + self.cu_splits.clear(); + self.coded_blk = [false; 64]; + self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?; + if hdr.deblock { + self.cu_splits.reverse(); + self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6); + } + } +if br.left() >= 8 { +println!(" left {} bits", br.left()); +} + Ok(()) + } + fn decode_cb_tree(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> { + if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); } + + let size = 1 << log_size; + let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?); + self.cu_splits.push(split); + if split { + let hsize = size >> 1; + self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?; + self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?; + self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?; + self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?; + } else { + let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?; + self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride; + self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride; + self.xpos = xpos; + self.ypos = ypos; + self.reconstruct_info(hdr, &cbh, size)?; + + let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters); + match cbh.cu_type { + CUType::Intra => { + let itype = self.blk_info[self.blk_pos].imode; + if !split_i4x4 { + let dstride = buf.get_stride(0); + let off = xpos + ypos * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true); + self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true); + } + for comp in 1..3 { + let dstride = buf.get_stride(comp); + let soff = buf.get_offset(comp); + let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false); + self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false); + } + }, + _ => { + let mut mv_x = xpos >> 2; + let mut mv_y = ypos >> 2; + let mut mv_pos = mv_x + mv_y * self.blk_stride; + for part_no in 0..cbh.pu_type.get_num_mvs() { + let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size); + let mv = self.blk_info[mv_pos].mv; + let bw = mv_w << 2; + let bh = mv_h << 2; + let bx = mv_x << 2; + let by = mv_y << 2; + match mv.mvref { + MVRef::Ref0 => { + if hdr.ftype != FrameType::B { + if let Some(ref prevbuf) = self.ipbs.get_lastref() { + self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false); + } + } else { + if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() { + self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false); + } + } + }, + MVRef::Ref1 => { + if let Some(ref prevbuf) = self.ipbs.get_nextref() { + self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false); + } + }, + MVRef::BRef => { + validate!(hdr.ftype == FrameType::B); + if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() { + self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false); + } + }, + MVRef::Ref0AndBRef => { + validate!(hdr.ftype == FrameType::B); + if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) { + self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false); + self.dsp.do_mc(&mut self.avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true); + self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh); + } + }, + _ => unreachable!(), + }; + if cbh.pu_type == PUType::Quarters { + if part_no != 1 { + mv_pos += mv_w; + mv_x += mv_w; + } else { + mv_pos += mv_h * self.blk_stride - mv_w; + mv_x -= mv_w; + mv_y += mv_h; + } + } else if cbh.pu_type.has_hor_split() { + mv_pos += mv_h * self.blk_stride; + mv_y += mv_h; + } else if cbh.pu_type.has_ver_split() { + mv_pos += mv_w; + mv_x += mv_w; + } + } + }, + }; + if cbh.ttype != TransformType::None { + self.y_coeffs = [0; 16 * 16]; + self.u_coeffs = [0; 8 * 8]; + self.v_coeffs = [0; 8 * 8]; + } + let is_intra = cbh.cu_type == CUType::Intra; + let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8; + match cbh.ttype { + TransformType::T4X4 => { + let subset = if is_intra { 0 } else { 2 }; + if size == 16 { + let cbp16; + if br.read_bool()? { + cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?; + } else { + cbp16 = 0; + } + if cbp16 != 0 { + self.coded_blk[cb_pos + 0] = true; + self.coded_blk[cb_pos + 1] = true; + self.coded_blk[cb_pos + 8] = true; + self.coded_blk[cb_pos + 9] = true; + 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)?; + for y in 0..4 { + for x in 0..4 { + let i = x + y * 4; + if ((cbp16 >> i) & 1) != 0 { + self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]); + let dstride = buf.get_stride(0); + let off = xpos + x * 4 + (ypos + y * 4) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4); + } + } + } + for y in 0..2 { + for x in 0..2 { + let i = x + y * 2; + let xoff = (xpos >> 1) + x * 4; + let yoff = (ypos >> 1) + y * 4; + if ((cbp16 >> (16 + i)) & 1) != 0 { + self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]); + let dstride = buf.get_stride(1); + let off = buf.get_offset(1) + xoff + yoff * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4); + } + if ((cbp16 >> (20 + i)) & 1) != 0 { + self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]); + let dstride = buf.get_stride(2); + let off = buf.get_offset(2) + xoff + yoff * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4); + } + } + } + } + } else { + let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?; + if cbp8 != 0 { + self.coded_blk[cb_pos] = true; + 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)?; + } + for i in 0..4 { + let xoff = (i & 1) * 4; + let yoff = (i & 2) * 2; + if split_i4x4 { + let dstride = buf.get_stride(0); + let off = xpos + xoff + (ypos + yoff) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true); + let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode; + self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false); + } + if ((cbp8 >> i) & 1) != 0 { + let blk = &mut self.y_coeffs[i * 16..][..16]; + self.dsp.transform4x4(blk); + let dstride = buf.get_stride(0); + let soff = buf.get_offset(0); + let off = soff + xpos + xoff + (ypos + yoff) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, blk, 4); + } + } + if ((cbp8 >> 4) & 1) != 0 { + self.dsp.transform4x4(&mut self.u_coeffs); + let dstride = buf.get_stride(1); + let soff = buf.get_offset(1); + let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4); + } + if ((cbp8 >> 5) & 1) != 0 { + self.dsp.transform4x4(&mut self.v_coeffs); + let dstride = buf.get_stride(2); + let soff = buf.get_offset(2); + let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4); + } + } + }, + TransformType::T8X8 => { + let subset = if is_intra { 1 } else { 3 }; + let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?; + if cbp8 != 0 { + self.coded_blk[cb_pos] = true; + 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)?; + if (cbp8 & 0xF) != 0 { + self.dsp.transform8x8(&mut self.y_coeffs); + let dstride = buf.get_stride(0); + let off = xpos + ypos * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8); + } + if ((cbp8 >> 4) & 1) != 0 { + self.dsp.transform4x4(&mut self.u_coeffs); + let dstride = buf.get_stride(1); + let soff = buf.get_offset(1); + let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4); + } + if ((cbp8 >> 5) & 1) != 0 { + self.dsp.transform4x4(&mut self.v_coeffs); + let dstride = buf.get_stride(2); + let soff = buf.get_offset(2); + let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4); + } + } + }, + TransformType::T16X16 => { + let subset = if is_intra { 1 } else { 3 }; + let num_clusters = size >> 4; + let cl_cbp = br.read((num_clusters * num_clusters) as u8)?; + for y in 0..num_clusters { + for x in 0..num_clusters { + if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; } + self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true; + self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true; + self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true; + self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true; + let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?; + if super_cbp != 0 { + self.y_coeffs = [0; 16 * 16]; + self.u_coeffs = [0; 8 * 8]; + self.v_coeffs = [0; 8 * 8]; + 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)?; + if (super_cbp & 0xFFFF) != 0 { + self.dsp.transform16x16(&mut self.y_coeffs); + let dstride = buf.get_stride(0); + let off = xpos + x * 16 + (ypos + y * 16) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16); + } + if ((super_cbp >> 16) & 0xF) != 0 { + self.dsp.transform8x8(&mut self.u_coeffs); + let dstride = buf.get_stride(1); + let soff = buf.get_offset(1); + let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8); + } + if ((super_cbp >> 20) & 0xF) != 0 { + self.dsp.transform8x8(&mut self.v_coeffs); + let dstride = buf.get_stride(2); + let soff = buf.get_offset(2); + let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride; + let mut data = buf.get_data_mut(); + let mut dst = &mut data; + self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8); + } + } + } + } + }, + _ => {}, + }; + } + Ok(()) + } + fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{ + let mut pui = PUInfo::default(); + let pu_size = size >> 3; + pui.cu_type = cbh.cu_type; + pui.ttype = cbh.ttype; + if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case + self.pu_info[self.pu_pos] = pui; + for y in 0..2 { + for x in 0..2 { + let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2); + validate!(imode <= MAX_IMODE); + self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode; + self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default(); + } + } + return Ok(()); + } + match cbh.cu_type { + CUType::Intra => { + self.pu_info[self.pu_pos] = pui; + let imode = self.reconstruct_intra(hdr, cbh, size, 0); + validate!(imode <= MAX_IMODE); + for y in 0..(size >> 2) { + for x in 0..(size >> 2) { + self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode; + } + } + }, + CUType::InterMV => { + let mut mv_x = self.xpos >> 2; + let mut mv_y = self.ypos >> 2; + let mut mv_pos = self.blk_pos; + let pu_type = cbh.pu_type; + for part_no in 0..pu_type.get_num_mvs() { + let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size); + let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]); + for y in 0..mv_h { + for x in 0..mv_w { + self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv; + } + } + if pu_type == PUType::Quarters { + if part_no != 1 { + mv_pos += mv_w; + mv_x += mv_w; + } else { + mv_pos += mv_h * self.blk_stride - mv_w; + mv_x -= mv_w; + mv_y += mv_h; + } + } else if pu_type.has_hor_split() { + mv_pos += mv_h * self.blk_stride; + mv_y += mv_h; + } else if pu_type.has_ver_split() { + mv_pos += mv_w; + mv_x += mv_w; + } + } + }, + _ => { + let skip_idx = cbh.mv[0].mvref.get_skip_mv_num(); + let mut skip_cand: UniqueList = UniqueList::new(4); + self.fill_skip_cand(hdr, &mut skip_cand, size); + let mv = skip_cand.list[skip_idx]; + + let mv_size = size >> 2; + for y in 0..mv_size { + for x in 0..mv_size { + self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv; + } + } + }, + }; + for y in 0..pu_size { + for x in 0..pu_size { + self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui; + } + } + Ok(()) + } + fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 { + match cbh.imode[0] { + IntraMode::DC64 => { return 1; }, + IntraMode::Plane64 => { return 0; }, + _ => {}, + }; + // form list of predictors + let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride; + let mut ipm_cand: UniqueList = UniqueList::new(3); + if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) { + let pu = &self.pu_info[self.pu_pos - self.pu_stride]; + if pu.is_intra() { + ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode); + } + } + if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) { + let pu = &self.pu_info[self.pu_pos - 1]; + if pu.is_intra() { + ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode); + } + } + let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos }; + let tl_y = self.ypos + (sub & 2) * 4; + if (tl_x > 0) && (tl_y > 0) { + let pu = match sub { + 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1], + 1 => &self.pu_info[self.pu_pos - self.pu_stride], + 2 => &self.pu_info[self.pu_pos - 1], + _ => &self.pu_info[self.pu_pos - 1], + }; + if pu.is_intra() { + if sub != 3 { + ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode); + } else { + ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode); + } + } + } + for el in RV60_CANDIDATE_INTRA_ANGLES.into_iter() { + ipm_cand.add(*el); + } + // actually decode prediction mode + match cbh.imode[sub] { + IntraMode::Index(idx) => { + ipm_cand.list[idx as usize] + }, + IntraMode::Mode(mode) => { + let mut imode = mode; + let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]]; + ipm_cs.sort(); + for ic in ipm_cs.into_iter() { + if imode >= *ic { + imode += 1; + } + } + imode + }, + _ => unreachable!(), + } + } + fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) { + let src_off = if is_luma { + soff + self.xpos + xoff + (self.ypos + yoff) * stride + } else { + soff + (self.xpos >> 1) + (self.ypos >> 1) * stride + }; + self.ipred = IntraPredContext::new(); + if (self.ypos + yoff) > 0 { + self.ipred.has_t = true; + for x in 0..size { + self.ipred.t[x + 1] = src[src_off - stride + x]; + } + if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) || + (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) { + self.ipred.has_tr = true; + for x in size..size*2 { + self.ipred.t[x + 1] = src[src_off - stride + x]; + } + } else { + for i in 0..size { + self.ipred.t[size + i + 1] = self.ipred.t[size]; + } + } + if (self.xpos + xoff) > 0 { + self.ipred.t[0] = src[src_off - stride - 1]; + } + } + if (self.xpos + xoff) > 0 { + self.ipred.has_l = true; + for y in 0..size { + self.ipred.l[y + 1] = src[src_off - 1 + y * stride]; + } + if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) || + (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) { + self.ipred.has_ld = true; + for y in size..size*2 { + self.ipred.l[y + 1] = src[src_off - 1 + y * stride]; + } + } else { + for i in 0..size { + self.ipred.l[size + i + 1] = self.ipred.l[size]; + } + } + if (self.ypos + yoff) > 0 { + self.ipred.l[0] = src[src_off - stride - 1]; + } + } + } + fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo { + let mv_pos = mv_x + mv_y * self.blk_stride; + let f_mv: MV; + let b_mv: MV; + if mvi.mvref.is_fwd() { + let mut mv_cand: [MV; 3] = [ZERO_MV; 3]; + let mut mv_cand_size: usize = 0; + if mv_x > 0 { + let ref_mv = &self.blk_info[mv_pos - 1].mv; + if ref_mv.matches_fwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.f_mv; + mv_cand_size += 1; + } + } + if mv_y > 0 { + let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv; + if ref_mv.matches_fwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.f_mv; + mv_cand_size += 1; + } + } + if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) { + let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv; + if ref_mv.matches_fwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.f_mv; + mv_cand_size += 1; + } + } + f_mv = match mv_cand_size { + 1 | 2 => { + let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x; + let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y; + if mv_cand_size == 1 { + MV { x, y } + } else { + MV { x: x >> 1, y: y >> 1 } + } + }, + 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]), + _ => ZERO_MV, + }; + } else { + f_mv = ZERO_MV; + } + if mvi.mvref.is_bwd() { + let mut mv_cand: [MV; 3] = [ZERO_MV; 3]; + let mut mv_cand_size: usize = 0; + if mv_x > 0 { + let ref_mv = &self.blk_info[mv_pos - 1].mv; + if ref_mv.matches_bwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.b_mv; + mv_cand_size += 1; + } + } + if mv_y > 0 { + let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv; + if ref_mv.matches_bwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.b_mv; + mv_cand_size += 1; + } + } + if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) { + let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv; + if ref_mv.matches_bwd(mvi.mvref) { + mv_cand[mv_cand_size] = ref_mv.b_mv; + mv_cand_size += 1; + } + } + b_mv = match mv_cand_size { + 1 | 2 => { + let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x; + let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y; + if mv_cand_size == 1 { + MV { x, y } + } else { + MV { x: x >> 1, y: y >> 1 } + } + }, + 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]), + _ => ZERO_MV, + }; + } else { + b_mv = ZERO_MV; + } + + MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref } + } + fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList, size: usize) { + let mv_size = size >> 2; + + if self.xpos > 0 { + let mv = &self.blk_info[self.blk_pos - 1].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if self.ypos > 0 { + let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) { + let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) { + let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) { + let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) { + let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + if (self.xpos > 0) && (self.ypos > 0) { + let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv; + if mv.is_some() { + skip_cand.add(*mv); + } + } + for i in skip_cand.fill..4 { + skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 }; + } + } + fn deblock_cb_tree(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) { + if (xpos >= hdr.width) || (ypos >= hdr.height) { return; } + let split = (log_size > 3) && self.cu_splits.pop().unwrap(); + if split { + let hsize = 1 << (log_size - 1); + self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1); + self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1); + self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1); + self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1); + } else { + let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride; + let cu_type = self.pu_info[pu_pos].cu_type; + let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 }; + let ntiles = 1 << (log_size - tsize); + let dparams = RV60DeblockParams { + deblock_chroma: hdr.deblock_chroma, + width: hdr.width, + height: hdr.height, + dblkstride: self.dblk.stride, + }; + for ty in 0..ntiles { + for tx in 0..ntiles { + let x = xpos + (tx << tsize); + let y = ypos + (ty << tsize); + let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8; + if cu_type == CUType::Intra { + self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2); + } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] { + self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1); + } else { + self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0); + self.derive_deblock_strength(x, y, 1 << (tsize - 2)); + } + self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize, + self.dblk.top_str.as_slice(), + self.dblk.left_str.as_slice(), + self.dblk.get_pos(x, y)); + } + } + } + } + fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) { + let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride; + let mut dblk_pos = self.dblk.get_pos(xpos, ypos); + if ypos > 0 { + let top_blk_pos = blk_pos - self.blk_stride; + for i in 0..size4 { + if self.dblk.get_top_strength(dblk_pos + i) == 0 { + if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) { + self.dblk.set_top_strength(dblk_pos + i, 1); + } + } + } + } + if xpos > 0 { + for i in 0..size4 { + if self.dblk.get_left_strength(dblk_pos) == 0 { + if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) { + self.dblk.set_left_strength(dblk_pos, 1); + } + } + dblk_pos += self.dblk.stride; + } + } + } +} + +impl NADecoder for RealVideo60Decoder { + fn init(&mut self, info: Rc) -> DecoderResult<()> { + if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() { + let fmt = YUV420_FORMAT; + let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt)); + self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata())); + + let edata = info.get_extradata().unwrap(); + let src: &[u8] = &edata; + + if src.len() < 8 { return Err(DecoderError::InvalidData); } + let mut mr = MemoryReader::new_read(src); + let mut br = ByteReader::new(&mut mr); + let _flags = br.read_u32be()?; + let version = br.read_u32be()?; + let _unk = br.read_u16be()?; + validate!((version >> 28) == 4); + // then width and height again as 16be + + //self.bd.width = vinfo.get_width(); + //self.bd.height = vinfo.get_height(); + //self.frmmgr.clear(); + Ok(()) + } else { +println!("???"); + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, pkt: &NAPacket) -> DecoderResult { + let src = pkt.get_buffer(); + + validate!(src.len() > 9); + let hsize = (src[0] as usize) * 8 + 9; + let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE); + let hdr = FrameHeader::read(&mut br)?; + let mut slices: Vec = Vec::new(); + hdr.parse_slice_sizes(&mut br, &mut slices)?; + + let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT); + let res = alloc_video_buffer(tmp_vinfo, 6); + if !res.is_ok() { return Err(DecoderError::InvalidData); } + let mut bufinfo = res.unwrap(); + let mut buf = bufinfo.get_vbuf().unwrap(); + + let cu_w = hdr.get_width_cu(); + let cu_h = hdr.get_height_cu(); + self.pu_stride = cu_w << 3; + self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default()); + self.blk_stride = cu_w << 4; + self.blk_info.truncate(0); + self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default()); + if hdr.deblock { + self.dblk.reinit(hdr.width, hdr.height); + } + let mut off = hsize + ((br.tell() >> 3) as usize); + for (cu_y, size) in slices.into_iter().enumerate() { + self.decode_cu_line(&mut buf, &hdr, &src[off..][..size], cu_y)?; + off += size; + } + if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) { + self.ipbs.add_frame(buf); + } + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); + frm.set_keyframe(hdr.ftype == FrameType::I); + frm.set_pts(Some(hdr.ts as u64)); + frm.set_frame_type(hdr.ftype); + Ok(Rc::new(RefCell::new(frm))) + } +} + +pub fn get_decoder() -> Box { + Box::new(RealVideo60Decoder::new()) +} + +#[cfg(test)] +mod test { + use test::dec_video::test_file_decoding; + #[test] + fn test_rv60() { + test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, /*None*/Some("rv60")); +panic!("end"); + } +} diff --git a/src/codecs/real/rv60codes.rs b/src/codecs/real/rv60codes.rs new file mode 100644 index 0000000..be949ab --- /dev/null +++ b/src/codecs/real/rv60codes.rs @@ -0,0 +1,1437 @@ +use codecs::*; +use io::bitreader::BitReader; +use io::codebook::*; +use std::mem; +use std::ptr; + +const NUM_INTRA_SETS: usize = 5; +const NUM_INTER_SETS: usize = 7; + +const NUM_COEFF_ENTRIES: usize = 3 * 3 * 3 * 4; +const NUM_ESC_ENTRIES: usize = 32; +const NUM_CBP_ENTRIES: usize = 64; +struct CoeffCodebooks { + l0_cb: [Codebook; 2], + l12_cb: [Codebook; 2], + l3_cb: [Codebook; 2], + esc_cb: Codebook, +} + +const MAX_ELEMS: usize = NUM_COEFF_ENTRIES * 8; +struct RV60CodebookDescReader { + len: usize, + codes: [u32; MAX_ELEMS], + bits: [u8; MAX_ELEMS], +} + +impl RV60CodebookDescReader { + fn new(table: &'static [u32], len: usize, ignfirst: bool) -> Self { + let mut prefixes: [u32; 18] = [0; 18]; + let mut counts: [usize; 17] = [0; 17]; + + let mut codes: [u32; MAX_ELEMS] = [0; MAX_ELEMS]; + let mut bits: [u8; MAX_ELEMS] = [0; MAX_ELEMS]; + for i in 0..(len + 7) >> 3 { + let code = table[i]; + for j in 0..8 { + if (i * 8 + j) == len { break; } + let b = if !ignfirst || (i != 0) || (j != 0) { + (((code >> ((7 - j) * 4)) & 0xF) as u8) + 1 + } else { + 0 + }; + bits[i * 8 + j] = b; + counts[b as usize] += 1; + } + } + for i in 1..17 { + prefixes[i + 1] = (prefixes[i] + (counts[i] as u32)) << 1; + } + for i in 0..len { + codes[i] = prefixes[bits[i] as usize]; + prefixes[bits[i] as usize] += 1; + } + + Self { len, codes, bits } + } +} + +impl CodebookDescReader for RV60CodebookDescReader { + fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] } + fn code(&mut self, idx: usize) -> u32 { self.codes[idx] } + fn sym (&mut self, idx: usize) -> u16 { idx as u16 } + fn len(&mut self) -> usize { self.len } +} + +impl CoeffCodebooks { + fn init(set_no: usize, intra: bool) -> Self { + let coeff_tabs = if intra { &RV60_INTRA_COEFFS_CB_DESC[set_no] } else { &RV60_INTER_COEFFS_CB_DESC[set_no] }; + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l0_tab[0], NUM_COEFF_ENTRIES * 8, true); + let l0c0 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l0_tab[1], NUM_COEFF_ENTRIES * 8, true); + let l0c1 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l12_tab[0], NUM_COEFF_ENTRIES, true); + let l12c0 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l12_tab[1], NUM_COEFF_ENTRIES, true); + let l12c1 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l3_tab[0], NUM_COEFF_ENTRIES, true); + let l3c0 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.l3_tab[1], NUM_COEFF_ENTRIES, true); + let l3c1 = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = RV60CodebookDescReader::new(&coeff_tabs.esc_tab, NUM_ESC_ENTRIES, false); + let esc_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + Self { + l0_cb: [ l0c0, l0c1 ], + l12_cb: [ l12c0, l12c1 ], + l3_cb: [ l3c0, l3c1 ], + esc_cb, + } + } +} + +pub struct RV60Codebooks { + cbp8_cb: [[Codebook; 4]; NUM_INTER_SETS], + cbp16_cb: [[Codebook; 12]; NUM_INTER_SETS], + intra_coeff_cb: [CoeffCodebooks; NUM_INTRA_SETS], + inter_coeff_cb: [CoeffCodebooks; NUM_INTER_SETS], +} + +impl RV60Codebooks { + pub fn init() -> Self { + let mut cbp8_cb: [[Codebook; 4]; NUM_INTER_SETS]; + let mut cbp16_cb: [[Codebook; 12]; NUM_INTER_SETS]; + unsafe { + cbp8_cb = mem::uninitialized(); + cbp16_cb = mem::uninitialized(); + for set_no in 0..NUM_INTER_SETS { + for i in 0..4 { + let mut cbr = RV60CodebookDescReader::new(&RV60_CBP8_TABS[set_no][i], NUM_CBP_ENTRIES, false); + ptr::write(&mut cbp8_cb[set_no][i], Codebook::new(&mut cbr, CodebookMode::MSB).unwrap()); + } + for i in 0..12 { + let mut cbr = RV60CodebookDescReader::new(&RV60_CBP16_TABS[set_no][i], NUM_CBP_ENTRIES, false); + ptr::write(&mut cbp16_cb[set_no][i], Codebook::new(&mut cbr, CodebookMode::MSB).unwrap()); + } + } + } + let mut intra_coeff_cb: [CoeffCodebooks; NUM_INTRA_SETS]; + let mut inter_coeff_cb: [CoeffCodebooks; NUM_INTER_SETS]; + unsafe { + intra_coeff_cb = mem::uninitialized(); + for set_no in 0..NUM_INTRA_SETS { + ptr::write(&mut intra_coeff_cb[set_no], CoeffCodebooks::init(set_no, true)); + } + inter_coeff_cb = mem::uninitialized(); + for set_no in 0..NUM_INTER_SETS { + ptr::write(&mut inter_coeff_cb[set_no], CoeffCodebooks::init(set_no, false)); + } + } + Self { cbp8_cb, cbp16_cb, intra_coeff_cb, inter_coeff_cb } + } + fn get_c4x4_set(qp: u8, is_intra: bool) -> usize { + if is_intra { + RV60_QP_TO_IDX[(qp as usize) + 32] + } else { + RV60_QP_TO_IDX[qp as usize] + } + } +} + +fn decode_coeff(br: &mut BitReader, cb: &Codebook, inval: i16, esc_val: i16) -> DecoderResult { + if inval != esc_val { + if inval != 0 && br.read_bool()? { + Ok(-inval) + } else { + Ok(inval) + } + } else { + let esc_sym = br.read_cb(cb)?; + let val = (if esc_sym > 23 { + let esc_bits = (esc_sym - 23) as u8; + let extrabits = br.read(esc_bits)? as i16; + (1 << esc_bits) + extrabits + 22 + } else { + esc_sym as i16 + }) + esc_val; + if br.read_bool()? { + Ok(-val) + } else { + Ok(val) + } + } +} + +fn quant(val: i16, q: i16) -> i16 { (val * q + 8) >> 4 } + +fn decode_2x2_dc(br: &mut BitReader, cb: &Codebook, coeffs: &mut [i16], stride: usize, block2: bool, dsc: usize, q_dc: i16, q_ac: i16) -> DecoderResult<()> { + if dsc == 0 { return Ok(()); } + let lx = RV60_DSC_TO_LX[dsc as usize]; + let l0 = ((lx >> 0) & 0xFF) as i16; + let l1 = ((lx >> 8) & 0xFF) as i16; + let l2 = ((lx >> 16) & 0xFF) as i16; + let l3 = ((lx >> 24) & 0xFF) as i16; + coeffs[0] = quant(decode_coeff(br, cb, l0, 3)?, q_dc); + if !block2 { + coeffs[1] = quant(decode_coeff(br, cb, l1, 2)?, q_ac); + coeffs[stride] = quant(decode_coeff(br, cb, l2, 2)?, q_ac); + } else { + coeffs[stride] = quant(decode_coeff(br, cb, l1, 2)?, q_ac); + coeffs[1] = quant(decode_coeff(br, cb, l2, 2)?, q_ac); + } + coeffs[stride + 1] = quant(decode_coeff(br, cb, l3, 2)?, q_ac); + Ok(()) +} +fn decode_2x2(br: &mut BitReader, cb: &Codebook, coeffs: &mut [i16], stride: usize, block2: bool, dsc: usize, q_ac: i16) -> DecoderResult<()> { + if dsc == 0 { return Ok(()); } + let lx = RV60_DSC_TO_LX[dsc as usize]; + let l0 = ((lx >> 0) & 0xFF) as i16; + let l1 = ((lx >> 8) & 0xFF) as i16; + let l2 = ((lx >> 16) & 0xFF) as i16; + let l3 = ((lx >> 24) & 0xFF) as i16; + coeffs[0] = quant(decode_coeff(br, cb, l0, 3)?, q_ac); + if !block2 { + coeffs[1] = quant(decode_coeff(br, cb, l1, 2)?, q_ac); + coeffs[stride] = quant(decode_coeff(br, cb, l2, 2)?, q_ac); + } else { + coeffs[stride] = quant(decode_coeff(br, cb, l1, 2)?, q_ac); + coeffs[1] = quant(decode_coeff(br, cb, l2, 2)?, q_ac); + } + coeffs[stride + 1] = quant(decode_coeff(br, cb, l3, 2)?, q_ac); + Ok(()) +} + +fn decode_4x4_block_dc(br: &mut BitReader, cbs: &CoeffCodebooks, is_luma: bool, coeffs: &mut [i16], stride: usize, q_dc: i16, q_ac: i16) -> DecoderResult<()> { + let tab_idx = if is_luma { 0 } else { 1 }; + let sym0 = br.read_cb(&cbs.l0_cb[tab_idx])?; + let grp0 = (sym0 >> 3) as usize; + let esc_cb = &cbs.esc_cb; + if grp0 != 0 { + decode_2x2_dc(br, esc_cb, &mut coeffs[0..], stride, false, grp0, q_dc, q_ac)?; + } + if (sym0 & 4) != 0 { + let grp = br.read_cb(&cbs.l12_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2..], stride, false, grp, q_ac)?; + } + if (sym0 & 2) != 0 { + let grp = br.read_cb(&cbs.l12_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2*stride..], stride, true, grp, q_ac)?; + } + if (sym0 & 1) != 0 { + let grp = br.read_cb(&cbs.l3_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2*stride+2..], stride, false, grp, q_ac)?; + } + Ok(()) +} + +fn decode_4x4_block(br: &mut BitReader, cbs: &CoeffCodebooks, is_luma: bool, coeffs: &mut [i16], stride: usize, q_ac: i16) -> DecoderResult<()> { + let tab_idx = if is_luma { 0 } else { 1 }; + let sym0 = br.read_cb(&cbs.l0_cb[tab_idx])?; + let grp0 = (sym0 >> 3) as usize; + let esc_cb = &cbs.esc_cb; + if grp0 != 0 { + decode_2x2(br, esc_cb, &mut coeffs[0..], stride, false, grp0, q_ac)?; + } + if (sym0 & 4) != 0 { + let grp = br.read_cb(&cbs.l12_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2..], stride, false, grp, q_ac)?; + } + if (sym0 & 2) != 0 { + let grp = br.read_cb(&cbs.l12_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2*stride..], stride, true, grp, q_ac)?; + } + if (sym0 & 1) != 0 { + let grp = br.read_cb(&cbs.l3_cb[tab_idx])? as usize; + decode_2x2(br, esc_cb, &mut coeffs[2*stride+2..], stride, false, grp, q_ac)?; + } + Ok(()) +} + +fn decode_cbp8(br: &mut BitReader, cbs: &[[Codebook; 4]; NUM_INTER_SETS], qp: u8, subset: usize) -> DecoderResult { + let cb_set = RV60_QP_TO_IDX[qp as usize]; + let cbp = br.read_cb(&cbs[cb_set][subset])?; + Ok(cbp) +} + +fn decode_super_cbp(br: &mut BitReader, cbs: &[Codebook]) -> DecoderResult { + let sym0 = br.read_cb(&cbs[0])? as u32; + let sym1 = br.read_cb(&cbs[1])? as u32; + let sym2 = br.read_cb(&cbs[2])? as u32; + let sym3 = br.read_cb(&cbs[3])? as u32; + + // luma/chroma interleaved CBPs + Ok(0 + + ((sym0 & 0x03) << 0) + + ((sym0 & 0x0C) << 2) + + ((sym0 & 0x10) << 12) + + ((sym0 & 0x20) << 15) + + ((sym1 & 0x03) << 2) + + ((sym1 & 0x0C) << 4) + + ((sym1 & 0x10) << 13) + + ((sym1 & 0x20) << 16) + + ((sym2 & 0x03) << 8) + + ((sym2 & 0x0C) << 10) + + ((sym2 & 0x10) << 14) + + ((sym2 & 0x20) << 17) + + ((sym3 & 0x03) << 10) + + ((sym3 & 0x0C) << 12) + + ((sym3 & 0x10) << 15) + + ((sym3 & 0x20) << 18) + ) +} + +pub fn rv6_decode_cbp8(br: &mut BitReader, cbs: &RV60Codebooks, subset: usize, qp: u8) -> DecoderResult { + let cbp8 = decode_cbp8(br, &cbs.cbp8_cb, qp, subset)?; + Ok(cbp8 as u32) +} + +pub fn rv6_decode_cbp16(br: &mut BitReader, cbs: &RV60Codebooks, subset: usize, qp: u8) -> DecoderResult { + let cb_set = RV60_QP_TO_IDX[qp as usize]; + let cbp16; + if subset == 0 { + cbp16 = decode_super_cbp(br, &cbs.cbp8_cb[cb_set])?; + } else { + cbp16 = decode_super_cbp(br, &cbs.cbp16_cb[cb_set][(subset - 1) * 4..][..4])?; + } + Ok(cbp16) +} + +pub fn rv6_decode_cu_8x8(br: &mut BitReader, cbs: &RV60Codebooks, is_intra: bool, qp: u8, sel_qp: u8, y_coeffs: &mut [i16; 16 * 16], u_coeffs: &mut [i16; 8 * 8], v_coeffs: &mut [i16; 8 * 8], ccbp: u32, mode4x4: bool) -> DecoderResult<()> { + let cb_set = RV60Codebooks::get_c4x4_set(sel_qp, is_intra); + let cb = if is_intra { &cbs.intra_coeff_cb[cb_set] } else { &cbs.inter_coeff_cb[cb_set] }; + let q_y = RV60_QUANTS_B[qp as usize]; + let q_c_dc = RV60_QUANTS_B[RV60_CHROMA_QUANT_DC[qp as usize] as usize]; + let q_c_ac = RV60_QUANTS_B[RV60_CHROMA_QUANT[qp as usize] as usize]; + for i in 0..4 { + if ((ccbp >> i) & 1) != 0 { + let (off, stride) = if mode4x4 { + (i * 16, 4) + } else { + ((i & 1) * 4 + (i & 2) * 2 * 8, 8) + }; + decode_4x4_block(br, cb, true, &mut y_coeffs[off..], stride, q_y)?; + } + } + if ((ccbp >> 4) & 1) != 0 { + decode_4x4_block_dc(br, cb, false, u_coeffs, 4, q_c_dc, q_c_ac)?; + } + if ((ccbp >> 5) & 1) != 0 { + decode_4x4_block_dc(br, cb, false, v_coeffs, 4, q_c_dc, q_c_ac)?; + } + Ok(()) +} + +pub fn rv6_decode_cu_16x16(br: &mut BitReader, cbs: &RV60Codebooks, is_intra: bool, qp: u8, sel_qp: u8, y_coeffs: &mut [i16; 16 * 16], u_coeffs: &mut [i16; 8 * 8], v_coeffs: &mut [i16; 8 * 8], ccbp: u32) -> DecoderResult<()> { + let cb_set = RV60Codebooks::get_c4x4_set(sel_qp, is_intra); + let cb = if is_intra { &cbs.intra_coeff_cb[cb_set] } else { &cbs.inter_coeff_cb[cb_set] }; + let q_y = RV60_QUANTS_B[qp as usize]; + let q_c_dc = RV60_QUANTS_B[RV60_CHROMA_QUANT_DC[qp as usize] as usize]; + let q_c_ac = RV60_QUANTS_B[RV60_CHROMA_QUANT[qp as usize] as usize]; + for i in 0..16 { + if ((ccbp >> i) & 1) != 0 { + let off = (i & 3) * 4 + (i >> 2) * 4 * 16; + decode_4x4_block(br, cb, true, &mut y_coeffs[off..], 16, q_y)?; + } + } + for i in 16..20 { + if ((ccbp >> i) & 1) != 0 { + let off = (i & 1) * 4 + (i & 2) * 2 * 8; + if i == 16 { + decode_4x4_block_dc(br, cb, false, &mut u_coeffs[off..], 8, q_c_dc, q_c_ac)?; + } else { + decode_4x4_block(br, cb, false, &mut u_coeffs[off..], 8, q_c_ac)?; + } + } + } + for i in 20..24 { + if ((ccbp >> i) & 1) != 0 { + let off = (i & 1) * 4 + (i & 2) * 2 * 8; + if i == 20 { + decode_4x4_block_dc(br, cb, false, &mut v_coeffs[off..], 8, q_c_dc, q_c_ac)?; + } else { + decode_4x4_block(br, cb, false, &mut v_coeffs[off..], 8, q_c_ac)?; + } + } + } + Ok(()) +} + +pub fn rv6_decode_cu_4x4in16x16(br: &mut BitReader, cbs: &RV60Codebooks, is_intra: bool, qp: u8, sel_qp: u8, y_coeffs: &mut [i16; 16 * 16], u_coeffs: &mut [i16; 8 * 8], v_coeffs: &mut [i16; 8 * 8], ccbp: u32) -> DecoderResult<()> { + let cb_set = RV60Codebooks::get_c4x4_set(sel_qp, is_intra); + let cb = if is_intra { &cbs.intra_coeff_cb[cb_set] } else { &cbs.inter_coeff_cb[cb_set] }; + let q_y = RV60_QUANTS_B[qp as usize]; + let q_c_dc = RV60_QUANTS_B[RV60_CHROMA_QUANT_DC[qp as usize] as usize]; + let q_c_ac = RV60_QUANTS_B[RV60_CHROMA_QUANT[qp as usize] as usize]; + for i in 0..16 { + if ((ccbp >> i) & 1) != 0 { + let off = i * 16; + decode_4x4_block(br, cb, true, &mut y_coeffs[off..], 4, q_y)?; + } + } + for i in 16..20 { + if ((ccbp >> i) & 1) != 0 { + let off = (i - 16) * 16; + decode_4x4_block_dc(br, cb, false, &mut u_coeffs[off..], 4, q_c_dc, q_c_ac)?; + } + } + for i in 20..24 { + if ((ccbp >> i) & 1) != 0 { + let off = (i - 20) * 16; + decode_4x4_block_dc(br, cb, false, &mut v_coeffs[off..], 4, q_c_dc, q_c_ac)?; + } + } + Ok(()) +} + +const RV60_QP_TO_IDX: [usize; 64] = [ + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0, 0 +]; +const RV60_QUANTS_B: [i16; 32] = [ + 60, 67, 76, 85, 96, 108, 121, 136, + 152, 171, 192, 216, 242, 272, 305, 341, + 383, 432, 481, 544, 606, 683, 767, 854, + 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211 +]; +const RV60_CHROMA_QUANT_DC: [u8; 32] = [ + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23 +]; +const RV60_CHROMA_QUANT: [u8; 32] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25 +]; + +const RV60_DSC_TO_LX: [u32; NUM_COEFF_ENTRIES] = [ + 0x00000000, 0x01000000, 0x02000000, 0x00010000, 0x01010000, 0x02010000, 0x00020000, 0x01020000, 0x02020000, + 0x00000100, 0x01000100, 0x02000100, 0x00010100, 0x01010100, 0x02010100, 0x00020100, 0x01020100, 0x02020100, + 0x00000200, 0x01000200, 0x02000200, 0x00010200, 0x01010200, 0x02010200, 0x00020200, 0x01020200, 0x02020200, + + 0x00000001, 0x01000001, 0x02000001, 0x00010001, 0x01010001, 0x02010001, 0x00020001, 0x01020001, 0x02020001, + 0x00000101, 0x01000101, 0x02000101, 0x00010101, 0x01010101, 0x02010101, 0x00020101, 0x01020101, 0x02020101, + 0x00000201, 0x01000201, 0x02000201, 0x00010201, 0x01010201, 0x02010201, 0x00020201, 0x01020201, 0x02020201, + + 0x00000002, 0x01000002, 0x02000002, 0x00010002, 0x01010002, 0x02010002, 0x00020002, 0x01020002, 0x02020002, + 0x00000102, 0x01000102, 0x02000102, 0x00010102, 0x01010102, 0x02010102, 0x00020102, 0x01020102, 0x02020102, + 0x00000202, 0x01000202, 0x02000202, 0x00010202, 0x01010202, 0x02010202, 0x00020202, 0x01020202, 0x02020202, + + 0x00000003, 0x01000003, 0x02000003, 0x00010003, 0x01010003, 0x02010003, 0x00020003, 0x01020003, 0x02020003, + 0x00000103, 0x01000103, 0x02000103, 0x00010103, 0x01010103, 0x02010103, 0x00020103, 0x01020103, 0x02020103, + 0x00000203, 0x01000203, 0x02000203, 0x00010203, 0x01010203, 0x02010203, 0x00020203, 0x01020203, 0x02020203 +]; + +const RV60_CBP8_TABS: [[[u32; 8]; 4]; NUM_INTER_SETS] = [ + [ + [ 0x66666675, 0x66656553, 0x77767675, 0x77656552, 0x88878786, 0x88767663, 0x88868674, 0x87646441 ], + [ 0x6383B594, 0xD8B7B6A2, 0x84A5B5A3, 0xD8C7B6A2, 0x94B5D5C5, 0xEAE9E8C4, 0xA4D4C4B3, 0xE9D7D6B2 ], + [ 0x45555565, 0x56555552, 0x66666675, 0x67656552, 0x88888897, 0x88878774, 0x88978786, 0x88867661 ], + [ 0x73639483, 0xB796A683, 0x849495A4, 0xD8C7B692, 0xA5B5C6C5, 0xEAD8D9C4, 0xA5B5B5C4, 0xE9D8D7B1 ], + ], [ + [ 0x66666675, 0x66656553, 0x77767675, 0x77656552, 0x88878786, 0x88767663, 0x88868674, 0x87646441 ], + [ 0x6383B594, 0xD8B7B6A2, 0x84A5B5A3, 0xD8C7B6A2, 0x94B5D5C5, 0xEAE9E8C4, 0xA4D4C4B3, 0xE9D7D6B2 ], + [ 0x45555565, 0x56555552, 0x66666675, 0x67656552, 0x88888897, 0x88878774, 0x88978786, 0x88867661 ], + [ 0x73639483, 0xB796A683, 0x849495A4, 0xD8C7B692, 0xA5B5C6C5, 0xEAD8D9C4, 0xA5B5B5C4, 0xE9D8D7B1 ], + ], [ + [ 0x45555565, 0x56545543, 0x66666675, 0x67656553, 0x77777786, 0x78767664, 0x77867675, 0x87656551 ], + [ 0x41848493, 0x86959582, 0x73A584A4, 0xA7B7A7A4, 0x84C6C6D6, 0xD9D8D8C5, 0x94D5B4D4, 0xD9D8D7D4 ], + [ 0x34544554, 0x45444442, 0x66766675, 0x67656552, 0x88988897, 0x89877774, 0x99989896, 0x99868663 ], + [ 0x52637373, 0x86857562, 0x84958494, 0xB8A79582, 0x94B6B6B6, 0xDAC8C8A4, 0x95B6A6C5, 0xDAC8C7A3 ], + ], [ + [ 0x34445565, 0x45445443, 0x66667675, 0x77656553, 0x77777786, 0x78667664, 0x77867685, 0x88656552 ], + [ 0x218383A4, 0x8696A694, 0x63B594C5, 0xC8D8C8D5, 0x63C5B5D6, 0xD9D9D9E7, 0x83C5B5E5, 0xD9E8E8D5 ], + [ 0x24444454, 0x45443442, 0x66766675, 0x67666653, 0x78878787, 0x88777775, 0x99988797, 0x99877774 ], + [ 0x41636373, 0x85757462, 0x73958595, 0xB8A79684, 0x84A6A6B6, 0xD9B8C8A5, 0x95B6A6B6, 0xDAC8C8B5 ], + ], [ + [ 0x34444455, 0x45444443, 0x66666675, 0x67656653, 0x67777786, 0x78667664, 0x77767685, 0x87656553 ], + [ 0x208494C5, 0xA8B7E9D7, 0x63C5B5E6, 0xEAEAEAE7, 0x63C6C6E7, 0xEBEAEBE8, 0x84D5C6E6, 0xEBEAEAE6 ], + [ 0x23333454, 0x35443443, 0x67766676, 0x67666665, 0x77777787, 0x78777775, 0x99988898, 0x99888886 ], + [ 0x40636374, 0x96757563, 0x749596A6, 0xB9A8A896, 0x84A6A6A7, 0xCAB8B9A7, 0x86A7B7C7, 0xDBC9DAB7 ], + ], [ + [ 0x24444455, 0x35444443, 0x56666676, 0x67666664, 0x67777787, 0x78667665, 0x77767685, 0x78667663 ], + [ 0x109495E7, 0xDAD9EAE8, 0x63C6C6E7, 0xECEBEBE9, 0x64C7C7E9, 0xEDEBECE9, 0x84D6D7E7, 0xECEBEBE8 ], + [ 0x13343454, 0x35443444, 0x67776787, 0x68777776, 0x67777787, 0x79787886, 0x899988A8, 0x9A998997 ], + [ 0x30535374, 0x87767665, 0x738586A7, 0xB9A9A9A7, 0x749697A8, 0xCAA9B9A8, 0x85A7B8C8, 0xDCCADAC8 ], + ], [ + [ 0x13343455, 0x35454544, 0x56666777, 0x67676776, 0x67777787, 0x78777776, 0x77777787, 0x78777776 ], + [ 0x018485D7, 0xDADADAD9, 0x53B6C7D9, 0xDDDCDCDB, 0x54C7C8DA, 0xDDDCDDDB, 0x64D7D8DA, 0xDDDDDDDB ], + [ 0x03353456, 0x35464666, 0x67887899, 0x798A8999, 0x68898899, 0x8A9A9999, 0x8AAA9ABB, 0xABABABBA ], + [ 0x10536487, 0x98879887, 0x74A7A8CA, 0xDCCBDBDA, 0x74A7B8CA, 0xDCDBCCCB, 0x85B8C9DB, 0xDDDCDDDB ] + ] +]; + +const RV60_CBP16_TABS: [[[u32; 8]; 12]; NUM_INTER_SETS] = [ + [ + [ 0x8563A594, 0xA795B7A4, 0x9584B5A4, 0xB8A6C7A3, 0x9674B6A4, 0xB8A6D8B2, 0xA594C4C3, 0xD8C6C6B1 ], + [ 0x02525474, 0x87978695, 0x56858797, 0xAAA9A796, 0x56A6A9DA, 0xEEEDECFB, 0x98B7B9D8, 0xFDDAEAC8 ], + [ 0x02545475, 0x67867674, 0x55978696, 0xA9B8A784, 0x459897B9, 0xBBDBCAD9, 0x87B8A6C7, 0xCBDAD8C5 ], + [ 0x03553364, 0x66876474, 0x67988585, 0xA8978474, 0x6BCCCACB, 0xCCCCCCCA, 0xBBCBCAB9, 0xCBB9B997 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x46555553, 0x56666675, 0x67656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x85639684, 0x9685A672, 0x96859594, 0xB795A582, 0xA786C7B6, 0xC9B7C8A3, 0xA796B5A3, 0xC7B6B591 ], + [ 0x12534363, 0x66867473, 0x45766575, 0x98A89694, 0x65A786A7, 0xCBDBC9C6, 0x87A897B6, 0xCBD9B8C4 ], + [ 0x12435464, 0x66757673, 0x44657585, 0x87979783, 0x558697A7, 0xA9A8B9A6, 0x879796A6, 0xB9B8B8A4 ], + [ 0x02454464, 0x66867484, 0x579986A5, 0xA9B8A5A4, 0x79BAA9C9, 0xDCDBDAD7, 0xABDCCAD8, 0xDDDBD9C5 ], + ], [ + [ 0x8563A594, 0xA795B7A4, 0x9584B5A4, 0xB8A6C7A3, 0x9674B6A4, 0xB8A6D8B2, 0xA594C4C3, 0xD8C6C6B1 ], + [ 0x02525474, 0x87978695, 0x56858797, 0xAAA9A796, 0x56A6A9DA, 0xEEEDECFB, 0x98B7B9D8, 0xFDDAEAC8 ], + [ 0x02545475, 0x67867674, 0x55978696, 0xA9B8A784, 0x459897B9, 0xBBDBCAD9, 0x87B8A6C7, 0xCBDAD8C5 ], + [ 0x03553364, 0x66876474, 0x67988585, 0xA8978474, 0x6BCCCACB, 0xCCCCCCCA, 0xBBCBCAB9, 0xCBB9B997 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x46555553, 0x56666675, 0x67656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x35555565, 0x55555553, 0x56666665, 0x66656552, 0x78888887, 0x88878774, 0x78878786, 0x88767661 ], + [ 0x85639684, 0x9685A672, 0x96859594, 0xB795A582, 0xA786C7B6, 0xC9B7C8A3, 0xA796B5A3, 0xC7B6B591 ], + [ 0x12534363, 0x66867473, 0x45766575, 0x98A89694, 0x65A786A7, 0xCBDBC9C6, 0x87A897B6, 0xCBD9B8C4 ], + [ 0x12435464, 0x66757673, 0x44657585, 0x87979783, 0x558697A7, 0xA9A8B9A6, 0x879796A6, 0xB9B8B8A4 ], + [ 0x02454464, 0x66867484, 0x579986A5, 0xA9B8A5A4, 0x79BAA9C9, 0xDCDBDAD7, 0xABDCCAD8, 0xDDDBD9C5 ], + ], [ + [ 0x63638493, 0x8696A6B4, 0x63847493, 0x87A696A4, 0x749595B4, 0xB8D7B7C4, 0x84A494A2, 0xA7B6A6D3 ], + [ 0x02333455, 0x57677776, 0x56767797, 0x899A99A9, 0x78B8BADA, 0xDDDDDCDC, 0x98C8D9D9, 0xDDDCDCD9 ], + [ 0x02444466, 0x56666666, 0x55776575, 0x77877575, 0x67AAA9DB, 0xCDDBDCDA, 0x98CAA7C8, 0xDCDBC9D8 ], + [ 0x02452366, 0x56896698, 0x46786689, 0x789A88B9, 0xACCCCCCC, 0xCCCCCCCC, 0xCCCCCCCC, 0xCCCCCDDC ], + [ 0x23443454, 0x45444443, 0x56666675, 0x67666663, 0x78878897, 0x89878775, 0x89979796, 0x99878773 ], + [ 0x24344454, 0x35444443, 0x56666676, 0x67656663, 0x78888897, 0x89878775, 0x89979896, 0x99868773 ], + [ 0x23443454, 0x45444443, 0x56666676, 0x67666663, 0x68888897, 0x89877775, 0x88988896, 0x99877673 ], + [ 0x24344455, 0x35444443, 0x56666676, 0x67666653, 0x68888897, 0x89878774, 0x89989897, 0x99877763 ], + [ 0x63537473, 0x85748562, 0x73848484, 0x96959683, 0x8596A5A4, 0xC8A7B794, 0x85A595A4, 0xC7B6B6A3 ], + [ 0x02443374, 0x77867684, 0x568776A7, 0xA9BAA8B6, 0x78C9A8C9, 0xDDECDAD7, 0x99B8B9C8, 0xEDEAEAD6 ], + [ 0x02445565, 0x56656664, 0x55878686, 0x98978674, 0x67A9A8C9, 0xABAACAB7, 0x87B9A7B8, 0xDBDAC9B6 ], + [ 0x02553264, 0x66877585, 0x67997697, 0x98B997A6, 0x9ACBA9DA, 0xDDDCDBC8, 0xCCDCDADA, 0xDCDCDAD8 ], + ], [ + [ 0x626383A3, 0x97A6C6C4, 0x538484B4, 0xA8C7C7E5, 0x74A4B5D5, 0xD9E8E8E5, 0x73B3B3E3, 0xC8E7E7E4 ], + [ 0x02324464, 0x78778786, 0x569697C8, 0xBCCCCCCA, 0x88B8BACB, 0xCCCCCCCB, 0xA8B8CAC9, 0xCCCCCCCA ], + [ 0x02444466, 0x46666767, 0x35775588, 0x78A988A8, 0x68CBB8CB, 0xCDCBDDDB, 0x98CAB8CA, 0xCCCCCBCA ], + [ 0x02452366, 0x56987697, 0x38AA79AB, 0x9ABBBBBA, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB ], + [ 0x13343454, 0x45444553, 0x56666676, 0x67766675, 0x68878897, 0x89888885, 0x89989897, 0x99888885 ], + [ 0x13344454, 0x35444543, 0x56667786, 0x78766765, 0x68888898, 0x89878875, 0x89989898, 0x99878885 ], + [ 0x13343454, 0x35454453, 0x56766786, 0x78776675, 0x68888898, 0x89888786, 0x899898A8, 0x9A988785 ], + [ 0x14343455, 0x35444543, 0x56676777, 0x67776764, 0x68888898, 0x89878875, 0x89989898, 0x99888875 ], + [ 0x51536373, 0x85758573, 0x63848495, 0xA796A694, 0x749595A5, 0xB8B7B8A5, 0x85A695A5, 0xB9B7B8A5 ], + [ 0x02433454, 0x67867674, 0x569787A7, 0xBBC9C9B7, 0x78B8A9C8, 0xDDDADBC8, 0x99A8BAC8, 0xDDDADBC7 ], + [ 0x02444465, 0x56556664, 0x55876686, 0x88988786, 0x68AAA8BA, 0xABBACAB8, 0x87BA98C9, 0xCCCBCAB8 ], + [ 0x02452364, 0x66877585, 0x57AA88B9, 0xA9CABAB8, 0x8ABAA9CA, 0xCCBBBBB9, 0xBBBBBBBB, 0xBBBBBBB9 ], + ], [ + [ 0x716383B3, 0xB8D7D7E4, 0x6394A4D4, 0xC9E8E8E5, 0x73B5B5E5, 0xEAE9E9E6, 0x83C4C4E4, 0xE9E8E7E4 ], + [ 0x01334575, 0x99A8A9B7, 0x66A7B8C8, 0xCCCCCCC8, 0x77B8CAC9, 0xCCCCCCCB, 0x98C8C9C9, 0xCCCCCBCA ], + [ 0x01444486, 0x57777897, 0x55A876B8, 0xCACAB9C8, 0x67CAC8CA, 0xCCCACBCA, 0x98CAC8C9, 0xCCCCCBCA ], + [ 0x01562486, 0x799998A8, 0x6AAA9999, 0x99999999, 0x99999999, 0x99999999, 0x9999999A, 0xAAAAAAA9 ], + [ 0x13343454, 0x35444443, 0x56767787, 0x78777776, 0x67877797, 0x79888886, 0x899898A8, 0x9A999997 ], + [ 0x13333454, 0x35444543, 0x57777787, 0x78777776, 0x67778898, 0x89888886, 0x899999A9, 0x9A989997 ], + [ 0x13343454, 0x35453443, 0x57777787, 0x78777776, 0x67887798, 0x89888886, 0x899998A9, 0x9A999997 ], + [ 0x13343454, 0x35443543, 0x57777787, 0x78777776, 0x68887898, 0x79888876, 0x899999A9, 0x9A999987 ], + [ 0x60636384, 0x86859684, 0x63858596, 0xA8A7A8A6, 0x749696A6, 0xB9A8B9A6, 0x85A6A7B7, 0xC9B8C9B7 ], + [ 0x02333454, 0x77768775, 0x678798A7, 0xCBB9CAB7, 0x6897A9B8, 0xDDC9DBB8, 0x89A8BAD8, 0xDDDADBC8 ], + [ 0x02344465, 0x56556664, 0x558777A8, 0x99A9A9A8, 0x679A98CA, 0xABBBBAB9, 0x78BA98CB, 0xCCCCCBCA ], + [ 0x01453366, 0x67777676, 0x79BBBABB, 0xBBBBBBB9, 0x8ABBABBB, 0xBBBBBBBA, 0xBBBBBBBB, 0xBBBBBBBB ], + ], [ + [ 0x816383C4, 0xB9D8D8E5, 0x62A4B4E5, 0xEAE9E9E6, 0x63B5B5E6, 0xEAEAEAE7, 0x82C4C4E5, 0xEAE9E9E5 ], + [ 0x01335485, 0x9AB9A8B7, 0x7697B8B8, 0xBBBBBBB9, 0x67B8BABB, 0xBBBBBBBB, 0x98B7BABA, 0xBBBBBBBB ], + [ 0x01445396, 0x78879AA6, 0x559897A9, 0xAAA9AAA9, 0x67A9A9AA, 0xAA9AAAAA, 0x97A9A8AA, 0xAAAAAAAA ], + [ 0x02643476, 0x76777776, 0x67777777, 0x77777777, 0x77777777, 0x77777777, 0x77777777, 0x77777777 ], + [ 0x03343455, 0x46564665, 0x57777898, 0x79898888, 0x688888A8, 0x89999998, 0x899999B9, 0xABAAAAA9 ], + [ 0x03344555, 0x36454655, 0x67788898, 0x79888998, 0x68888999, 0x8A899998, 0x899AAABA, 0xABAAAAA9 ], + [ 0x03443465, 0x36564555, 0x57887898, 0x79898898, 0x688988A9, 0x8A998998, 0x89AA99BA, 0xABAAAAA9 ], + [ 0x03344556, 0x36454655, 0x57787899, 0x79898988, 0x68898999, 0x8A898998, 0x8AAAAABA, 0x9BABABA9 ], + [ 0x50536374, 0x86859685, 0x53858596, 0xA8A8B8A6, 0x648696A7, 0xB9A8B9B7, 0x759797B7, 0xB9B9CAC8 ], + [ 0x02324465, 0x78768886, 0x668698A8, 0xBBB9CBB9, 0x6797A9B9, 0xCCB9CCB9, 0x7897BBC9, 0xCCCACCCA ], + [ 0x02354366, 0x46666665, 0x458987BA, 0x9AAABAA9, 0x58AB99CA, 0xACBBBABA, 0x78BCA9CB, 0xCCCCCBCB ], + [ 0x01453466, 0x66766675, 0x79AAA9AA, 0xAAAAAAAA, 0x7AAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA ], + ], [ + [ 0x807473D6, 0xC9C9E9E7, 0x52B6A5E7, 0xDBEAEAE8, 0x53B6B6E8, 0xEBEAEBE9, 0x63C5B5E7, 0xEBEAEAE7 ], + [ 0x01435495, 0x99999999, 0x66989999, 0x99999999, 0x57989999, 0x99999999, 0x97979999, 0x999999AA ], + [ 0x01445487, 0x77778787, 0x55888888, 0x88999999, 0x57999999, 0x99999999, 0x77999999, 0x99999999 ], + [ 0x03675677, 0x76666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66777777, 0x77666677 ], + [ 0x02343566, 0x36575777, 0x588988AA, 0x8A9A9AAA, 0x588989BA, 0x8A9BAABA, 0x7AA9AABB, 0xACBCBCCB ], + [ 0x03343556, 0x36464666, 0x577888A9, 0x8A8A9AAA, 0x588989AA, 0x8A9A9BBA, 0x7A9AAACB, 0xABABBCBA ], + [ 0x03343466, 0x36564666, 0x578978A9, 0x7A9A8AA9, 0x578979AA, 0x8A9B99AA, 0x79AA9ABB, 0x9BABAABA ], + [ 0x03343556, 0x36464666, 0x588979AA, 0x7B8A8A9A, 0x588989AA, 0x8A9A9AAA, 0x7AAB9ABB, 0x9BABABBA ], + [ 0x50535385, 0x879797A7, 0x438686A8, 0xA9B9BAD9, 0x438686B8, 0xB9CACBDA, 0x649797C9, 0xBACADBDA ], + [ 0x01334677, 0x78778887, 0x5797AAAB, 0xBBBBBBBB, 0x6898BBBB, 0xBBBAAAAA, 0x8AA9AAAA, 0xAAAAAAAA ], + [ 0x01464488, 0x46566677, 0x57AAAAAA, 0xAAAAAAAA, 0x5AAAAAAA, 0xAAAAAAAA, 0x8AAAAAAA, 0xAAAAAAAA ], + [ 0x02453466, 0x67777777, 0x77777777, 0x77777777, 0x77777777, 0x77777777, 0x77777777, 0x77777788 ], + ] +]; + +struct CoeffsCBDesc { + l0_tab: [[u32; 108]; 2], + l12_tab: [[u32; 14]; 2], + l3_tab: [[u32; 14]; 2], + esc_tab: [u32; 4], +} +const RV60_INTRA_COEFFS_CB_DESC: [CoeffsCBDesc; NUM_INTRA_SETS] = [ + CoeffsCBDesc { + l0_tab: [ + [ + 0xF6464655, 0x68677866, 0x9C9BAB99, 0x58576766, 0x8A788977, 0xBDBCCCA9, 0x8B8A9A88, 0xBD9ABB98, + 0xBEBCCDA9, 0x58676766, 0x7A888877, 0xBDBCBCA9, 0x79788876, 0x9B999987, 0xDECCCCA9, 0xACAABB98, + 0xCEABCCA9, 0xEECCDEB9, 0x8B9A8A88, 0xBDBBAB98, 0xBEBDBCA9, 0xADABAB98, 0xCEBCBBA9, 0xEEDDCDB9, + 0xBEBCBCA9, 0xDECCCDA9, 0xDECDDDA8, 0x47566766, 0x79788877, 0xBDABBCA9, 0x59677876, 0x8A899987, + 0xCEBCCCA9, 0x9C9AAB98, 0xBDAABC98, 0xDEBCDDB9, 0x69787876, 0x8A898987, 0xCECCCCA9, 0x7A898977, + 0x9B9A9A87, 0xDECCCDBA, 0xADAABB98, 0xBEABBC98, 0xEECCDEB9, 0x9CAB9A98, 0xBDBCAB99, 0xDECDCCB9, + 0xADBBAB98, 0xBEBCBBA9, 0xEEDDCCA9, 0xCEBCCCA9, 0xDECCCCA9, 0xEECCCD98, 0x69798987, 0x9B9AAA98, + 0xBEBDCDBA, 0x8B899A88, 0xACAAAB98, 0xEEDDDDCA, 0xAD9BAB98, 0xCEBBCCA9, 0xDECDDEB9, 0x8B899A88, + 0xACAAAB98, 0xEEDDDDCA, 0x9B9A9A98, 0xADABABA9, 0xEEDDDEBA, 0xBEABBCA9, 0xCEBCCCA9, 0xEECDEEB9, + 0xADABAB99, 0xCECCBCA9, 0xDEDECDBA, 0xBEBCACA9, 0xCECCBCA9, 0xEEDECDB9, 0xCEBCCCA9, 0xDECCCDA9, + 0xEECCCD98, 0x9C9AAA98, 0xBDBBBB98, 0xEEDDDDB9, 0x9C9A9A98, 0xBDBBBB98, 0xEEDDDDB9, 0xADAAAB97, + 0xCEABBB98, 0xEECCCD97, 0x9C9AAB98, 0xBDABBB98, 0xEEDDDDB9, 0x9C9AAB98, 0xBEABBB98, 0xEEDDDDB9, + 0xADAAAB97, 0xBEABBB97, 0xEEBBCC97, 0xADABAB98, 0xCEBBBB98, 0xEECDCC98, 0xADABAB98, 0xBEBBAB98, + 0xEECCBC97, 0xBDAAAB87, 0xAD9AAB86, 0xCE9A9A75 + ], [ + 0xF6374878, 0x59798B9A, 0xDEDDEEDC, 0x49597A89, 0x8B8AACAA, 0xEEDEEEDD, 0x9D9BBDAB, 0xBEACDEBC, + 0xEEDEEEDD, 0x49796A89, 0x8B9A9CAA, 0xEEDEEEDD, 0x7B8A9B9A, 0x9DABADAB, 0xEEDEEEDD, 0xBEACCEBC, + 0xCEBDDECC, 0xEEEEEEDD, 0x9DBC9CAB, 0xBECDBDBC, 0xEEEEEEDD, 0xBEBDBDBC, 0xCECDBECC, 0xEEEEEEDD, + 0xDEDEDECC, 0xEEDEDECD, 0xEEEEEEDC, 0x17485979, 0x6A798B9A, 0xEEDDDECC, 0x49697A89, 0x8B8AACAA, + 0xEEDDEEDD, 0x9D8BBDAB, 0xBEACCEBC, 0xEEDEEEDD, 0x49797A89, 0x8C9B9CAA, 0xEEDEEEDD, 0x6B8A9B9A, + 0x9D9BACAB, 0xEEDEEEDD, 0xAEACCEBB, 0xCEBDDEBC, 0xEEDEEEDD, 0x9DBC9CAB, 0xBECDBDBC, 0xEEEEDEDD, + 0xAEBCBDBB, 0xCECDBDBC, 0xEEEEDEDD, 0xDEDEDECC, 0xDEDEDECC, 0xEEEEEECC, 0x39697A89, 0x8B9B9CAA, + 0xEEDEEEDD, 0x6B7A9B9A, 0x9C9BBDAB, 0xEEEEEEDD, 0x9E9CBEBB, 0xBEBCDECC, 0xEEEEEEDD, 0x6B8A8B9A, + 0x9DABACAB, 0xEEEEEEDD, 0x7C9B9CAB, 0x9DACBDBB, 0xEEEEEEDD, 0xAEACCEBC, 0xBEBDDECC, 0xEEDEEEDD, + 0x9EBC9DBB, 0xBECDBDBC, 0xEEEEEEDD, 0xAEBDBDBC, 0xBECEBECC, 0xEEEEDEDD, 0xDEDEDECC, 0xDEDEDECC, + 0xEEDEDECC, 0x6A7A8B99, 0x9C9BACAA, 0xEEDDDECC, 0x7B8A9B9A, 0x9DABACAB, 0xEEDDDECC, 0x9D9BAC9A, + 0xBEACBDAB, 0xEEDDDEBB, 0x7B8A8B9A, 0x9DABACAB, 0xEEDDDECC, 0x7C9B9C9A, 0x9DABADAB, 0xEEDEDECC, + 0x9D9BADAA, 0xAEACBDAA, 0xEECDDEBB, 0x8D9B9C9A, 0xBEBCACAA, 0xEEDECDBB, 0x9DAC9C9A, 0xAEBCACAA, + 0xDEDECDBB, 0xAEACAC99, 0xAEACAC99, 0xCEABAB98 + ]], + l12_tab: [ + [ + 0xF3624857, 0x82484587, 0x89578689, 0x89924735, 0x86794585, 0x69789679, 0x78989957, 0x867A7896, + 0x7A78A89A, 0x79989A99, 0x97897897, 0x8878A789, 0x78888988, 0x87760000 + ], [ + 0xF3915968, 0xB25957A8, 0x9B78B89C, 0xBBC15936, 0xA79B46A5, 0x7A89C79B, 0x9ACBBC57, 0xB68B8AC6, + 0x8B79C9AC, 0x9ACAACBB, 0xC79B89C9, 0xAB8AC8AC, 0x9AB9ACAA, 0xCAAB0000 + ]], + l3_tab: [ + [ + 0xF3524747, 0x83574687, 0x8A588789, 0x89914735, 0x86894685, 0x6988A789, 0x89A9AA47, 0x868A79A6, + 0x8A78A9AB, 0x7AA9AB9A, 0xA79A89A9, 0x9A89A99A, 0x99A9AA9A, 0xA9980000 + ], [ + 0xF4B16C7A, 0xE37C68CA, 0xBE9BEABE, 0xCCE06B37, 0xC8BE58C7, 0x9CABEABE, 0xACECDD68, 0xC79DACE8, + 0xAD9ADBCE, 0xBCEBCEDD, 0xEAACABDC, 0xDEBBDBCD, 0xCDECDECD, 0xEDDD0000 + ]], + esc_tab: [ 0x01334555, 0x66777788, 0x88999AAA, 0x999BCEED ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF5364655, 0x58687877, 0xBECDCDBA, 0x48576766, 0x7A798988, 0xDECDDDBB, 0x9C8AAB99, 0xBE9BBCA9, + 0xEECCDEBA, 0x48676766, 0x7A898978, 0xDECDCDBA, 0x6A797977, 0x8B9A9A88, 0xEECDCDBA, 0xADABBCA9, + 0xBEACCDAA, 0xEECDDEBA, 0x9CAB8A99, 0xBDBC9BA9, 0xDEDECCBA, 0xBDBCAB99, 0xBEBDACAA, 0xEEDECDB9, + 0xCECDCDA9, 0xDECDCDA9, 0xEECDCDA8, 0x37575766, 0x79798977, 0xDECDCDBA, 0x59687877, 0x8B8A9A88, + 0xEECDDDBA, 0x9C9AAC99, 0xBEABBCA9, 0xEECDDEBA, 0x59786877, 0x8B8A8A88, 0xEEDDCDBA, 0x7A898988, + 0x9B9A9A99, 0xEECDCDBA, 0xADABBC99, 0xBEABBDA9, 0xEEBDDEA9, 0x9DAB9A99, 0xBEBCABA9, 0xEEDECCBA, + 0xADBCABA9, 0xBEBCACA9, 0xEEDEBCA9, 0xCECDCDA9, 0xDEBDBDA9, 0xEECDCD98, 0x6A798A88, 0x9C9BAB99, + 0xEEDEDECB, 0x7B8A8A99, 0xACABABA9, 0xEEDEEECB, 0xAD9BBCA9, 0xBEACCDAA, 0xEECDEEBA, 0x8B9A8A99, + 0xADABABA9, 0xEEEEDECB, 0x8C9B9B99, 0xADACACAA, 0xEEDEDECB, 0xBEACBCAA, 0xBEACCDAA, 0xEECDDEBA, + 0xAEBCABA9, 0xBECDACAA, 0xEEEECDBA, 0xBEBDACAA, 0xBECDACAA, 0xEEDECDBA, 0xCECDCDA9, 0xCEBDBDA9, + 0xEEBCCD98, 0x9C9A9B99, 0xBEBCBCA9, 0xEEDDDEBA, 0x9C9B9B99, 0xBEABACA9, 0xEEDDDDBA, 0xAD9BAB98, + 0xBEABAC98, 0xEECCCD98, 0x9D9B9B99, 0xBEACBCA9, 0xEEDDDDBA, 0x9D9B9B99, 0xAEACACA9, 0xEEDDDDB9, + 0xAD9BAB98, 0xAE9BAC98, 0xDEACCD98, 0xADAB9B98, 0xBEACAB98, 0xEECDCC98, 0xAEAB9B98, 0xBEACAB98, + 0xDECCBC98, 0xAE9B9B87, 0xAE9B9B87, 0xBE8A9A75 + ], [ + 0xF7484979, 0x6A7A8BAB, 0xDEDEEEEE, 0x39598B9A, 0x8C8BADBC, 0xEEEEEEEE, 0x9E9CBEBD, 0xBEBEDECD, + 0xEEEEEEEE, 0x3A7A6A9A, 0x8C9C9CAC, 0xEEEEEEEE, 0x6B8B9CAC, 0x9DADADBC, 0xEEEEEEDE, 0xAEBECECD, + 0xCEBEDECD, 0xEEEEEEDE, 0x9EBD9DBD, 0xBECEADCD, 0xEEEEDEEE, 0xAECEBECD, 0xBEDEBECD, 0xEEEEDEDE, + 0xDEDEDECD, 0xEEDEDECD, 0xEEEEEEDD, 0x18585A8A, 0x6A8A9BAB, 0xEEEEEEDE, 0x4A6A8B9B, 0x8C9BADBC, + 0xEEEEEEEE, 0x8E8DBEBC, 0xBEADDECD, 0xEEDEEEEE, 0x4A7A6B9B, 0x8C9C9CAC, 0xEEEEEEEE, 0x6C8B9CAC, + 0x8D9DADBC, 0xEEDEEEDE, 0xAEADCECD, 0xBEBEDECD, 0xEEDEEEDE, 0x8EBD8DBC, 0xBECEADCD, 0xEEEEDEDE, + 0xAECEAEBD, 0xBECEAECD, 0xEEEEDEDD, 0xDEDEDECD, 0xDEDEDECD, 0xEEDEDECC, 0x3A6A7B9B, 0x8C9B9CBC, + 0xEEEEEEEE, 0x5B7B8CAB, 0x9DACADBC, 0xEEEEEEEE, 0x8E9DBEBC, 0xBEBEDECD, 0xEEEEEEEE, 0x5B8B7CAB, + 0x9DADADBD, 0xEEEEEEEE, 0x7C9C9DAC, 0x9DADADBD, 0xEEEEEEEE, 0xAEAECECD, 0xBEBEDECD, 0xEEDEEEDD, + 0x9EBE9DBC, 0xBECEAECD, 0xEEEEDEEE, 0xAECEAECD, 0xBECEAECD, 0xEEEEDEDD, 0xCECEDECD, 0xCEDECECD, + 0xEEDEDECC, 0x5B7B8B9B, 0x9D9CACAC, 0xEEDEDECC, 0x6C8C8C9B, 0x9DACADAC, 0xEEDEDECC, 0x8E8C9CAB, + 0xAEADBDAB, 0xEEDEDECB, 0x6C8B8C9B, 0x9DADADAC, 0xEEDEDECC, 0x7C9C9CAB, 0x9DADADAC, 0xEEDEDECC, + 0x8E9CADAB, 0x9E9CADAB, 0xDECDDEBB, 0x8D9C8C9B, 0xAEBDADAB, 0xEEDECECB, 0x8EAD9CAB, 0x9EAD9CAB, + 0xDEDEBDBB, 0x9EACAC9A, 0x9DAC9C9A, 0xBDABAB99 + ]], + l12_tab: [ + [ + 0xF3824968, 0x92494597, 0x89679789, 0x99924935, 0x96793595, 0x69789689, 0x78989857, 0xA67A78A6, + 0x7A78A889, 0x89A89999, 0x87897897, 0x78789789, 0x77878878, 0x87760000 + ], [ + 0xF4B26C7A, 0xD26C58DA, 0xBD8AEABE, 0xCDE05C37, 0xC8AD47C6, 0x8CAAD9BD, 0xABECCE58, 0xC79D9BD7, + 0xAD8ADABE, 0xACEBCECC, 0xE8AC9ACA, 0xBD9AD9BD, 0xABDACEBC, 0xDBCD0000 + ]], + l3_tab: [ + [ + 0xF3824968, 0xA24946A8, 0x9B78A89A, 0x9AA14936, 0xA78A36A5, 0x7A89A89A, 0x89A99957, 0xA68B89B6, + 0x8B78B99B, 0x89B9ABAA, 0xA79A89A8, 0x9989A89A, 0x89999999, 0x98880000 + ], [ + 0xF4B16C9B, 0xE36D58DA, 0xBE9BEABE, 0xCCE05B47, 0xD9BE47C7, 0x8CABEABE, 0xABECCE68, 0xB8ADBCE8, + 0x9D9ACCCE, 0xBCEBDEDE, 0xEAABBBCD, 0xEEBCDBCD, 0xDDECDEDD, 0xEDDE0000 + ]], + esc_tab: [ 0x02233455, 0x56667788, 0x88999AAA, 0x999BDDDD ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF8484878, 0x6A7A7A89, 0xDECDCDBA, 0x4A597A89, + 0x7B8A8B99, 0xDECDCDBA, 0x8E8BAD99, 0xAE8BBD9A, + 0xDEBCCDAA, 0x4A7A5989, 0x7B8B8A99, 0xDECDCDBA, + 0x6C7B8B89, 0x8C8B8B99, 0xDECDBDBA, 0xAE9CBD9A, + 0xAE9CBD9A, 0xDEBCCDA9, 0x8EAC7B99, 0x9EBD8B9A, + 0xDECEBCAA, 0xAEAD9C99, 0xAEBD9C9A, 0xDECDBCA9, + 0xCEBDBDA9, 0xCEBDBD99, 0xEEBCBC98, 0x29595989, + 0x7B8A8A99, 0xDECDCDBA, 0x4B6A7A89, 0x7C8B8B99, + 0xDECDCDBA, 0x8E8BAC99, 0xAE8BBD9A, 0xDEBCCEA9, + 0x5B7A6A89, 0x7C9B8A99, 0xDECDCCBA, 0x6C8B8B99, + 0x8C8B8B99, 0xDECDCDBA, 0x9E9CAD99, 0xAE9BBD99, + 0xDEACCDA9, 0x8EAC7B99, 0xAEBD8B99, 0xDECEBCA9, + 0x9EAD9C99, 0xAEAD9C9A, 0xDECDACA9, 0xCEBDBD99, + 0xCEACBC99, 0xDEACBC98, 0x5C7B7B99, 0x9D9B9BAA, + 0xEEDDDDBB, 0x6C7B8B9A, 0x9D9BACAA, 0xEEDDDDBB, + 0x9E8CAC99, 0xAE9CBDAA, 0xEEBDDEAA, 0x6C8B8B9A, + 0x9D9C9CAA, 0xEEDDDDBB, 0x7D8B8C9A, 0x9D9C9CAA, + 0xEECDCDBA, 0x9E9CAD9A, 0x9E8CBDAA, 0xDEACCEA9, + 0x9EAC8B99, 0xAEBD9CAA, 0xDEDEBCAA, 0x9EAD9C9A, + 0x9EBD9CAA, 0xDECEACA9, 0xBEBDBD99, 0xAEACAC99, + 0xCEABAC88, 0x8D9C9C99, 0xAEACAC9A, 0xEEDDCDB9, + 0x8D9C8C99, 0xAEACAC99, 0xEEDDCDB9, 0x9D8B9B88, + 0xAE9CAC88, 0xDEBCCC98, 0x8E8C9C99, 0xAEACACAA, + 0xEEDDCDB9, 0x7E8C8C99, 0x9EAC9C9A, 0xEECDCDA9, + 0x8E8B9B88, 0x9E8B9C88, 0xCEABBC98, 0x9E9B8B88, + 0xAE9C9C88, 0xDECCBC98, 0x9E9B8B88, 0x9E9B8B88, + 0xDEBCAB98, 0x9E8B9B77, 0x8D8A8A77, 0x9D798965, + ], [ + 0xFA5C5BAD, 0x7CAD9DCE, 0xEEEEEEEE, 0x4D7D9EBD, + 0x8EAEBEDE, 0xEEEEEEEE, 0x9EAEDEDE, 0xCECEEEEE, + 0xEEEEEEEE, 0x3D9E7DBE, 0x8EBEAEDE, 0xEEEEEEEE, + 0x7EAEAECE, 0x9EBEBEDE, 0xEEEEEEEE, 0xBECEDEDE, + 0xCECEEEEE, 0xEEEEEEEE, 0x9EDEAEDE, 0xBEEEBEEE, + 0xEEEEEEEE, 0xBEDEBEDE, 0xCEEECEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x0B6C6CBC, + 0x7CAD9DCE, 0xEEEEEEEE, 0x4D7D9EBD, 0x8EAEBEDE, + 0xEEEEEEEE, 0x9E9ECECE, 0xCEBEEEEE, 0xEEEEEEEE, + 0x4D9E7DBD, 0x8EBEAEDE, 0xEEEEEEEE, 0x6EAE9ECE, + 0x8EBEAECE, 0xEEEEEEEE, 0xBEBEDEDE, 0xCECEDEDE, + 0xEEEEEEEE, 0x9ECE9EDE, 0xBEEEBEEE, 0xEEEEEEEE, + 0xAEDEBEDE, 0xBEEEBEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x3D8D7DBD, 0x8DAEAEDE, + 0xEEEEEEEE, 0x5E8E9ECD, 0x9EBEBEDE, 0xEEEEEEEE, + 0x9E9ECECE, 0xCECEEEEE, 0xEEEEEEEE, 0x5E9E8ECE, + 0x9ECEBEDE, 0xEEEEEEEE, 0x7EAEAECE, 0x9EBEBEDE, + 0xEEEEEEEE, 0xAEBEDEDE, 0xBEBEDEDE, 0xEEEEEEEE, + 0x8ECE9ECE, 0xBEEEBEDE, 0xEEEEEEEE, 0xAEDEBEDE, + 0xBEDEBEDE, 0xEEEEEEEE, 0xDEEEEEEE, 0xDEEEEEEE, + 0xEEEEEEEE, 0x5D9E8EBD, 0x9EBEAECD, 0xEEEEEEEE, + 0x6E9E9EBD, 0xAEBEBECE, 0xEEEEEEEE, 0x8E9EAEBD, + 0xBEBECECD, 0xEEEEEEDE, 0x6E9E9EBD, 0xAEBEAECE, + 0xEEEEEEEE, 0x7EAE9EBD, 0x9EBEAECD, 0xEEEEEEEE, + 0x8E9EBEBD, 0xAEAEBEBD, 0xEEDEEEDE, 0x8EAE9EBD, + 0xBECEBECD, 0xEEEEEEDE, 0x8EBE9EBD, 0xAEBEAEBD, + 0xEEEEDEDE, 0xAEBEBEAC, 0xAEBDBDBC, 0xCECDBDBC, + ]], + l12_tab: [ + [ + 0xF4925967, 0x93595697, 0x79789889, 0x88915935, 0x96794695, 0x69779789, 0x88988846, 0x95796795, + 0x7A67A779, 0x78988988, 0x86796796, 0x78689679, 0x77878878, 0x87760000 + ], [ + 0xF5D26E7A, 0xE27D68E9, 0xBE8BEACE, 0xCDD05C37, 0xD7AE48E6, 0x8D9BE9BE, 0xABEEEE48, 0xD69D9BE6, + 0x9E7AEACE, 0xACEBCEED, 0xE7AD8AEA, 0xCE8BE9BE, 0xBCEBCEBC, 0xEDCE0000 + ]], + l3_tab: [ + [ + 0xF4926968, 0xA26946A7, 0x8A78A78A, 0x89915936, 0x968A3695, 0x7978A78A, 0x78A89946, 0x957A78A5, + 0x7A68A89A, 0x89A89A99, 0x96797898, 0x99789789, 0x89989989, 0x98880000 + ], [ + 0xF3B27C9D, 0xD26D57C9, 0xBC8BD9CD, 0xBCD04B48, 0xCACD47B6, 0x8DBBD9DD, 0xABCDBD57, 0x989CDCC7, + 0xAC9BCCDD, 0xBBDBDDDD, 0xD99BDDDD, 0xDDBBCBAD, 0xDDDDDDCD, 0xDDDD0000 + ]], + esc_tab: [ 0x01244556, 0x6778999A, 0xAABBCCCC, 0xCCCEEEFF ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF8494978, 0x6A7A7A89, 0xDECDCDBB, 0x4B597A89, + 0x7C7A8B99, 0xDECDCDBB, 0x8E8BAD9A, 0xAE8BBDAA, + 0xDEBCCEAA, 0x3A7A5989, 0x7B8B7A99, 0xDECDCDBB, + 0x6C8A8B89, 0x7C8B8B99, 0xDECDBDBA, 0xAE9CBD9A, + 0xAE9CBDAA, 0xEEBCCEAA, 0x8EAD8B99, 0x9EBD8B9A, + 0xDECEBCAA, 0xAEBD9C9A, 0xAEBD9CAA, 0xDECDBCAA, + 0xCEBDBDAA, 0xCEBDBDA9, 0xEEBDBDA9, 0x2A595989, + 0x7B8A8A99, 0xEECDCCBB, 0x4B6A7A89, 0x7C8B8B99, + 0xEECDCDBB, 0x8E8BAD99, 0xAE8BBD9A, 0xDEBCCEAA, + 0x4B7A6A89, 0x7C9B8B99, 0xEECDCCBB, 0x6C8B7B89, + 0x7C8B8B99, 0xDEBDCDBA, 0x9E9CAD9A, 0xAE8BBD9A, + 0xDEACCDAA, 0x8EAC7B99, 0xAEBD8B9A, 0xDECEBCAA, + 0xAEAD9C9A, 0xAEAD8C9A, 0xDECDACAA, 0xCEBDBDA9, + 0xBEBDBD99, 0xDEACBC98, 0x5C7B7B99, 0x9D9B9BAA, + 0xEEDDDDBB, 0x6C7B8B9A, 0x9D9B9CAA, 0xEEDDDEBB, + 0x9E8CAC9A, 0xAE9CBDAA, 0xEECDDEBA, 0x6D8B8B9A, + 0x9D9C9CAA, 0xEEDDDDCB, 0x7D8B8C9A, 0x8D9C9CAA, + 0xEECECEBB, 0x9E9CAD9A, 0x9E8CBDAA, 0xDEACCEAA, + 0x9EAD8C9A, 0xAEBD9CAA, 0xEEDECDBA, 0x9EBD9CAA, + 0x9EBD9C9A, 0xDECEBCAA, 0xBEBDBDA9, 0xAEACAD99, + 0xCEACAC98, 0x7E9C9C9A, 0xAEACACAA, 0xEEDDCDBA, + 0x8E9C8C9A, 0xAEACACAA, 0xEEDDDDBA, 0x9E8B9C89, + 0xBE9CAC99, 0xEECCCD99, 0x8E9C9C9A, 0xAEACACAA, + 0xEEDDDDBA, 0x7E9C8C9A, 0x9EAC9C9A, 0xEECDDDBA, + 0x8E8B9C89, 0x9E8B9C89, 0xDEABBC98, 0x9E9C8C89, + 0xAEAC9C99, 0xDECDBC98, 0x9E9C8C89, 0x9EAC8C99, + 0xDECCAC98, 0x9E9B9B77, 0x8D8A8B77, 0x9D898A76, + ], [ + 0xFA6C6CBD, 0x7CAEAEDE, 0xEEEEEEEE, 0x3D7E9ECE, + 0x8EAEBEDE, 0xEEEEEEEE, 0x9EAEDEEE, 0xCECEEEEE, + 0xEEEEEEEE, 0x3D9E7DCE, 0x8DCEAEDE, 0xEEEEEEEE, + 0x7EAEAECE, 0x9EBEBEEE, 0xEEEEEEEE, 0xBECEEEEE, + 0xDEDEEEEE, 0xEEEEEEEE, 0x9EDEAEDE, 0xCEEECEEE, + 0xEEEEEEEE, 0xBEEECEEE, 0xDEEECEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x0B6C6CBD, + 0x7CAEADDE, 0xEEEEEEEE, 0x4E7E9ECE, 0x8EAEBEDE, + 0xEEEEEEEE, 0x9EAEDEEE, 0xCECEEEEE, 0xEEEEEEEE, + 0x4E9E7DCE, 0x8ECEAEDE, 0xEEEEEEEE, 0x6EAEAECE, + 0x8EBEBEDE, 0xEEEEEEEE, 0xBECEDEDE, 0xCECEEEEE, + 0xEEEEEEEE, 0x9EDE9EDE, 0xCEEECEEE, 0xEEEEEEEE, + 0xBEDEBEEE, 0xCEEECEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x3D8E8ECE, 0x8DBEAEDE, + 0xEEEEEEEE, 0x5E8E9ECE, 0x9EBECEDE, 0xEEEEEEEE, + 0x9EAECEDE, 0xCECEEEEE, 0xEEEEEEEE, 0x5E9E8ECE, + 0x9ECEBEDE, 0xEEEEEEEE, 0x7EAEAECE, 0x9ECEBEDE, + 0xEEEEEEEE, 0xAEBEDEDE, 0xBEBEEEEE, 0xEEEEEEEE, + 0x8ECE9EDE, 0xCEEECEEE, 0xEEEEEEEE, 0xAEDEBEEE, + 0xBEEEBEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xDEEEEEEE, + 0xEEEEEEEE, 0x5E9E8EBE, 0x9EBEAECE, 0xEEEEEEEE, + 0x6E9E9EBE, 0xAEBEBECE, 0xEEEEEEEE, 0x8E9EBEBE, + 0xBEBECECE, 0xEEEEEEEE, 0x6E9E9EBE, 0xAEBEBECE, + 0xEEEEEEEE, 0x7EAE9EBE, 0x9EBEBECE, 0xEEEEEEEE, + 0x9EAEBEBE, 0xAEAECECE, 0xEEEEEEEE, 0x8EBE9EBE, + 0xBEDEBECE, 0xEEEEEEEE, 0x9EBEAECE, 0xAECEAECE, + 0xEEEEDEEE, 0xAEBEBEBD, 0xAEBEBEBD, 0xDECECECD, + ]], + l12_tab: [ + [ + 0xF4925967, 0xA3595697, 0x89789889, 0x99915935, 0x96793695, 0x69779789, 0x78998946, 0x957A68A5, + 0x7A67A78A, 0x78A88A98, 0x96796897, 0x89689779, 0x77878978, 0x97770000 + ], [ + 0xF5D26D7A, 0xD27D68D9, 0xBD8BDACD, 0xDDD05C37, 0xD8AD47D6, 0x8DABD8BD, 0xBCDDDD47, 0xD69D9CD6, + 0x9D8ADBBD, 0xACDBDDDD, 0xD7AD8BDA, 0xDD8BD9BD, 0xCCDBDDCD, 0xDDCD0000 + ]], + l3_tab: [ + [ + 0xF4925A68, 0xB25A46A7, 0x8A78A78A, 0x99A14936, 0x978B36A5, 0x6A78A78A, 0x88A99A46, 0x957A89B5, + 0x7A68A89B, 0x89B89B9A, 0xA78978A9, 0x9A78A89A, 0x99A99A99, 0xA9990000 + ], [ + 0xF3D26DAE, 0xE26E58BA, 0xBEADDBDD, 0xDDD04848, 0xDADD47D6, 0x8DBDDDBD, 0xDDDBDD56, 0x979DBBD8, + 0xADABDDDD, 0xBDDADDDD, 0xDB9BBBDD, 0xDDDBDDDD, 0xDDDDDDDD, 0xDDDD0000 + ]], + esc_tab: [ 0x01234577, 0x8899ABBB, 0xCCDDDEEE, 0xEEEEEFFE ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF8494989, 0x6A7A7A9A, 0xEEDEDDCC, 0x3B5A7A89, + 0x7C8B8B9A, 0xEECDDECC, 0x9E8CBDAB, 0xAE9CBEAB, + 0xEECDDECC, 0x3A7A5A89, 0x7B8B8A9A, 0xEEDEDDCC, + 0x6C8B8B9A, 0x7C8B8B9A, 0xDECECDBC, 0xAEADBEAB, + 0xBE9DBEAB, 0xEECDDECC, 0x8EBD8CAA, 0xAECE9CAB, + 0xEEEECDCC, 0xAEBD9DAB, 0xBECEADAB, 0xEEEECDBB, + 0xDECECEBB, 0xDECECEBB, 0xEEDEDEBB, 0x1A5A5989, + 0x7B8B8A9A, 0xEEDDDDCC, 0x4B6A7A89, 0x7C8B9B9A, + 0xEECDDECC, 0x8E8CAD9A, 0xAE9CBDAB, 0xEECDEECB, + 0x4B7B6A89, 0x7C9B8B9A, 0xEEDECDCC, 0x6C8B8B9A, + 0x7C8B8B9A, 0xEECDCEBC, 0xAE9DBDAB, 0xAE9CBDAB, + 0xEEBDDEBB, 0x8EBD7C9A, 0xAEBE9CAB, 0xEEEECDCB, + 0xAEBD9DAB, 0xAEBE9CAB, 0xEEDEBDBB, 0xCECECEBB, + 0xCEBDCEBB, 0xEECDCDBA, 0x5C7B7B9A, 0x9D9C9CAB, + 0xEEEEDECC, 0x6D7C8C9A, 0x9E9CACAB, 0xEEDEEEDC, + 0x9E8CADAB, 0xBEADCEBB, 0xEEDEEECC, 0x6D8C8C9A, + 0x9DAD9CAB, 0xEEEEDECC, 0x7D9C8CAB, 0x8E9C9CAB, + 0xEEDEDECC, 0x9E9DBDAB, 0x9E8DBDAB, 0xEEBDEECB, + 0x9EAD8CAA, 0xBECEADAB, 0xEEEEDECC, 0xAEBE9DAB, + 0xAEBE9CAB, 0xEEEECDCB, 0xCECECEBB, 0xBEBDBDBB, + 0xCEBCBDAA, 0x7E9D9DAB, 0xAEBDADAB, 0xEEEEDECB, + 0x8E9D9CAB, 0xAEADADAB, 0xEEEEEECB, 0x9E9CAC9A, + 0xBEADADAA, 0xEEDDDEBA, 0x8E9D9DAB, 0xBEADADAB, + 0xEEEEEECB, 0x8E9D9DAB, 0xAEADADAB, 0xEEDEDECB, + 0x8E8CAC9A, 0xAE8CAD9A, 0xEEBDCDBA, 0x9EAC9D9A, + 0xBEBDADAA, 0xEEDEDDBA, 0x9EAD9D9A, 0xAEAD9D9A, + 0xEEDDCDBA, 0x9E9CAC89, 0x9E9B9C99, 0xBEAAAB98, + ], [ + 0xFB6D6DCD, 0x7CADAEDE, 0xEEDDDDDD, 0x4D7DADDD, + 0x9DBDDDDD, 0xDDDDDDDD, 0xADADDDDD, 0xCDDDDDDD, + 0xDDDDDEEE, 0x3EAE7EDE, 0x9ECEBEEE, 0xEEEEEEEE, + 0x7EBEBECE, 0x9ECECEEE, 0xEEEEEEEE, 0xCEDEEEEE, + 0xDEDEEEEE, 0xEEEEEEEE, 0x9EEEAEEE, 0xDEEECEEE, + 0xEEEEEEEE, 0xCEEECEEE, 0xDEEEDEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x0C7D6ECE, + 0x7CBEAEEE, 0xEEEEEEEE, 0x4E8E9ECE, 0x9EBECEEE, + 0xEEEEEEEE, 0x9EAEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, + 0x4EAE7EDE, 0x9ECEBEEE, 0xEEEEEEEE, 0x7EBEAEDE, + 0x8ECEBEEE, 0xEEEEEEEE, 0xBECEEEEE, 0xCECEEEEE, + 0xEEEEEEEE, 0x9EEEAEEE, 0xCEEECEEE, 0xEEEEEEEE, + 0xBEEECEEE, 0xCEEECEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x2E8E8ECE, 0x8DBEBEDE, + 0xEEEEEEEE, 0x5E9E9EDE, 0xAECEDEEE, 0xEEEEEEEE, + 0x9EAEDEEE, 0xCEDEEEEE, 0xEEEEEEEE, 0x5EAE8ECE, + 0xAEDEBEEE, 0xEEEEEEEE, 0x7EBEAEDE, 0x9ECECEEE, + 0xEEEEEEEE, 0xBECEEEEE, 0xCECEEEEE, 0xEEEEEEEE, + 0x9EEE9EEE, 0xCEEECEEE, 0xEEEEEEEE, 0xBEEEBEEE, + 0xBEEECEEE, 0xEEEEEEEE, 0xDEEEEEEE, 0xDEEEEEEE, + 0xEEEEEEEE, 0x5E9E9ECE, 0x9EBEBEDE, 0xEEEEEEEE, + 0x6E9E9ECE, 0xAECEBEDE, 0xEEEEEEEE, 0x9EAEBECE, + 0xDECECEDE, 0xEEEEEEEE, 0x6EAE9ECE, 0xAECEBEDD, + 0xDDDDDDDD, 0x7DAD9DCD, 0xADCDBDDD, 0xDDDDDDDD, + 0x9DADCDCD, 0xBDBDCDDD, 0xDDDDDDDD, 0x8DBD9DCD, + 0xCDDDBDDD, 0xDDDDDDDD, 0x9DCDADCD, 0xBDCDADDD, + 0xDDDDDDDD, 0xADCDCDCD, 0xBDDDBDCD, 0xDDDDDDDD, + ]], + l12_tab: [ + [ + 0xF5B26B79, 0xC36B57B8, 0x9B89B99B, 0xABC05A36, 0xB78C47B5, 0x7B89B79B, 0x99BAAB57, 0xB68B89C6, + 0x8B68B99C, 0x8AB99CAA, 0xB79B89B8, 0x9B89B89B, 0x99B9AB99, 0xB9AA0000 + ], [ + 0xF5D27E8B, 0xE27E68EA, 0xBE9CDBDE, 0xEEE06B37, 0xC9BC38E7, 0x8EBCE9CE, 0xBDEDED48, 0xC69EABC6, + 0xAE8BEBEE, 0x9CDCCDCE, 0xE8AD9CEA, 0xCD8CEABE, 0xCEECCEBC, 0xDDDD0000 + ]], + l3_tab: [ + [ + 0xF4B26B8A, 0xC26B57B8, 0xAC89C99D, 0xABC05A46, 0xB8AC47A5, 0x7B9AC8AC, 0x9ACBBC57, 0xB78B9BC7, + 0x8B79BABD, 0x9BCABCBC, 0xD89B9ABC, 0xCC9ABABC, 0xBCCBBCBB, 0xDBCC0000 + ], [ + 0xF4D29DDD, 0xD27D57D8, 0xDD8DDDDD, 0xDDD04D48, 0xD7DD38D6, 0xDDDDDDDD, 0xDDDDDD46, 0xD88DDDDD, + 0xDD9DDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDD9DDDDD, 0xEEEEEEEE, 0xDDDD0000 + ]], + esc_tab: [ 0x01234577, 0x8899ABBD, 0xDDDDDDDD, 0xDDDDDEED ], + }, +]; +const RV60_INTER_COEFFS_CB_DESC: [CoeffsCBDesc; NUM_INTER_SETS] = [ + CoeffsCBDesc { + l0_tab: [ + [ + 0xF5354544, 0x57676765, 0xACAABA97, 0x57566765, + 0x79788876, 0xCDBBCBA8, 0x9B89AA87, 0xBDAABB98, + 0xDECCDDB9, 0x57676765, 0x79888876, 0xCDBBCBA8, + 0x79788876, 0x9B999987, 0xDECBCCA8, 0xBDAABB98, + 0xDEBBCCA8, 0xEEDDDDB9, 0x9B9A9A87, 0xBDBBBB98, + 0xDECCDCA8, 0xBDABBB98, 0xDECBCBA8, 0xEEDDDDB9, + 0xCEBCCCA8, 0xEEDDDDB9, 0xEEDDEDB8, 0x47565765, + 0x79788876, 0xBDBBBBA8, 0x69787876, 0x9B999987, + 0xDEBBCCA8, 0xAC9ABB98, 0xCEBBCCA8, 0xEECCDDB9, + 0x69787876, 0x9B999987, 0xDECCCCA8, 0x8A899987, + 0xACAAAA97, 0xEECCDCB9, 0xCDABCCA8, 0xDEBCCCA8, + 0xEEDDEDB9, 0xACAAAA97, 0xCEBBBBA8, 0xEEDDDCB9, + 0xCEBBBBA8, 0xDECCCCA8, 0xEEDDDDB9, 0xDECCDDB9, + 0xEEDDDDB9, 0xEEDDEDB8, 0x7A898987, 0xACAAAB98, + 0xDECCDDB9, 0x9B9AAA98, 0xCDBBBBA8, 0xEEDDEDB9, + 0xBEABCCA9, 0xDECCDDB9, 0xEEDDEECA, 0x9CAA9A98, + 0xCDBBBBA8, 0xEEDDEDB9, 0xBDABBBA8, 0xCECCCCA9, + 0xEEEDEDCA, 0xDEBCDDB9, 0xEECCDDB9, 0xEEEEEEC9, + 0xBEBCBBA9, 0xDEDDCCB9, 0xEEEEEDC9, 0xDECCCCB9, + 0xEEDDDDB9, 0xEEEEEEC9, 0xEEDDDDB9, 0xEEDDEEB9, + 0xEEEDEEB9, 0xACABABA9, 0xCECCCCB9, 0xEEDDEECA, + 0xBDBBBCA9, 0xDECCDDB9, 0xEEEEEECA, 0xCEBCCDA9, + 0xEECCDDB9, 0xEEDDEEB9, 0xBDBCBCA9, 0xDECDCCB9, + 0xEEEEEECA, 0xCECCCCB9, 0xEEDDDDBA, 0xEEEEEECA, + 0xDECCDDB9, 0xEECDEDB9, 0xEEDDEEB9, 0xCECDBCA9, + 0xEEDDCCB9, 0xEEEEEDB9, 0xDEDDCCB9, 0xEEDDDDB9, + 0xEEEEEDB9, 0xEECDDDA8, 0xEEDDDDA8, 0xEECCDCA7, + ], [ + 0xF5263656, 0x48687978, 0xCECCDDBB, 0x38576978, + 0x7A899A99, 0xEEDDDECB, 0xADABCDAA, 0xCEBCDEBB, + 0xEEEEEEED, 0x48686878, 0x7A899A99, 0xEEDDDECB, + 0x7A899A99, 0xACAAABAA, 0xEEDDEECC, 0xCEBCDEBB, + 0xEEDDEECC, 0xEEEEEEED, 0xBDBCACBA, 0xDECDCDCB, + 0xEEEEEEED, 0xCECDCDBB, 0xEEDDDECC, 0xEEEEEEED, + 0xEEEEEEDD, 0xEEEEEEED, 0xEEEEEEEE, 0x17475867, + 0x69798988, 0xDECCDDCB, 0x59687988, 0x8B9AAB99, + 0xEEDDEECB, 0xBDABCDBA, 0xDECCDECB, 0xEEEEEEED, + 0x59797988, 0x8B9A9B99, 0xEEDDEECC, 0x8B8A9B99, + 0xACABBCAA, 0xEEDDEEDC, 0xDECCDECB, 0xEECDEECC, + 0xEEEEEEED, 0xBEBCACBB, 0xDEDDCDCB, 0xEEEEEEED, + 0xDECDCDCB, 0xEEDEDECC, 0xEEEEEEED, 0xEEEEEEDD, + 0xEEEEEEED, 0xEEEEEEED, 0x6A898A99, 0xACABBCAA, + 0xEEEEEEDC, 0x8C9AACAA, 0xBDBCCDBB, 0xEEEEEEDD, + 0xCEBDDECB, 0xEEDDEEDC, 0xEEEEEEEE, 0x9C9B9BAA, + 0xBDBCBCBB, 0xEEEEEEDD, 0xADBBBCBA, 0xCECCCDBB, + 0xEEEEEEED, 0xEEDDEEDC, 0xEEDEEEDC, 0xEEEEEEED, + 0xCEDDBDCB, 0xEEEEDEDC, 0xEEEEEEEE, 0xEEEEDECC, + 0xEEEEDEDC, 0xEEEEEEED, 0xEEEEEEED, 0xEEEEEEED, + 0xEEEEEEED, 0x9DACBDBB, 0xCECDDECB, 0xEEEEEEED, + 0xBEBCCDBB, 0xDEDDDECC, 0xEEEEEEED, 0xDECDEECC, + 0xEEDEEEDC, 0xEEEEEEED, 0xBECCBDBB, 0xDEDDDECC, + 0xEEEEEEED, 0xCECDCECC, 0xEEDEEECC, 0xEEEEEEED, + 0xDEDEEEDC, 0xEEDEEEDC, 0xEEEEEEED, 0xCEDEBECC, + 0xEEEEDEDC, 0xEEEEEEED, 0xDEEEDECC, 0xEEEEDEDC, + 0xEEEEEEED, 0xEEEEEEDC, 0xEEEEEEDC, 0xEEEEEECB, + ]], + l12_tab: [ + [ + 0xF3624757, 0x82474577, 0x78568678, 0x78824735, 0x86784575, 0x68788678, 0x78888857, 0x86797896, + 0x79789899, 0x78989999, 0x979989A8, 0x9989989A, 0x99989989, 0x98880000 + ], [ + 0xF3815978, 0xB2594698, 0x9B78A89B, 0xABC14936, 0x979B4695, 0x7A99B79B, 0x89BBBC68, 0xA78B9AC7, + 0x8B89BABC, 0x9ACABCCC, 0xC9ACABDB, 0xCD9BCABD, 0xBCDABDBC, 0xDCCC0000 + ]], + l3_tab: [ + [ + 0xF3624757, 0x82474586, 0x78578778, 0x78824735, 0x76784575, 0x68789678, 0x78989847, 0x86797896, + 0x79789899, 0x79989999, 0x979A89A8, 0x9989A99A, 0x9999AA9A, 0xA9980000 + ], [ + 0xF2915A69, 0xC25A47B8, 0xAD89C9AD, 0xCCE15A36, 0xB79D47B6, 0x8B9AD9AD, 0xABDCDE68, 0xB79CACE8, + 0x9C9ADBCE, 0xBCEBCEDD, 0xEABDBCED, 0xDEBCECDE, 0xDEEDDEDD, 0xEEEE0000 + ]], + esc_tab: [ 0x01235566, 0x788899AA, 0xABBBBBCC, 0xBBBCEEEE ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF5354544, 0x57676765, 0xACAABA97, 0x57566765, + 0x79788876, 0xCDBBCBA8, 0x9B89AA87, 0xBDAABB98, + 0xDECCDDB9, 0x57676765, 0x79888876, 0xCDBBCBA8, + 0x79788876, 0x9B999987, 0xDECBCCA8, 0xBDAABB98, + 0xDEBBCCA8, 0xEEDDDDB9, 0x9B9A9A87, 0xBDBBBB98, + 0xDECCDCA8, 0xBDABBB98, 0xDECBCBA8, 0xEEDDDDB9, + 0xCEBCCCA8, 0xEEDDDDB9, 0xEEDDEDB8, 0x47565765, + 0x79788876, 0xBDBBBBA8, 0x69787876, 0x9B999987, + 0xDEBBCCA8, 0xAC9ABB98, 0xCEBBCCA8, 0xEECCDDB9, + 0x69787876, 0x9B999987, 0xDECCCCA8, 0x8A899987, + 0xACAAAA97, 0xEECCDCB9, 0xCDABCCA8, 0xDEBCCCA8, + 0xEEDDEDB9, 0xACAAAA97, 0xCEBBBBA8, 0xEEDDDCB9, + 0xCEBBBBA8, 0xDECCCCA8, 0xEEDDDDB9, 0xDECCDDB9, + 0xEEDDDDB9, 0xEEDDEDB8, 0x7A898987, 0xACAAAB98, + 0xDECCDDB9, 0x9B9AAA98, 0xCDBBBBA8, 0xEEDDEDB9, + 0xBEABCCA9, 0xDECCDDB9, 0xEEDDEECA, 0x9CAA9A98, + 0xCDBBBBA8, 0xEEDDEDB9, 0xBDABBBA8, 0xCECCCCA9, + 0xEEEDEDCA, 0xDEBCDDB9, 0xEECCDDB9, 0xEEEEEEC9, + 0xBEBCBBA9, 0xDEDDCCB9, 0xEEEEEDC9, 0xDECCCCB9, + 0xEEDDDDB9, 0xEEEEEEC9, 0xEEDDDDB9, 0xEEDDEEB9, + 0xEEEDEEB9, 0xACABABA9, 0xCECCCCB9, 0xEEDDEECA, + 0xBDBBBCA9, 0xDECCDDB9, 0xEEEEEECA, 0xCEBCCDA9, + 0xEECCDDB9, 0xEEDDEEB9, 0xBDBCBCA9, 0xDECDCCB9, + 0xEEEEEECA, 0xCECCCCB9, 0xEEDDDDBA, 0xEEEEEECA, + 0xDECCDDB9, 0xEECDEDB9, 0xEEDDEEB9, 0xCECDBCA9, + 0xEEDDCCB9, 0xEEEEEDB9, 0xDEDDCCB9, 0xEEDDDDB9, + 0xEEEEEDB9, 0xEECDDDA8, 0xEEDDDDA8, 0xEECCDCA7, + ], [ + 0xF5263656, 0x48687978, 0xCECCDDBB, 0x38576978, + 0x7A899A99, 0xEEDDDECB, 0xADABCDAA, 0xCEBCDEBB, + 0xEEEEEEED, 0x48686878, 0x7A899A99, 0xEEDDDECB, + 0x7A899A99, 0xACAAABAA, 0xEEDDEECC, 0xCEBCDEBB, + 0xEEDDEECC, 0xEEEEEEED, 0xBDBCACBA, 0xDECDCDCB, + 0xEEEEEEED, 0xCECDCDBB, 0xEEDDDECC, 0xEEEEEEED, + 0xEEEEEEDD, 0xEEEEEEED, 0xEEEEEEEE, 0x17475867, + 0x69798988, 0xDECCDDCB, 0x59687988, 0x8B9AAB99, + 0xEEDDEECB, 0xBDABCDBA, 0xDECCDECB, 0xEEEEEEED, + 0x59797988, 0x8B9A9B99, 0xEEDDEECC, 0x8B8A9B99, + 0xACABBCAA, 0xEEDDEEDC, 0xDECCDECB, 0xEECDEECC, + 0xEEEEEEED, 0xBEBCACBB, 0xDEDDCDCB, 0xEEEEEEED, + 0xDECDCDCB, 0xEEDEDECC, 0xEEEEEEED, 0xEEEEEEDD, + 0xEEEEEEED, 0xEEEEEEED, 0x6A898A99, 0xACABBCAA, + 0xEEEEEEDC, 0x8C9AACAA, 0xBDBCCDBB, 0xEEEEEEDD, + 0xCEBDDECB, 0xEEDDEEDC, 0xEEEEEEEE, 0x9C9B9BAA, + 0xBDBCBCBB, 0xEEEEEEDD, 0xADBBBCBA, 0xCECCCDBB, + 0xEEEEEEED, 0xEEDDEEDC, 0xEEDEEEDC, 0xEEEEEEED, + 0xCEDDBDCB, 0xEEEEDEDC, 0xEEEEEEEE, 0xEEEEDECC, + 0xEEEEDEDC, 0xEEEEEEED, 0xEEEEEEED, 0xEEEEEEED, + 0xEEEEEEED, 0x9DACBDBB, 0xCECDDECB, 0xEEEEEEED, + 0xBEBCCDBB, 0xDEDDDECC, 0xEEEEEEED, 0xDECDEECC, + 0xEEDEEEDC, 0xEEEEEEED, 0xBECCBDBB, 0xDEDDDECC, + 0xEEEEEEED, 0xCECDCECC, 0xEEDEEECC, 0xEEEEEEED, + 0xDEDEEEDC, 0xEEDEEEDC, 0xEEEEEEED, 0xCEDEBECC, + 0xEEEEDEDC, 0xEEEEEEED, 0xDEEEDECC, 0xEEEEDEDC, + 0xEEEEEEED, 0xEEEEEEDC, 0xEEEEEEDC, 0xEEEEEECB, + ]], + l12_tab: [ + [ + 0xF3624757, 0x82474577, 0x78568678, 0x78824735, 0x86784575, 0x68788678, 0x78888857, 0x86797896, + 0x79789899, 0x78989999, 0x979989A8, 0x9989989A, 0x99989989, 0x98880000 + ], [ + 0xF3815978, 0xB2594698, 0x9B78A89B, 0xABC14936, 0x979B4695, 0x7A99B79B, 0x89BBBC68, 0xA78B9AC7, + 0x8B89BABC, 0x9ACABCCC, 0xC9ACABDB, 0xCD9BCABD, 0xBCDABDBC, 0xDCCC0000 + ]], + l3_tab: [ + [ + 0xF3624757, 0x82474586, 0x78578778, 0x78824735, 0x76784575, 0x68789678, 0x78989847, 0x86797896, + 0x79789899, 0x79989999, 0x979A89A8, 0x9989A99A, 0x9999AA9A, 0xA9980000 + ], [ + 0xF2915A69, 0xC25A47B8, 0xAD89C9AD, 0xCCE15A36, 0xB79D47B6, 0x8B9AD9AD, 0xABDCDE68, 0xB79CACE8, + 0x9C9ADBCE, 0xBCEBCEDD, 0xEABDBCED, 0xDEBCECDE, 0xDEEDDEDD, 0xEEEE0000 + ]], + esc_tab: [ 0x01235566, 0x788899AA, 0xABBBBBCC, 0xBBBCEEEE ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF4343444, 0x57676765, 0xBDBBBBA9, 0x47566765, + 0x79788877, 0xCECCCCB9, 0xAC9AAB98, 0xCEBBCCA9, + 0xEEDDEECA, 0x47575665, 0x79888877, 0xCECCCCB9, + 0x79788877, 0x9B9A9A98, 0xEEDDDDBA, 0xBEBBCCA9, + 0xDECCDDBA, 0xEEEEEECA, 0xACAB9A98, 0xCDBCBBA9, + 0xEEDDDDCA, 0xBEBCBBA9, 0xDECCCCBA, 0xEEEEEECA, + 0xEEDDDECA, 0xEEEEEECA, 0xEEEEEECA, 0x37565665, + 0x79788877, 0xCECCCCB9, 0x69787877, 0x9B999A88, + 0xDEDDDDBA, 0xAD9BBCA9, 0xCEBCCDB9, 0xEEEEEECA, + 0x69787877, 0x9B9A9988, 0xDEDDDDBA, 0x8B999988, + 0xACABAB98, 0xEEDDDDCA, 0xCEBCCCB9, 0xDECCDDBA, + 0xEEEEEECA, 0xBDBBABA9, 0xCECCBCB9, 0xEEEEEDCA, + 0xCECCBCA9, 0xDEDDCCBA, 0xEEEEEECA, 0xEEDEEECA, + 0xEEEEEECA, 0xEEEEEECA, 0x7A8A9A98, 0xADABBBA9, + 0xEEEEEEDB, 0x9C9BABA9, 0xCEBCCCBA, 0xEEEEEEDB, + 0xCEBCDDBA, 0xEECDEECB, 0xEEEEEEDB, 0x9CABABA9, + 0xCECCBCBA, 0xEEEEEEDB, 0xBDBCBCAA, 0xCECDCDBA, + 0xEEEEEEDB, 0xDECDDECB, 0xEEDDEECB, 0xEEEEEEDB, + 0xCECDBCBA, 0xEEDECDCA, 0xEEEEEEDB, 0xDEDECDCA, + 0xEEEEDDCB, 0xEEEEEEDB, 0xEEEEEECB, 0xEEEEEECB, + 0xEEEEEECA, 0xACACBCAA, 0xCECDCDBB, 0xEEEEEEDB, + 0xBEBCCDBA, 0xDEDDDDCB, 0xEEEEEEDB, 0xCEBCDDBA, + 0xEECDEECA, 0xEEEEEECA, 0xBECDBCBA, 0xDEDEDDCB, + 0xEEEEEEDB, 0xCECDCDBB, 0xEEDEDECB, 0xEEEEEEDB, + 0xDECDDEBA, 0xEEDDEECA, 0xEEEEEECA, 0xCEDDBCBA, + 0xEEEECDBA, 0xEEEEEECA, 0xDEDECDBA, 0xEEEECDCA, + 0xEEEEEECA, 0xEEDDDDB9, 0xEEDDDDB9, 0xEECDDDA8, + ], [ + 0xF4263657, 0x48687989, 0xCECDDEDD, 0x38586978, + 0x7A8A9B9A, 0xEEDEEEEE, 0xADACCECC, 0xDECEEEDD, + 0xEEEEEEEE, 0x38686878, 0x7A8A8A9A, 0xEEDEEEDE, + 0x7A8A9B9A, 0x9CACACBB, 0xEEEEEEEE, 0xDECEDEDD, + 0xEEDEEEEE, 0xEEEEEEEE, 0xBEBDADBC, 0xDEDECEDD, + 0xEEEEEEEE, 0xDEDECEDD, 0xEEEEDEDE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x17475868, + 0x69798A9A, 0xDEDEEEDD, 0x59698A89, 0x8B9BACAB, + 0xEEEEEEEE, 0xBEADDECC, 0xDECEEEDD, 0xEEEEEEEE, + 0x59797A89, 0x8B9B9BAB, 0xEEEEEEEE, 0x8B9B9BAB, + 0xADACBDBC, 0xEEEEEEEE, 0xDECEEEDE, 0xEEDEEEEE, + 0xEEEEEEEE, 0xBECEADCC, 0xDEEECEDD, 0xEEEEEEEE, + 0xDEDECEDD, 0xEEEEDEDE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x6A8A8B9A, 0x9CACBCBC, + 0xEEEEEEEE, 0x8C9BACAB, 0xBEBDCECD, 0xEEEEEEEE, + 0xCEBEDEDD, 0xEEDEEEEE, 0xEEEEEEEE, 0x8C9C9CAB, + 0xBECDBDCD, 0xEEEEEEEE, 0xAEBDBDCC, 0xBECECECD, + 0xEEEEEEEE, 0xEEDEEEEE, 0xEEDEEEEE, 0xEEEEEEEE, + 0xCEDEBECD, 0xEEEEDEDE, 0xEEEEEEEE, 0xDEEEDEDE, + 0xEEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x9DBDBDCC, 0xCECEDEDD, 0xEEEEEEEE, + 0xAEBECECD, 0xDEDEDEDD, 0xEEEEEEEE, 0xCECEDEDD, + 0xEEDEEEEE, 0xEEEEEEEE, 0xAECEBECD, 0xDEDEDEDD, + 0xEEEEEEEE, 0xBECECEDD, 0xDEDEDEDE, 0xEEEEEEEE, + 0xDEDEEEDD, 0xEEDEEEDE, 0xEEEEEEEE, 0xBEDEBECD, + 0xEEEEDEDD, 0xEEEEEEEE, 0xCEEECEDD, 0xDEEECEDD, + 0xEEEEEEEE, 0xEEEEEEED, 0xDEEEDEDD, 0xEEEEDEDC, + ]], + l12_tab: [ + [ + 0xF2724868, 0x92484688, 0x8A679789, 0x9AA14846, 0x978A4585, 0x6989A789, 0x88A9AA67, 0xA78A89B7, + 0x8A89A9AB, 0x89A9AAAA, 0xA8AB9AB9, 0xAA9AB9AB, 0xAAA9AA9A, 0xAA990000 + ], [ + 0xF2915A89, 0xD25A57B9, 0xBD79C9AD, 0xCDE14A46, 0xB8AD36B6, 0x7BABD8AC, 0xAADCDE68, 0xC8ADACE7, + 0x9D9ADBCE, 0x9BDBCDDD, 0xDABDBCDC, 0xDDACDBCD, 0xCDEBDECD, 0xDDDD0000 + ]], + l3_tab: [ + [ + 0xF2724868, 0x92484698, 0x9A68989A, 0x9AA14836, 0x978A4695, 0x7989A78A, 0x89AAAA58, 0xA78A9AB7, + 0x9A89BAAB, 0x9ABAABBB, 0xB9ABAABA, 0xBBABCABC, 0xBBBBBBBB, 0xBBBA0000 + ], [ + 0xF4B16C9B, 0xF27C69DB, 0xCFABFBDF, 0xEFF06C48, 0xDACF58D7, 0xAECDFBCF, 0xCDFEEF8A, 0xDABFDEFA, + 0xCFBCFEFF, 0xDEFEEFFF, 0xFDEFEEFF, 0xFFEFFEFF, 0xFFFFFFFF, 0xFFFE0000 + ]], + esc_tab: [ 0x01235566, 0x788899AA, 0xABBBBCCC, 0xBBBCDDDD ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF4243444, 0x47576766, 0xCDBCCCBA, 0x47566766, + 0x79798988, 0xDECDDDBA, 0xAD9BBCA9, 0xCEBCCDBA, + 0xEEDEEECB, 0x47575666, 0x79898888, 0xDECCCCBA, + 0x79798988, 0x9B9A9A99, 0xEEDDDDCB, 0xBEBCCDBA, + 0xDECDDEBB, 0xEEEEEECB, 0xACAB9A99, 0xBECCBBAA, + 0xEEDEDDCB, 0xBECCBCBA, 0xDECDCDBA, 0xEEEEEECB, + 0xEEDEDECB, 0xEEEEEECB, 0xEEEEEECB, 0x36565766, + 0x79798988, 0xDECDDDCA, 0x69687977, 0x9B9A9A99, + 0xEEDDDDCB, 0xAD9BBCAA, 0xCEBCDDBA, 0xEEEEEECB, + 0x69797877, 0x9B9A9A99, 0xEEDDDDCB, 0x8B9A9A99, + 0xACABABA9, 0xEEDEDECB, 0xCEBCCDBA, 0xDECDDECB, + 0xEEEEEECB, 0xADBC9BAA, 0xCECDBCBA, 0xEEEEEECB, + 0xCECDBCBA, 0xDEDECDBB, 0xEEEEEECB, 0xEEDEDECB, + 0xEEEEEECB, 0xEEEEEECA, 0x7B8A9A99, 0xADBCBCBA, + 0xEEEEEEDC, 0x9C9BABAA, 0xBEBCCDBB, 0xEEEEEEDC, + 0xBEACCEBB, 0xDECDEECB, 0xEEEEEEDC, 0x9CAB9BAA, + 0xBECDBCBB, 0xEEEEEEDC, 0xADBCBCBA, 0xCECDCDCB, + 0xEEEEEEDC, 0xDECDDECB, 0xDECEEECB, 0xEEEEEEDC, + 0xBECDACBA, 0xDEDECDCB, 0xEEEEEEDC, 0xDEDECDCB, + 0xDEEECDCB, 0xEEEEEEDB, 0xEEEEEEDB, 0xEEEEEECB, + 0xEEDEEECA, 0x9CACACBB, 0xCECDCDCB, 0xEEEEEEDC, + 0xAEBDBDBB, 0xDECEDECB, 0xEEEEEEDC, 0xBEBDCEBA, + 0xEECDDECB, 0xEEEEEECB, 0xAEBDBCBB, 0xDEDECDCB, + 0xEEEEEEDC, 0xBECDCDCB, 0xDEDEDECC, 0xEEEEEEDC, + 0xCECDDEBB, 0xDECDDECB, 0xEEDEEECA, 0xBECEACBA, + 0xDEDECDBB, 0xEEEEEECA, 0xCEDEBDBA, 0xDEDECDBB, + 0xEEEEDECA, 0xDECDCDBA, 0xDECDCDBA, 0xEECDCCA8, + ], [ + 0xF5262668, 0x4869799A, 0xEEEEEEEE, 0x38597A8A, + 0x7B9B9CAC, 0xEEEEEEEE, 0xBEBEDEDE, 0xDEDEEEEE, + 0xEEEEEEEE, 0x3869598A, 0x7B9C9BAC, 0xEEEEEEEE, + 0x7B9C9CAC, 0x9DBDBDCD, 0xEEEEEEEE, 0xDEDEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xBEDEAECE, 0xDEEECEEE, + 0xEEEEEEEE, 0xDEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x17485879, + 0x6A8B8BAB, 0xEEEEEEEE, 0x5A6A8B9B, 0x8CACADBD, + 0xEEEEEEEE, 0xBEBEDEDE, 0xDEDEEEEE, 0xEEEEEEEE, + 0x5A7B7A9B, 0x8CAD9CBC, 0xEEEEEEEE, 0x8CAC9CBC, + 0x9EBEBDCD, 0xEEEEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xBEDEAECE, 0xDEEECEEE, 0xEEEEEEEE, + 0xDEEEDEEE, 0xEEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x5B8C8CAC, 0xADBDBDCD, + 0xEEEEEEEE, 0x8D9DADBD, 0xBECECEDE, 0xEEEEEEEE, + 0xCEBEEEDE, 0xEEDEEEEE, 0xEEEEEEEE, 0x8DAD9DBC, + 0xBECEBEDE, 0xEEEEEEEE, 0x9EBEBECD, 0xBECECEDE, + 0xEEEEEEEE, 0xDEEEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, + 0xBEDEAEDE, 0xEEEEDEEE, 0xEEEEEEEE, 0xDEEEDEEE, + 0xDEEECEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x8EBEBECD, 0xCEDECEEE, 0xEEEEEEEE, + 0xAEBECECD, 0xDEDEDEEE, 0xEEEEEEEE, 0xBEBEDEDE, + 0xEEDEEEEE, 0xEEEEEEEE, 0x9ECEBECD, 0xCEEEDEEE, + 0xEEEEEEEE, 0xAECECEDE, 0xDEDEDEEE, 0xEEEEEEEE, + 0xCEDEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, 0xAEDEAECD, + 0xEEEEDEEE, 0xEEEEEEEE, 0xBEEECEDE, 0xDEEECEDE, + 0xEEEEEEEE, 0xDEEEEEEE, 0xDEEEDEEE, 0xEEDEDEDD, + ]], + l12_tab: [ + [ + 0xF2724878, 0xA2484698, 0x9A67989A, 0xAAA14846, 0x978A3695, 0x7A89A78A, 0x89AAAA68, 0xA78B9AB7, + 0x8B89B9AB, 0x89B9ABAA, 0xA8AB9AB9, 0xAB9AB9AB, 0xAAA9AB9A, 0xBAA90000 + ], [ + 0xF3B26C9B, 0xE25C58DB, 0xCE8ADABE, 0xEEE05B47, 0xD9BE37D7, 0x9DBCE8BE, 0xBCEEEE79, 0xD8BEBCE8, + 0xAEABECCE, 0xACECDEEE, 0xEACECDED, 0xEEBDECDE, 0xDEECEEDE, 0xEEEE0000 + ]], + l3_tab: [ + [ + 0xF2815979, 0xB24946A8, 0x9B79B99B, 0xABC15946, 0xA89B46A6, 0x8A9AB89B, 0x9ABBBC68, 0xB89BABC8, + 0x9B9ACABC, 0xABCBBCCC, 0xCABCABCB, 0xCCABCBCC, 0xBCCBCCBC, 0xCCCC0000 + ], [ + 0xF3D17EBD, 0xF27E6AFC, 0xEFBDFCEF, 0xFFF06D5A, 0xECEF59E9, 0xBEDFFCEF, 0xDFFFFF9B, 0xEBDFEFFB, + 0xDFCEFFFF, 0xEFFFFFFF, 0xFEEFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000 + ]], + esc_tab: [ 0x01235566, 0x788899AA, 0xAABBBCCC, 0xCBBCEEEE ], + }, + CoeffsCBDesc { + l0_tab:[ + [ + 0xF4252545, 0x47676777, 0xCECCCCBB, 0x47576877, + 0x7A898A99, 0xDEDDCDCB, 0xAD9BBDAA, 0xBEBCCDBB, + 0xEEDEDECB, 0x47675777, 0x7A898989, 0xDECDCDCB, + 0x7A898A89, 0x9C9BABAA, 0xEEDEDECB, 0xBEBDCDBB, + 0xDECDDECB, 0xEEEEEECC, 0x9DBC9BAA, 0xBECDACBB, + 0xEEDEDECB, 0xBECDBCBB, 0xCECECDBB, 0xEEEEDECB, + 0xDEDEDECB, 0xEEDEDECC, 0xEEEEEECB, 0x27575767, + 0x7A898999, 0xDEDDDDCB, 0x59697988, 0x9C9BABAA, + 0xEEDEDECC, 0xAE9CBDAA, 0xCEBDCEBB, 0xEEEEEEDC, + 0x59797988, 0x9B9B9AAA, 0xEEDEDECB, 0x8B9B9B9A, + 0x9DACACAA, 0xEEDEDECC, 0xCEBDCEBB, 0xCEBDDECB, + 0xEEDEEECC, 0xADBD9BAA, 0xCECDBCBB, 0xEEEEDECB, + 0xCECDBDBB, 0xCEDEBDBB, 0xEEEEDECB, 0xEEDEDECB, + 0xEEDEDECB, 0xEEEEDECB, 0x6B8B8B9A, 0xADBCACBB, + 0xEEEEEEDC, 0x8C9CACAA, 0xBEBDCDBB, 0xEEEEEEDC, + 0xBEADCEBB, 0xDECEDECC, 0xEEEEEEDC, 0x8CAC9BAA, + 0xBEBDBDBB, 0xEEEEEEDC, 0xAEBDBDBB, 0xBECDCDCB, + 0xEEEEEEDC, 0xCECEDECC, 0xDECEDECC, 0xEEDEEEDC, + 0xBECEACBB, 0xDEDECDCB, 0xEEEEEEDC, 0xCEDECDCB, + 0xDEDECDCC, 0xEEEEDEDC, 0xEEEEEECC, 0xDEDEDECC, + 0xEEDEDECB, 0x8DADACBB, 0xCECECDCB, 0xEEEEEEDC, + 0xAEBDBDBB, 0xCECECECC, 0xEEEEEEDC, 0xBEADCEBB, + 0xDECDDEBB, 0xEEEEEECB, 0xAEBDADBB, 0xCEDECDCC, + 0xEEEEEEDC, 0xAECEBDCB, 0xCEDECECC, 0xEEEEEEDC, + 0xBEBDCEBB, 0xCEBEDEBB, 0xEEDEEECB, 0xBECEACBA, + 0xDEDEBDBB, 0xEEEEDECB, 0xBECEBDBB, 0xCEDEBDBB, + 0xEEEEDECB, 0xCECDCDBA, 0xCEBDBDBA, 0xDEBCBCA9, + ], [ + 0xF5383879, 0x498B7BAC, 0xEEEEEEEE, 0x3A6A7BAC, + 0x8CADAECE, 0xEEEEEEEE, 0xCECEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x3A7B6A9C, 0x8CAD9DCE, 0xEEEEEEEE, + 0x7DAEADCD, 0xAECECEDE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xBEEEBEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x085A5A9B, + 0x6A9C9CBD, 0xEEEEEEEE, 0x5B7C9CBC, 0x9EBEBECE, + 0xEEEEEEEE, 0xCECEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0x5B9C7CAC, 0x9EBEAEDE, 0xEEEEEEEE, 0x8EBEAECE, + 0xAECEBEDE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xBEEEBEEE, 0xEEEEDEEE, 0xEEEEEEEE, + 0xEEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x6D9D9DCD, 0xAECECEEE, + 0xEEEEEEEE, 0x8EAEBECE, 0xBEDEDEEE, 0xEEEEEEEE, + 0xCECEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x8EBEAECE, + 0xBEDECEEE, 0xEEEEEEEE, 0xAECECEDE, 0xBEDECEEE, + 0xEEEEEEEE, 0xDEEEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, + 0xBEEEBEDE, 0xEEEEDEEE, 0xEEEEEEEE, 0xDEEEDEEE, + 0xDEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x8ECEBEDE, 0xCEDEDEEE, 0xEEEEEEEE, + 0xAECECEDE, 0xDEEEEEEE, 0xEEEEEEEE, 0xBECEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x9ECEBEDE, 0xDEEEDEEE, + 0xEEEEEEEE, 0xAEDEDEEE, 0xDEEEEEEE, 0xEEEEEEEE, + 0xCEDEEEEE, 0xDEDEEEEE, 0xEEEEEEEE, 0xAEDEBEDE, + 0xEEEEDEEE, 0xEEEEEEEE, 0xBEEECEEE, 0xDEEEDEEE, + 0xEEEEEEEE, 0xDEEEEEEE, 0xDEEEEEEE, 0xEEEEEEEE, + ]], + l12_tab: [ + [ + 0xF2825978, 0xB15956A9, 0x9B68A89B, 0xABB15946, 0xA79B46A6, 0x7A99B79B, 0x99BABB68, 0xB79B9AC7, + 0x9B89CAAC, 0x8ACAACBB, 0xB8AB9AC9, 0xAB9ACAAC, 0xAAB9ABAA, 0xBAAA0000 + ], [ + 0xF4D27EAC, 0xE16E69EC, 0xDE9BECDE, 0xEEE06D59, 0xEBDE49E8, 0xAECDE9CE, 0xCDEEEE7A, 0xE9CECEE9, + 0xCEACEDEE, 0xBDEDEEEE, 0xEBEECEEE, 0xEECEEDEE, 0xEEEDEEEE, 0xEEEE0000 + ]], + l3_tab: [ + [ + 0xF2815979, 0xB25946A8, 0x9B79B9AB, 0xBBC14946, 0xA89B46A6, 0x8A9AC89B, 0x9ACBBC68, 0xB79BABD8, + 0x9B9ACBBD, 0xABCBBCCC, 0xDABCABCB, 0xCDABCBCD, 0xCCDBCDCC, 0xDCCC0000 + ], [ + 0xF3D17FCF, 0xF27F6AFD, 0xFFBDFCEF, 0xFFF06D59, 0xFCFF59E9, 0xBFEFFDFF, 0xDFFFFF9B, 0xEBDFFFFB, + 0xDFCEFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000 + ]], + esc_tab: [ 0x01235566, 0x788899AA, 0xABBBBCCC, 0xBBBCDDDD ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF4352556, 0x47686878, 0xCECDCDBB, 0x38586878, + 0x7A8A8A99, 0xDEDDCDCB, 0x9E9CBDAB, 0xBEBCCDBB, + 0xEEDEDECC, 0x37685777, 0x7A8A7999, 0xDECDCDCB, + 0x6A8A8A99, 0x8C9B9BAA, 0xDEDEDDCC, 0xBEBDCDBB, + 0xCEBDCECB, 0xEEDEDECC, 0x9DAC8BAA, 0xBEBDACBB, + 0xEEDECECB, 0xBECDACBB, 0xCECEBDBB, 0xEEDEDECC, + 0xDEDEDECC, 0xEEDEDECC, 0xEEEEEECB, 0x27575777, + 0x6A8A8999, 0xDEDDCDCB, 0x5A697989, 0x8B9B9B9A, + 0xEEDEDECC, 0x9E9CBDAB, 0xCEBDCEBB, 0xEEDEEECC, + 0x59796989, 0x8B9B9A9A, 0xEEDEDDCC, 0x7B9B8B9A, + 0x9C9C9BAA, 0xEEDEDECC, 0xBEBDCDBB, 0xCEBDCEBB, + 0xEEDEEECC, 0x9EBD8BAA, 0xBECDACBB, 0xEEEEDECB, + 0xBECEACBB, 0xBECEBDBB, 0xEEEEDECB, 0xDEDEDECC, + 0xDEDEDECB, 0xEEDEDECB, 0x6B8B8B9A, 0x9DACACBB, + 0xEEEEEEDC, 0x7C9C9CAA, 0xAEBDBDBB, 0xEEEEEEDC, + 0xAEADBEBB, 0xCEBEDECC, 0xEEEEEEDC, 0x7C9C9BAA, + 0xAEBDACBB, 0xEEEEEEDC, 0x9DACACBB, 0xAEBDBDBB, + 0xEEEEEEDC, 0xBEBDCEBC, 0xCEBEDECC, 0xEEDEEEDC, + 0xAEBD9CAB, 0xCEDEBDBB, 0xEEEEEEDC, 0xBECEBDBB, + 0xCEDEBDCB, 0xEEEEDECC, 0xDEDEDECC, 0xDEDEDECC, + 0xEECECEBB, 0x8DAC9CAB, 0xBEBDBDBB, 0xEEEEEEDC, + 0x9DADADBB, 0xCECECDCB, 0xEEEEEEDC, 0xAEADBDAB, + 0xCEBDCEBB, 0xEEDEEECB, 0x9DBDACBB, 0xCECEBDCB, + 0xEEEEEEDC, 0xAEBDBDBB, 0xCECECECC, 0xEEEEEEDC, + 0xAEBDBEBB, 0xCEBDCEBB, 0xEEDEEECB, 0xAEBD9CAA, + 0xCECEBDBB, 0xEEEEDECB, 0xAECDADBB, 0xCECEBDBB, + 0xEEEEDDCB, 0xBEBEBDAA, 0xBEBDBDAA, 0xCEBCBCA9, + ], [ + 0xF638388A, 0x498B8BBD, 0xEEEEEEEE, 0x3A6B8CAC, + 0x8DADBEDE, 0xEEEEEEEE, 0xCECEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x3A8C6BAC, 0x8DBEADDE, 0xEEEEEEEE, + 0x8DAEAECE, 0xAECECEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xBEEECEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x095A5A9B, + 0x7B9D9DCE, 0xEEEEEEEE, 0x5C7D9DBD, 0x9EBECEDE, + 0xEEEEEEEE, 0xCECEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0x4C9D7CBD, 0x9ECEBEDE, 0xEEEEEEEE, 0x8EBEBEDE, + 0x9ECEBEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xBEEEBEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x5D9E9DCD, 0xAECECEEE, + 0xEEEEEEEE, 0x8EAEBEDE, 0xBEDEDEEE, 0xEEEEEEEE, + 0xCECEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0x7EBEAEDE, + 0xBEEECEEE, 0xEEEEEEEE, 0x9ECECEEE, 0xBEDEDEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xBEEEBEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xDEEEEEEE, + 0xDEEEDEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, + 0xEEEEEEEE, 0x7EBEBEDE, 0xCEEEDEEE, 0xEEEEEEEE, + 0x9ECECEEE, 0xDEEEEEEE, 0xEEEEEEEE, 0xBECEEEEE, + 0xEEEEEEEE, 0xEEEEEEEE, 0x9ECEBEEE, 0xDEEEDEEE, + 0xEEEEEEEE, 0xAEDECEEE, 0xDEEEEEEE, 0xEEEEEEEE, + 0xCEDEEEEE, 0xEEDEEEEE, 0xEEEEEEEE, 0xAEDEBEEE, + 0xEEEEDEEE, 0xEEEEEEEE, 0xCEEEDEEE, 0xDEEEDEEE, + 0xEEEEEEEE, 0xDEEEEEEE, 0xDEEEEEEE, 0xEEEEEEEE, + ]], + l12_tab: [ + [ + 0xF2825978, 0xB24956A8, 0x9B68A89B, 0xABB14936, 0xA79B36A5, 0x7A99B78B, 0x99BAAB58, 0xB68B8AC6, + 0x8B89B9AC, 0x8AC9ACBB, 0xB8AB9AC9, 0xAB8AB9AC, 0xAAB9ABAA, 0xBAAA0000 + ], [ + 0xF4D27EAD, 0xE16E69EC, 0xEE9CECEE, 0xEEE06E59, 0xEBEE49E8, 0xAEDDE9DE, 0xDEEEEE7A, 0xE9CECEE8, + 0xCEBCEEEE, 0xBEEEEEEE, 0xEBEEDEEE, 0xEECEEEEE, 0xEEEEEEEE, 0xEEEE0000 + ]], + l3_tab: [ + [ + 0xF2815979, 0xB25A46A9, 0xAC79B9AC, 0xBBC14946, 0xA8AC46A6, 0x8B9AC89C, 0x9ACBCC68, 0xB79CABD7, + 0x9C8ACBBD, 0xABDBBDCC, 0xD9ACABCB, 0xCDABCBCD, 0xCCDBCDCC, 0xDCCC0000 + ], [ + 0xF3D17FCF, 0xF27F6AFE, 0xEFBEFCEF, 0xEFF05F69, 0xFEFF59F9, 0xCFFFFDFF, 0xDFFFFF9A, 0xEBEFFFFB, + 0xCFCEFFFF, 0xFFFEFFFF, 0xFFEFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000 + ]], + esc_tab: [ 0x01235566, 0x7888999A, 0xABBBCCCC, 0xCBCDDEED ], + }, + CoeffsCBDesc { + l0_tab: [ + [ + 0xF5373667, 0x58796989, 0xDEDECECD, 0x39596989, + 0x6B8B8B9A, 0xDEDEDEDD, 0x9E9DBDBC, 0xBEBDCECD, + 0xEEEEEEDD, 0x38695889, 0x6A8B8A9A, 0xDEDEDEDD, + 0x6B8B8B9A, 0x8C9C9CAB, 0xEEDEDEDD, 0xBEBECEBC, + 0xCECEDECD, 0xEEEEEEDE, 0x9EBD9CAB, 0xAECEADCC, + 0xEEEEDEDD, 0xAECEBDBC, 0xCEDEBDCC, 0xEEEEEEDD, + 0xDEDEDEDD, 0xEEEEEEDD, 0xEEEEEEDD, 0x18585878, + 0x6A8A8A9A, 0xDEDEDEDD, 0x4A6A7A8A, 0x8C9B9CAB, + 0xEEEEDEDD, 0x9E9DBEBC, 0xBEBECECD, 0xEEEEEEED, + 0x4A7A6A8A, 0x7C9C8BAB, 0xEEEEDEDD, 0x6B8C8BAB, + 0x8C9C9CAB, 0xDEDEDEDD, 0xBEBECECD, 0xBEAECECD, + 0xEEDEEEDD, 0x9EBD8CAB, 0xBECEADBC, 0xEEEEDEDD, + 0xAECEADBC, 0xBECEADCC, 0xEEEEDEDD, 0xDEDEDEDD, + 0xDEDEDECD, 0xEEEEDEDD, 0x5B8B7B9A, 0x9DACACBC, + 0xEEEEEEEE, 0x7D8C9CAB, 0xAEBDBDBC, 0xEEEEEEEE, + 0x9E9DBEBC, 0xCEBEDECD, 0xEEEEEEEE, 0x7C9C8CAB, + 0xAEBDADBC, 0xEEEEEEEE, 0x8DADADBC, 0xAEBDBDBC, + 0xEEEEEEEE, 0xBEBECECD, 0xBEAECECD, 0xEECEEEDE, + 0x9EBE9DBC, 0xCECEBDCD, 0xEEEEEEEE, 0xAECEBECC, + 0xBECEADCD, 0xEEEEDEDD, 0xDEEEDEDD, 0xCEDEDECD, + 0xDECEDECD, 0x7DAD9DBC, 0xBEBEBDCC, 0xEEEEEEED, + 0x8EADADBC, 0xCECECECC, 0xEEEEEEDD, 0x9E9DBEBC, + 0xCEBEDECC, 0xEEEEEEDD, 0x8EBDADBC, 0xBECEBECC, + 0xEEEEEEDD, 0x9EBEAEBC, 0xBECECECC, 0xEEEEEEED, + 0xAEAEBEBC, 0xBEAECECC, 0xEEDEEEDC, 0x9EBE9DAB, + 0xCEDEBDBC, 0xEEEEEEDD, 0xAEBEADBC, 0xBECEBEBC, + 0xEEEEDEDC, 0xBEBECEBC, 0xBEBEBEBB, 0xCEBCCDBB, + ], [ + 0xF649398B, 0x5A9C9CDD, 0xDDDDDDDD, 0x3B6C9DBD, + 0x8DBDCDDD, 0xDDDDDDDD, 0xCDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0x3B9D6CBD, 0x8DCDBDDD, 0xDDDDDDDD, + 0x8DBDBDDD, 0xADDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xBDDDCDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0x0A6B5BAC, + 0x6BADADDD, 0xDDDDDDDD, 0x4C8D9DCD, 0x9DBDCDDD, + 0xDDDDDDDD, 0xCDCDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0x4DAD7DCD, 0x9DDDCDDD, 0xDDDDDDDD, 0x8DBDCDDD, + 0x9DDDCDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xBDDDBDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0x4D9D8DCD, 0x9DCDBDDD, + 0xDDDDDDDD, 0x7DADBDDD, 0xBDDDDDDD, 0xDDDDDDDD, + 0xBDBDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0x6DBD9DDD, + 0xBDDDDDDD, 0xDDDDDDDD, 0x9DDDCDDD, 0xADDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xADDDADDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0x6DBDADDD, 0xBDDDCDDD, 0xDDDDDDDD, + 0x9DBDCDDD, 0xCDDDDDDD, 0xDDDDDDDD, 0xBDBDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0x8DDDBDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xADDDCDDD, 0xDDDDDDDD, 0xDDDDDDDD, + 0xCDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xADDDBDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xBDDDDDDD, 0xDDDDDDDD, + 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDDDD, 0xDDDDDEED, + ]], + l12_tab: [ + [ + 0xF3A26B8A, 0xD26B57CA, 0xBD89CABD, 0xCDE05B47, 0xC8AD47C6, 0x8DABD8AD, 0xABDCDE58, 0xC79D9BE7, + 0x9D8AEABE, 0x9BEBBEDC, 0xE9ADABDA, 0xCE9BDABE, 0xBCEACEBC, 0xDCCD0000 + ], [ + 0xF4D26EAC, 0xE17E69EE, 0xEEACEDEE, 0xEEE06C58, 0xEBDE49E8, 0xAEDDEADE, 0xEEEEEE79, 0xEACEEEE8, + 0xAECCEDDE, 0xBEEEEEEE, 0xEDDEDEEE, 0xEEDEEEEE, 0xEEEEEEEE, 0xEEEE0000 + ]], + l3_tab: [ + [ + 0xF3B25B9B, 0xE25B57CA, 0xCE8AD9BE, 0xDDE04A47, 0xCACE47C7, 0x8DBCE9BD, 0xABEDDE68, 0xB8ADCDE8, + 0xADABECDE, 0xBDECDEEE, 0xEBCDCDEE, 0xEEBCECDE, 0xEEEDDEEE, 0xEEEE0000 + ], [ + 0xF3D27DEE, 0xE18E69EE, 0xEEAEEEBE, 0xEEE05E6A, 0xEEEE59E8, 0xBEEEEBEE, 0xEEEEEEAA, 0xEEEEEEEB, + 0xEEEEEEEE, 0xEBEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEED0000 + ]], + esc_tab: [ 0x01234577, 0x8899AABD, 0xDEEEEEEE, 0xEDDDDEED ], + }, +]; diff --git a/src/codecs/real/rv60dsp.rs b/src/codecs/real/rv60dsp.rs new file mode 100644 index 0000000..64c32c6 --- /dev/null +++ b/src/codecs/real/rv60dsp.rs @@ -0,0 +1,928 @@ +use frame::NAVideoBuffer; +use codecs::MV; +use codecs::blockdsp::edge_emu; + +fn clip8(val: i16) -> u8 { val.min(255).max(0) as u8 } + +macro_rules! el { + ($s: ident, $o: expr) => ( $s[$o] as i16 ) +} + +macro_rules! filter { + (01; $s: ident, $o: expr, $step: expr) => ( + clip8((( el!($s, $o - 2 * $step) + -5 * el!($s, $o - 1 * $step) + +52 * el!($s, $o - 0 * $step) + +20 * el!($s, $o + 1 * $step) + -5 * el!($s, $o + 2 * $step) + + el!($s, $o + 3 * $step) + 32) >> 6) as i16) + ); + (02; $s: ident, $o: expr, $step: expr) => ( + clip8((( el!($s, $o - 2 * $step) + -5 * el!($s, $o - 1 * $step) + +20 * el!($s, $o - 0 * $step) + +20 * el!($s, $o + 1 * $step) + -5 * el!($s, $o + 2 * $step) + + el!($s, $o + 3 * $step) + 16) >> 5) as i16) + ); + (03; $s: ident, $o: expr, $step: expr) => ( + clip8((( el!($s, $o - 2 * $step) + -5 * el!($s, $o - 1 * $step) + +20 * el!($s, $o - 0 * $step) + +52 * el!($s, $o + 1 * $step) + -5 * el!($s, $o + 2 * $step) + + el!($s, $o + 3 * $step) + 32) >> 6) as i16) + ); +} + +macro_rules! filter_row { + ($d: ident, $do: expr, $s: ident, $so: expr, $step: expr, $size: expr, $mode: expr) => ({ + match $mode { + 1 => { + for x in 0..$size { + $d[$do + x] = filter!(01; $s, $so + x, $step); + } + }, + 2 => { + for x in 0..$size { + $d[$do + x] = filter!(02; $s, $so + x, $step); + } + }, + 3 => { + for x in 0..$size { + $d[$do + x] = filter!(03; $s, $so + x, $step); + } + }, + _ => {}, + }; + }); +} + +fn luma_mc(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, w: usize, h: usize, cx: usize, cy: usize) { + if (cx == 0) && (cy == 0) { + for _ in 0..h { + for x in 0..w { dst[didx + x] = src[sidx + x]; } + didx += dstride; + sidx += sstride; + } + } else if cy == 0 { + for _ in 0..h { + filter_row!(dst, didx, src, sidx, 1, w, cx); + didx += dstride; + sidx += sstride; + } + } else if cx == 0 { + for _ in 0..h { + filter_row!(dst, didx, src, sidx, sstride, w, cy); + didx += dstride; + sidx += sstride; + } + } else if (cx != 3) || (cy != 3) { + let mut tmp: [u8; 70 * 64] = [0; 70 * 64]; + for y in 0..h+5 { + filter_row!(tmp, y * 64, src, sidx - sstride * 2, 1, w, cx); + sidx += sstride; + } + for y in 0..h { + filter_row!(dst, didx, tmp, (y + 2) * 64, 64, w, cy); + didx += dstride; + } + } else { + for _ in 0..h { + for x in 0..w { + dst[didx + x] = ((el!(src, sidx + x) + el!(src, sidx + x + 1) + + el!(src, sidx + x + sstride) + el!(src, sidx + x + 1 + sstride) + 2) >> 2) as u8; + } + didx += dstride; + sidx += sstride; + } + } +} + +fn chroma_mc(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, w: usize, h: usize, x: usize, y: usize) { + if (x == 0) && (y == 0) { + for _ in 0..h { + for x in 0..w { dst[didx + x] = src[sidx + x]; } + didx += dstride; + sidx += sstride; + } + return; + } + if (x > 0) && (y > 0) { + let a = ((4 - x) * (4 - y)) as u16; + let b = (( x) * (4 - y)) as u16; + let c = ((4 - x) * ( y)) as u16; + let d = (( x) * ( y)) as u16; + for _ in 0..h { + for x in 0..w { + dst[didx + x] = ((a * (src[sidx + x] as u16) + + b * (src[sidx + x + 1] as u16) + + c * (src[sidx + x + sstride] as u16) + + d * (src[sidx + x + 1 + sstride] as u16) + 8) >> 4) as u8; + } + didx += dstride; + sidx += sstride; + } + } else { + let a = ((4 - x) * (4 - y)) as u16; + let e = (( x) * (4 - y) + (4 - x) * ( y)) as u16; + let step = if y > 0 { sstride } else { 1 }; + for _ in 0..h { + for x in 0..w { + dst[didx + x] = ((a * (src[sidx + x] as u16) + + e * (src[sidx + x + step] as u16) + 8) >> 4) as u8; + } + didx += dstride; + sidx += sstride; + } + } +} + +fn check_pos(x: usize, y: usize, cw: usize, ch: usize, w: usize, h: usize, dx: i16, dy: i16, e0: isize, e1: isize, e2: isize, e3: isize) -> bool { + let xn = (x as isize) + (dx as isize); + let yn = (y as isize) + (dy as isize); + + (xn - e0 >= 0) && (xn + (cw as isize) + e1 <= (w as isize)) && (yn - e2 >= 0) && (yn + (ch as isize) + e3 <= (h as isize)) +} + +macro_rules! diff{ + ($src: ident, $e1: expr, $e2: expr) => ( + ($src[$e1] as i16) - ($src[$e2] as i16) + ) +} +macro_rules! strength{ + ($el: expr, $lim: expr) => (if $el < $lim { 3 } else { 1 }) +} +fn clip_symm(val: i16, lim: i16) -> i16 { val.max(-lim).min(lim) } + +fn filter_luma_edge(dst: &mut [u8], mut offset: usize, step: usize, stride: usize, mode1: u8, mode2: u8, lim1: i16, lim2: i16) { + let mut diff_q1q0: [i16; 4] = [0; 4]; + let mut diff_p1p0: [i16; 4] = [0; 4]; + for i in 0..4 { + let off = offset + i * stride; + diff_q1q0[i] = diff!(dst, off - 2 * step, off - step); + diff_p1p0[i] = diff!(dst, off + step, off); + } + let str_p = strength!(diff_q1q0[0] + diff_q1q0[1] + diff_q1q0[2] + diff_q1q0[3], lim2); + let str_q = strength!(diff_p1p0[0] + diff_p1p0[1] + diff_p1p0[2] + diff_p1p0[3], lim2); + if str_p + str_q > 2 { + let msum = ((mode1 + mode2 + str_q + str_p) >> 1) as i16; + let (maxprod, weak) = if (str_q == 1) || (str_p == 1) { (512, true) } else { (384, false) }; + for y in 0..4 { + let diff_p0q0 = diff!(dst, offset, offset - step); + if (diff_p0q0 != 0) && (lim1 * diff_p0q0.abs() < maxprod) { + let diff_q1q2 = diff!(dst, offset - 2 * step, offset - 3 * step); + let diff_p1p2 = diff!(dst, offset + step, offset + 2 * step); + let delta = if weak { + clip_symm((diff_p0q0 + 1) >> 1, msum >> 1) + } else { + let diff_strg = (diff!(dst, offset - 2 * step, offset + step) + 4 * diff_p0q0 + 4) >> 3; + clip_symm(diff_strg, msum) + }; + dst[offset - step] = clip8((dst[offset - step] as i16) + delta); + dst[offset] = clip8((dst[offset] as i16) - delta); + if (str_q != 1) && (diff_q1q2.abs() <= (lim1 >> 2)) { + let diff = (diff_q1q0[y] + diff_q1q2 - delta) >> 1; + let delta_q1 = if weak { + clip_symm(diff, (mode1 >> 1) as i16) + } else { + clip_symm(diff, mode1 as i16) + }; + dst[offset - 2 * step] = clip8((dst[offset - 2 * step] as i16) - delta_q1); + } + if (str_p != 1) && (diff_p1p2.abs() <= (lim1 >> 2)) { + let diff = (diff_p1p0[y] + diff_p1p2 + delta) >> 1; + let delta_p1 = if weak { + clip_symm(diff, (mode2 >> 1) as i16) + } else { + clip_symm(diff, mode2 as i16) + }; + dst[offset + step] = clip8((dst[offset + step] as i16) - delta_p1); + } + } + offset += stride; + } + } +} +fn filter_chroma_edge(dst: &mut [u8], mut offset: usize, step: usize, stride: usize, mode1: u8, mode2: u8, lim1: i16, lim2: i16) { + let diff_q = 4 * diff!(dst, offset - 2 * step, offset - step).abs(); + let diff_p = 4 * diff!(dst, offset + step, offset ).abs(); + let str_q = strength!(diff_q, lim2); + let str_p = strength!(diff_p, lim2); + if str_p + str_q > 2 { + let msum = ((mode1 + mode2 + str_q + str_p) >> 1) as i16; + let (maxprod, weak) = if (str_q == 1) || (str_p == 1) { (512, true) } else { (384, false) }; + for _ in 0..2 { + let diff_pq = diff!(dst, offset, offset - step); + if (diff_pq != 0) && (lim1 * diff_pq.abs() < maxprod) { + let delta = if weak { + clip_symm((diff_pq + 1) >> 1, msum >> 1) + } else { + let diff_strg = (diff!(dst, offset - 2 * step, offset + step) + 4 * diff_pq + 4) >> 3; + clip_symm(diff_strg, msum) + }; + dst[offset - step] = clip8((dst[offset - step] as i16) + delta); + dst[offset] = clip8((dst[offset] as i16) - delta); + } + offset += stride; + } + } +} + +pub struct RV60DeblockParams { + pub deblock_chroma: bool, + pub width: usize, + pub height: usize, + pub dblkstride: usize, +} + +pub struct RV60DSP {} +/*pub fn rv6_transform4x4_dc(coeffs: &mut [i16]) { + let dc = (((coeffs[0] * 13 + 0x10) >> 5) * 13 + 0x10) >> 5; + for el in coeffs.iter_mut().take(16) { + *el = dc; + } +}*/ + +impl RV60DSP { + pub fn new() -> Self { Self{} } + pub fn transform4x4(&self, blk: &mut [i16]) { + let mut tmp: [i32; 4 * 4] = [0; 4 * 4]; + + for i in 0..4 { + let a = blk[i + 0 * 4] as i32; + let b = blk[i + 1 * 4] as i32; + let c = blk[i + 2 * 4] as i32; + let d = blk[i + 3 * 4] as i32; + + let t0 = 13 * (a + c); + let t1 = 13 * (a - c); + let t2 = 7 * b - 17 * d; + let t3 = 7 * d + 17 * b; + tmp[i + 0 * 4] = (t0 + t3 + 0x10) >> 5; + tmp[i + 1 * 4] = (t1 + t2 + 0x10) >> 5; + tmp[i + 2 * 4] = (t1 - t2 + 0x10) >> 5; + tmp[i + 3 * 4] = (t0 - t3 + 0x10) >> 5; + } + for (dst, src) in blk.chunks_mut(4).zip(tmp.chunks(4)) { + let a = src[0]; + let b = src[1]; + let c = src[2]; + let d = src[3]; + + let t0 = 13 * (a + c); + let t1 = 13 * (a - c); + let t2 = 7 * b - 17 * d; + let t3 = 7 * d + 17 * b; + dst[0] = ((t0 + t3 + 0x10) >> 5) as i16; + dst[1] = ((t1 + t2 + 0x10) >> 5) as i16; + dst[2] = ((t1 - t2 + 0x10) >> 5) as i16; + dst[3] = ((t0 - t3 + 0x10) >> 5) as i16; + } + } + /*pub fn transform8x8_dc(&self, blk: &mut [i16]) { + assert!(blk.len() >= 8 * 8); + let dc = (((coeffs[0] * 37 + 0x40) >> 7) * 37 + 0x40) >> 7; + for el in coeffs.iter_mut().take(8 * 8) { + *el = dc; + } + }*/ + pub fn transform8x8(&self, blk: &mut [i16]) { + assert!(blk.len() >= 8 * 8); + let mut tmp: [i32; 8 * 8] = [0; 8 * 8]; + for i in 0..8 { + let s0 = blk[i + 0 * 8] as i32; + let s1 = blk[i + 1 * 8] as i32; + let s2 = blk[i + 2 * 8] as i32; + let s3 = blk[i + 3 * 8] as i32; + let s4 = blk[i + 4 * 8] as i32; + let s5 = blk[i + 5 * 8] as i32; + let s6 = blk[i + 6 * 8] as i32; + let s7 = blk[i + 7 * 8] as i32; + + let t0 = 37 * (s0 + s4); + let t1 = 37 * (s0 - s4); + let t2 = 48 * s2 + 20 * s6; + let t3 = 20 * s2 - 48 * s6; + let t4 = t0 + t2; + let t5 = t0 - t2; + let t6 = t1 + t3; + let t7 = t1 - t3; + let t8 = 51 * s1 + 43 * s3 + 29 * s5 + 10 * s7; + let t9 = 43 * s1 - 10 * s3 - 51 * s5 - 29 * s7; + let ta = 29 * s1 - 51 * s3 + 10 * s5 + 43 * s7; + let tb = 10 * s1 - 29 * s3 + 43 * s5 - 51 * s7; + tmp[i + 0 * 8] = (t4 + t8 + 0x40) >> 7; + tmp[i + 1 * 8] = (t6 + t9 + 0x40) >> 7; + tmp[i + 2 * 8] = (t7 + ta + 0x40) >> 7; + tmp[i + 3 * 8] = (t5 + tb + 0x40) >> 7; + tmp[i + 4 * 8] = (t5 - tb + 0x40) >> 7; + tmp[i + 5 * 8] = (t7 - ta + 0x40) >> 7; + tmp[i + 6 * 8] = (t6 - t9 + 0x40) >> 7; + tmp[i + 7 * 8] = (t4 - t8 + 0x40) >> 7; + } + for (dst, src) in blk.chunks_mut(8).zip(tmp.chunks(8)) { + let s0 = src[0]; + let s1 = src[1]; + let s2 = src[2]; + let s3 = src[3]; + let s4 = src[4]; + let s5 = src[5]; + let s6 = src[6]; + let s7 = src[7]; + + let t0 = 37 * (s0 + s4); + let t1 = 37 * (s0 - s4); + let t2 = 48 * s2 + 20 * s6; + let t3 = 20 * s2 - 48 * s6; + let t4 = t0 + t2; + let t5 = t0 - t2; + let t6 = t1 + t3; + let t7 = t1 - t3; + let t8 = 51 * s1 + 43 * s3 + 29 * s5 + 10 * s7; + let t9 = 43 * s1 - 10 * s3 - 51 * s5 - 29 * s7; + let ta = 29 * s1 - 51 * s3 + 10 * s5 + 43 * s7; + let tb = 10 * s1 - 29 * s3 + 43 * s5 - 51 * s7; + dst[0] = ((t4 + t8 + 0x40) >> 7) as i16; + dst[1] = ((t6 + t9 + 0x40) >> 7) as i16; + dst[2] = ((t7 + ta + 0x40) >> 7) as i16; + dst[3] = ((t5 + tb + 0x40) >> 7) as i16; + dst[4] = ((t5 - tb + 0x40) >> 7) as i16; + dst[5] = ((t7 - ta + 0x40) >> 7) as i16; + dst[6] = ((t6 - t9 + 0x40) >> 7) as i16; + dst[7] = ((t4 - t8 + 0x40) >> 7) as i16; + } + } + /*pub fn transform16x16_dc(&self, blk: &mut [i16; 16 * 16]) { + let dc = (((coeffs[0] * 26 + 0x40) >> 7) * 26 + 0x40) >> 7; + for el in coeffs.iter_mut() { + *el = dc; + } + }*/ + #[allow(non_snake_case)] + fn transform16(blk: &mut [i16; 16 * 16], off: usize, step: usize) { + let src0 = blk[off + 0 * step] as i32; + let src1 = blk[off + 1 * step] as i32; + let src2 = blk[off + 2 * step] as i32; + let src3 = blk[off + 3 * step] as i32; + let src4 = blk[off + 4 * step] as i32; + let src5 = blk[off + 5 * step] as i32; + let src6 = blk[off + 6 * step] as i32; + let src7 = blk[off + 7 * step] as i32; + let src8 = blk[off + 8 * step] as i32; + let src9 = blk[off + 9 * step] as i32; + let srcA = blk[off + 10 * step] as i32; + let srcB = blk[off + 11 * step] as i32; + let srcC = blk[off + 12 * step] as i32; + let srcD = blk[off + 13 * step] as i32; + let srcE = blk[off + 14 * step] as i32; + let srcF = blk[off + 15 * step] as i32; + let t0 = 26 * (src0 + src8); + let t1 = 26 * (src0 - src8); + let t2 = 14 * src4 - 34 * srcC; + let t3 = 34 * src4 + 14 * srcC; + let t4 = t0 + t3; + let t5 = t0 - t3; + let t6 = t1 + t2; + let t7 = t1 - t2; + let tmp00 = 31 * src2 + -7 * src6 + -36 * srcA + -20 * srcE; + let tmp01 = 36 * src2 + 31 * src6 + 20 * srcA + 7 * srcE; + let tmp02 = 20 * src2 + -36 * src6 + 7 * srcA + 31 * srcE; + let tmp03 = 7 * src2 + -20 * src6 + 31 * srcA + -36 * srcE; + let tm0 = t4 + tmp01; + let tm1 = t4 - tmp01; + let tm2 = t5 + tmp03; + let tm3 = t5 - tmp03; + let tm4 = t6 + tmp00; + let tm5 = t6 - tmp00; + let tm6 = t7 + tmp02; + let tm7 = t7 - tmp02; + let tt0 = 37 * src1 + 35 * src3 + 32 * src5 + 28 * src7 + 23 * src9 + 17 * srcB + 11 * srcD + 4 * srcF; + let tt1 = 35 * src1 + 23 * src3 + 4 * src5 + -17 * src7 + -32 * src9 + -37 * srcB + -28 * srcD + -11 * srcF; + let tt2 = 32 * src1 + 4 * src3 + -28 * src5 + -35 * src7 + -11 * src9 + 23 * srcB + 37 * srcD + 17 * srcF; + let tt3 = 28 * src1 + -17 * src3 + -35 * src5 + 4 * src7 + 37 * src9 + 11 * srcB + -32 * srcD + -23 * srcF; + let tt4 = 23 * src1 + -32 * src3 + -11 * src5 + 37 * src7 + -4 * src9 + -35 * srcB + 17 * srcD + 28 * srcF; + let tt5 = 17 * src1 + -37 * src3 + 23 * src5 + 11 * src7 + -35 * src9 + 28 * srcB + 4 * srcD + -32 * srcF; + let tt6 = 11 * src1 + -28 * src3 + 37 * src5 + -32 * src7 + 17 * src9 + 4 * srcB + -23 * srcD + 35 * srcF; + let tt7 = 4 * src1 + -11 * src3 + 17 * src5 + -23 * src7 + 28 * src9 + -32 * srcB + 35 * srcD + -37 * srcF; + blk[off + 0 * step] = ((tm0 + tt0 + 64) >> 7) as i16; + blk[off + 1 * step] = ((tm4 + tt1 + 64) >> 7) as i16; + blk[off + 2 * step] = ((tm6 + tt2 + 64) >> 7) as i16; + blk[off + 3 * step] = ((tm4 + tt3 + 64) >> 7) as i16; + blk[off + 4 * step] = ((tm3 + tt4 + 64) >> 7) as i16; + blk[off + 5 * step] = ((tm7 + tt5 + 64) >> 7) as i16; + blk[off + 6 * step] = ((tm5 + tt6 + 64) >> 7) as i16; + blk[off + 7 * step] = ((tm1 + tt7 + 64) >> 7) as i16; + blk[off + 8 * step] = ((tm1 - tt7 + 64) >> 7) as i16; + blk[off + 9 * step] = ((tm5 - tt6 + 64) >> 7) as i16; + blk[off + 10 * step] = ((tm7 - tt5 + 64) >> 7) as i16; + blk[off + 11 * step] = ((tm3 - tt4 + 64) >> 7) as i16; + blk[off + 12 * step] = ((tm2 - tt3 + 64) >> 7) as i16; + blk[off + 13 * step] = ((tm6 - tt2 + 64) >> 7) as i16; + blk[off + 14 * step] = ((tm4 - tt1 + 64) >> 7) as i16; + blk[off + 15 * step] = ((tm0 - tt0 + 64) >> 7) as i16; + } + pub fn transform16x16(&self, blk: &mut [i16; 16 * 16]) { + for i in 0..16 { + Self::transform16(blk, i, 16); + } + for i in 0..16 { + Self::transform16(blk, i * 16, 1); + } + } + + pub fn add_block(&self, dst: &mut [u8], mut doff: usize, dstride: usize, blk: &[i16], size: usize) { + for y in 0..size { + for x in 0..size { + dst[doff + x] = clip8((dst[doff + x] as i16) + blk[x + y * size]); + } + doff += dstride; + } + } + fn avg(&self, dst: &mut [u8], mut didx: usize, dstride: usize, + src: &[u8], mut sidx: usize, sstride: usize, + w: usize, h: usize) { + for _ in 0..h { + for x in 0..w { + dst[didx + x] = (((dst[didx + x] as u16) + (src[sidx + x] as u16)) >> 1) as u8; + } + didx += dstride; + sidx += sstride; + } + } + pub fn do_avg(&self, frame: &mut NAVideoBuffer, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize) { + for comp in 0..3 { + let dstride = frame.get_stride(comp); + let sstride = prev_frame.get_stride(comp); + let doff = if comp == 0 { x + y * dstride } else { frame.get_offset(comp) + (x >> 1) + (y >> 1) * dstride }; + let soff = prev_frame.get_offset(comp); + let mut ddata = frame.get_data_mut(); + let dst: &mut [u8] = ddata.as_mut_slice(); + let sdata = prev_frame.get_data(); + let src: &[u8] = sdata.as_slice(); + + if comp == 0 { + self.avg(dst, doff, dstride, src, soff, sstride, w, h); + } else { + self.avg(dst, doff, dstride, src, soff, sstride, w >> 1, h >> 1); + } + } + } + pub fn do_mc(&self, frame: &mut NAVideoBuffer, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize, mv: MV, avg: bool) { + { // luma + let dstride = frame.get_stride(0); + let doffset = frame.get_offset(0) + (if !avg { x + y * dstride } else { 0 }); + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + + let (w_, h_) = prev_frame.get_dimensions(0); + let fw = (w_ + 15) & !15; + let fh = (h_ + 15) & !15; + + let dx = mv.x >> 2; + let cx = (mv.x & 3) as usize; + let dy = mv.y >> 2; + let cy = (mv.y & 3) as usize; + + if check_pos(x, y, w, h, fw, fh, dx, dy, RV60_EDGE1[cx], RV60_EDGE2[cx], RV60_EDGE1[cy], RV60_EDGE2[cy]) { + let sstride = prev_frame.get_stride(0); + let mut soffset = prev_frame.get_offset(0) + x + y * sstride; + let data = prev_frame.get_data(); + let src: &[u8] = data.as_slice(); + soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize; + luma_mc(dst, doffset, dstride, src, soffset, sstride, w, h, cx, cy); + } else { + let mut ebuf: [u8; 70*70] = [0; 70*70]; + edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, w+5, h+5, &mut ebuf, 70, 0); + luma_mc(dst, doffset, dstride, &ebuf, 70*2 + 2, 70, w, h, cx, cy); + } + } + let (w_, h_) = prev_frame.get_dimensions(1); + let fw = (w_ + 7) & !7; + let fh = (h_ + 7) & !7; + let mvx = mv.x / 2; + let mvy = mv.y / 2; + let dx = mvx >> 2; + let cx = (mvx & 3) as usize; + let dy = mvy >> 2; + let cy = (mvy & 3) as usize; + let cw = w >> 1; + let ch = h >> 1; + + for comp in 1..3 { // chroma + let dstride = frame.get_stride(comp); + let doffset = frame.get_offset(comp) + (if !avg { (x >> 1) + (y >> 1) * dstride } else { 0 }); + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + if check_pos(x >> 1, y >> 1, cw, ch, fw, fh, dx, dy, 0, 1, 0, 1) { + let sstride = prev_frame.get_stride(comp); + let mut soffset = prev_frame.get_offset(comp) + (x >> 1) + (y >> 1) * sstride; + let data = prev_frame.get_data(); + let src: &[u8] = data.as_slice(); + soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize; + chroma_mc(dst, doffset, dstride, src, soffset, sstride, cw, ch, cx, cy); + } else { + let mut ebuf: [u8; 40*40] = [0; 40*40]; + edge_emu(prev_frame, ((x >> 1) as isize) + (dx as isize), ((y >> 1) as isize) + (dy as isize), cw+1, ch+1, &mut ebuf, 40, comp); + chroma_mc(dst, doffset, dstride, &ebuf, 0, 40, cw, ch, cx, cy); + } + } + } + fn deblock_edge4_ver(&self, frame: &mut NAVideoBuffer, xpos: usize, ypos: usize, + dblk_l: u8, dblk_r: u8, deblock_chroma: bool) { + let qp_l = dblk_l >> 2; + let str_l = dblk_l & 3; + let qp_r = dblk_r >> 2; + let str_r = dblk_r & 3; + let dl_l = &RV60_DEB_LIMITS[qp_l as usize]; + let dl_r = &RV60_DEB_LIMITS[qp_r as usize]; + let mode_l = if str_l != 0 { dl_l[(str_l - 1) as usize] } else { 0 }; + let mode_r = if str_r != 0 { dl_r[(str_r - 1) as usize] } else { 0 }; + let lim1 = dl_r[2] as i16; + let lim2 = (dl_r[3] * 4) as i16; + { + let stride = frame.get_stride(0); + let offset = frame.get_offset(0) + xpos + ypos * stride; + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + filter_luma_edge(dst, offset, 1, stride, mode_l, mode_r, lim1, lim2); + } + if ((str_l | str_r) >= 2) && deblock_chroma { + for comp in 1..2 { + let stride = frame.get_stride(comp); + let offset = frame.get_offset(comp) + (xpos >> 1) + (ypos >> 1) * stride; + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + filter_chroma_edge(dst, offset, 1, stride, mode_l, mode_r, lim1, lim2); + } + } + } + fn deblock_edge4_hor(&self, frame: &mut NAVideoBuffer, xpos: usize, ypos: usize, + dblk_t: u8, dblk_d: u8, deblock_chroma: bool) { + let qp_t = dblk_t >> 2; + let str_t = dblk_t & 3; + let qp_d = dblk_d >> 2; + let str_d = dblk_d & 3; + let dl_t = &RV60_DEB_LIMITS[qp_t as usize]; + let dl_d = &RV60_DEB_LIMITS[qp_d as usize]; + let mode_t = if str_t != 0 { dl_t[(str_t - 1) as usize] } else { 0 }; + let mode_d = if str_d != 0 { dl_d[(str_d - 1) as usize] } else { 0 }; + let lim1 = dl_d[2] as i16; + let lim2 = (dl_d[3] * 4) as i16; + { + let stride = frame.get_stride(0); + let offset = frame.get_offset(0) + xpos + ypos * stride; + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + filter_luma_edge(dst, offset, stride, 1, mode_t, mode_d, lim1, lim2); + } + if ((str_t | str_d) >= 2) && deblock_chroma { + for comp in 1..2 { + let stride = frame.get_stride(comp); + let offset = frame.get_offset(comp) + (xpos >> 1) + (ypos >> 1) * stride; + let mut data = frame.get_data_mut(); + let dst: &mut [u8] = data.as_mut_slice(); + filter_chroma_edge(dst, offset, stride, 1, mode_t, mode_d, lim1, lim2); + } + } + } + fn deblock8x8(&self, dparams: &RV60DeblockParams, frame: &mut NAVideoBuffer, + xpos: usize, ypos: usize, top_str: &[u8], left_str: &[u8], dblkpos: usize) { + if xpos > 0 { + if ypos > 0 { + let str_l = left_str[dblkpos - dparams.dblkstride]; + let str_r = left_str[dblkpos]; + if (str_l | str_r) != 0 { + self.deblock_edge4_ver(frame, xpos, ypos - 4, str_l, str_r, dparams.deblock_chroma); + } + } + { + let str_l = left_str[dblkpos]; + let str_r = left_str[dblkpos + dparams.dblkstride]; + if (str_l | str_r) != 0 { + self.deblock_edge4_ver(frame, xpos, ypos + 0, str_l, str_r, dparams.deblock_chroma); + } + } + if ypos + 4 >= dparams.height { + let str_l = left_str[dblkpos + dparams.dblkstride]; + let str_r = left_str[dblkpos + dparams.dblkstride * 2]; + if (str_l | str_r) != 0 { + self.deblock_edge4_ver(frame, xpos, ypos + 4, str_l, str_r, dparams.deblock_chroma); + } + } + } + if ypos > 0 { + if xpos > 0 { + let str_t = top_str[dblkpos - 1]; + let str_d = top_str[dblkpos]; + if (str_t | str_d) != 0 { + self.deblock_edge4_hor(frame, xpos - 4, ypos, str_t, str_d, dparams.deblock_chroma); + } + } + { + let str_t = top_str[dblkpos]; + let str_d = top_str[dblkpos + 1]; + if (str_t | str_d) != 0 { + self.deblock_edge4_hor(frame, xpos + 0, ypos, str_t, str_d, dparams.deblock_chroma); + } + } + if xpos + 4 >= dparams.width { + let str_t = top_str[dblkpos + 1]; + let str_d = top_str[dblkpos + 2]; + if (str_t | str_d) != 0 { + self.deblock_edge4_hor(frame, xpos + 4, ypos, str_t, str_d, dparams.deblock_chroma); + } + } + } + } + pub fn do_deblock(&self, dparams: &RV60DeblockParams, frame: &mut NAVideoBuffer, + xpos: usize, ypos: usize, size: usize, top_str: &[u8], left_str: &[u8], dpos: usize) { + for x in 0..(size >> 3) { + self.deblock8x8(dparams, frame, xpos + x * 8, ypos, + top_str, left_str, dpos + x * 2); + } + for y in 1..(size >> 3) { + self.deblock8x8(dparams, frame, xpos, ypos + y * 8, + top_str, left_str, dpos + y * 2 * dparams.dblkstride); + } + } +} + +const RV60_DEB_LIMITS: [[u8; 4]; 32] = [ + [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], + [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], [ 0, 0, 128, 0 ], + [ 0, 0, 128, 3 ], [ 0, 1, 128, 3 ], [ 0, 1, 122, 3 ], [ 1, 1, 96, 4 ], + [ 1, 1, 75, 4 ], [ 1, 1, 59, 4 ], [ 1, 1, 47, 6 ], [ 1, 1, 37, 6 ], + [ 1, 1, 29, 6 ], [ 1, 2, 23, 7 ], [ 1, 2, 18, 8 ], [ 1, 2, 15, 8 ], + [ 1, 2, 13, 9 ], [ 2, 3, 11, 9 ], [ 2, 3, 10, 10 ], [ 2, 3, 9, 10 ], + [ 2, 4, 8, 11 ], [ 3, 4, 7, 11 ], [ 3, 5, 6, 12 ], [ 3, 5, 5, 13 ], + [ 3, 5, 4, 14 ], [ 4, 7, 3, 15 ], [ 5, 8, 2, 16 ], [ 5, 9, 1, 17 ] +]; + +#[derive(Clone)] +pub struct IntraPredContext { + pub t: [u8; 129], // 0 - TL or 0x80, two block sizes or replicated last val from block0 + pub l: [u8; 129], + pub has_t: bool, + pub has_tr: bool, + pub has_l: bool, + pub has_ld: bool, +} + +impl IntraPredContext { + pub fn new() -> Self { + Self { + t: [0x80; 129], l: [0x80; 129], has_t: false, has_tr: false, has_l: false, has_ld: false, + } + } + pub fn pred_dc(&self, dst: &mut [u8], mut doff: usize, dstride: usize, size: usize, filter: bool) { + let dc; + if !self.has_t && !self.has_l { + dc = 0x80; + } else { + let mut sum = 0; + if self.has_t { + for x in 0..size { sum += self.t[x + 1] as u16; } + } + if self.has_l { + for y in 0..size { sum += self.l[y + 1] as u16; } + } + if self.has_t && self.has_l { + dc = ((sum + (size as u16)) / ((size as u16) * 2)) as u8; + } else { + dc = ((sum + ((size >> 1) as u16)) / (size as u16)) as u8; + } + } + for _ in 0..size { + for x in 0..size { dst[doff + x] = dc; } + doff += dstride; + } + if filter && self.has_t && self.has_l { + doff -= dstride * size; + dst[doff] = (((self.t[1] as u16) + (self.l[1] as u16) + 2 * (dst[doff] as u16) + 2) >> 2) as u8; + for x in 1..size { + dst[doff + x] = (((self.t[x + 1] as u16) + 3 * (dst[doff + x] as u16) + 2) >> 2) as u8; + } + for y in 1..size { + doff += dstride; + dst[doff] = (((self.l[y + 1] as u16) + 3 * (dst[doff] as u16) + 2) >> 2) as u8; + } + } + } + pub fn pred_plane(&self, dst: &mut [u8], mut doff: usize, dstride: usize, size: usize) { + let lastl = self.l[size + 1] as i32; + let lastt = self.t[size + 1] as i32; + let mut tmp1: [i32; 64] = [0; 64]; + let mut tmp2: [i32; 64] = [0; 64]; + for i in 0..size { + tmp1[i] = lastl - (self.t[i + 1] as i32); + tmp2[i] = lastt - (self.l[i + 1] as i32); + } + let shift = match size { + 4 => 3, + 8 => 4, + 16 => 5, + 32 => 6, + _ => 7, + }; + let mut top_ref: [i32; 64] = [0; 64]; + let mut left_ref:[i32; 64] = [0; 64]; + for i in 0..size { + top_ref [i] = (self.t[i + 1] as i32) << (shift - 1); + left_ref[i] = (self.l[i + 1] as i32) << (shift - 1); + } + for y in 0..size { + let add = tmp2[y]; + let mut sum = left_ref[y] + (size as i32); + for x in 0..size { + let v = tmp1[x] + top_ref[x]; + sum += add; + top_ref[x] = v; + dst[doff + x] = ((sum + v) >> shift) as u8; + } + doff += dstride; + } + } + fn pred_hor_angle(dst: &mut [u8], doff: usize, dstride: usize, size: usize, weight: i16, src: &[u8]) { + let mut sum = 0; + for x in 0..size { + sum += weight; + let off = ((sum >> 5) + 32) as usize; + let frac = (sum & 0x1F) as u16; + if frac == 0 { + for y in 0..size { + dst[doff + x + y * dstride] = src[off + y]; + } + } else { + for y in 0..size { + let a = src[off + y + 0] as u16; + let b = src[off + y + 1] as u16; + dst[doff + x + y * dstride] = (((32 - frac) * a + frac * b + 0x10) >> 5) as u8; + } + } + } + } + fn pred_ver_angle(dst: &mut [u8], mut doff: usize, dstride: usize, size: usize, weight: i16, src: &[u8]) { + let mut sum = 0; + for _ in 0..size { + sum += weight; + let off = ((sum >> 5) + 32) as usize; + let frac = (sum & 0x1F) as u16; + if frac == 0 { + for x in 0..size { + dst[doff + x] = src[off + x]; + } + } else { + for x in 0..size { + let a = src[off + x + 0] as u16; + let b = src[off + x + 1] as u16; + dst[doff + x] = (((32 - frac) * a + frac * b + 0x10) >> 5) as u8; + } + } + doff += dstride; + } + } + fn filter_weak(dst: &mut [u8], src: &[u8], size: usize) { + dst[0] = src[0]; + for i in 1..size-1 { + dst[i] = (((src[i - 1] as u16) + 2 * (src[i] as u16) + (src[i + 1] as u16) + 2) >> 2) as u8; + } + dst[size - 1] = src[size - 1]; + } + fn filter_bilin32(dst: &mut [u8], v0: u8, v1: u8, size: usize) { + let diff = (v1 as i16) - (v0 as i16); + let mut sum = ((v0 as i16) << 5) + (1 << (5 - 1)); + for i in 0..size { + dst[i] = (sum >> 5) as u8; + sum += diff; + } + } + pub fn pred_angle(&self, dst: &mut [u8], mut doff: usize, dstride: usize, size: usize, angle: usize, filter: bool) { + let mut filtered1: [u8; 96] = [0; 96]; + let mut filtered2: [u8; 96] = [0; 96]; + if angle == 0 { + self.pred_plane(dst, doff, dstride, size); + } else if angle == 1 { + self.pred_dc(dst, doff, dstride, size, filter); + } else if angle <= 9 { + let ang_weight = RV60_IPRED_ANGLE[10 - angle]; + let add_size = (size * (ang_weight as usize) + 31) >> 5; + if size <= 16 { + Self::filter_weak(&mut filtered1[32..], &self.l[1..], size + add_size); + } else { + Self::filter_bilin32(&mut filtered1[32..], self.l[1], self.l[33], 32); + Self::filter_bilin32(&mut filtered1[64..], self.l[32], self.l[64], add_size); + } + Self::pred_hor_angle(dst, doff, dstride, size, ang_weight as i16, &filtered1); + } else if angle == 10 { + if size <= 16 { + Self::filter_weak(&mut filtered1[32..], &self.l[1..], size); + } else { + Self::filter_bilin32(&mut filtered1[32..], self.l[1], self.l[33], 32); + } + for y in 0..size { + for x in 0..size { + dst[doff + x] = filtered1[32 + y]; + } + doff += dstride; + } + if filter { + doff -= dstride * size; + let tl = self.t[0] as i16; + for x in 0..size { + dst[doff + x] = clip8((dst[doff + x] as i16) + (((self.t[x + 1] as i16) - tl) >> 1)); + } + } + } else if angle <= 17 { + let ang_weight = RV60_IPRED_ANGLE [angle - 10]; + let inv_angle = RV60_IPRED_INV_ANGLE[angle - 10]; + let add_size = (size * (ang_weight as usize) + 31) >> 5; + if size <= 16 { + for i in 0..size+1 { + filtered1[32-1 + i] = self.l[i]; + } + for i in 0..size+1 { + filtered2[32-1 + i] = self.t[i]; + } + } else { + filtered1[32-1] = self.l[0]; + Self::filter_bilin32(&mut filtered1[32..], self.l[0], self.l[32], 32); + filtered2[32-1] = self.t[0]; + Self::filter_bilin32(&mut filtered2[32..], self.t[0], self.t[32], 32); + } + if add_size > 1 { + let mut sum = 0x80; + for i in 1..add_size { + sum += inv_angle; + let pos = ((sum >> 8) + 32 - 1) as usize; + filtered1[32 - 1 - i] = filtered2[pos]; + } + } + Self::pred_hor_angle(dst, doff, dstride, size, -(ang_weight as i16), &filtered1); + } else if angle <= 25 { + let ang_weight = RV60_IPRED_ANGLE[26 - angle]; + let inv_angle = RV60_IPRED_INV_ANGLE[26 - angle]; + let add_size = (size * (ang_weight as usize) + 31) >> 5; + if size <= 16 { + for i in 0..size+1 { + filtered1[32-1 + i] = self.t[i]; + } + for i in 0..size+1 { + filtered2[32-1 + i] = self.l[i]; + } + } else { + filtered1[32-1] = self.t[0]; + Self::filter_bilin32(&mut filtered1[32..], self.t[0], self.t[32], 32); + filtered2[32-1] = self.l[0]; + Self::filter_bilin32(&mut filtered2[32..], self.l[0], self.l[32], 32); + } + if add_size > 1 { + let mut sum = 0x80; + for i in 1..add_size { + sum += inv_angle; + let pos = ((sum >> 8) + 32 - 1) as usize; + filtered1[32 - 1 - i] = filtered2[pos]; + } + } + Self::pred_ver_angle(dst, doff, dstride, size, -(ang_weight as i16), &filtered1); + } else if angle == 26 { + if size <= 16 { + Self::filter_weak(&mut filtered1[32..], &self.t[1..], size); + } else { + Self::filter_bilin32(&mut filtered1[32..], self.t[1], self.t[33], 32); + } + for _ in 0..size { + for x in 0..size { + dst[doff + x] = filtered1[32 + x]; + } + doff += dstride; + } + if filter { + doff -= dstride * size; + let tl = self.l[0] as i16; + for y in 0..size { + dst[doff] = clip8((dst[doff] as i16) + (((self.l[y + 1] as i16) - tl) >> 1)); + doff += dstride; + } + } + } else if angle <= 34 { + let ang_weight = RV60_IPRED_ANGLE[angle - 26]; + let add_size = (size * (ang_weight as usize) + 31) >> 5; + if size <= 16 { + Self::filter_weak(&mut filtered1[32..], &self.t[1..], size + add_size); + } else { + Self::filter_bilin32(&mut filtered1[32..], self.t[1], self.t[33], 32); + Self::filter_bilin32(&mut filtered1[64..], self.t[32], self.t[64], add_size); + } + Self::pred_ver_angle(dst, doff, dstride, size, ang_weight as i16, &filtered1); + } else { + unreachable!(); + } + } +} + +const RV60_IPRED_ANGLE: [u8; 9] = [ 0, 2, 5, 9, 13, 17, 21, 26, 32 ]; +const RV60_IPRED_INV_ANGLE: [i16; 9] = [ 0, 4096, 1638, 910, 630, 482, 390, 315, 256 ]; +const RV60_EDGE1: [isize; 4] = [ 0, 2, 2, 2 ]; +const RV60_EDGE2: [isize; 4] = [ 0, 3, 3, 3 ]; + -- 2.30.2