Commit 475d5d56 authored by Deb Mukherjee's avatar Deb Mukherjee
Browse files

Making subpel filters switchable at frame level

Various refactoring to make the subpel motion compensation
filters switchable by a frame level field.
Two types of 8-tap filters are supported in addition to the existing
bilinar and sixtap filters. One is the default 8-tap and the
other has a sharper cut-off for use with frames with substantial
edge content.

Patch 2: Added a preliminary strategy for filter selection based on
edginess detecton. Also includes some filter changes.

Change-Id: I866085bda5ae143cfdf2ec88157feaabdf7bd63a
parent 57d95347
This diff is collapsed.
......@@ -25,6 +25,8 @@
#endif
extern const short vp8_bilinear_filters[SUBPEL_SHIFTS][2];
extern const short vp8_sub_pel_filters[SUBPEL_SHIFTS][INTERP_EXTEND*2];
extern const short vp8_sub_pel_filters_6[SUBPEL_SHIFTS][6];
extern const short vp8_sub_pel_filters_8[SUBPEL_SHIFTS][8];
extern const short vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][8];
#endif //FILTER_H
......@@ -79,6 +79,20 @@ void vp8_machine_specific_config(VP8_COMMON *ctx)
vp8_comp_intra_uv4x4_predict;
#endif
#if CONFIG_ENHANCED_INTERP
rtcd->subpix.eighttap16x16 = vp8_eighttap_predict16x16_c;
rtcd->subpix.eighttap8x8 = vp8_eighttap_predict8x8_c;
rtcd->subpix.eighttap_avg16x16 = vp8_eighttap_predict_avg16x16_c;
rtcd->subpix.eighttap_avg8x8 = vp8_eighttap_predict_avg8x8_c;
rtcd->subpix.eighttap8x4 = vp8_eighttap_predict8x4_c;
rtcd->subpix.eighttap4x4 = vp8_eighttap_predict_c;
rtcd->subpix.eighttap16x16_sharp = vp8_eighttap_predict16x16_sharp_c;
rtcd->subpix.eighttap8x8_sharp = vp8_eighttap_predict8x8_sharp_c;
rtcd->subpix.eighttap_avg16x16_sharp = vp8_eighttap_predict_avg16x16_sharp_c;
rtcd->subpix.eighttap_avg8x8_sharp = vp8_eighttap_predict_avg8x8_sharp_c;
rtcd->subpix.eighttap8x4_sharp = vp8_eighttap_predict8x4_sharp_c;
rtcd->subpix.eighttap4x4_sharp = vp8_eighttap_predict_sharp_c;
#endif
rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_c;
rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_c;
rtcd->subpix.sixtap_avg16x16 = vp8_sixtap_predict_avg16x16_c;
......
......@@ -71,7 +71,11 @@ typedef enum
typedef enum
{
SIXTAP = 0,
BILINEAR = 1
BILINEAR = 1,
#if CONFIG_ENHANCED_INTERP
EIGHTTAP = 2,
EIGHTTAP_SHARP = 3,
#endif
} INTERPOLATIONFILTERTYPE;
typedef enum
......
......@@ -53,6 +53,68 @@ extern prototype_subpixel_predict(vp8_subpix_sixtap8x4);
#endif
extern prototype_subpixel_predict(vp8_subpix_sixtap4x4);
#if CONFIG_ENHANCED_INTERP
#ifndef vp8_subpix_eighttap16x16
#define vp8_subpix_eighttap16x16 vp8_eighttap_predict16x16_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap16x16);
#ifndef vp8_subpix_eighttap8x8
#define vp8_subpix_eighttap8x8 vp8_eighttap_predict8x8_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap8x8);
#ifndef vp8_subpix_eighttap_avg16x16
#define vp8_subpix_eighttap_avg16x16 vp8_eighttap_predict_avg16x16_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap_avg16x16);
#ifndef vp8_subpix_eighttap_avg8x8
#define vp8_subpix_eighttap_avg8x8 vp8_eighttap_predict_avg8x8_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap_avg8x8);
#ifndef vp8_subpix_eighttap8x4
#define vp8_subpix_eighttap8x4 vp8_eighttap_predict8x4_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap8x4);
#ifndef vp8_subpix_eighttap4x4
#define vp8_subpix_eighttap4x4 vp8_eighttap_predict_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap4x4);
#ifndef vp8_subpix_eighttap16x16_sharp
#define vp8_subpix_eighttap16x16_sharp vp8_eighttap_predict16x16_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap16x16_sharp);
#ifndef vp8_subpix_eighttap8x8_sharp
#define vp8_subpix_eighttap8x8_sharp vp8_eighttap_predict8x8_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap8x8_sharp);
#ifndef vp8_subpix_eighttap_avg16x16_sharp
#define vp8_subpix_eighttap_avg16x16_sharp vp8_eighttap_predict_avg16x16_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap_avg16x16_sharp);
#ifndef vp8_subpix_eighttap_avg8x8_sharp
#define vp8_subpix_eighttap_avg8x8_sharp vp8_eighttap_predict_avg8x8_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap_avg8x8_sharp);
#ifndef vp8_subpix_eighttap8x4_sharp
#define vp8_subpix_eighttap8x4_sharp vp8_eighttap_predict8x4_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap8x4_sharp);
#ifndef vp8_subpix_eighttap4x4_sharp
#define vp8_subpix_eighttap4x4_sharp vp8_eighttap_predict_sharp_c
#endif
extern prototype_subpixel_predict(vp8_subpix_eighttap4x4_sharp);
#endif /* CONFIG_ENAHNCED_INTERP */
#ifndef vp8_subpix_bilinear16x16
#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_c
#endif
......@@ -86,6 +148,20 @@ extern prototype_subpixel_predict(vp8_subpix_bilinear4x4);
typedef prototype_subpixel_predict((*vp8_subpix_fn_t));
typedef struct
{
#if CONFIG_ENHANCED_INTERP
vp8_subpix_fn_t eighttap16x16;
vp8_subpix_fn_t eighttap8x8;
vp8_subpix_fn_t eighttap_avg16x16;
vp8_subpix_fn_t eighttap_avg8x8;
vp8_subpix_fn_t eighttap8x4;
vp8_subpix_fn_t eighttap4x4;
vp8_subpix_fn_t eighttap16x16_sharp;
vp8_subpix_fn_t eighttap8x8_sharp;
vp8_subpix_fn_t eighttap_avg16x16_sharp;
vp8_subpix_fn_t eighttap_avg8x8_sharp;
vp8_subpix_fn_t eighttap8x4_sharp;
vp8_subpix_fn_t eighttap4x4_sharp;
#endif
vp8_subpix_fn_t sixtap16x16;
vp8_subpix_fn_t sixtap8x8;
vp8_subpix_fn_t sixtap_avg16x16;
......
......@@ -650,7 +650,11 @@ static void init_frame(VP8D_COMP *pbi)
{
if (!pc->use_bilinear_mc_filter)
#if CONFIG_ENHANCED_INTERP
pc->mcomp_filter_type = EIGHTTAP;
#else
pc->mcomp_filter_type = SIXTAP;
#endif
else
pc->mcomp_filter_type = BILINEAR;
......@@ -664,6 +668,30 @@ static void init_frame(VP8D_COMP *pbi)
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16);
}
#if CONFIG_ENHANCED_INTERP
else if (pc->mcomp_filter_type == EIGHTTAP)
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
RTCD_VTABLE(subpix), eighttap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
RTCD_VTABLE(subpix), eighttap_avg16x16);
}
else if (pc->mcomp_filter_type == EIGHTTAP_SHARP)
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
RTCD_VTABLE(subpix), eighttap_avg8x8_sharp);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
RTCD_VTABLE(subpix), eighttap_avg16x16_sharp);
}
#endif
else
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4);
......@@ -1052,6 +1080,47 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_HIGH_PRECISION_MV
/* Is high precision mv allowed */
xd->allow_high_precision_mv = (unsigned char)vp8_read_bit(bc);
#endif
#if CONFIG_ENHANCED_INTERP
// Read the type of subpel filter to use
pc->mcomp_filter_type = vp8_read_literal(bc, 2);
/* To enable choice of different interploation filters */
if (pc->mcomp_filter_type == SIXTAP)
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16);
}
else if (pc->mcomp_filter_type == EIGHTTAP)
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16);
}
else if (pc->mcomp_filter_type == EIGHTTAP_SHARP)
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8_sharp);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16_sharp);
}
else
{
xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16);
}
#endif
}
......
......@@ -2038,6 +2038,10 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
#if CONFIG_HIGH_PRECISION_MV
// Signal whether to allow high MV precision
vp8_write_bit(bc, (xd->allow_high_precision_mv) ? 1 : 0);
#endif
#if CONFIG_ENHANCED_INTERP
// Signal the type of subpel filter to use
vp8_write_literal(bc, (pc->mcomp_filter_type), 2);
#endif
}
......
......@@ -672,6 +672,38 @@ static void encode_frame_internal(VP8_COMP *cpi)
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, sixtap_avg16x16);
}
#if CONFIG_ENHANCED_INTERP
else if (cm->mcomp_filter_type == EIGHTTAP)
{
xd->subpixel_predict = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap4x4);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap16x16);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap_avg16x16);
}
else if (cm->mcomp_filter_type == EIGHTTAP_SHARP)
{
xd->subpixel_predict = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap4x4_sharp);
xd->subpixel_predict8x4 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap8x4_sharp);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap8x8_sharp);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap16x16_sharp);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap_avg8x8_sharp);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, eighttap_avg16x16_sharp);
}
#endif
else
{
xd->subpixel_predict = SUBPIX_INVOKE(
......
......@@ -1434,7 +1434,11 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->cq_target_quality = cpi->oxcf.cq_level;
if (!cm->use_bilinear_mc_filter)
#if CONFIG_ENHANCED_INTERP
cm->mcomp_filter_type = EIGHTTAP;
#else
cm->mcomp_filter_type = SIXTAP;
#endif
else
cm->mcomp_filter_type = BILINEAR;
......@@ -2552,6 +2556,36 @@ void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
}
#endif
static double compute_edge_pixel_proportion(YV12_BUFFER_CONFIG *frame)
{
#define EDGE_THRESH 128
int i, j;
int num_edge_pels = 0;
int num_pels = (frame->y_height - 2) * (frame->y_width - 2);
unsigned char *prev = frame->y_buffer + 1;
unsigned char *curr = frame->y_buffer + 1 + frame->y_stride;
unsigned char *next = frame->y_buffer + 1 + 2*frame->y_stride;
for (i = 1; i < frame->y_height - 1; i++)
{
for (j = 1; j < frame->y_width - 1; j++)
{
/* Sobel hor and ver gradients */
int v = 2*(curr[1] - curr[-1]) + (prev[1] - prev[-1]) + (next[1] - next[-1]);
int h = 2*(prev[0] - next[0]) + (prev[1] - next[1]) + (prev[-1] - next[-1]);
h = (h < 0 ? -h : h);
v = (v < 0 ? -v : v);
if (h > EDGE_THRESH || v > EDGE_THRESH) num_edge_pels++;
curr++;
prev++;
next++;
}
curr += frame->y_stride - frame->y_width + 2;
prev += frame->y_stride - frame->y_width + 2;
next += frame->y_stride - frame->y_width + 2;
}
return (double)num_edge_pels/(double)num_pels;
}
// Function to test for conditions that indeicate we should loop
// back and recode a frame.
static BOOL recode_loop_test( VP8_COMP *cpi,
......@@ -3070,11 +3104,18 @@ static void encode_frame_to_data_rate
loop_count = 0;
#if CONFIG_HIGH_PRECISION_MV
/* Decide this based on various factors */
#if CONFIG_HIGH_PRECISION_MV || CONFIG_ENHANCED_INTERP
if (cm->frame_type != KEY_FRAME)
{
double e = compute_edge_pixel_proportion(cpi->Source);
#if CONFIG_HIGH_PRECISION_MV
/* TODO: Decide this more intelligently */
xd->allow_high_precision_mv = (Q < HIGH_PRECISION_MV_QTHRESH);
#endif
#if CONFIG_ENHANCED_INTERP
/* TODO: Decide this more intelligently */
cm->mcomp_filter_type = (e > 0.1 ? EIGHTTAP_SHARP : EIGHTTAP);
#endif
}
#endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment