ref: fcd6e4a1c2b3765ae6aa1ad703ef106e1cf7a533
parent: 870cf4356c074f7150b01c3f98cfc5d6a6a44487
parent: 4e23998fb4d4d0b1f16c7e2960561bc9a3d7b92a
author: Marco Paniconi <marpan@google.com>
date: Wed May 10 13:10:51 EDT 2017
Merge "vp9: SVC: Add option to set downsampling filter type."
--- a/vp9/common/vp9_rtcd_defs.pl
+++ b/vp9/common/vp9_rtcd_defs.pl
@@ -225,7 +225,7 @@
#
# frame based scale
#
-add_proto qw/void vp9_scale_and_extend_frame/, "const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler";
+add_proto qw/void vp9_scale_and_extend_frame/, "const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler";
specialize qw/vp9_scale_and_extend_frame ssse3/;
}
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2391,6 +2391,7 @@
#if CONFIG_VP9_HIGHBITDEPTH
static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *dst, int bd,
+ INTERP_FILTER filter_type,
int phase_scaler) {
const int src_w = src->y_crop_width;
const int src_h = src->y_crop_height;
@@ -2401,7 +2402,7 @@
const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride };
uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer };
const int dst_strides[3] = { dst->y_stride, dst->uv_stride, dst->uv_stride };
- const InterpKernel *const kernel = vp9_filter_kernels[EIGHTTAP];
+ const InterpKernel *const kernel = vp9_filter_kernels[filter_type];
int x, y, i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
@@ -2714,7 +2715,8 @@
cm->byte_alignment, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
- scale_and_extend_frame(ref, &new_fb_ptr->buf, (int)cm->bit_depth, 0);
+ scale_and_extend_frame(ref, &new_fb_ptr->buf, (int)cm->bit_depth,
+ EIGHTTAP, 0);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
alloc_frame_mvs(cm, new_fb);
}
@@ -2737,7 +2739,7 @@
cm->byte_alignment, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
- vp9_scale_and_extend_frame(ref, &new_fb_ptr->buf, 0);
+ vp9_scale_and_extend_frame(ref, &new_fb_ptr->buf, EIGHTTAP, 0);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
alloc_frame_mvs(cm, new_fb);
}
@@ -3124,10 +3126,13 @@
uint8_t *dest) {
VP9_COMMON *const cm = &cpi->common;
int q = 0, bottom_index = 0, top_index = 0; // Dummy variables.
+ const INTERP_FILTER filter_scaler =
+ (is_one_pass_cbr_svc(cpi))
+ ? cpi->svc.downsample_filter_type[cpi->svc.spatial_layer_id]
+ : EIGHTTAP;
const int phase_scaler =
- (is_one_pass_cbr_svc(cpi) &&
- cpi->svc.filtertype_downsample_source[cpi->svc.spatial_layer_id])
- ? 8
+ (is_one_pass_cbr_svc(cpi))
+ ? cpi->svc.downsample_filter_phase[cpi->svc.spatial_layer_id]
: 0;
// Flag to check if its valid to compute the source sad (used for
@@ -3148,10 +3153,11 @@
// For svc, if it is a 1/4x1/4 downscaling, do a two-stage scaling to take
// advantage of the 1:2 optimized scaler. In the process, the 1/2x1/2
// result will be saved in scaled_temp and might be used later.
- int phase_scaler2 = (cpi->svc.filtertype_downsample_source[1]) ? 8 : 0;
+ const INTERP_FILTER filter_scaler2 = cpi->svc.downsample_filter_type[1];
+ const int phase_scaler2 = cpi->svc.downsample_filter_phase[1];
cpi->Source = vp9_svc_twostage_scale(
cm, cpi->un_scaled_source, &cpi->scaled_source, &cpi->svc.scaled_temp,
- phase_scaler, phase_scaler2);
+ filter_scaler, phase_scaler, filter_scaler2, phase_scaler2);
cpi->svc.scaled_one_half = 1;
} else if (is_one_pass_cbr_svc(cpi) &&
cpi->un_scaled_source->y_width == cm->width << 1 &&
@@ -3162,9 +3168,9 @@
cpi->Source = &cpi->svc.scaled_temp;
cpi->svc.scaled_one_half = 0;
} else {
- cpi->Source =
- vp9_scale_if_required(cm, cpi->un_scaled_source, &cpi->scaled_source,
- (cpi->oxcf.pass == 0), phase_scaler);
+ cpi->Source = vp9_scale_if_required(
+ cm, cpi->un_scaled_source, &cpi->scaled_source, (cpi->oxcf.pass == 0),
+ filter_scaler, phase_scaler);
}
// Unfiltered raw source used in metrics calculation if the source
// has been filtered.
@@ -3173,7 +3179,7 @@
if (is_spatial_denoise_enabled(cpi)) {
cpi->raw_source_frame = vp9_scale_if_required(
cm, &cpi->raw_unscaled_source, &cpi->raw_scaled_source,
- (cpi->oxcf.pass == 0), phase_scaler);
+ (cpi->oxcf.pass == 0), EIGHTTAP, phase_scaler);
} else {
cpi->raw_source_frame = cpi->Source;
}
@@ -3205,9 +3211,9 @@
cpi->sf.partition_search_type == SOURCE_VAR_BASED_PARTITION ||
(cpi->noise_estimate.enabled && !cpi->oxcf.noise_sensitivity) ||
cpi->compute_source_sad_onepass))
- cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
- &cpi->scaled_last_source,
- (cpi->oxcf.pass == 0), 0);
+ cpi->Last_Source = vp9_scale_if_required(
+ cm, cpi->unscaled_last_source, &cpi->scaled_last_source,
+ (cpi->oxcf.pass == 0), EIGHTTAP, 0);
if (cpi->Last_Source == NULL ||
cpi->Last_Source->y_width != cpi->Source->y_width ||
@@ -3392,7 +3398,7 @@
cpi->Source =
vp9_scale_if_required(cm, cpi->un_scaled_source, &cpi->scaled_source,
- (cpi->oxcf.pass == 0), 0);
+ (cpi->oxcf.pass == 0), EIGHTTAP, 0);
// Unfiltered raw source used in metrics calculation if the source
// has been filtered.
@@ -3401,7 +3407,7 @@
if (is_spatial_denoise_enabled(cpi)) {
cpi->raw_source_frame = vp9_scale_if_required(
cm, &cpi->raw_unscaled_source, &cpi->raw_scaled_source,
- (cpi->oxcf.pass == 0), 0);
+ (cpi->oxcf.pass == 0), EIGHTTAP, 0);
} else {
cpi->raw_source_frame = cpi->Source;
}
@@ -3411,9 +3417,9 @@
}
if (cpi->unscaled_last_source != NULL)
- cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
- &cpi->scaled_last_source,
- (cpi->oxcf.pass == 0), 0);
+ cpi->Last_Source = vp9_scale_if_required(
+ cm, cpi->unscaled_last_source, &cpi->scaled_last_source,
+ (cpi->oxcf.pass == 0), EIGHTTAP, 0);
if (frame_is_intra_only(cm) == 0) {
if (loop_count > 0) {
@@ -3693,22 +3699,26 @@
YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(
VP9_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled,
- YV12_BUFFER_CONFIG *scaled_temp, int phase_scaler, int phase_scaler2) {
+ YV12_BUFFER_CONFIG *scaled_temp, INTERP_FILTER filter_type,
+ int phase_scaler, INTERP_FILTER filter_type2, int phase_scaler2) {
if (cm->mi_cols * MI_SIZE != unscaled->y_width ||
cm->mi_rows * MI_SIZE != unscaled->y_height) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->bit_depth == VPX_BITS_8) {
- vp9_scale_and_extend_frame(unscaled, scaled_temp, phase_scaler2);
- vp9_scale_and_extend_frame(scaled_temp, scaled, phase_scaler);
+ vp9_scale_and_extend_frame(unscaled, scaled_temp, filter_type2,
+ phase_scaler2);
+ vp9_scale_and_extend_frame(scaled_temp, scaled, filter_type,
+ phase_scaler);
} else {
scale_and_extend_frame(unscaled, scaled_temp, (int)cm->bit_depth,
- phase_scaler2);
+ filter_type2, phase_scaler2);
scale_and_extend_frame(scaled_temp, scaled, (int)cm->bit_depth,
- phase_scaler);
+ filter_type, phase_scaler);
}
#else
- vp9_scale_and_extend_frame(unscaled, scaled_temp, phase_scaler2);
- vp9_scale_and_extend_frame(scaled_temp, scaled, phase_scaler);
+ vp9_scale_and_extend_frame(unscaled, scaled_temp, filter_type2,
+ phase_scaler2);
+ vp9_scale_and_extend_frame(scaled_temp, scaled, filter_type, phase_scaler);
#endif // CONFIG_VP9_HIGHBITDEPTH
return scaled;
} else {
@@ -3716,11 +3726,9 @@
}
}
-YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
- YV12_BUFFER_CONFIG *unscaled,
- YV12_BUFFER_CONFIG *scaled,
- int use_normative_scaler,
- int phase_scaler) {
+YV12_BUFFER_CONFIG *vp9_scale_if_required(
+ VP9_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled,
+ int use_normative_scaler, INTERP_FILTER filter_type, int phase_scaler) {
if (cm->mi_cols * MI_SIZE != unscaled->y_width ||
cm->mi_rows * MI_SIZE != unscaled->y_height) {
#if CONFIG_VP9_HIGHBITDEPTH
@@ -3727,16 +3735,16 @@
if (use_normative_scaler && unscaled->y_width <= (scaled->y_width << 1) &&
unscaled->y_height <= (scaled->y_height << 1))
if (cm->bit_depth == VPX_BITS_8)
- vp9_scale_and_extend_frame(unscaled, scaled, phase_scaler);
+ vp9_scale_and_extend_frame(unscaled, scaled, filter_type, phase_scaler);
else
scale_and_extend_frame(unscaled, scaled, (int)cm->bit_depth,
- phase_scaler);
+ filter_type, phase_scaler);
else
scale_and_extend_frame_nonnormative(unscaled, scaled, (int)cm->bit_depth);
#else
if (use_normative_scaler && unscaled->y_width <= (scaled->y_width << 1) &&
unscaled->y_height <= (scaled->y_height << 1))
- vp9_scale_and_extend_frame(unscaled, scaled, phase_scaler);
+ vp9_scale_and_extend_frame(unscaled, scaled, filter_type, phase_scaler);
else
scale_and_extend_frame_nonnormative(unscaled, scaled);
#endif // CONFIG_VP9_HIGHBITDEPTH
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -836,17 +836,14 @@
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
-YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(VP9_COMMON *cm,
- YV12_BUFFER_CONFIG *unscaled,
- YV12_BUFFER_CONFIG *scaled,
- YV12_BUFFER_CONFIG *scaled_temp,
- int phase_scaler, int phase_scaler2);
+YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(
+ VP9_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled,
+ YV12_BUFFER_CONFIG *scaled_temp, INTERP_FILTER filter_type,
+ int phase_scaler, INTERP_FILTER filter_type2, int phase_scaler2);
-YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
- YV12_BUFFER_CONFIG *unscaled,
- YV12_BUFFER_CONFIG *scaled,
- int use_normative_scaler,
- int phase_scaler);
+YV12_BUFFER_CONFIG *vp9_scale_if_required(
+ VP9_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled,
+ int use_normative_scaler, INTERP_FILTER filter_type, int phase_scaler);
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -1400,7 +1400,7 @@
(cpi->ref_frame_flags & VP9_GOLD_FLAG) ? GOLDEN_FRAME : NONE);
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
- &cpi->scaled_source, 0, 0);
+ &cpi->scaled_source, 0, EIGHTTAP, 0);
}
vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
--- a/vp9/encoder/vp9_frame_scale.c
+++ b/vp9/encoder/vp9_frame_scale.c
@@ -16,7 +16,8 @@
#include "vpx_scale/yv12config.h"
void vp9_scale_and_extend_frame_c(const YV12_BUFFER_CONFIG *src,
- YV12_BUFFER_CONFIG *dst, int phase_scaler) {
+ YV12_BUFFER_CONFIG *dst,
+ INTERP_FILTER filter_type, int phase_scaler) {
const int src_w = src->y_crop_width;
const int src_h = src->y_crop_height;
const int dst_w = dst->y_crop_width;
@@ -26,7 +27,7 @@
const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride };
uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer };
const int dst_strides[3] = { dst->y_stride, dst->uv_stride, dst->uv_stride };
- const InterpKernel *const kernel = vp9_filter_kernels[EIGHTTAP];
+ const InterpKernel *const kernel = vp9_filter_kernels[filter_type];
int x, y, i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -38,11 +38,12 @@
svc->current_superframe = 0;
for (i = 0; i < REF_FRAMES; ++i) svc->ref_frame_index[i] = -1;
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
- cpi->svc.ext_frame_flags[sl] = 0;
- cpi->svc.ext_lst_fb_idx[sl] = 0;
- cpi->svc.ext_gld_fb_idx[sl] = 1;
- cpi->svc.ext_alt_fb_idx[sl] = 2;
- cpi->svc.filtertype_downsample_source[sl] = 0;
+ svc->ext_frame_flags[sl] = 0;
+ svc->ext_lst_fb_idx[sl] = 0;
+ svc->ext_gld_fb_idx[sl] = 1;
+ svc->ext_alt_fb_idx[sl] = 2;
+ svc->downsample_filter_type[sl] = EIGHTTAP;
+ svc->downsample_filter_phase[sl] = 0; // Set to 8 for averaging filter.
}
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
@@ -651,10 +652,12 @@
lc->scaling_factor_num, lc->scaling_factor_den, &width,
&height);
- // For low resolutions: set the filtertype for downsampling source to 1,
- // to get averaging filter.
- if (width <= 320 && height <= 240)
- cpi->svc.filtertype_downsample_source[cpi->svc.spatial_layer_id] = 1;
+ // For low resolutions: set phase of the filter = 8 (for symmetric averaging
+ // filter), use bilinear for now.
+ if (width <= 320 && height <= 240) {
+ cpi->svc.downsample_filter_type[cpi->svc.spatial_layer_id] = BILINEAR;
+ cpi->svc.downsample_filter_phase[cpi->svc.spatial_layer_id] = 8;
+ }
// The usage of use_base_mv assumes down-scale of 2x2. For now, turn off use
// of base motion vectors if spatial scale factors for any layers are not 2,
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -89,11 +89,12 @@
int current_superframe;
int use_base_mv;
// Used to control the downscaling filter for source scaling, for 1 pass CBR.
- // 0 will do sub-sampling (no weighted average), 1 will center the target
- // pixel and use the averaging filter, for the default eightap_regular:
- // {-1, 6, -19, 78, 78, -19, 6, -1 }.
- // TODO(marpan): Add option for bilinear.
- int filtertype_downsample_source[VPX_SS_MAX_LAYERS];
+ // downsample_filter_phase: = 0 will do sub-sampling (no weighted average),
+ // = 8 will center the target pixel and get a symmetric averaging filter.
+ // downsample_filter_type: 4 filters may be used: eighttap_regular,
+ // eighttap_smooth, eighttap_sharp, and bilinear.
+ INTERP_FILTER downsample_filter_type[VPX_SS_MAX_LAYERS];
+ int downsample_filter_phase[VPX_SS_MAX_LAYERS];
} SVC;
struct VP9_COMP;
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -755,7 +755,8 @@
"Failed to reallocate alt_ref_buffer");
}
frames[frame] = vp9_scale_if_required(
- cm, frames[frame], &cpi->svc.scaled_frames[frame_used], 0, 0);
+ cm, frames[frame], &cpi->svc.scaled_frames[frame_used], 0,
+ EIGHTTAP, 0);
++frame_used;
}
}
--- a/vp9/encoder/x86/vp9_frame_scale_ssse3.c
+++ b/vp9/encoder/x86/vp9_frame_scale_ssse3.c
@@ -17,7 +17,7 @@
extern void vp9_scale_and_extend_frame_c(const YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *dst,
- int phase_scaler);
+ uint8_t filter_type, int phase_scaler);
static void downsample_2_to_1_ssse3(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride, int w,
@@ -170,7 +170,7 @@
void vp9_scale_and_extend_frame_ssse3(const YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *dst,
- int phase_scaler) {
+ uint8_t filter_type, int phase_scaler) {
const int src_w = src->y_crop_width;
const int src_h = src->y_crop_height;
const int dst_w = dst->y_crop_width;
@@ -198,9 +198,9 @@
dst->uv_stride, dst_uv_w, dst_uv_h);
vpx_extend_frame_borders(dst);
} else {
- vp9_scale_and_extend_frame_c(src, dst, phase_scaler);
+ vp9_scale_and_extend_frame_c(src, dst, filter_type, phase_scaler);
}
} else {
- vp9_scale_and_extend_frame_c(src, dst, phase_scaler);
+ vp9_scale_and_extend_frame_c(src, dst, filter_type, phase_scaler);
}
}