Skip to content

Commit

Permalink
Early termination for bottomup partition search (i.e. speed 0 only) (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
ycho committed Jan 16, 2019
1 parent de68ab1 commit 3a261f3
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions src/encoder.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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; }

This comment has been minimized.

Copy link
@KyleSiefring

KyleSiefring Jan 16, 2019

Collaborator

Should this be !(best_rd < rd_cost) || !(rd_cost < ref_rd_cost)?

This comment has been minimized.

Copy link
@ycho

ycho Jan 18, 2019

Author Collaborator

Right, and that is equivalent to adding equality conditions, i.e. rd_cost >= best_rd || rd_cost >= ref_rd_cost.

else { child_modes.push(mode_decision); }
}
});
};

if rd_cost < best_rd {
if rd_cost < best_rd && rd_cost < ref_rd_cost {

This comment has been minimized.

Copy link
@KyleSiefring

KyleSiefring Jan 16, 2019

Collaborator

To match this?

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);
Expand All @@ -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))
}

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 3a261f3

Please sign in to comment.