Index: source/libvpx/vp9/encoder/vp9_rdopt.c |
diff --git a/source/libvpx/vp9/encoder/vp9_rdopt.c b/source/libvpx/vp9/encoder/vp9_rdopt.c |
index 51397a791a26fce21cec6c34ac3211865113a253..09512df18949fdea6ef21106feccbd17f06bc442 100644 |
--- a/source/libvpx/vp9/encoder/vp9_rdopt.c |
+++ b/source/libvpx/vp9/encoder/vp9_rdopt.c |
@@ -1261,13 +1261,6 @@ static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode, |
return cpi->inter_mode_cost[mode_context][INTER_OFFSET(mode)]; |
} |
-static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x, |
- BLOCK_SIZE bsize, |
- int_mv *frame_mv, |
- int mi_row, int mi_col, |
- int_mv single_newmv[MAX_REF_FRAMES], |
- int *rate_mv); |
- |
static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i, |
PREDICTION_MODE mode, int_mv this_mv[2], |
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES], |
@@ -1541,6 +1534,192 @@ static int check_best_zero_mv( |
return 1; |
} |
+static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x, |
+ BLOCK_SIZE bsize, |
+ int_mv *frame_mv, |
+ int mi_row, int mi_col, |
+ int_mv single_newmv[MAX_REF_FRAMES], |
+ int *rate_mv) { |
+ const int pw = 4 * num_4x4_blocks_wide_lookup[bsize]; |
+ const int ph = 4 * num_4x4_blocks_high_lookup[bsize]; |
+ MACROBLOCKD *xd = &x->e_mbd; |
+ MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; |
+ const int refs[2] = {mbmi->ref_frame[0], |
+ mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]}; |
+ int_mv ref_mv[2]; |
+ int ite, ref; |
+ // Prediction buffer from second frame. |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ uint8_t *second_pred; |
+ uint8_t *second_pred_alloc; |
+#else |
+ uint8_t *second_pred = vpx_memalign(16, pw * ph * sizeof(uint8_t)); |
+#endif // CONFIG_VP9_HIGHBITDEPTH |
+ const InterpKernel *kernel = vp9_get_interp_kernel(mbmi->interp_filter); |
+ |
+ // Do joint motion search in compound mode to get more accurate mv. |
+ struct buf_2d backup_yv12[2][MAX_MB_PLANE]; |
+ int last_besterr[2] = {INT_MAX, INT_MAX}; |
+ const YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = { |
+ vp9_get_scaled_ref_frame(cpi, mbmi->ref_frame[0]), |
+ vp9_get_scaled_ref_frame(cpi, mbmi->ref_frame[1]) |
+ }; |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { |
+ second_pred_alloc = vpx_memalign(16, pw * ph * sizeof(uint16_t)); |
+ second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc); |
+ } else { |
+ second_pred_alloc = vpx_memalign(16, pw * ph * sizeof(uint8_t)); |
+ second_pred = second_pred_alloc; |
+ } |
+#endif // CONFIG_VP9_HIGHBITDEPTH |
+ |
+ for (ref = 0; ref < 2; ++ref) { |
+ ref_mv[ref] = mbmi->ref_mvs[refs[ref]][0]; |
+ |
+ if (scaled_ref_frame[ref]) { |
+ int i; |
+ // Swap out the reference frame for a version that's been scaled to |
+ // match the resolution of the current frame, allowing the existing |
+ // motion search code to be used without additional modifications. |
+ for (i = 0; i < MAX_MB_PLANE; i++) |
+ backup_yv12[ref][i] = xd->plane[i].pre[ref]; |
+ vp9_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col, |
+ NULL); |
+ } |
+ |
+ frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int; |
+ } |
+ |
+ // Allow joint search multiple times iteratively for each reference frame |
+ // and break out of the search loop if it couldn't find a better mv. |
+ for (ite = 0; ite < 4; ite++) { |
+ struct buf_2d ref_yv12[2]; |
+ int bestsme = INT_MAX; |
+ int sadpb = x->sadperbit16; |
+ MV tmp_mv; |
+ int search_range = 3; |
+ |
+ int tmp_col_min = x->mv_col_min; |
+ int tmp_col_max = x->mv_col_max; |
+ int tmp_row_min = x->mv_row_min; |
+ int tmp_row_max = x->mv_row_max; |
+ int id = ite % 2; // Even iterations search in the first reference frame, |
+ // odd iterations search in the second. The predictor |
+ // found for the 'other' reference frame is factored in. |
+ |
+ // Initialized here because of compiler problem in Visual Studio. |
+ ref_yv12[0] = xd->plane[0].pre[0]; |
+ ref_yv12[1] = xd->plane[0].pre[1]; |
+ |
+ // Get the prediction block from the 'other' reference frame. |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { |
+ vp9_highbd_build_inter_predictor(ref_yv12[!id].buf, |
+ ref_yv12[!id].stride, |
+ second_pred, pw, |
+ &frame_mv[refs[!id]].as_mv, |
+ &xd->block_refs[!id]->sf, |
+ pw, ph, 0, |
+ kernel, MV_PRECISION_Q3, |
+ mi_col * MI_SIZE, mi_row * MI_SIZE, |
+ xd->bd); |
+ } else { |
+ vp9_build_inter_predictor(ref_yv12[!id].buf, |
+ ref_yv12[!id].stride, |
+ second_pred, pw, |
+ &frame_mv[refs[!id]].as_mv, |
+ &xd->block_refs[!id]->sf, |
+ pw, ph, 0, |
+ kernel, MV_PRECISION_Q3, |
+ mi_col * MI_SIZE, mi_row * MI_SIZE); |
+ } |
+#else |
+ vp9_build_inter_predictor(ref_yv12[!id].buf, |
+ ref_yv12[!id].stride, |
+ second_pred, pw, |
+ &frame_mv[refs[!id]].as_mv, |
+ &xd->block_refs[!id]->sf, |
+ pw, ph, 0, |
+ kernel, MV_PRECISION_Q3, |
+ mi_col * MI_SIZE, mi_row * MI_SIZE); |
+#endif // CONFIG_VP9_HIGHBITDEPTH |
+ |
+ // Do compound motion search on the current reference frame. |
+ if (id) |
+ xd->plane[0].pre[0] = ref_yv12[id]; |
+ vp9_set_mv_search_range(x, &ref_mv[id].as_mv); |
+ |
+ // Use the mv result from the single mode as mv predictor. |
+ tmp_mv = frame_mv[refs[id]].as_mv; |
+ |
+ tmp_mv.col >>= 3; |
+ tmp_mv.row >>= 3; |
+ |
+ // Small-range full-pixel motion search. |
+ bestsme = vp9_refining_search_8p_c(x, &tmp_mv, sadpb, |
+ search_range, |
+ &cpi->fn_ptr[bsize], |
+ &ref_mv[id].as_mv, second_pred); |
+ if (bestsme < INT_MAX) |
+ bestsme = vp9_get_mvpred_av_var(x, &tmp_mv, &ref_mv[id].as_mv, |
+ second_pred, &cpi->fn_ptr[bsize], 1); |
+ |
+ x->mv_col_min = tmp_col_min; |
+ x->mv_col_max = tmp_col_max; |
+ x->mv_row_min = tmp_row_min; |
+ x->mv_row_max = tmp_row_max; |
+ |
+ if (bestsme < INT_MAX) { |
+ int dis; /* TODO: use dis in distortion calculation later. */ |
+ unsigned int sse; |
+ bestsme = cpi->find_fractional_mv_step( |
+ x, &tmp_mv, |
+ &ref_mv[id].as_mv, |
+ cpi->common.allow_high_precision_mv, |
+ x->errorperbit, |
+ &cpi->fn_ptr[bsize], |
+ 0, cpi->sf.mv.subpel_iters_per_step, |
+ NULL, |
+ x->nmvjointcost, x->mvcost, |
+ &dis, &sse, second_pred, |
+ pw, ph); |
+ } |
+ |
+ // Restore the pointer to the first (possibly scaled) prediction buffer. |
+ if (id) |
+ xd->plane[0].pre[0] = ref_yv12[0]; |
+ |
+ if (bestsme < last_besterr[id]) { |
+ frame_mv[refs[id]].as_mv = tmp_mv; |
+ last_besterr[id] = bestsme; |
+ } else { |
+ break; |
+ } |
+ } |
+ |
+ *rate_mv = 0; |
+ |
+ for (ref = 0; ref < 2; ++ref) { |
+ if (scaled_ref_frame[ref]) { |
+ // Restore the prediction frame pointers to their unscaled versions. |
+ int i; |
+ for (i = 0; i < MAX_MB_PLANE; i++) |
+ xd->plane[i].pre[ref] = backup_yv12[ref][i]; |
+ } |
+ |
+ *rate_mv += vp9_mv_bit_cost(&frame_mv[refs[ref]].as_mv, |
+ &mbmi->ref_mvs[refs[ref]][0].as_mv, |
+ x->nmvjointcost, x->mvcost, MV_COST_WEIGHT); |
+ } |
+ |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ vpx_free(second_pred_alloc); |
+#else |
+ vpx_free(second_pred); |
+#endif // CONFIG_VP9_HIGHBITDEPTH |
+} |
+ |
static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x, |
const TileInfo * const tile, |
int_mv *best_ref_mv, |
@@ -2172,189 +2351,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, |
} |
} |
-static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x, |
- BLOCK_SIZE bsize, |
- int_mv *frame_mv, |
- int mi_row, int mi_col, |
- int_mv single_newmv[MAX_REF_FRAMES], |
- int *rate_mv) { |
- const int pw = 4 * num_4x4_blocks_wide_lookup[bsize]; |
- const int ph = 4 * num_4x4_blocks_high_lookup[bsize]; |
- MACROBLOCKD *xd = &x->e_mbd; |
- MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; |
- const int refs[2] = { mbmi->ref_frame[0], |
- mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] }; |
- int_mv ref_mv[2]; |
- int ite, ref; |
- // Prediction buffer from second frame. |
-#if CONFIG_VP9_HIGHBITDEPTH |
- uint8_t *second_pred; |
- uint8_t *second_pred_alloc; |
-#else |
- uint8_t *second_pred = vpx_memalign(16, pw * ph * sizeof(uint8_t)); |
-#endif // CONFIG_VP9_HIGHBITDEPTH |
- const InterpKernel *kernel = vp9_get_interp_kernel(mbmi->interp_filter); |
- |
- // Do joint motion search in compound mode to get more accurate mv. |
- struct buf_2d backup_yv12[2][MAX_MB_PLANE]; |
- struct buf_2d scaled_first_yv12 = xd->plane[0].pre[0]; |
- int last_besterr[2] = {INT_MAX, INT_MAX}; |
- const YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = { |
- vp9_get_scaled_ref_frame(cpi, mbmi->ref_frame[0]), |
- vp9_get_scaled_ref_frame(cpi, mbmi->ref_frame[1]) |
- }; |
-#if CONFIG_VP9_HIGHBITDEPTH |
- if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { |
- second_pred_alloc = vpx_memalign(16, pw * ph * sizeof(uint16_t)); |
- second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc); |
- } else { |
- second_pred_alloc = vpx_memalign(16, pw * ph * sizeof(uint8_t)); |
- second_pred = second_pred_alloc; |
- } |
-#endif // CONFIG_VP9_HIGHBITDEPTH |
- |
- for (ref = 0; ref < 2; ++ref) { |
- ref_mv[ref] = mbmi->ref_mvs[refs[ref]][0]; |
- |
- if (scaled_ref_frame[ref]) { |
- int i; |
- // Swap out the reference frame for a version that's been scaled to |
- // match the resolution of the current frame, allowing the existing |
- // motion search code to be used without additional modifications. |
- for (i = 0; i < MAX_MB_PLANE; i++) |
- backup_yv12[ref][i] = xd->plane[i].pre[ref]; |
- vp9_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col, |
- NULL); |
- } |
- |
- frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int; |
- } |
- |
- // Allow joint search multiple times iteratively for each ref frame |
- // and break out the search loop if it couldn't find better mv. |
- for (ite = 0; ite < 4; ite++) { |
- struct buf_2d ref_yv12[2]; |
- int bestsme = INT_MAX; |
- int sadpb = x->sadperbit16; |
- MV tmp_mv; |
- int search_range = 3; |
- |
- int tmp_col_min = x->mv_col_min; |
- int tmp_col_max = x->mv_col_max; |
- int tmp_row_min = x->mv_row_min; |
- int tmp_row_max = x->mv_row_max; |
- int id = ite % 2; |
- |
- // Initialized here because of compiler problem in Visual Studio. |
- ref_yv12[0] = xd->plane[0].pre[0]; |
- ref_yv12[1] = xd->plane[0].pre[1]; |
- |
- // Get pred block from second frame. |
-#if CONFIG_VP9_HIGHBITDEPTH |
- if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { |
- vp9_highbd_build_inter_predictor(ref_yv12[!id].buf, |
- ref_yv12[!id].stride, |
- second_pred, pw, |
- &frame_mv[refs[!id]].as_mv, |
- &xd->block_refs[!id]->sf, |
- pw, ph, 0, |
- kernel, MV_PRECISION_Q3, |
- mi_col * MI_SIZE, mi_row * MI_SIZE, |
- xd->bd); |
- } else { |
- vp9_build_inter_predictor(ref_yv12[!id].buf, |
- ref_yv12[!id].stride, |
- second_pred, pw, |
- &frame_mv[refs[!id]].as_mv, |
- &xd->block_refs[!id]->sf, |
- pw, ph, 0, |
- kernel, MV_PRECISION_Q3, |
- mi_col * MI_SIZE, mi_row * MI_SIZE); |
- } |
-#else |
- vp9_build_inter_predictor(ref_yv12[!id].buf, |
- ref_yv12[!id].stride, |
- second_pred, pw, |
- &frame_mv[refs[!id]].as_mv, |
- &xd->block_refs[!id]->sf, |
- pw, ph, 0, |
- kernel, MV_PRECISION_Q3, |
- mi_col * MI_SIZE, mi_row * MI_SIZE); |
-#endif // CONFIG_VP9_HIGHBITDEPTH |
- |
- // Compound motion search on first ref frame. |
- if (id) |
- xd->plane[0].pre[0] = ref_yv12[id]; |
- vp9_set_mv_search_range(x, &ref_mv[id].as_mv); |
- |
- // Use mv result from single mode as mvp. |
- tmp_mv = frame_mv[refs[id]].as_mv; |
- |
- tmp_mv.col >>= 3; |
- tmp_mv.row >>= 3; |
- |
- // Small-range full-pixel motion search |
- bestsme = vp9_refining_search_8p_c(x, &tmp_mv, sadpb, |
- search_range, |
- &cpi->fn_ptr[bsize], |
- &ref_mv[id].as_mv, second_pred); |
- if (bestsme < INT_MAX) |
- bestsme = vp9_get_mvpred_av_var(x, &tmp_mv, &ref_mv[id].as_mv, |
- second_pred, &cpi->fn_ptr[bsize], 1); |
- |
- x->mv_col_min = tmp_col_min; |
- x->mv_col_max = tmp_col_max; |
- x->mv_row_min = tmp_row_min; |
- x->mv_row_max = tmp_row_max; |
- if (bestsme < INT_MAX) { |
- int dis; /* TODO: use dis in distortion calculation later. */ |
- unsigned int sse; |
- bestsme = cpi->find_fractional_mv_step( |
- x, &tmp_mv, |
- &ref_mv[id].as_mv, |
- cpi->common.allow_high_precision_mv, |
- x->errorperbit, |
- &cpi->fn_ptr[bsize], |
- 0, cpi->sf.mv.subpel_iters_per_step, |
- NULL, |
- x->nmvjointcost, x->mvcost, |
- &dis, &sse, second_pred, |
- pw, ph); |
- } |
- |
- if (id) |
- xd->plane[0].pre[0] = scaled_first_yv12; |
- |
- if (bestsme < last_besterr[id]) { |
- frame_mv[refs[id]].as_mv = tmp_mv; |
- last_besterr[id] = bestsme; |
- } else { |
- break; |
- } |
- } |
- |
- *rate_mv = 0; |
- |
- for (ref = 0; ref < 2; ++ref) { |
- if (scaled_ref_frame[ref]) { |
- // restore the predictor |
- int i; |
- for (i = 0; i < MAX_MB_PLANE; i++) |
- xd->plane[i].pre[ref] = backup_yv12[ref][i]; |
- } |
- |
- *rate_mv += vp9_mv_bit_cost(&frame_mv[refs[ref]].as_mv, |
- &mbmi->ref_mvs[refs[ref]][0].as_mv, |
- x->nmvjointcost, x->mvcost, MV_COST_WEIGHT); |
- } |
- |
-#if CONFIG_VP9_HIGHBITDEPTH |
- vpx_free(second_pred_alloc); |
-#else |
- vpx_free(second_pred); |
-#endif // CONFIG_VP9_HIGHBITDEPTH |
-} |
static INLINE void restore_dst_buf(MACROBLOCKD *xd, |
uint8_t *orig_dst[MAX_MB_PLANE], |