vp9-svc: Allow for 2 stage downscaling for spatial layers.
For 1 pass cbr mode: allow for two-stage 1:2 scaling (which will use the 1:2 optimized scaler) if the spatial layer is 1/4x1/4 of souce. Without this change, the base layer for 3 spatial layers would be using the non-normative scaler which is un-optimized/C code. Change-Id: I9d73f92a4a96927d0f1d6bf75315c1e60513226a
This commit is contained in:
@@ -957,7 +957,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||||
ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
|
ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
|
||||||
<< " The datarate for the file exceeds the target by too much!";
|
<< " The datarate for the file exceeds the target by too much!";
|
||||||
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.17)
|
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
|
||||||
<< " The datarate for the file is lower than the target by too much!";
|
<< " The datarate for the file is lower than the target by too much!";
|
||||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||||
}
|
}
|
||||||
@@ -1035,7 +1035,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||||
ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
|
ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
|
||||||
<< " The datarate for the file exceeds the target by too much!";
|
<< " The datarate for the file exceeds the target by too much!";
|
||||||
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.17)
|
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
|
||||||
<< " The datarate for the file is lower than the target by too much!";
|
<< " The datarate for the file is lower than the target by too much!";
|
||||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||||
}
|
}
|
||||||
|
@@ -410,6 +410,9 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
|
|||||||
memset(&cpi->svc.scaled_frames[0], 0,
|
memset(&cpi->svc.scaled_frames[0], 0,
|
||||||
MAX_LAG_BUFFERS * sizeof(cpi->svc.scaled_frames[0]));
|
MAX_LAG_BUFFERS * sizeof(cpi->svc.scaled_frames[0]));
|
||||||
|
|
||||||
|
vpx_free_frame_buffer(&cpi->svc.scaled_temp);
|
||||||
|
memset(&cpi->svc.scaled_temp, 0, sizeof(cpi->svc.scaled_temp));
|
||||||
|
|
||||||
vpx_free_frame_buffer(&cpi->svc.empty_frame.img);
|
vpx_free_frame_buffer(&cpi->svc.empty_frame.img);
|
||||||
memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
|
memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
|
||||||
|
|
||||||
@@ -3357,11 +3360,22 @@ static void encode_without_recode_loop(VP9_COMP *cpi,
|
|||||||
vpx_clear_system_state();
|
vpx_clear_system_state();
|
||||||
|
|
||||||
set_frame_size(cpi);
|
set_frame_size(cpi);
|
||||||
cpi->Source = vp9_scale_if_required(cm,
|
|
||||||
cpi->un_scaled_source,
|
|
||||||
&cpi->scaled_source,
|
|
||||||
(cpi->oxcf.pass == 0));
|
|
||||||
|
|
||||||
|
if (is_one_pass_cbr_svc(cpi) &&
|
||||||
|
cpi->un_scaled_source->y_width == cm->width << 2 &&
|
||||||
|
cpi->un_scaled_source->y_height == cm->height << 2 &&
|
||||||
|
cpi->svc.scaled_temp.y_width == cm->width << 1 &&
|
||||||
|
cpi->svc.scaled_temp.y_height == cm->height << 1) {
|
||||||
|
cpi->Source = vp9_svc_twostage_scale(cm,
|
||||||
|
cpi->un_scaled_source,
|
||||||
|
&cpi->scaled_source,
|
||||||
|
&cpi->svc.scaled_temp);
|
||||||
|
} else {
|
||||||
|
cpi->Source = vp9_scale_if_required(cm,
|
||||||
|
cpi->un_scaled_source,
|
||||||
|
&cpi->scaled_source,
|
||||||
|
(cpi->oxcf.pass == 0));
|
||||||
|
}
|
||||||
// Avoid scaling last_source unless its needed.
|
// Avoid scaling last_source unless its needed.
|
||||||
// Last source is needed if vp9_avg_source_sad() is used, or if
|
// Last source is needed if vp9_avg_source_sad() is used, or if
|
||||||
// partition_search_type == SOURCE_VAR_BASED_PARTITION, or if noise
|
// partition_search_type == SOURCE_VAR_BASED_PARTITION, or if noise
|
||||||
@@ -3780,6 +3794,25 @@ static void set_ext_overrides(VP9_COMP *cpi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(VP9_COMMON *cm,
|
||||||
|
YV12_BUFFER_CONFIG *unscaled,
|
||||||
|
YV12_BUFFER_CONFIG *scaled,
|
||||||
|
YV12_BUFFER_CONFIG *scaled_temp) {
|
||||||
|
if (cm->mi_cols * MI_SIZE != unscaled->y_width ||
|
||||||
|
cm->mi_rows * MI_SIZE != unscaled->y_height) {
|
||||||
|
#if CONFIG_VP9_HIGHBITDEPTH
|
||||||
|
scale_and_extend_frame(unscaled, scaled_temp, (int)cm->bit_depth);
|
||||||
|
scale_and_extend_frame(scaled_temp, scaled, (int)cm->bit_depth);
|
||||||
|
#else
|
||||||
|
vp9_scale_and_extend_frame(unscaled, scaled_temp);
|
||||||
|
vp9_scale_and_extend_frame(scaled_temp, scaled);
|
||||||
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||||
|
return scaled;
|
||||||
|
} else {
|
||||||
|
return unscaled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
|
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
|
||||||
YV12_BUFFER_CONFIG *unscaled,
|
YV12_BUFFER_CONFIG *unscaled,
|
||||||
YV12_BUFFER_CONFIG *scaled,
|
YV12_BUFFER_CONFIG *scaled,
|
||||||
|
@@ -623,6 +623,11 @@ void vp9_update_reference_frames(VP9_COMP *cpi);
|
|||||||
|
|
||||||
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
|
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);
|
||||||
|
|
||||||
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
|
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
|
||||||
YV12_BUFFER_CONFIG *unscaled,
|
YV12_BUFFER_CONFIG *unscaled,
|
||||||
YV12_BUFFER_CONFIG *scaled,
|
YV12_BUFFER_CONFIG *scaled,
|
||||||
|
@@ -43,6 +43,26 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
|
|||||||
cpi->svc.ext_alt_fb_idx[sl] = 2;
|
cpi->svc.ext_alt_fb_idx[sl] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For 1 pass cbr: allocate scaled_frame that may be used as an intermediate
|
||||||
|
// buffer for a 2 stage down-sampling: two stages of 1:2 down-sampling for a
|
||||||
|
// target of 1/4x1/4.
|
||||||
|
if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
|
||||||
|
if (vpx_realloc_frame_buffer(&cpi->svc.scaled_temp,
|
||||||
|
cpi->common.width >> 1,
|
||||||
|
cpi->common.height >> 1,
|
||||||
|
cpi->common.subsampling_x,
|
||||||
|
cpi->common.subsampling_y,
|
||||||
|
#if CONFIG_VP9_HIGHBITDEPTH
|
||||||
|
cpi->common.use_highbitdepth,
|
||||||
|
#endif
|
||||||
|
VP9_ENC_BORDER_IN_PIXELS,
|
||||||
|
cpi->common.byte_alignment,
|
||||||
|
NULL, NULL, NULL))
|
||||||
|
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
|
||||||
|
"Failed to allocate scaled_frame for svc ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
|
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
|
||||||
if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img,
|
if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img,
|
||||||
SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
|
SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
|
||||||
|
@@ -70,6 +70,8 @@ typedef struct {
|
|||||||
// Store scaled source frames to be used for temporal filter to generate
|
// Store scaled source frames to be used for temporal filter to generate
|
||||||
// a alt ref frame.
|
// a alt ref frame.
|
||||||
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
||||||
|
// Temp buffer used for 2-stage down-sampling, for real-time mode.
|
||||||
|
YV12_BUFFER_CONFIG scaled_temp;
|
||||||
|
|
||||||
// Layer context used for rate control in one pass temporal CBR mode or
|
// Layer context used for rate control in one pass temporal CBR mode or
|
||||||
// two pass spatial mode.
|
// two pass spatial mode.
|
||||||
|
Reference in New Issue
Block a user