use super::sad::*;
use super::*;
use crate::def::*;
use crate::plane::*;
use crate::region::*;
lazy_static! {
pub(crate) static ref entropy_bits: Box<[i32]> = {
let mut bits = vec![0; 1024].into_boxed_slice();
for i in 0..1024 {
let p = (512.0 * (i as f64 + 0.5)) / 1024.0;
bits[i] = (-32768.0 * (p.log10() / (2.0f64).log10() - 9.0)) as i32;
}
bits
};
}
pub(crate) fn biari_no_bits(symbol: usize, cm: SBAC_CTX_MODEL) -> i32 {
let mps = cm & 1;
let mut state = cm >> 1;
let sym = if symbol != 0 { 1 } else { 0 };
state = if sym != mps { state } else { 512 - state };
entropy_bits[(state as usize) << 1]
}
impl EvceCtx {
pub(crate) fn evce_set_qp(&mut self, qp: u8) {
self.core.qp = qp;
self.core.qp_y = GET_LUMA_QP(self.core.qp as i8) as u8;
let qp_i_cb = EVC_CLIP3(
-6 * (BIT_DEPTH as i8 - 8),
57,
self.core.qp as i8 + self.sh.qp_u_offset,
);
let qp_i_cr = EVC_CLIP3(
-6 * (BIT_DEPTH as i8 - 8),
57,
self.core.qp as i8 + self.sh.qp_v_offset,
);
self.core.qp_u = (self.core.evc_tbl_qp_chroma_dynamic_ext[0]
[(EVC_TBL_CHROMA_QP_OFFSET + qp_i_cb) as usize]
+ 6 * (BIT_DEPTH as i8 - 8)) as u8;
self.core.qp_v = (self.core.evc_tbl_qp_chroma_dynamic_ext[1]
[(EVC_TBL_CHROMA_QP_OFFSET + qp_i_cr) as usize]
+ 6 * (BIT_DEPTH as i8 - 8)) as u8;
}
}
pub(crate) fn evc_check_split_mode(split_allow: &mut [bool]) {
split_allow[SplitMode::NO_SPLIT as usize] = false;
split_allow[SplitMode::SPLIT_QUAD as usize] = true;
}
pub(crate) fn evc_get_default_tree_cons() -> TREE_CONS {
TREE_CONS {
changed: false,
tree_type: TREE_TYPE::TREE_LC,
mode_cons: MODE_CONS::eAll,
}
}
pub(crate) fn evc_get_avail_block(
x_scu: u16,
y_scu: u16,
w_scu: u16,
h_scu: u16,
scup: u32,
log2_cuw: u8,
log2_cuh: u8,
map_scu: &[MCU],
) -> u16 {
let mut avail = 0;
let log2_scuw = log2_cuw - MIN_CU_LOG2 as u8;
let log2_scuh = log2_cuh - MIN_CU_LOG2 as u8;
let scuw = 1 << log2_scuw;
let scuh = 1 << log2_scuh;
if x_scu > 0 && map_scu[(scup - 1) as usize].GET_COD() != 0 {
SET_AVAIL(&mut avail, AVAIL_LE);
if y_scu + scuh < h_scu
&& map_scu[(scup + (scuh * w_scu) as u32 - 1) as usize].GET_COD() != 0
{
SET_AVAIL(&mut avail, AVAIL_LO_LE);
}
}
if y_scu > 0 {
SET_AVAIL(&mut avail, AVAIL_UP);
SET_AVAIL(&mut avail, AVAIL_RI_UP);
if x_scu > 0 && map_scu[(scup - w_scu as u32 - 1) as usize].GET_COD() != 0 {
SET_AVAIL(&mut avail, AVAIL_UP_LE);
}
if x_scu + scuw < w_scu
&& map_scu[(scup - w_scu as u32 + scuw as u32) as usize].GET_COD() != 0
{
SET_AVAIL(&mut avail, AVAIL_UP_RI);
}
}
if x_scu + scuw < w_scu && map_scu[(scup + scuw as u32) as usize].GET_COD() != 0 {
SET_AVAIL(&mut avail, AVAIL_RI);
if y_scu + scuh < h_scu
&& map_scu[(scup + (w_scu * scuh) as u32 + scuw as u32) as usize].GET_COD() != 0
{
SET_AVAIL(&mut avail, AVAIL_LO_RI);
}
}
avail
}
pub(crate) fn evc_get_luma_cup(
x_scu: u16,
y_scu: u16,
cu_w_scu: u16,
cu_h_scu: u16,
w_scu: u16,
) -> u16 {
(y_scu + (cu_h_scu >> 1)) * w_scu + x_scu + (cu_w_scu >> 1)
}
pub(crate) enum TQC_RUN {
RUN_L = 1,
RUN_CB = 2,
RUN_CR = 4,
}
pub(crate) fn evc_get_run(run_list: u8, tree_cons: &TREE_CONS) -> u8 {
let mut ans = 0;
if evc_check_luma(tree_cons) {
ans |= run_list & TQC_RUN::RUN_L as u8;
}
if evc_check_chroma(tree_cons) {
ans |= run_list & TQC_RUN::RUN_CB as u8;
ans |= run_list & TQC_RUN::RUN_CR as u8;
}
return ans;
}
pub(crate) fn evce_diff_pred(
mut x: usize,
mut y: usize,
mut log2_cuw: usize,
mut log2_cuh: usize,
planes: &[Plane<pel>],
pred: &CUBuffer<pel>,
diff: &mut CUBuffer<i16>,
) {
let mut cuw = 1 << log2_cuw;
let mut cuh = 1 << log2_cuh;
evce_diff_16b(
x,
y,
log2_cuw,
log2_cuh,
&planes[Y_C].as_region(),
&pred.data[Y_C],
&mut diff.data[Y_C],
);
cuw >>= 1;
cuh >>= 1;
x >>= 1;
y >>= 1;
log2_cuw -= 1;
log2_cuh -= 1;
let buf = &planes[U_C].as_region();
evce_diff_16b(
x,
y,
log2_cuw,
log2_cuh,
&planes[U_C].as_region(),
&pred.data[U_C],
&mut diff.data[U_C],
);
let buf = &planes[V_C].as_region();
evce_diff_16b(
x,
y,
log2_cuw,
log2_cuh,
&planes[V_C].as_region(),
&pred.data[V_C],
&mut diff.data[V_C],
);
}
pub(crate) fn copy_tu_from_cu(
tu_resi: &mut CUBuffer<i16>,
cu_resi: &CUBuffer<i16>,
log2_cuw: usize,
log2_cuh: usize,
) {
let cuwh = (1 << log2_cuw) * (1 << log2_cuh);
tu_resi.data[Y_C][0..cuwh].copy_from_slice(&cu_resi.data[Y_C][0..cuwh]);
let cuwh = cuwh >> 2;
tu_resi.data[U_C][0..cuwh].copy_from_slice(&cu_resi.data[U_C][0..cuwh]);
tu_resi.data[V_C][0..cuwh].copy_from_slice(&cu_resi.data[V_C][0..cuwh]);
}
pub(crate) fn get_org_bi(
org_bi: &mut [i16],
org: &PlaneRegion<'_, pel>,
pred: &[pel],
x: usize,
y: usize,
cuw: usize,
cuh: usize,
) {
for j in 0..cuh {
for i in 0..cuw {
org_bi[j * cuw + i] = (org[y + j][x + i] << 1) as i16 - pred[j * cuw + i] as i16;
}
}
}
#[inline]
pub(crate) fn get_exp_golomb_bits(abs_mvd: u32) -> u32 {
let mut bits = 0;
let mut nn = ((abs_mvd + 1) >> 1);
let mut len_i = 0;
while len_i < 16 && nn != 0 {
nn >>= 1;
len_i += 1;
}
let len_c = (len_i << 1) + 1;
bits += len_c;
if abs_mvd != 0 {
bits += 1;
}
return bits;
}
pub(crate) fn get_mv_bits(mvd_x: i16, mvd_y: i16, num_refp: u8, refi: i8) -> u32 {
let mut bits = if mvd_x > 2048 || mvd_x <= -2048 {
get_exp_golomb_bits(mvd_x.abs() as u32)
} else {
evce_tbl_mv_bits_data[(MV_BITS_BASE as i16 + mvd_x) as usize] as u32
};
bits += if mvd_y > 2048 || mvd_y <= -2048 {
get_exp_golomb_bits(mvd_y.abs() as u32)
} else {
evce_tbl_mv_bits_data[(MV_BITS_BASE as i16 + mvd_y) as usize] as u32
};
bits += evce_tbl_refi_bits[num_refp as usize][refi as usize] as u32;
bits
}
#[inline]
pub(crate) fn MV_COST(lambda_mv: u32, mv_bits: u32) -> u32 {
(lambda_mv * mv_bits + (1 << 15)) >> 16
}
pub(crate) fn fill_dbf_block(
x: i16,
y: i16,
x_offset: i16,
y_offset: i16,
cuw: i16,
cuh: i16,
avail_lr: u16,
dst: &mut PlaneRegionMut<'_, pel>,
src: &[pel],
rec: &PlaneRegion<'_, pel>,
) {
for j in 0..cuh {
for i in 0..cuw {
dst[(y + j) as usize][(x + i) as usize] =
src[(j as i32 * cuw as i32 + i as i32) as usize];
}
}
if y != 0 {
for j in 0..y_offset {
for i in 0..cuw {
dst[std::cmp::max(y - y_offset + j, 0) as usize][(x + i) as usize] =
rec[std::cmp::max(y - y_offset + j, 0) as usize][(x + i) as usize];
}
}
}
if avail_lr == LR_10 || avail_lr == LR_11 {
for j in 0..cuh {
for i in 0..x_offset {
dst[(y + j) as usize][std::cmp::max(x - x_offset + i, 0) as usize] =
rec[(y + j) as usize][std::cmp::max(x - x_offset + i, 0) as usize];
}
}
}
if avail_lr == LR_01 || avail_lr == LR_11 {
for j in 0..cuh {
for i in 0..x_offset {
dst[(y + j) as usize][(x + cuw + i) as usize] =
rec[(y + j) as usize][(x + cuw + i) as usize];
}
}
}
}
pub(crate) fn dist_nofilt(
x: i16,
y: i16,
x_tm: i16,
y_tm: i16,
log2_cuw: usize,
log2_cuh: usize,
log2_x_tm: usize,
log2_y_tm: usize,
avail_lr: u16,
dst: &PlaneRegion<'_, pel>,
org: &PlaneRegion<'_, pel>,
) -> i64 {
let mut dist_nofilt = evce_ssd_16i(x, y, log2_cuw, log2_cuh, dst, org);
if y != 0 {
dist_nofilt += evce_ssd_16i(x, y - y_tm, log2_cuw, log2_y_tm, dst, org);
}
if avail_lr == LR_10 || avail_lr == LR_11 {
dist_nofilt += evce_ssd_16i(x - x_tm, y, log2_x_tm, log2_cuh, dst, org);
}
if avail_lr == LR_01 || avail_lr == LR_11 {
dist_nofilt += evce_ssd_16i(x + (1 << log2_cuw), y, log2_x_tm, log2_cuh, dst, org);
}
dist_nofilt
}