Commit c0b01f05 authored by Monty's avatar Monty Committed by Monty Montgomery
Browse files

Add block-level loop deblocking filter delta coding infrastructure

Add storage for block-level loop deblocking filter delta adjustments, as well as infrastructure for writing out these parameters.

Unused as yet.  No funcitonal change to current encoder.
parent 1f532552
......@@ -13,6 +13,7 @@ use std::cmp;
use context::*;
use plane::*;
use util::clamp;
use util::msb;
use FrameInvariants;
use Frame;
......@@ -24,10 +25,6 @@ pub struct CdefDirections {
pub const CDEF_VERY_LARGE: u16 = 30000;
const CDEF_SEC_STRENGTHS: u8 = 4;
fn msb(x: i32) -> i32 {
31 ^ (x.leading_zeros() as i32)
}
// Instead of dividing by n between 2 and 8, we multiply by 3*5*7*8/n.
// The output is then 840 times larger, but we don't care for finding
// the max. */
......
......@@ -24,6 +24,7 @@ use partition::TxType::*;
use partition::*;
use plane::*;
use util::clamp;
use util::msb;
use std::*;
use self::REF_CONTEXTS;
......@@ -71,6 +72,11 @@ const TX_SETS_INTER: usize = 4;
const MAX_REF_MV_STACK_SIZE: usize = 8;
pub const REF_CAT_LEVEL: u32 = 640;
const FRAME_LF_COUNT: usize = 4;
const MAX_LOOP_FILTER: usize = 63;
const DELTA_LF_SMALL: u32 = 3;
const DELTA_LF_PROBS: usize = DELTA_LF_SMALL as usize;
// Number of transform types in each set type
static num_tx_set: [usize; TX_SETS] =
[1, 2, 5, 7, 7, 10, 12, 16, 16];
......@@ -810,6 +816,8 @@ extern "C" {
static default_single_ref_cdf: [[[u16; 2 + 1]; SINGLE_REFS - 1]; REF_CONTEXTS];
static av1_scan_orders: [[SCAN_ORDER; TX_TYPES]; TxSize::TX_SIZES_ALL];
static default_delta_lf_multi_cdf: [[u16; DELTA_LF_PROBS + 1 + 1]; FRAME_LF_COUNT];
static default_delta_lf_cdf: [u16; DELTA_LF_PROBS + 1 + 1];
// lv_map
static av1_default_txb_skip_cdfs:
......@@ -875,6 +883,8 @@ pub struct CDFContext {
single_ref_cdfs: [[[u16; 2 + 1]; SINGLE_REFS - 1]; REF_CONTEXTS],
drl_cdfs: [[u16; 2 + 1]; DRL_MODE_CONTEXTS],
nmv_context: NMVContext,
deblock_delta_multi_cdf: [[u16; DELTA_LF_PROBS + 1 + 1]; FRAME_LF_COUNT],
deblock_delta_cdf: [u16; DELTA_LF_PROBS + 1 + 1],
// lv_map
txb_skip_cdf: [[[u16; 3]; TXB_SKIP_CONTEXTS]; TxSize::TX_SIZES],
......@@ -925,6 +935,8 @@ impl CDFContext {
single_ref_cdfs: default_single_ref_cdf,
drl_cdfs: default_drl_cdf,
nmv_context: default_nmv_context,
deblock_delta_multi_cdf: default_delta_lf_multi_cdf,
deblock_delta_cdf: default_delta_lf_cdf,
// lv_map
txb_skip_cdf: av1_default_txb_skip_cdfs[qctx],
......@@ -987,6 +999,19 @@ impl CDFContext {
self.filter_intra_cdfs.first().unwrap().as_ptr() as usize;
let filter_intra_cdfs_end =
filter_intra_cdfs_start + size_of_val(&self.filter_intra_cdfs);
let deblock_delta_multi_cdf_start =
self.deblock_delta_multi_cdf.first().unwrap().as_ptr() as usize;
let deblock_delta_multi_cdf_end =
deblock_delta_multi_cdf_start + size_of_val(&self.deblock_delta_multi_cdf);
let deblock_delta_cdf_start =
self.deblock_delta_cdf.as_ptr() as usize;
let deblock_delta_cdf_end =
deblock_delta_cdf_start + size_of_val(&self.deblock_delta_cdf);
let filter_intra_cdf_start =
self.filter_intra_cdfs.first().unwrap().as_ptr() as usize;
let filter_intra_cdfs_end =
filter_intra_cdfs_start + size_of_val(&self.filter_intra_cdfs);
let txb_skip_cdf_start =
self.txb_skip_cdf.first().unwrap().as_ptr() as usize;
let txb_skip_cdf_end =
......@@ -1052,6 +1077,8 @@ impl CDFContext {
("intra_inter_cdfs", intra_inter_cdfs_start, intra_inter_cdfs_end),
("angle_delta_cdf", angle_delta_cdf_start, angle_delta_cdf_end),
("filter_intra_cdfs", filter_intra_cdfs_start, filter_intra_cdfs_end),
("deblock_delta_multi_cdf", deblock_delta_multi_cdf_start, deblock_delta_multi_cdf_end),
("deblock_delta_cdf", deblock_delta_cdf_start, deblock_delta_cdf_end),
("txb_skip_cdf", txb_skip_cdf_start, txb_skip_cdf_end),
("dc_sign_cdf", dc_sign_cdf_start, dc_sign_cdf_end),
("eob_extra_cdf", eob_extra_cdf_start, eob_extra_cdf_end),
......@@ -1209,6 +1236,10 @@ pub struct Block {
pub tx_w: usize, /* transform width in the unit of mode_info */
pub tx_h: usize, /* transform height in the unit of mode_info */
pub is_sec_rect: bool,
// The block-level deblock_deltas are left-shifted by
// fi.deblock.block_delta_shift and added to the frame-configured
// deltas
pub deblock_deltas: [i8; FRAME_LF_COUNT]
}
impl Block {
......@@ -1226,6 +1257,7 @@ impl Block {
tx_w: TX_64X64.width_mi(),
tx_h: TX_64X64.height_mi(),
is_sec_rect: false,
deblock_deltas: [0, 0, 0, 0]
}
}
pub fn is_inter(&self) -> bool {
......@@ -1246,6 +1278,7 @@ pub struct BlockContext {
pub cols: usize,
pub rows: usize,
pub cdef_coded: bool,
pub code_deltas: bool,
above_partition_context: Vec<u8>,
left_partition_context: [u8; MAX_MIB_SIZE],
above_coeff_context: [Vec<u8>; PLANES],
......@@ -1262,6 +1295,7 @@ impl BlockContext {
cols,
rows,
cdef_coded: false,
code_deltas: false,
above_partition_context: vec![0; aligned_cols],
left_partition_context: [0; MAX_MIB_SIZE],
above_coeff_context: [
......@@ -1279,6 +1313,7 @@ impl BlockContext {
cols: self.cols,
rows: self.rows,
cdef_coded: self.cdef_coded,
code_deltas: self.code_deltas,
above_partition_context: self.above_partition_context.clone(),
left_partition_context: self.left_partition_context,
above_coeff_context: self.above_coeff_context.clone(),
......@@ -2571,6 +2606,32 @@ impl ContextWriter {
w.literal(bits, strength_index as u32);
}
pub fn write_block_deblock_deltas(&mut self, w: &mut dyn Writer,
bo: &BlockOffset, multi: bool) {
let block = self.bc.at(bo);
let deltas = if multi { FRAME_LF_COUNT + PLANES - 3 } else { 1 };
for i in 0..deltas {
let delta = block.deblock_deltas[i];
let abs:u32 = delta.abs() as u32;
if multi {
symbol_with_update!(self, w, cmp::min(abs, DELTA_LF_SMALL),
&mut self.fc.deblock_delta_multi_cdf[i]);
} else {
symbol_with_update!(self, w, cmp::min(abs, DELTA_LF_SMALL),
&mut self.fc.deblock_delta_cdf);
};
if abs >= DELTA_LF_SMALL {
let bits = msb(abs as i32 - 1) as u32;
w.literal(3, bits - 1);
w.literal(bits as u8, abs - (1<<bits) - 1);
}
if abs > 0 {
w.bool(delta < 0, 16384);
}
}
}
pub fn write_is_inter(&mut self, w: &mut dyn Writer, bo: &BlockOffset, is_inter: bool) {
let ctx = self.bc.intra_inter_context(bo);
symbol_with_update!(self, w, is_inter as u32, &mut self.fc.intra_inter_cdfs[ctx]);
......
......@@ -1226,7 +1226,7 @@ pub fn encode_block_a(seq: &Sequence,
cw.bc.cdef_coded
}
pub fn encode_block_b(fi: &FrameInvariants, fs: &mut FrameState,
pub fn encode_block_b(seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState,
cw: &mut ContextWriter, w: &mut dyn Writer,
luma_mode: PredictionMode, chroma_mode: PredictionMode,
ref_frame: usize, mv: MotionVector,
......@@ -1234,9 +1234,18 @@ pub fn encode_block_b(fi: &FrameInvariants, fs: &mut FrameState,
cfl: CFLParams) {
let is_inter = !luma_mode.is_intra();
if is_inter { assert!(luma_mode == chroma_mode); };
let sb_size = if seq.use_128x128_superblock {
BlockSize::BLOCK_128X128
} else {
BlockSize::BLOCK_64X64
};
cw.bc.set_block_size(bo, bsize);
cw.bc.set_mode(bo, bsize, luma_mode);
//write_q_deltas();
if cw.bc.code_deltas && fi.deblock.block_deltas_enabled && (bsize < sb_size || !skip) {
cw.write_block_deblock_deltas(w, bo, fi.deblock.block_delta_multi);
}
cw.bc.code_deltas = false;
if fi.frame_type == FrameType::INTER {
cw.write_is_inter(w, bo, is_inter);
......@@ -1617,7 +1626,7 @@ fn encode_partition_bottomup(seq: &Sequence, fi: &FrameInvariants, fs: &mut Fram
cdef_coded = encode_block_a(seq, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
bsize, bo, skip);
encode_block_b(fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
encode_block_b(seq, fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
mode_luma, mode_chroma, ref_frame, mv, bsize, bo, skip, seq.bit_depth, cfl);
best_decision = mode_decision;
......@@ -1670,7 +1679,7 @@ fn encode_partition_bottomup(seq: &Sequence, fi: &FrameInvariants, fs: &mut Fram
let mut cdef_coded = cw.bc.cdef_coded;
cdef_coded = encode_block_a(seq, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
bsize, bo, skip);
encode_block_b(fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
encode_block_b(seq, fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
mode_luma, mode_chroma, ref_frame, mv, bsize, bo, skip, seq.bit_depth, cfl);
}
}
......@@ -1751,7 +1760,7 @@ fn encode_partition_topdown(seq: &Sequence, fi: &FrameInvariants, fs: &mut Frame
// FIXME: every final block that has gone through the RDO decision process is encoded twice
cdef_coded = encode_block_a(seq, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
bsize, bo, skip);
encode_block_b(fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
encode_block_b(seq, fi, fs, cw, if cdef_coded {w_post_cdef} else {w_pre_cdef},
mode_luma, mode_chroma, ref_frame, mv, bsize, bo, skip, seq.bit_depth, cfl);
},
PartitionType::PARTITION_SPLIT => {
......@@ -1804,6 +1813,7 @@ fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameStat
let sbo = SuperBlockOffset { x: sbx, y: sby };
let bo = sbo.block_offset(0, 0);
cw.bc.cdef_coded = false;
cw.bc.code_deltas = fi.delta_q_present;
// Encode SuperBlock
if fi.config.speed == 0 {
......
......@@ -261,7 +261,7 @@ pub fn rdo_mode_decision(
encode_block_a(seq, cw, wr, bsize, bo, skip);
encode_block_b(fi, fs, cw, wr, luma_mode, chroma_mode, ref_frame, mv, bsize, bo, skip, seq.bit_depth, cfl);
encode_block_b(seq, fi, fs, cw, wr, luma_mode, chroma_mode, ref_frame, mv, bsize, bo, skip, seq.bit_depth, cfl);
let cost = wr.tell_frac() - tell;
let rd = compute_rd_cost(
......
......@@ -209,3 +209,9 @@ pub trait ILog : PrimInt {
}
impl<T> ILog for T where T: PrimInt {}
pub fn msb(x: i32) -> i32 {
debug_assert!(x>0);
31 ^ (x.leading_zeros() as i32)
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment