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 038d1e11e301bc91a0e4f993b6c202ee73b4ff17..3c84a7753789930ea5f210441f8672cc70750a33 100644 |
--- a/source/libvpx/vp9/encoder/vp9_rdopt.c |
+++ b/source/libvpx/vp9/encoder/vp9_rdopt.c |
@@ -14,6 +14,7 @@ |
#include "./vp9_rtcd.h" |
#include "./vpx_dsp_rtcd.h" |
+#include "vpx_dsp/vpx_dsp_common.h" |
#include "vpx_mem/vpx_mem.h" |
#include "vpx_ports/mem.h" |
#include "vpx_ports/system_state.h" |
@@ -3785,6 +3786,7 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, |
int this_skip2 = 0; |
int64_t total_sse = INT_MAX; |
int early_term = 0; |
+ struct buf_2d backup_yv12[2][MAX_MB_PLANE]; |
ref_frame = vp9_ref_order[ref_index].ref_frame[0]; |
second_ref_frame = vp9_ref_order[ref_index].ref_frame[1]; |
@@ -3842,16 +3844,6 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, |
continue; |
} |
- // TODO(jingning, jkoleszar): scaling reference frame not supported for |
- // sub8x8 blocks. |
- if (ref_frame > INTRA_FRAME && |
- vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf)) |
- continue; |
- |
- if (second_ref_frame > INTRA_FRAME && |
- vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf)) |
- continue; |
- |
if (comp_pred) |
mode_excluded = cm->reference_mode == SINGLE_REFERENCE; |
else if (ref_frame != INTRA_FRAME) |
@@ -3930,6 +3922,25 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, |
int pred_exists = 0; |
int uv_skippable; |
+ YV12_BUFFER_CONFIG *scaled_ref_frame[2] = {NULL, NULL}; |
+ int ref; |
+ |
+ for (ref = 0; ref < 2; ++ref) { |
+ scaled_ref_frame[ref] = mbmi->ref_frame[ref] > INTRA_FRAME ? |
+ vp9_get_scaled_ref_frame(cpi, mbmi->ref_frame[ref]) : NULL; |
+ |
+ 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); |
+ } |
+ } |
+ |
this_rd_thresh = (ref_frame == LAST_FRAME) ? |
rd_opt->threshes[segment_id][bsize][THR_LAST] : |
rd_opt->threshes[segment_id][bsize][THR_ALTR]; |
@@ -4063,14 +4074,31 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, |
BLOCK_8X8); |
memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm)); |
if (!super_block_uvrd(cpi, x, &rate_uv, &distortion_uv, &uv_skippable, |
- &uv_sse, BLOCK_8X8, tmp_best_rdu)) |
+ &uv_sse, BLOCK_8X8, tmp_best_rdu)) { |
+ for (ref = 0; ref < 2; ++ref) { |
+ if (scaled_ref_frame[ref]) { |
+ int i; |
+ for (i = 0; i < MAX_MB_PLANE; ++i) |
+ xd->plane[i].pre[ref] = backup_yv12[ref][i]; |
+ } |
+ } |
continue; |
+ } |
rate2 += rate_uv; |
distortion2 += distortion_uv; |
skippable = skippable && uv_skippable; |
total_sse += uv_sse; |
} |
+ |
+ 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]; |
+ } |
+ } |
} |
if (cm->reference_mode == REFERENCE_MODE_SELECT) |