From b6d766bf5e0cae21483dd5d7772b3110543d2990 Mon Sep 17 00:00:00 2001 From: Yushin Cho <cho.yushin@gmail.com> Date: Wed, 12 Sep 2018 21:14:38 -0700 Subject: [PATCH] [WIP] ME use predicted search center for topdown partition search (#569) ME use predicted search center for topdown partition search --- src/encoder.rs | 6 ++++-- src/me.rs | 10 +++++----- src/rdo.rs | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/encoder.rs b/src/encoder.rs index 8bf74a38..69ddf1b2 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -1678,7 +1678,8 @@ fn encode_partition_bottomup(seq: &Sequence, fi: &FrameInvariants, fs: &mut Fram cw.write_partition(w, bo, partition, bsize); cost = (w.tell_frac() - tell) as f64 * get_lambda(fi, seq.bit_depth)/ ((1 << OD_BITRES) as f64); } - let mode_decision = rdo_mode_decision(seq, fi, fs, cw, bsize, bo).part_modes[0].clone(); + let pmv = MotionVector { row: 0, col: 0 }; + let mode_decision = rdo_mode_decision(seq, fi, fs, cw, bsize, bo, &pmv).part_modes[0].clone(); let (mode_luma, mode_chroma) = (mode_decision.pred_mode_luma, mode_decision.pred_mode_chroma); let cfl = mode_decision.pred_cfl_params; let ref_frame = mode_decision.ref_frame; @@ -1818,6 +1819,7 @@ fn encode_partition_topdown(seq: &Sequence, fi: &FrameInvariants, fs: &mut Frame let hbs = bs >> 1; // Half the block size in blocks let subsize = get_subsize(bsize, partition); + let pmv = MotionVector { row: 0, col: 0 }; if bsize >= BlockSize::BLOCK_8X8 { let w: &mut dyn Writer = if cw.bc.cdef_coded {w_post_cdef} else {w_pre_cdef}; @@ -1831,7 +1833,7 @@ fn encode_partition_topdown(seq: &Sequence, fi: &FrameInvariants, fs: &mut Frame rdo_output.part_modes[0].clone() } else { // Make a prediction mode decision for blocks encoded with no rdo_partition_decision call (e.g. edges) - rdo_mode_decision(seq, fi, fs, cw, bsize, bo).part_modes[0].clone() + rdo_mode_decision(seq, fi, fs, cw, bsize, bo, &pmv).part_modes[0].clone() }; let mut mode_luma = part_decision.pred_mode_luma; diff --git a/src/me.rs b/src/me.rs index 8a6267e4..329fd129 100644 --- a/src/me.rs +++ b/src/me.rs @@ -41,7 +41,7 @@ pub fn get_sad( pub fn motion_estimation( fi: &FrameInvariants, fs: &mut FrameState, bsize: BlockSize, - bo: &BlockOffset, ref_frame: usize + bo: &BlockOffset, ref_frame: usize, pmv: &MotionVector ) -> MotionVector { match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] { Some(ref rec) => { @@ -58,10 +58,10 @@ pub fn motion_estimation( let mvx_max = (fi.w_in_b - bo.x - blk_w / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_w; let mvy_min = -(bo.y as isize) * (8 * MI_SIZE) as isize - border_h; let mvy_max = (fi.h_in_b - bo.y - blk_h / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_h; - let x_lo = po.x + ((-range).max(mvx_min / 8)); - let x_hi = po.x + (range.min(mvx_max / 8)); - let y_lo = po.y + ((-range).max(mvy_min / 8)); - let y_hi = po.y + (range.min(mvy_max / 8)); + let x_lo = po.x + ((-range + (pmv.col / 8) as isize).max(mvx_min / 8)); + let x_hi = po.x + ((range + (pmv.col / 8) as isize).min(mvx_max / 8)); + let y_lo = po.y + ((-range + (pmv.row / 8) as isize).max(mvy_min / 8)); + let y_hi = po.y + ((range + (pmv.row / 8) as isize).min(mvy_max / 8)); let mut lowest_sad = 128 * 128 * 4096 as u32; let mut best_mv = MotionVector { row: 0, col: 0 }; diff --git a/src/rdo.rs b/src/rdo.rs index b5fbb9fb..5198abf5 100755 --- a/src/rdo.rs +++ b/src/rdo.rs @@ -251,7 +251,8 @@ pub fn rdo_tx_size_type( // RDO-based mode decision pub fn rdo_mode_decision( seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, - cw: &mut ContextWriter, bsize: BlockSize, bo: &BlockOffset + cw: &mut ContextWriter, bsize: BlockSize, bo: &BlockOffset, + pmv: &MotionVector ) -> RDOOutput { let mut best_mode_luma = PredictionMode::DC_PRED; let mut best_mode_chroma = PredictionMode::DC_PRED; @@ -312,7 +313,7 @@ pub fn rdo_mode_decision( let ref_frame = if luma_mode_is_intra { INTRA_FRAME } else { LAST_FRAME }; let mv = match luma_mode { - PredictionMode::NEWMV => motion_estimation(fi, fs, bsize, bo, ref_frame), + PredictionMode::NEWMV => motion_estimation(fi, fs, bsize, bo, ref_frame, pmv), PredictionMode::NEARESTMV => if mv_stack.len() > 0 { mv_stack[0].this_mv } else { @@ -578,6 +579,7 @@ pub fn rdo_partition_decision( let mut rd: f64; let mut child_modes = std::vec::Vec::new(); + let mut pmv = MotionVector { row: 0, col: 0 }; match partition { PartitionType::PARTITION_NONE => { @@ -589,7 +591,7 @@ pub fn rdo_partition_decision( .part_modes .get(0) .unwrap_or( - &rdo_mode_decision(seq, fi, fs, cw, bsize, bo).part_modes[0] + &rdo_mode_decision(seq, fi, fs, cw, bsize, bo, &pmv).part_modes[0] ).clone(); child_modes.push(mode_decision); } @@ -599,32 +601,33 @@ pub fn rdo_partition_decision( if subsize == BlockSize::BLOCK_INVALID { continue; } + pmv = best_pred_modes[0].mv; + assert!(best_pred_modes.len() <= 4); let bs = bsize.width_mi(); let hbs = bs >> 1; // Half the block size in blocks - let offset = BlockOffset { x: bo.x, y: bo.y }; let mode_decision = - rdo_mode_decision(seq, fi, fs, cw, subsize, &offset).part_modes[0] + rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, &pmv).part_modes[0] .clone(); child_modes.push(mode_decision); let offset = BlockOffset { x: bo.x + hbs as usize, y: bo.y }; let mode_decision = - rdo_mode_decision(seq, fi, fs, cw, subsize, &offset).part_modes[0] + rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, &pmv).part_modes[0] .clone(); child_modes.push(mode_decision); let offset = BlockOffset { x: bo.x, y: bo.y + hbs as usize }; let mode_decision = - rdo_mode_decision(seq, fi, fs, cw, subsize, &offset).part_modes[0] + rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, &pmv).part_modes[0] .clone(); child_modes.push(mode_decision); let offset = BlockOffset { x: bo.x + hbs as usize, y: bo.y + hbs as usize }; let mode_decision = - rdo_mode_decision(seq, fi, fs, cw, subsize, &offset).part_modes[0] + rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, &pmv).part_modes[0] .clone(); child_modes.push(mode_decision); } -- GitLab