Commit bd333263 authored by Jingning Han's avatar Jingning Han
Browse files

Dual prediction filter type for motion compensated reference

Make the bit-stream level support per direction filter type coding
for motion compensated reference.

Change-Id: I61a2360b301075f6734cfd9711b7ae68f214174d
parent 7c5fd6aa
...@@ -12,9 +12,18 @@ using libvpx_test::ACMRandom; ...@@ -12,9 +12,18 @@ using libvpx_test::ACMRandom;
namespace { namespace {
TEST(VP10ConvolveTest, vp10_convolve8) { TEST(VP10ConvolveTest, vp10_convolve8) {
ACMRandom rnd(ACMRandom::DeterministicSeed()); ACMRandom rnd(ACMRandom::DeterministicSeed());
#if CONFIG_DUAL_FILTER
INTERP_FILTER interp_filter[4] = {
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR,
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR
};
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter[0]);
#else
INTERP_FILTER interp_filter = EIGHTTAP_REGULAR; INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params = InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter); vp10_get_interp_filter_params(interp_filter);
#endif
ptrdiff_t filter_size = filter_params.taps; ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1; int filter_center = filter_size / 2 - 1;
uint8_t src[12 * 12]; uint8_t src[12 * 12];
...@@ -36,7 +45,7 @@ TEST(VP10ConvolveTest, vp10_convolve8) { ...@@ -36,7 +45,7 @@ TEST(VP10ConvolveTest, vp10_convolve8) {
} }
vp10_convolve(src + src_stride * filter_center + filter_center, src_stride, vp10_convolve(src + src_stride * filter_center + filter_center, src_stride,
dst, dst_stride, w, h, filter_params, subpel_x_q4, x_step_q4, dst, dst_stride, w, h, interp_filter, subpel_x_q4, x_step_q4,
subpel_y_q4, y_step_q4, avg); subpel_y_q4, y_step_q4, avg);
const int16_t* x_filter = const int16_t* x_filter =
...@@ -50,9 +59,18 @@ TEST(VP10ConvolveTest, vp10_convolve8) { ...@@ -50,9 +59,18 @@ TEST(VP10ConvolveTest, vp10_convolve8) {
} }
TEST(VP10ConvolveTest, vp10_convolve) { TEST(VP10ConvolveTest, vp10_convolve) {
ACMRandom rnd(ACMRandom::DeterministicSeed()); ACMRandom rnd(ACMRandom::DeterministicSeed());
#if CONFIG_DUAL_FILTER
INTERP_FILTER interp_filter[4] = {
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR,
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR
};
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter[0]);
#else
INTERP_FILTER interp_filter = EIGHTTAP_REGULAR; INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params = InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter); vp10_get_interp_filter_params(interp_filter);
#endif
ptrdiff_t filter_size = filter_params.taps; ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1; int filter_center = filter_size / 2 - 1;
uint8_t src[12 * 12]; uint8_t src[12 * 12];
...@@ -75,7 +93,7 @@ TEST(VP10ConvolveTest, vp10_convolve) { ...@@ -75,7 +93,7 @@ TEST(VP10ConvolveTest, vp10_convolve) {
for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) { for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) {
for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) { for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
vp10_convolve(src + src_stride * filter_center + filter_center, vp10_convolve(src + src_stride * filter_center + filter_center,
src_stride, dst, dst_stride, w, h, filter_params, src_stride, dst, dst_stride, w, h, interp_filter,
subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg); subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg);
const int16_t* x_filter = const int16_t* x_filter =
...@@ -101,9 +119,18 @@ TEST(VP10ConvolveTest, vp10_convolve) { ...@@ -101,9 +119,18 @@ TEST(VP10ConvolveTest, vp10_convolve) {
TEST(VP10ConvolveTest, vp10_convolve_avg) { TEST(VP10ConvolveTest, vp10_convolve_avg) {
ACMRandom rnd(ACMRandom::DeterministicSeed()); ACMRandom rnd(ACMRandom::DeterministicSeed());
#if CONFIG_DUAL_FILTER
INTERP_FILTER interp_filter[4] = {
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR,
EIGHTTAP_REGULAR, EIGHTTAP_REGULAR
};
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter[0]);
#else
INTERP_FILTER interp_filter = EIGHTTAP_REGULAR; INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params = InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter); vp10_get_interp_filter_params(interp_filter);
#endif
ptrdiff_t filter_size = filter_params.taps; ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1; int filter_center = filter_size / 2 - 1;
uint8_t src0[12 * 12]; uint8_t src0[12 * 12];
...@@ -134,20 +161,20 @@ TEST(VP10ConvolveTest, vp10_convolve_avg) { ...@@ -134,20 +161,20 @@ TEST(VP10ConvolveTest, vp10_convolve_avg) {
for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) { for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
avg = 0; avg = 0;
vp10_convolve(src0 + offset, src_stride, dst0, dst_stride, w, h, vp10_convolve(src0 + offset, src_stride, dst0, dst_stride, w, h,
filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg); y_step_q4, avg);
avg = 0; avg = 0;
vp10_convolve(src1 + offset, src_stride, dst1, dst_stride, w, h, vp10_convolve(src1 + offset, src_stride, dst1, dst_stride, w, h,
filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg); y_step_q4, avg);
avg = 0; avg = 0;
vp10_convolve(src0 + offset, src_stride, dst, dst_stride, w, h, vp10_convolve(src0 + offset, src_stride, dst, dst_stride, w, h,
filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg); y_step_q4, avg);
avg = 1; avg = 1;
vp10_convolve(src1 + offset, src_stride, dst, dst_stride, w, h, vp10_convolve(src1 + offset, src_stride, dst, dst_stride, w, h,
filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg); y_step_q4, avg);
EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1)); EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
......
...@@ -198,7 +198,11 @@ typedef struct { ...@@ -198,7 +198,11 @@ typedef struct {
PALETTE_MODE_INFO palette_mode_info; PALETTE_MODE_INFO palette_mode_info;
// Only for INTER blocks // Only for INTER blocks
#if CONFIG_DUAL_FILTER
INTERP_FILTER interp_filter[4];
#else
INTERP_FILTER interp_filter; INTERP_FILTER interp_filter;
#endif
MV_REFERENCE_FRAME ref_frame[2]; MV_REFERENCE_FRAME ref_frame[2];
TX_TYPE tx_type; TX_TYPE tx_type;
......
...@@ -14,6 +14,44 @@ ...@@ -14,6 +14,44 @@
#include "vp10/common/seg_common.h" #include "vp10/common/seg_common.h"
// Returns a context number for the given MB prediction signal // Returns a context number for the given MB prediction signal
#if CONFIG_DUAL_FILTER
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir) {
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
MV_REFERENCE_FRAME ref_frame = (dir < 2) ?
mbmi->ref_frame[0] : mbmi->ref_frame[1];
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
int left_type = SWITCHABLE_FILTERS;
int above_type = SWITCHABLE_FILTERS;
if (xd->left_available) {
if (left_mbmi->ref_frame[0] == ref_frame)
left_type = left_mbmi->interp_filter[(dir & 0x01)];
else if (left_mbmi->ref_frame[1] == ref_frame)
left_type = left_mbmi->interp_filter[(dir & 0x01) + 2];
}
if (xd->up_available) {
if (above_mbmi->ref_frame[0] == ref_frame)
above_type = above_mbmi->interp_filter[(dir & 0x01)];
else if (above_mbmi->ref_frame[1] == ref_frame)
above_type = above_mbmi->interp_filter[(dir & 0x01) + 2];
}
if (left_type == above_type)
return left_type;
else if (left_type == SWITCHABLE_FILTERS && above_type != SWITCHABLE_FILTERS)
return above_type;
else if (left_type != SWITCHABLE_FILTERS && above_type == SWITCHABLE_FILTERS)
return left_type;
else
return SWITCHABLE_FILTERS;
}
#else
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) { int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
// Note: // Note:
// The mode info data structure has a one element border above and to the // The mode info data structure has a one element border above and to the
...@@ -35,6 +73,7 @@ int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) { ...@@ -35,6 +73,7 @@ int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
else else
return SWITCHABLE_FILTERS; return SWITCHABLE_FILTERS;
} }
#endif
#if CONFIG_EXT_INTRA #if CONFIG_EXT_INTRA
// Obtain the reference filter type from the above/left neighbor blocks. // Obtain the reference filter type from the above/left neighbor blocks.
...@@ -44,7 +83,11 @@ static INTRA_FILTER get_ref_intra_filter(const MB_MODE_INFO *ref_mbmi) { ...@@ -44,7 +83,11 @@ static INTRA_FILTER get_ref_intra_filter(const MB_MODE_INFO *ref_mbmi) {
if (ref_mbmi->sb_type >= BLOCK_8X8) { if (ref_mbmi->sb_type >= BLOCK_8X8) {
PREDICTION_MODE mode = ref_mbmi->mode; PREDICTION_MODE mode = ref_mbmi->mode;
if (is_inter_block(ref_mbmi)) { if (is_inter_block(ref_mbmi)) {
#if CONFIG_DUAL_FILTER
switch (ref_mbmi->interp_filter[0]) {
#else
switch (ref_mbmi->interp_filter) { switch (ref_mbmi->interp_filter) {
#endif
case EIGHTTAP_REGULAR: case EIGHTTAP_REGULAR:
ref_type = INTRA_FILTER_8TAP; ref_type = INTRA_FILTER_8TAP;
break; break;
......
...@@ -66,7 +66,11 @@ static INLINE vpx_prob vp10_get_skip_prob(const VP10_COMMON *cm, ...@@ -66,7 +66,11 @@ static INLINE vpx_prob vp10_get_skip_prob(const VP10_COMMON *cm,
return cm->fc->skip_probs[vp10_get_skip_context(xd)]; return cm->fc->skip_probs[vp10_get_skip_context(xd)];
} }
#if CONFIG_DUAL_FILTER
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir);
#else
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd); int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd);
#endif
#if CONFIG_EXT_INTRA #if CONFIG_EXT_INTRA
int vp10_get_pred_context_intra_interp(const MACROBLOCKD *xd); int vp10_get_pred_context_intra_interp(const MACROBLOCKD *xd);
......
...@@ -461,7 +461,11 @@ void vp10_make_masked_inter_predictor( ...@@ -461,7 +461,11 @@ void vp10_make_masked_inter_predictor(
const int subpel_y, const int subpel_y,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int w, int h,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
int xs, int ys, int xs, int ys,
#if CONFIG_SUPERTX #if CONFIG_SUPERTX
int wedge_offset_x, int wedge_offset_y, int wedge_offset_x, int wedge_offset_y,
...@@ -557,7 +561,11 @@ void vp10_build_inter_predictor(const uint8_t *src, int src_stride, ...@@ -557,7 +561,11 @@ void vp10_build_inter_predictor(const uint8_t *src, int src_stride,
const MV *src_mv, const MV *src_mv,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int ref, int w, int h, int ref,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
enum mv_precision precision, enum mv_precision precision,
int x, int y) { int x, int y) {
const int is_q4 = precision == MV_PRECISION_Q4; const int is_q4 = precision == MV_PRECISION_Q4;
...@@ -591,7 +599,6 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane, ...@@ -591,7 +599,6 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane,
const MODE_INFO *mi = xd->mi[0]; const MODE_INFO *mi = xd->mi[0];
#endif // CONFIG_OBMC #endif // CONFIG_OBMC
const int is_compound = has_second_ref(&mi->mbmi); const int is_compound = has_second_ref(&mi->mbmi);
const INTERP_FILTER interp_filter = mi->mbmi.interp_filter;
int ref; int ref;
for (ref = 0; ref < 1 + is_compound; ++ref) { for (ref = 0; ref < 1 + is_compound; ++ref) {
...@@ -640,7 +647,7 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane, ...@@ -640,7 +647,7 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane,
vp10_make_masked_inter_predictor( vp10_make_masked_inter_predictor(
pre, pre_buf->stride, dst, dst_buf->stride, pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, subpel_x, subpel_y, sf, w, h,
interp_filter, xs, ys, mi->mbmi.interp_filter, xs, ys,
#if CONFIG_SUPERTX #if CONFIG_SUPERTX
wedge_offset_x, wedge_offset_y, wedge_offset_x, wedge_offset_y,
#endif // CONFIG_SUPERTX #endif // CONFIG_SUPERTX
...@@ -649,7 +656,7 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane, ...@@ -649,7 +656,7 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane,
#endif // CONFIG_EXT_INTER #endif // CONFIG_EXT_INTER
vp10_make_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, vp10_make_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref, subpel_x, subpel_y, sf, w, h, ref,
interp_filter, xs, ys, xd); mi->mbmi.interp_filter, xs, ys, xd);
} }
} }
...@@ -665,7 +672,6 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, ...@@ -665,7 +672,6 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane,
uint8_t *const dst = &pd->dst.buf[(ir * pd->dst.stride + ic) << 2]; uint8_t *const dst = &pd->dst.buf[(ir * pd->dst.stride + ic) << 2];
int ref; int ref;
const int is_compound = has_second_ref(&mi->mbmi); const int is_compound = has_second_ref(&mi->mbmi);
const INTERP_FILTER interp_filter = mi->mbmi.interp_filter;
for (ref = 0; ref < 1 + is_compound; ++ref) { for (ref = 0; ref < 1 + is_compound; ++ref) {
const uint8_t *pre = const uint8_t *pre =
...@@ -676,7 +682,8 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, ...@@ -676,7 +682,8 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane,
dst, pd->dst.stride, dst, pd->dst.stride,
&mi->bmi[i].as_mv[ref].as_mv, &mi->bmi[i].as_mv[ref].as_mv,
&xd->block_refs[ref]->sf, width, height, &xd->block_refs[ref]->sf, width, height,
ref, interp_filter, MV_PRECISION_Q3, ref, mi->mbmi.interp_filter,
MV_PRECISION_Q3,
mi_col * MI_SIZE + 4 * ic, mi_col * MI_SIZE + 4 * ic,
mi_row * MI_SIZE + 4 * ir, xd->bd); mi_row * MI_SIZE + 4 * ir, xd->bd);
} else { } else {
...@@ -684,7 +691,7 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, ...@@ -684,7 +691,7 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane,
dst, pd->dst.stride, dst, pd->dst.stride,
&mi->bmi[i].as_mv[ref].as_mv, &mi->bmi[i].as_mv[ref].as_mv,
&xd->block_refs[ref]->sf, width, height, ref, &xd->block_refs[ref]->sf, width, height, ref,
interp_filter, MV_PRECISION_Q3, mi->mbmi.interp_filter, MV_PRECISION_Q3,
mi_col * MI_SIZE + 4 * ic, mi_col * MI_SIZE + 4 * ic,
mi_row * MI_SIZE + 4 * ir); mi_row * MI_SIZE + 4 * ir);
} }
...@@ -693,7 +700,7 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, ...@@ -693,7 +700,7 @@ void vp10_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane,
dst, pd->dst.stride, dst, pd->dst.stride,
&mi->bmi[i].as_mv[ref].as_mv, &mi->bmi[i].as_mv[ref].as_mv,
&xd->block_refs[ref]->sf, width, height, ref, &xd->block_refs[ref]->sf, width, height, ref,
interp_filter, MV_PRECISION_Q3, mi->mbmi.interp_filter, MV_PRECISION_Q3,
mi_col * MI_SIZE + 4 * ic, mi_col * MI_SIZE + 4 * ic,
mi_row * MI_SIZE + 4 * ir); mi_row * MI_SIZE + 4 * ir);
#endif // CONFIG_VP9_HIGHBITDEPTH #endif // CONFIG_VP9_HIGHBITDEPTH
...@@ -2151,7 +2158,6 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane, ...@@ -2151,7 +2158,6 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane,
int ext_dst_stride) { int ext_dst_stride) {
struct macroblockd_plane *const pd = &xd->plane[plane]; struct macroblockd_plane *const pd = &xd->plane[plane];
const MODE_INFO *mi = xd->mi[0]; const MODE_INFO *mi = xd->mi[0];
const INTERP_FILTER interp_filter = mi->mbmi.interp_filter;
const struct scale_factors *const sf = &xd->block_refs[ref]->sf; const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
struct buf_2d *const pre_buf = &pd->pre[ref]; struct buf_2d *const pre_buf = &pd->pre[ref];
...@@ -2199,7 +2205,7 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane, ...@@ -2199,7 +2205,7 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane,
vp10_make_inter_predictor(pre, pre_buf->stride, dst, ext_dst_stride, vp10_make_inter_predictor(pre, pre_buf->stride, dst, ext_dst_stride,
subpel_x, subpel_y, sf, w, h, 0, subpel_x, subpel_y, sf, w, h, 0,
interp_filter, xs, ys, xd); mi->mbmi.interp_filter, xs, ys, xd);
} }
void vp10_build_inter_predictors_for_planes_single_buf( void vp10_build_inter_predictors_for_planes_single_buf(
......
...@@ -25,16 +25,37 @@ static INLINE void inter_predictor(const uint8_t *src, int src_stride, ...@@ -25,16 +25,37 @@ static INLINE void inter_predictor(const uint8_t *src, int src_stride,
const int subpel_x, const int subpel_x,
const int subpel_y, const int subpel_y,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int ref, int w, int h, int ref_idx,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
int xs, int ys) { int xs, int ys) {
#if CONFIG_DUAL_FILTER
InterpFilterParams interp_filter_params_x =
vp10_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]);
InterpFilterParams interp_filter_params_y =
vp10_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]);
#else
InterpFilterParams interp_filter_params = InterpFilterParams interp_filter_params =
vp10_get_interp_filter_params(interp_filter); vp10_get_interp_filter_params(interp_filter);
#endif
#if CONFIG_DUAL_FILTER
if (interp_filter_params_x.taps == SUBPEL_TAPS &&
interp_filter_params_y.taps == SUBPEL_TAPS) {
const int16_t *kernel_x =
vp10_get_interp_filter_subpel_kernel(interp_filter_params_x, subpel_x);
const int16_t *kernel_y =
vp10_get_interp_filter_subpel_kernel(interp_filter_params_y, subpel_y);
#else
if (interp_filter_params.taps == SUBPEL_TAPS) { if (interp_filter_params.taps == SUBPEL_TAPS) {
const int16_t *kernel_x = const int16_t *kernel_x =
vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x); vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x);
const int16_t *kernel_y = const int16_t *kernel_y =
vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y); vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y);
#endif
#if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS #if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
if (IsInterpolatingFilter(interp_filter)) { if (IsInterpolatingFilter(interp_filter)) {
// Interpolating filter // Interpolating filter
...@@ -47,17 +68,16 @@ static INLINE void inter_predictor(const uint8_t *src, int src_stride, ...@@ -47,17 +68,16 @@ static INLINE void inter_predictor(const uint8_t *src, int src_stride,
kernel_x, xs, kernel_y, ys, w, h); kernel_x, xs, kernel_y, ys, w, h);
} }
#else #else
sf->predict[subpel_x != 0][subpel_y != 0][ref]( sf->predict[subpel_x != 0][subpel_y != 0][ref_idx](
src, src_stride, dst, dst_stride, src, src_stride, dst, dst_stride,
kernel_x, xs, kernel_y, ys, w, h); kernel_x, xs, kernel_y, ys, w, h);
#endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS #endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
} else { } else {
// ref > 0 means this is the second reference frame // ref_idx > 0 means this is the second reference frame
// first reference frame's prediction result is already in dst // first reference frame's prediction result is already in dst
// therefore we need to average the first and second results // therefore we need to average the first and second results
int avg = ref > 0; vp10_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter,
vp10_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter_params, subpel_x, xs, subpel_y, ys, ref_idx);
subpel_x, xs, subpel_y, ys, avg);
} }
} }
...@@ -126,7 +146,11 @@ static INLINE void vp10_make_inter_predictor( ...@@ -126,7 +146,11 @@ static INLINE void vp10_make_inter_predictor(
const int subpel_y, const int subpel_y,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int ref, int w, int h, int ref,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
int xs, int ys, int xs, int ys,
const MACROBLOCKD *xd) { const MACROBLOCKD *xd) {
(void) xd; (void) xd;
...@@ -152,7 +176,11 @@ void vp10_make_masked_inter_predictor( ...@@ -152,7 +176,11 @@ void vp10_make_masked_inter_predictor(
const int subpel_y, const int subpel_y,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int w, int h,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
int xs, int ys, int xs, int ys,
#if CONFIG_SUPERTX #if CONFIG_SUPERTX
int wedge_offset_x, int wedge_offset_y, int wedge_offset_x, int wedge_offset_y,
...@@ -284,7 +312,11 @@ void vp10_build_inter_predictor(const uint8_t *src, int src_stride, ...@@ -284,7 +312,11 @@ void vp10_build_inter_predictor(const uint8_t *src, int src_stride,
const MV *mv_q3, const MV *mv_q3,
const struct scale_factors *sf, const struct scale_factors *sf,
int w, int h, int do_avg, int w, int h, int do_avg,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter, const INTERP_FILTER interp_filter,
#endif
enum mv_precision precision, enum mv_precision precision,
int x, int y); int x, int y);
...@@ -325,6 +357,54 @@ void vp10_setup_pre_planes(MACROBLOCKD *xd, int idx, ...@@ -325,6 +357,54 @@ void vp10_setup_pre_planes(MACROBLOCKD *xd, int idx,
const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col, const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
const struct scale_factors *sf); const struct scale_factors *sf);
#if CONFIG_DUAL_FILTER
// Detect if the block have sub-pixel level motion vectors
// per component.
static INLINE int has_subpel_mv_component(const MACROBLOCKD *const xd,
int dir) {
MODE_INFO *const mi = xd->mi[0];
MB_MODE_INFO *const mbmi = &mi->mbmi;
const BLOCK_SIZE bsize = mbmi->sb_type;
int plane;
int ref = (dir >> 1);
if (bsize >= BLOCK_8X8) {
if (dir & 0x01) {
if (mbmi->mv[ref].as_mv.col & SUBPEL_MASK)
return 1;
} else {
if (mbmi->mv[ref].as_mv.row & SUBPEL_MASK)
return 1;
}
} else {
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
const PARTITION_TYPE bp = BLOCK_8X8 - bsize;
const struct macroblockd_plane *const pd = &xd->plane[plane];
const int have_vsplit = bp != PARTITION_HORZ;
const int have_hsplit = bp != PARTITION_VERT;
const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
int x, y;
for (y = 0; y < num_4x4_h; ++y) {
for (x = 0; x < num_4x4_w; ++x) {
const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x);
if (dir & 0x01) {
if (mv.col & SUBPEL_MASK)
return 1;
} else {
if (mv.row & SUBPEL_MASK)
return 1;
}
}
}
}
}
return 0;
}
#endif
#if CONFIG_EXT_INTERP #if CONFIG_EXT_INTERP
static INLINE int vp10_is_interp_needed(const MACROBLOCKD *const xd) { static INLINE int vp10_is_interp_needed(const MACROBLOCKD *const xd) {