From f02f8aef1d9b4bac1a7c67f3f5dfab863fc52eaa Mon Sep 17 00:00:00 2001 From: Zhijie Yang Date: Thu, 26 Oct 2017 17:58:29 -0700 Subject: [PATCH] Add short_filter experiment Reduce the motion interpolation filter taps for inter prediction blocks with widths or heights smaller than or equal to 4 to alleviate the memory bandwidth increase. AWCY HL: 0.01% Y, -0.20% U, -0.29% V (positive number means loss) Change-Id: Ic454340e20aea2f1aae622336990f24a9e5b54d8 --- av1/common/convolve.c | 33 +++++++++++++++-- av1/common/convolve.h | 18 +++++++--- av1/common/filter.c | 51 +++++++++++++++++++++++++++ av1/common/filter.h | 9 +++++ av1/common/reconinter.h | 11 ++++++ build/cmake/aom_config_defaults.cmake | 1 + configure | 1 + 7 files changed, 118 insertions(+), 6 deletions(-) diff --git a/av1/common/convolve.c b/av1/common/convolve.c index 1aa08a4d3..cc3a87379 100644 --- a/av1/common/convolve.c +++ b/av1/common/convolve.c @@ -634,8 +634,13 @@ void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst, (void)dst_stride; InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x, &filter_params_y); +#endif if (filter_params_y.taps < filter_params_x.taps) { uint8_t tr_src[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * @@ -959,8 +964,13 @@ void av1_highbd_convolve_2d_facade(const uint8_t *src8, int src_stride, (void)dst_stride; InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x, &filter_params_y); +#endif const uint16_t *src = CONVERT_TO_SHORTPTR(src8); if (filter_params_y.taps < filter_params_x.taps) { @@ -1026,8 +1036,13 @@ static void convolve_helper(const uint8_t *src, int src_stride, uint8_t *dst, int ignore_vert = y_step_q4 == SUBPEL_SHIFTS && subpel_y_q4 == 0; InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); +#endif assert(conv_params->round == CONVOLVE_OPT_ROUND); @@ -1123,9 +1138,14 @@ static void convolve_scale_helper(const uint8_t *src, int src_stride, int ignore_vert = y_step_qn == SCALE_SUBPEL_SHIFTS && subpel_y_qn == 0; InterpFilterParams filter_params_x, filter_params_y; + +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); - +#endif assert(conv_params->round == CONVOLVE_OPT_ROUND); assert(w <= MAX_BLOCK_WIDTH); @@ -1515,8 +1535,13 @@ void av1_highbd_convolve(const uint8_t *src8, int src_stride, uint8_t *dst8, } InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); +#endif if (ignore_vert) { av1_highbd_convolve_horiz_facade(src8, src_stride, dst8, dst_stride, w, h, @@ -1535,7 +1560,6 @@ void av1_highbd_convolve(const uint8_t *src8, int src_stride, uint8_t *dst8, uint8_t *temp8 = CONVERT_TO_BYTEPTR(temp); int max_intermediate_size = ((MAX_SB_SIZE * 2 + 16) + 16); int filter_size; - #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER av1_convolve_filter_params_fixup_1212(&filter_params_x, &filter_params_y); @@ -1609,8 +1633,13 @@ void av1_highbd_convolve_scale(const uint8_t *src8, int src_stride, } InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); +#endif if (ignore_vert) { av1_highbd_convolve_horiz_facade_scale(src8, src_stride, dst8, dst_stride, diff --git a/av1/common/convolve.h b/av1/common/convolve.h index 61f290adf..c9f6785f6 100644 --- a/av1/common/convolve.h +++ b/av1/common/convolve.h @@ -64,9 +64,15 @@ static INLINE void av1_convolve_filter_params_fixup_1212( } #endif -static INLINE void av1_get_convolve_filter_params( - InterpFilters interp_filters, int avoid_1212, InterpFilterParams *params_x, - InterpFilterParams *params_y) { +static INLINE void av1_get_convolve_filter_params(InterpFilters interp_filters, + int avoid_1212, + InterpFilterParams *params_x, + InterpFilterParams *params_y +#if CONFIG_SHORT_FILTER + , + int w, int h +#endif + ) { #if CONFIG_DUAL_FILTER InterpFilter filter_x = av1_extract_interp_filter(interp_filters, 1); InterpFilter filter_y = av1_extract_interp_filter(interp_filters, 0); @@ -74,9 +80,13 @@ static INLINE void av1_get_convolve_filter_params( InterpFilter filter_x = av1_extract_interp_filter(interp_filters, 0); InterpFilter filter_y = av1_extract_interp_filter(interp_filters, 0); #endif - +#if CONFIG_SHORT_FILTER + *params_x = av1_get_interp_filter_params_with_block_size(filter_x, w); + *params_y = av1_get_interp_filter_params_with_block_size(filter_y, h); +#else *params_x = av1_get_interp_filter_params(filter_x); *params_y = av1_get_interp_filter_params(filter_y); +#endif if (avoid_1212) { #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER diff --git a/av1/common/filter.c b/av1/common/filter.c index d766f65de..4d0a8bde0 100644 --- a/av1/common/filter.c +++ b/av1/common/filter.c @@ -259,6 +259,39 @@ static const InterpFilterParams av1_interp_temporalfilter_12tap = { }; #endif // USE_TEMPORALFILTER_12TAP +#if CONFIG_SHORT_FILTER + +DECLARE_ALIGNED(256, static const InterpKernel, + sub_pel_filters_4[SUBPEL_SHIFTS]) = { + { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, -4, 126, 8, -2, 0, 0 }, + { 0, 0, -8, 122, 18, -4, 0, 0 }, { 0, 0, -10, 116, 28, -6, 0, 0 }, + { 0, 0, -12, 110, 38, -8, 0, 0 }, { 0, 0, -12, 102, 48, -10, 0, 0 }, + { 0, 0, -14, 94, 58, -10, 0, 0 }, { 0, 0, -12, 84, 66, -10, 0, 0 }, + { 0, 0, -12, 76, 76, -12, 0, 0 }, { 0, 0, -10, 66, 84, -12, 0, 0 }, + { 0, 0, -10, 58, 94, -14, 0, 0 }, { 0, 0, -10, 48, 102, -12, 0, 0 }, + { 0, 0, -8, 38, 110, -12, 0, 0 }, { 0, 0, -6, 28, 116, -10, 0, 0 }, + { 0, 0, -4, 18, 122, -8, 0, 0 }, { 0, 0, -2, 8, 126, -4, 0, 0 } +}; +DECLARE_ALIGNED(256, static const InterpKernel, + sub_pel_filters_4smooth[SUBPEL_SHIFTS]) = { + { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, 30, 62, 34, 2, 0, 0 }, + { 0, 0, 26, 62, 36, 4, 0, 0 }, { 0, 0, 22, 62, 40, 4, 0, 0 }, + { 0, 0, 20, 60, 42, 6, 0, 0 }, { 0, 0, 18, 58, 44, 8, 0, 0 }, + { 0, 0, 16, 56, 46, 10, 0, 0 }, { 0, 0, 14, 54, 48, 12, 0, 0 }, + { 0, 0, 12, 52, 52, 12, 0, 0 }, { 0, 0, 12, 48, 54, 14, 0, 0 }, + { 0, 0, 10, 46, 56, 16, 0, 0 }, { 0, 0, 8, 44, 58, 18, 0, 0 }, + { 0, 0, 6, 42, 60, 20, 0, 0 }, { 0, 0, 4, 40, 62, 22, 0, 0 }, + { 0, 0, 4, 36, 62, 26, 0, 0 }, { 0, 0, 2, 34, 62, 30, 0, 0 } +}; + +static const InterpFilterParams av1_interp_4tap[2] = { + { (const int16_t *)sub_pel_filters_4, SUBPEL_TAPS, SUBPEL_SHIFTS, + FOURTAP_REGULAR }, + { (const int16_t *)sub_pel_filters_4smooth, SUBPEL_TAPS, SUBPEL_SHIFTS, + FOURTAP_SMOOTH }, +}; +#endif + InterpFilterParams av1_get_interp_filter_params( const InterpFilter interp_filter) { #if USE_TEMPORALFILTER_12TAP @@ -268,6 +301,24 @@ InterpFilterParams av1_get_interp_filter_params( return av1_interp_filter_params_list[interp_filter]; } +#if CONFIG_SHORT_FILTER +InterpFilterParams av1_get_interp_filter_params_with_block_size( + const InterpFilter interp_filter, const int w) { +#if USE_TEMPORALFILTER_12TAP + if (interp_filter == TEMPORALFILTER_12TAP) + return av1_interp_temporalfilter_12tap; +#endif // USE_TEMPORALFILTER_12TAP + + if (w <= 4 && + (interp_filter == MULTITAP_SHARP || interp_filter == EIGHTTAP_REGULAR)) + return av1_interp_4tap[0]; + else if (w <= 4 && interp_filter == EIGHTTAP_SMOOTH) + return av1_interp_4tap[1]; + + return av1_interp_filter_params_list[interp_filter]; +} +#endif + const int16_t *av1_get_interp_filter_kernel(const InterpFilter interp_filter) { #if USE_TEMPORALFILTER_12TAP if (interp_filter == TEMPORALFILTER_12TAP) diff --git a/av1/common/filter.h b/av1/common/filter.h index 2f1689a9f..19caf7c31 100644 --- a/av1/common/filter.h +++ b/av1/common/filter.h @@ -44,6 +44,10 @@ typedef enum ATTRIBUTE_PACKED { FILTER_SHARP_UV, FILTER_SMOOTH2_UV, #endif // USE_EXTRA_FILTER +#if CONFIG_SHORT_FILTER + FOURTAP_REGULAR, + FOURTAP_SMOOTH, +#endif INTERP_FILTERS_ALL, SWITCHABLE_FILTERS = BILINEAR, SWITCHABLE = SWITCHABLE_FILTERS + 1, /* the last switchable one */ @@ -125,6 +129,11 @@ InterpFilterParams av1_get_interp_filter_params( const int16_t *av1_get_interp_filter_kernel(const InterpFilter interp_filter); +#if CONFIG_SHORT_FILTER +InterpFilterParams av1_get_interp_filter_params_with_block_size( + const InterpFilter interp_filter, const int w); +#endif + static INLINE const int16_t *av1_get_interp_filter_subpel_kernel( const InterpFilterParams filter_params, const int subpel) { return filter_params.filter_ptr + filter_params.taps * subpel; diff --git a/av1/common/reconinter.h b/av1/common/reconinter.h index 7fbd8c306..094d42ca8 100644 --- a/av1/common/reconinter.h +++ b/av1/common/reconinter.h @@ -86,9 +86,15 @@ static INLINE void inter_predictor(const uint8_t *src, int src_stride, assert(conv_params->round == CONVOLVE_OPT_ROUND); InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); +#endif + if (w <= 2 || h <= 2) { av1_convolve_c(src, src_stride, dst, dst_stride, w, h, interp_filters, subpel_x, xs, subpel_y, ys, conv_params); @@ -154,8 +160,13 @@ static INLINE void highbd_inter_predictor(const uint8_t *src, int src_stride, #endif // CONFIG_CONVOLVE_ROUND } else { InterpFilterParams filter_params_x, filter_params_y; +#if CONFIG_SHORT_FILTER + av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, + &filter_params_y, w, h); +#else av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x, &filter_params_y); +#endif if (filter_params_x.taps == SUBPEL_TAPS && filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) { diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake index df7cab21b..9c550d3ab 100644 --- a/build/cmake/aom_config_defaults.cmake +++ b/build/cmake/aom_config_defaults.cmake @@ -191,6 +191,7 @@ set(CONFIG_RECT_TX_EXT 0 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_REFERENCE_BUFFER 1 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_REF_ADAPT 0 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_SEGMENT_ZEROMV 0 CACHE NUMBER "AV1 experiment flag.") +set(CONFIG_SHORT_FILTER 0 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_SIMPLE_BWD_ADAPT 0 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_SMOOTH_HV 1 CACHE NUMBER "AV1 experiment flag.") set(CONFIG_STRIPED_LOOP_RESTORATION 0 CACHE NUMBER "AV1 experiment flag.") diff --git a/configure b/configure index 0c6e8ed12..984a58b97 100755 --- a/configure +++ b/configure @@ -252,6 +252,7 @@ EXPERIMENT_LIST=" rect_tx rect_tx_ext tpl_mv + short_filter dual_filter convolve_round compound_round -- GitLab