Unverified Commit c2d7b6af authored by fbossen's avatar fbossen Committed by GitHub
Browse files

Test skip on and off in RDO loop (#474)

* Refactor RDO loop to avoid code duplication

Use same code regardless of whether a loop over chroma modes
is needed

* Test skip on and off in RDO loop

* Don't search transform type when skipping

* Don't try to skip when using intra modes

* Fix issues with speed 0 and speed 1

Handling of < 8x8 was incorrect in CDEF and in reset_skip_context()

* Use dense sampling for chroma components in above_coeff_context and left_coeff_context
parent bf537275
......@@ -211,7 +211,11 @@ pub fn cdef_analyze_superblock(in_frame: &mut Frame,
// in the main frame.
let global_block_offset = sbo_global.block_offset(bx<<1, by<<1);
if global_block_offset.x < bc_global.cols && global_block_offset.y < bc_global.rows {
let skip = bc_global.at(&global_block_offset).skip;
let skip = bc_global.at(&global_block_offset).skip
& bc_global.at(&sbo_global.block_offset(2*bx+1, 2*by)).skip
& bc_global.at(&sbo_global.block_offset(2*bx, 2*by+1)).skip
& bc_global.at(&sbo_global.block_offset(2*bx+1, 2*by+1)).skip;
if !skip {
let mut var: i32 = 0;
let mut in_plane = &mut in_frame.planes[0];
......@@ -260,7 +264,10 @@ pub fn cdef_filter_superblock(fi: &FrameInvariants,
for bx in 0..8 {
let global_block_offset = sbo_global.block_offset(bx<<1, by<<1);
if global_block_offset.x < bc_global.cols && global_block_offset.y < bc_global.rows {
let skip = bc_global.at(&global_block_offset).skip;
let skip = bc_global.at(&global_block_offset).skip
& bc_global.at(&sbo_global.block_offset(2*bx+1, 2*by)).skip
& bc_global.at(&sbo_global.block_offset(2*bx, 2*by+1)).skip
& bc_global.at(&sbo_global.block_offset(2*bx+1, 2*by+1)).skip;
if !skip {
let dir = cdef_dirs.dir[bx][by];
let var = cdef_dirs.var[bx][by];
......
......@@ -1248,14 +1248,12 @@ impl BlockContext {
&mut self, plane: usize, bo: &BlockOffset, tx_size: TxSize, xdec: usize,
ydec: usize, value: u8
) {
// for subsampled planes, coeff contexts are stored sparsely at the moment
// so we need to scale our fill by xdec and ydec
for bx in 0..tx_size.width_mi() {
self.above_coeff_context[plane][bo.x + (bx << xdec)] = value;
self.above_coeff_context[plane][(bo.x >> xdec) + bx] = value;
}
let bo_y = bo.y_in_sb();
for by in 0..tx_size.height_mi() {
self.left_coeff_context[plane][bo_y + (by << ydec)] = value;
self.left_coeff_context[plane][(bo_y >> ydec) + by] = value;
}
}
......@@ -1303,12 +1301,12 @@ impl BlockContext {
let bh = plane_bsize.height_mi();
for bx in 0..bw {
self.above_coeff_context[plane][bo.x + (bx << xdec2) as usize] = 0;
self.above_coeff_context[plane][(bo.x >> xdec2) + bx] = 0;
}
let bo_y = bo.y_in_sb();
for by in 0..bh {
self.left_coeff_context[plane][bo_y + (by << ydec2) as usize] = 0;
self.left_coeff_context[plane][(bo_y >> ydec2) + by] = 0;
}
}
}
......@@ -1470,14 +1468,14 @@ impl BlockContext {
// Decide txb_ctx.dc_sign_ctx
for k in 0..txb_w_unit {
let sign = self.above_coeff_context[plane][bo.x + (k << xdec)]
let sign = self.above_coeff_context[plane][(bo.x >> xdec) + k]
>> COEFF_CONTEXT_BITS;
assert!(sign <= 2);
dc_sign += signs[sign as usize] as i16;
}
for k in 0..txb_h_unit {
let sign = self.left_coeff_context[plane][bo.y_in_sb() + (k << ydec)]
let sign = self.left_coeff_context[plane][(bo.y_in_sb() >> ydec) + k]
>> COEFF_CONTEXT_BITS;
assert!(sign <= 2);
dc_sign += signs[sign as usize] as i16;
......@@ -1513,12 +1511,12 @@ impl BlockContext {
let mut left: u8 = 0;
for k in 0..txb_w_unit {
top |= self.above_coeff_context[0][bo.x + k];
top |= self.above_coeff_context[0][(bo.x >> xdec) + k];
}
top &= COEFF_CONTEXT_MASK as u8;
for k in 0..txb_h_unit {
left |= self.left_coeff_context[0][bo.y_in_sb() + k];
left |= self.left_coeff_context[0][(bo.y_in_sb() >> ydec) + k];
}
left &= COEFF_CONTEXT_MASK as u8;
......@@ -1532,10 +1530,10 @@ impl BlockContext {
let mut left: u8 = 0;
for k in 0..txb_w_unit {
top |= self.above_coeff_context[plane][bo.x + (k << xdec)];
top |= self.above_coeff_context[plane][(bo.x >> xdec) + k];
}
for k in 0..txb_h_unit {
left |= self.left_coeff_context[plane][bo.y_in_sb() + (k << ydec)];
left |= self.left_coeff_context[plane][(bo.y_in_sb() >> ydec) + k];
}
let ctx_base = (top != 0) as usize + (left != 0) as usize;
let ctx_offset = if num_pels_log2_lookup[plane_bsize as usize]
......
......@@ -1214,7 +1214,7 @@ fn encode_block_b(fi: &FrameInvariants, fs: &mut FrameState,
// Luma plane transform type decision
let tx_set = get_tx_set(tx_size, is_inter, fi.use_reduced_tx_set);
let tx_type = if tx_set > TxSet::TX_SET_DCTONLY && fi.config.speed <= 3 {
let tx_type = if tx_set > TxSet::TX_SET_DCTONLY && fi.config.speed <= 3 && !skip {
// FIXME: there is one redundant transform type decision per encoded block
rdo_tx_type_decision(fi, fs, cw, luma_mode, bsize, bo, tx_size, tx_set, bit_depth)
} else {
......
......@@ -192,8 +192,6 @@ pub fn rdo_mode_decision(
h_uv = 4;
}
let skip = false;
let cw_checkpoint = cw.checkpoint();
// Exclude complex prediction modes at higher speed levels
......@@ -208,12 +206,22 @@ pub fn rdo_mode_decision(
for &luma_mode in mode_set {
assert!(fi.frame_type == FrameType::INTER || luma_mode.is_intra());
if is_chroma_block && fi.config.speed <= 3 && luma_mode.is_intra() {
// Find the best chroma prediction mode for the current luma prediction mode
for &chroma_mode in RAV1E_INTRA_MODES {
let same_as_luma_modes = &[ luma_mode ];
let mode_set_chroma = if is_chroma_block && fi.config.speed <= 3 && luma_mode.is_intra() {
RAV1E_INTRA_MODES
} else {
same_as_luma_modes
};
// Find the best chroma prediction mode for the current luma prediction mode
for &chroma_mode in mode_set_chroma {
for &skip in &[false, true] {
// Don't skip when using intra modes
if skip && luma_mode.is_intra() { continue; }
let mut wr: &mut dyn Writer = &mut WriterCounter::new();
let tell = wr.tell_frac();
encode_block_a(seq, cw, wr, bsize, bo, skip);
encode_block_b(fi, fs, cw, wr, luma_mode, chroma_mode, bsize, bo, skip, seq.bit_depth);
......@@ -239,33 +247,6 @@ pub fn rdo_mode_decision(
cw.rollback(&cw_checkpoint);
}
} else {
let mut wr: &mut dyn Writer = &mut WriterCounter::new();
let tell = wr.tell_frac();
encode_block_a(seq, cw, wr, bsize, bo, skip);
encode_block_b(fi, fs, cw, wr, luma_mode, luma_mode, bsize, bo, skip, seq.bit_depth);
let cost = wr.tell_frac() - tell;
let rd = compute_rd_cost(
fi,
fs,
w,
h,
w_uv,
h_uv,
bo,
cost,
seq.bit_depth
);
if rd < best_rd {
best_rd = rd;
best_mode_luma = luma_mode;
best_mode_chroma = luma_mode;
best_skip = skip;
}
cw.rollback(&cw_checkpoint);
}
}
......
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