vpx/vp9/encoder/vp9_motion_field.c
Debargha Mukherjee fb093a337f Global motion enhancements
Adds warping functions. Also includes some refactoring.

Change-Id: I909830650f29046edf108ddaddceb1a5e7c6c61c
2015-05-14 16:33:01 -07:00

174 lines
5.9 KiB
C

/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits.h>
#include "vpx_mem/vpx_mem.h"
#include "vp9/encoder/vp9_segmentation.h"
#include "vp9/encoder/vp9_mcomp.h"
#include "vp9/common/vp9_blockd.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_systemdependent.h"
#include "vp9/encoder/vp9_global_motion.h"
unsigned int get_sby_perpixel_variance(VP9_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs);
unsigned int get_sby_perpixel_ssd(VP9_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs);
#if CONFIG_VP9_HIGHBITDEPTH
unsigned int high_get_sby_perpixel_ssd(
VP9_COMP *cpi, const struct buf_2d *ref, BLOCK_SIZE bs, int bd);
unsigned int high_get_sby_perpixel_variance(
VP9_COMP *cpi, const struct buf_2d *ref, BLOCK_SIZE bs, int bd);
#endif
static int do_motion_iteration(MACROBLOCK *const x,
const vp9_variance_fn_ptr_t *v_fn_ptr,
const MV *ref_mv,
MV *dst_mv) {
MV ref_full;
unsigned int sse;
int besterr, distortion;
// Further step/diamond searches as necessary
// int step_param = mv_sf->reduce_first_step_size;
// step_param = MIN(step_param, MAX_MVSEARCH_STEPS - 2);
int step_param = 0;
int subpel_iters_per_step = 2;
int allow_high_precision_mv = 1;
vp9_set_mv_search_range(x, ref_mv);
ref_full.col = ref_mv->col >> 3;
ref_full.row = ref_mv->row >> 3;
/*cpi->sf.search_method == HEX*/
vp9_hex_search(x, &ref_full, step_param, x->errorperbit, 0, NULL,
v_fn_ptr, 0, ref_mv, dst_mv);
besterr = vp9_find_best_sub_pixel_tree(
x, dst_mv, ref_mv, allow_high_precision_mv, x->errorperbit,
v_fn_ptr, 0, subpel_iters_per_step,
NULL, NULL, NULL, &distortion, &sse, NULL, 0, 0);
return besterr;
}
static int do_motion_search(MACROBLOCK *const x,
const vp9_variance_fn_ptr_t *v_fn_ptr,
const MV *ref_mv,
int_mv *dst_mv) {
int err = do_motion_iteration(x, v_fn_ptr,
ref_mv, &dst_mv->as_mv);
// If the current best reference mv is not centered on 0,0 then do a 0,0
// based search as well.
if (ref_mv->row != 0 || ref_mv->col != 0) {
int tmp_err;
MV zero_ref_mv = {0, 0}, tmp_mv;
tmp_err = do_motion_iteration(x, v_fn_ptr,
&zero_ref_mv, &tmp_mv);
if (tmp_err < err) {
dst_mv->as_mv = tmp_mv;
err = tmp_err;
}
}
return err;
}
void vp9_get_frame_motionfield(struct VP9_COMP *cpi,
YV12_BUFFER_CONFIG *buf,
YV12_BUFFER_CONFIG *ref,
BLOCK_SIZE bsize,
MV *motionfield,
double *confidence) {
MACROBLOCK mx;
MACROBLOCK *const x = &mx;
MACROBLOCKD *const xd = &x->e_mbd;
VP9_COMMON *const cm = &cpi->common;
int mb_col, mb_row;
int mb_y_offset = 0, ref_y_offset = 0;
int border = BORDER_MV_PIXELS_B16;
int bwidth = num_4x4_blocks_wide_lookup[bsize] << 2;
int bheight = num_4x4_blocks_high_lookup[bsize] << 2;
MV ref_top_mv = {0, 0};
x->errorperbit =
vp9_compute_rd_mult(cpi, cm->base_qindex + cm->y_dc_delta_q) /
64;
x->errorperbit += (x->errorperbit == 0);
// the UMV borders.
x->mv_row_min = -border;
x->mv_row_max = cm->mi_rows * 8 + border;
xd->up_available = 0;
xd->plane[0].dst.stride = buf->y_stride;
xd->plane[1].dst.stride = buf->uv_stride;
xd->plane[0].pre[0].stride = buf->y_stride;
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
MV ref_left_mv = ref_top_mv;
int mb_y_in_offset = mb_y_offset;
int ref_y_in_offset = ref_y_offset;
// Set up limit values for motion vectors to prevent them extending outside
// the UMV borders.
x->mv_col_min = -border;
x->mv_col_max = cm->mi_cols * 8 + border;
xd->left_available = 0;
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
int_mv intmv;
unsigned int ssd, err;
x->plane[0].src.buf = buf->y_buffer + mb_y_in_offset;
x->plane[0].src.stride = buf->y_stride;
xd->plane[0].pre[0].buf = ref->y_buffer + ref_y_in_offset;
xd->plane[0].pre[0].stride = ref->y_stride;
ssd = get_sby_perpixel_ssd(cpi, &x->plane[0].src, bsize);
err =
do_motion_search(x,
&cpi->fn_ptr[bsize],
&ref_left_mv,
&intmv);
confidence[mb_row * cm->mb_cols + mb_col] = (double)ssd / (err + 1);
motionfield[mb_row * cm->mb_cols + mb_col] = intmv.as_mv;
if (mb_col == 0) {
ref_top_mv = ref_left_mv;
}
xd->left_available = 1;
mb_y_in_offset += bwidth;
ref_y_in_offset += bwidth;
x->mv_col_min -= bwidth;
x->mv_col_max -= bwidth;
}
xd->up_available = 1;
mb_y_offset += buf->y_stride * bheight;
ref_y_offset += ref->y_stride * bheight;
x->mv_row_min -= bheight;
x->mv_row_max -= bheight;
}
}
void vp9_get_ref_motionfield(VP9_COMP *cpi, int ref, BLOCK_SIZE bsize,
MV *motionfield, double *confidence) {
YV12_BUFFER_CONFIG *ref_buf = get_ref_frame_buffer(cpi, ref);
if (cpi->Source && ref_buf) {
vp9_get_frame_motionfield(cpi, cpi->Source, ref_buf,
bsize, motionfield, confidence);
}
}