Unverified Commit 3a261f32 authored by Yushin Cho's avatar Yushin Cho Committed by GitHub

Early termination for bottomup partition search (i.e. speed 0 only) (#858)

This works for speed 0 (i.e. bottomup partition search) only.

Almost no change in bdrate with more than x2 faster for large QIndex 252
with no change in its bitstream size.
parent de68ab15
......@@ -2223,7 +2223,8 @@ pub fn encode_block_with_modes(fi: &FrameInvariants, fs: &mut FrameState,
fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
cw: &mut ContextWriter, w_pre_cdef: &mut dyn Writer, w_post_cdef: &mut dyn Writer,
bsize: BlockSize, bo: &BlockOffset, pmvs: &[[Option<MotionVector>; REF_FRAMES]; 5]
bsize: BlockSize, bo: &BlockOffset, pmvs: &[[Option<MotionVector>; REF_FRAMES]; 5],
ref_rd_cost: f64
) -> (f64, Option<RDOPartitionOutput>) {
let mut rd_cost = std::f64::MAX;
let mut best_rd = std::f64::MAX;
......@@ -2267,14 +2268,12 @@ fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
// Code the whole block
// TODO(yushin): Try move PARTITION_NONE to below partition loop
if !must_split {
best_partition = PartitionType::PARTITION_NONE;
let mut cost: f64 = 0.0;
if bsize.gte(BlockSize::BLOCK_8X8) && is_square {
let w: &mut dyn Writer = if cw.bc.cdef_coded {w_post_cdef} else {w_pre_cdef};
let tell = w.tell_frac();
cw.write_partition(w, bo, best_partition, bsize);
cw.write_partition(w, bo, PartitionType::PARTITION_NONE, bsize);
cost = (w.tell_frac() - tell) as f64 * get_lambda(fi)/ ((1 << OD_BITRES) as f64);
}
......@@ -2288,13 +2287,16 @@ fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
let mode_decision = rdo_mode_decision(fi, fs, cw, bsize, bo, spmvs, false).part_modes[0].clone();
rd_cost = mode_decision.rd_cost + cost;
best_rd = rd_cost;
encode_block_with_modes(fi, fs, cw, w_pre_cdef, w_post_cdef, bsize, bo,
&mode_decision);
if rd_cost < ref_rd_cost {
best_partition = PartitionType::PARTITION_NONE;
best_rd = rd_cost;
best_decision = mode_decision.clone();
best_pred_modes.push(best_decision.clone());
best_decision = mode_decision;
best_pred_modes.push(best_decision.clone());
encode_block_with_modes(fi, fs, cw, w_pre_cdef, w_post_cdef, bsize, bo,
&mode_decision);
}
}
// Test all partition types other than PARTITION_NONE by comparing their RD costs
......@@ -2342,7 +2344,7 @@ fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
// If either of horz or vert partition types is being tested,
// two partitioned rectangles, defined in 'partitions', of the current block
// is passed to encode_partition_bottomup()
partitions.iter().for_each(|&offset| {
for offset in partitions {
if let (cost, Some(mode_decision)) = encode_partition_bottomup(
fi,
fs,
......@@ -2351,22 +2353,25 @@ fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
w_post_cdef,
subsize,
offset,
pmvs//&best_decision.mvs[0]
pmvs,//&best_decision.mvs[0]
best_rd
) {
rd_cost += cost;
child_modes.push(mode_decision);
if rd_cost > best_rd || rd_cost > ref_rd_cost { break; }
else { child_modes.push(mode_decision); }
}
});
};
if rd_cost < best_rd {
if rd_cost < best_rd && rd_cost < ref_rd_cost {
best_rd = rd_cost;
best_partition = partition;
best_pred_modes = child_modes.clone();
}
}
// If the best partition is not PARTITION_SPLIT, recode it
if best_partition != PartitionType::PARTITION_SPLIT {
// If the best partition is not PARTITION_SPLIT or PARTITION_INVALID, recode it
if best_partition != PartitionType::PARTITION_SPLIT &&
best_partition != PartitionType::PARTITION_INVALID {
cw.rollback(&cw_checkpoint);
w_pre_cdef.rollback(&w_pre_checkpoint);
w_post_cdef.rollback(&w_post_checkpoint);
......@@ -2388,13 +2393,14 @@ fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState,
}
}
let subsize = bsize.subsize(best_partition);
if best_partition != PartitionType::PARTITION_INVALID {
let subsize = bsize.subsize(best_partition);
if bsize.gte(BlockSize::BLOCK_8X8) &&
(bsize == BlockSize::BLOCK_8X8 || best_partition != PartitionType::PARTITION_SPLIT) {
cw.bc.update_partition_context(bo, subsize, bsize);
if bsize.gte(BlockSize::BLOCK_8X8) &&
(bsize == BlockSize::BLOCK_8X8 || best_partition != PartitionType::PARTITION_SPLIT) {
cw.bc.update_partition_context(bo, subsize, bsize);
}
}
(best_rd, Some(best_decision))
}
......@@ -2701,7 +2707,7 @@ fn encode_tile(fi: &FrameInvariants, fs: &mut FrameState) -> Vec<u8> {
if fi.config.speed_settings.encode_bottomup {
encode_partition_bottomup(fi, fs, &mut cw,
&mut w_pre_cdef, &mut w_post_cdef,
BlockSize::BLOCK_64X64, &bo, &pmvs);
BlockSize::BLOCK_64X64, &bo, &pmvs, std::f64::MAX);
}
else {
encode_partition_topdown(fi, fs, &mut cw,
......
Markdown is supported
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