ref: acdda50a0d142c6c556956425370d8bcca1c35a3
parent: a16608aba040957e269ec1e7905c72140cb721b6
author: Deb Mukherjee <debargha@google.com>
date: Mon Apr 16 10:53:37 EDT 2012
Adds search option for best interpolation filter. Adds a speed feature to conduct a brute force search among a set of available interpolation filters for the best one in an RD sense. There is a gain of 0.4% on derf, 1.0% on Std-HD. Patch 2: A macro added to determine if the encoder state is reset for each new filter tried. Patch 3: rebase, also fixes a bug (decodframe.c) introduced by a couple of missing function pointer assignements. Patch 4: rebase. Change-Id: Ic9ccca9d8c35c6af557449ae867391a2f996cc29
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -1334,6 +1334,7 @@
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_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4);
xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8);
xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16);
}
@@ -1343,6 +1344,7 @@
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_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4_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);
}
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -36,6 +36,7 @@
#include "vp8/common/seg_common.h"
#include "mbgraph.h"
#include "vp8/common/pred_common.h"
+#include "vp8/encoder/rdopt.h"
#if ARCH_ARM
#include "vpx_ports/arm.h"
@@ -78,6 +79,11 @@
extern const int vp8_gf_interval_table[101];
+#if CONFIG_ENHANCED_INTERP
+#define SEARCH_BEST_FILTER 1 /* to search exhaustively for best filter */
+#define RESET_FOREACH_FILTER 0 /* whether to reset the encoder state
+ before trying each new filter */
+#endif
#if CONFIG_HIGH_PRECISION_MV
#define ALTREF_HIGH_PRECISION_MV 1 /* whether to use high precision mv for altref computation */
#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision mv */
@@ -786,6 +792,9 @@
sf->first_step = 0;
sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+#if CONFIG_ENHANCED_INTERP
+ sf->search_best_filter = SEARCH_BEST_FILTER;
+#endif
break;
case 1:
sf->thresh_mult[THR_NEARESTMV] = 0;
@@ -2825,6 +2834,7 @@
int q_high;
int zbin_oq_high;
int zbin_oq_low = 0;
+
int top_index;
int bottom_index;
int active_worst_qchanged = FALSE;
@@ -2834,6 +2844,28 @@
int loop_size_estimate = 0;
+#if CONFIG_ENHANCED_INTERP
+ SPEED_FEATURES *sf = &cpi->sf;
+#if RESET_FOREACH_FILTER
+ int q_low0;
+ int q_high0;
+ int zbin_oq_high0;
+ int zbin_oq_low0 = 0;
+ int Q0;
+ int last_zbin_oq0;
+ int active_best_quality0;
+ int active_worst_quality0;
+ double rate_correction_factor0;
+ double gf_rate_correction_factor0;
+#endif
+
+ /* list of filters to search over */
+ int mcomp_filters_to_search[] = {EIGHTTAP, EIGHTTAP_SHARP, SIXTAP};
+ int mcomp_filters = sizeof(mcomp_filters_to_search)/sizeof(*mcomp_filters_to_search);
+ int mcomp_filter_index = 0;
+ INT64 mcomp_filter_cost[4];
+#endif
+
// Clear down mmx registers to allow floating point in what follows
vp8_clear_system_state();
@@ -3040,21 +3072,26 @@
q_low = cpi->active_best_quality;
q_high = cpi->active_worst_quality;
-
loop_count = 0;
#if CONFIG_HIGH_PRECISION_MV || CONFIG_ENHANCED_INTERP
if (cm->frame_type != KEY_FRAME)
{
+#if CONFIG_ENHANCED_INTERP
double e = 0; //compute_edge_pixel_proportion(cpi->Source);
+ /* TODO: Decide this more intelligently */
+ if (sf->search_best_filter)
+ {
+ cm->mcomp_filter_type = mcomp_filters_to_search[0];
+ mcomp_filter_index = 0;
+ }
+ else
+ cm->mcomp_filter_type = EIGHTTAP;
+#endif
#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
@@ -3077,8 +3114,7 @@
l = 60;
break;
case 4:
- l = 80;
- break;
+
case 5:
l = 100;
break;
@@ -3111,6 +3147,21 @@
vp8_write_yuv_frame(cpi->Source);
#endif
+#if CONFIG_ENHANCED_INTERP && RESET_FOREACH_FILTER
+ if (sf->search_best_filter)
+ {
+ q_low0 = q_low;
+ q_high0 = q_high;
+ Q0 = Q;
+ zbin_oq_low0 = zbin_oq_low;
+ zbin_oq_high0 = zbin_oq_high;
+ last_zbin_oq0 = last_zbin_oq;
+ rate_correction_factor0 = cpi->rate_correction_factor;
+ gf_rate_correction_factor0 = cpi->gf_rate_correction_factor;
+ active_best_quality0 = cpi->active_best_quality;
+ active_worst_quality0 = cpi->active_worst_quality;
+ }
+#endif
do
{
vp8_clear_system_state(); //__asm emms;
@@ -3120,6 +3171,7 @@
if ( loop_count == 0 )
{
+
// setup skip prob for costing in mode/mv decision
if (cpi->common.mb_no_coeff_skip)
{
@@ -3214,6 +3266,7 @@
}
// transform / motion compensation build reconstruction frame
+
vp8_encode_frame(cpi);
// Update the skip mb flag probabilities based on the distribution
@@ -3222,11 +3275,6 @@
vp8_clear_system_state(); //__asm emms;
- if (frame_over_shoot_limit == 0)
- frame_over_shoot_limit = 1;
-
- active_worst_qchanged = FALSE;
-
// Dummy pack of the bitstream using up to date stats to get an
// accurate estimate of output frame size to determine if we need
// to recode.
@@ -3235,6 +3283,10 @@
cpi->projected_frame_size = (*size) << 3;
vp8_restore_coding_context(cpi);
+ if (frame_over_shoot_limit == 0)
+ frame_over_shoot_limit = 1;
+ active_worst_qchanged = FALSE;
+
// Special case handling for forced key frames
if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
{
@@ -3409,6 +3461,70 @@
if (cpi->is_src_frame_alt_ref)
Loop = FALSE;
+
+#if CONFIG_ENHANCED_INTERP
+ if (Loop == FALSE && cm->frame_type != KEY_FRAME && sf->search_best_filter)
+ {
+ if (mcomp_filter_index < mcomp_filters)
+ {
+ INT64 err = vp8_calc_ss_err(cpi->Source,
+ &cm->yv12_fb[cm->new_fb_idx],
+ IF_RTCD(&cpi->rtcd.variance));
+ INT64 rate = cpi->projected_frame_size << 8;
+ mcomp_filter_cost[mcomp_filter_index] =
+ (RDCOST(cpi->RDMULT, cpi->RDDIV, rate, err));
+ mcomp_filter_index++;
+ if (mcomp_filter_index < mcomp_filters)
+ {
+ cm->mcomp_filter_type = mcomp_filters_to_search[mcomp_filter_index];
+ loop_count = -1;
+ Loop = TRUE;
+ }
+ else
+ {
+ int f;
+ INT64 best_cost = mcomp_filter_cost[0];
+ int mcomp_best_filter = mcomp_filters_to_search[0];
+ for (f = 1; f < mcomp_filters; f++)
+ {
+ if (mcomp_filter_cost[f] < best_cost)
+ {
+ mcomp_best_filter = mcomp_filters_to_search[f];
+ best_cost = mcomp_filter_cost[f];
+ }
+ }
+ if (mcomp_best_filter != mcomp_filters_to_search[mcomp_filters-1])
+ {
+ loop_count = -1;
+ Loop = TRUE;
+ cm->mcomp_filter_type = mcomp_best_filter;
+ }
+ /*
+ printf(" best filter = %d, ( ", mcomp_best_filter);
+ for (f=0;f<mcomp_filters; f++) printf("%d ", mcomp_filter_cost[f]);
+ printf(")\n");
+ */
+ }
+#if RESET_FOREACH_FILTER
+ if (Loop == TRUE)
+ {
+ overshoot_seen = FALSE;
+ undershoot_seen = FALSE;
+ zbin_oq_low = zbin_oq_low0;
+ zbin_oq_high = zbin_oq_high0;
+ q_low = q_low0;
+ q_high = q_high0;
+ Q = Q0;
+ cpi->zbin_over_quant = last_zbin_oq = last_zbin_oq0;
+ cpi->rate_correction_factor = rate_correction_factor0;
+ cpi->gf_rate_correction_factor = gf_rate_correction_factor0;
+ cpi->active_best_quality = active_best_quality0;
+ cpi->active_worst_quality = active_worst_quality0;
+ }
+#endif
+ }
+ }
+#endif
if (Loop == TRUE)
{
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -230,6 +230,9 @@
int optimize_coefficients;
int no_skip_block4x4_search;
int improved_mv_pred;
+#if CONFIG_ENHANCED_INTERP
+ int search_best_filter;
+#endif
} SPEED_FEATURES;
--
⑨