vp9: Allow for disabling loopfilter per spatial layer
For SVC: add parameter to the control SET_SVC_PARAMS to allow for disabling the loopfilter per spatial layer. Note this svc setting will override the setting via VP9E_SET_DISABLE_LOOPFILTER (which should only be used for non-SVC). Add unittest to handle both SVC (spatial or temporal layers) and non-SVC (single layer) case. Change-Id: I4092f01668bae42aac724a6df5b6f6a604337448
This commit is contained in:
@@ -494,7 +494,31 @@ class LoopfilterOnePassCbrSvc : public OnePassCbrSvc,
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
PreEncodeFrameHookSetup(video, encoder);
|
||||
encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
|
||||
if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
|
||||
// Consider 3 cases:
|
||||
if (loopfilter_off_ == 0) {
|
||||
// loopfilter is on for all spatial layers on every superrframe.
|
||||
for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
svc_params_.loopfilter_ctrl[i] = 0;
|
||||
}
|
||||
} else if (loopfilter_off_ == 1) {
|
||||
// loopfilter is off for non-reference frames for all spatial layers.
|
||||
for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
svc_params_.loopfilter_ctrl[i] = 1;
|
||||
}
|
||||
} else {
|
||||
// loopfilter is off for all SL0 frames, and off only for non-reference
|
||||
// frames for SL > 0.
|
||||
svc_params_.loopfilter_ctrl[0] = 2;
|
||||
for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
svc_params_.loopfilter_ctrl[i] = 1;
|
||||
}
|
||||
}
|
||||
encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
|
||||
} else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 1) {
|
||||
// For non-SVC mode use the single layer control.
|
||||
encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
@@ -524,6 +548,35 @@ class LoopfilterOnePassCbrSvc : public OnePassCbrSvc,
|
||||
int num_nonref_frames_;
|
||||
};
|
||||
|
||||
TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL1TLLoopfilterOff) {
|
||||
SetSvcConfig(1, 1);
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_min_quantizer = 0;
|
||||
cfg_.rc_max_quantizer = 63;
|
||||
cfg_.g_threads = 1;
|
||||
cfg_.rc_dropframe_thresh = 0;
|
||||
cfg_.rc_target_bitrate = 800;
|
||||
cfg_.kf_max_dist = 9999;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.g_error_resilient = 1;
|
||||
cfg_.ts_rate_decimator[0] = 1;
|
||||
cfg_.temporal_layering_mode = 0;
|
||||
::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
|
||||
0, 400);
|
||||
cfg_.rc_target_bitrate = 600;
|
||||
AssignLayerBitrates();
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
#if CONFIG_VP9_DECODER
|
||||
if (loopfilter_off_ == 0)
|
||||
EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
|
||||
else
|
||||
EXPECT_EQ(GetMismatchFrames(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL3TLLoopfilterOff) {
|
||||
SetSvcConfig(1, 3);
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
@@ -542,7 +595,37 @@ TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL3TLLoopfilterOff) {
|
||||
cfg_.ts_rate_decimator[1] = 2;
|
||||
cfg_.ts_rate_decimator[2] = 1;
|
||||
cfg_.temporal_layering_mode = 3;
|
||||
::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
|
||||
0, 400);
|
||||
cfg_.rc_target_bitrate = 600;
|
||||
AssignLayerBitrates();
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
#if CONFIG_VP9_DECODER
|
||||
if (loopfilter_off_ == 0)
|
||||
EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
|
||||
else
|
||||
EXPECT_EQ(GetMismatchFrames(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc3SL3TLLoopfilterOff) {
|
||||
SetSvcConfig(3, 3);
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_min_quantizer = 0;
|
||||
cfg_.rc_max_quantizer = 63;
|
||||
cfg_.g_threads = 1;
|
||||
cfg_.rc_dropframe_thresh = 0;
|
||||
cfg_.rc_target_bitrate = 800;
|
||||
cfg_.kf_max_dist = 9999;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.g_error_resilient = 1;
|
||||
cfg_.ts_rate_decimator[0] = 4;
|
||||
cfg_.ts_rate_decimator[1] = 2;
|
||||
cfg_.ts_rate_decimator[2] = 1;
|
||||
cfg_.temporal_layering_mode = 3;
|
||||
::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
|
||||
0, 400);
|
||||
cfg_.rc_target_bitrate = 600;
|
||||
|
||||
+7
-6
@@ -43,13 +43,14 @@ void OnePassCbrSvc::PreEncodeFrameHookSetup(::libvpx_test::VideoSource *video,
|
||||
svc_params_.max_quantizers[i] = 63;
|
||||
svc_params_.min_quantizers[i] = 0;
|
||||
}
|
||||
svc_params_.speed_per_layer[0] = base_speed_setting_;
|
||||
for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
svc_params_.speed_per_layer[i] = speed_setting_;
|
||||
if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
|
||||
svc_params_.speed_per_layer[0] = base_speed_setting_;
|
||||
for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
svc_params_.speed_per_layer[i] = speed_setting_;
|
||||
}
|
||||
encoder->Control(VP9E_SET_SVC, 1);
|
||||
encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
|
||||
}
|
||||
|
||||
encoder->Control(VP9E_SET_SVC, 1);
|
||||
encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
|
||||
encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
|
||||
encoder->Control(VP9E_SET_AQ_MODE, 3);
|
||||
encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
|
||||
|
||||
@@ -357,6 +357,8 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) {
|
||||
if (is_one_pass_cbr_svc(cpi) && lc->speed > 0) {
|
||||
cpi->oxcf.speed = lc->speed;
|
||||
}
|
||||
if (lc->loopfilter_ctrl >= 0 || lc->loopfilter_ctrl < 3)
|
||||
cpi->loopfilter_ctrl = lc->loopfilter_ctrl;
|
||||
// Reset the frames_since_key and frames_to_key counters to their values
|
||||
// before the layer restore. Keep these defined for the stream (not layer).
|
||||
if (cpi->svc.number_temporal_layers > 1 ||
|
||||
|
||||
@@ -71,6 +71,7 @@ typedef struct {
|
||||
int actual_num_seg2_blocks;
|
||||
int counter_encode_maxq_scene_change;
|
||||
uint8_t speed;
|
||||
int loopfilter_ctrl;
|
||||
} LAYER_CONTEXT;
|
||||
|
||||
typedef struct SVC {
|
||||
|
||||
@@ -1573,6 +1573,7 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
|
||||
lc->scaling_factor_num = params->scaling_factor_num[sl];
|
||||
lc->scaling_factor_den = params->scaling_factor_den[sl];
|
||||
lc->speed = params->speed_per_layer[sl];
|
||||
lc->loopfilter_ctrl = params->loopfilter_ctrl[sl];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -705,6 +705,7 @@ typedef struct vpx_svc_parameters {
|
||||
int scaling_factor_den[VPX_MAX_LAYERS]; /**< Scaling factor-denominator */
|
||||
int speed_per_layer[VPX_MAX_LAYERS]; /**< Speed setting for each sl */
|
||||
int temporal_layering_mode; /**< Temporal layering mode */
|
||||
int loopfilter_ctrl[VPX_MAX_LAYERS]; /**< Loopfilter ctrl for each sl */
|
||||
} vpx_svc_extra_cfg_t;
|
||||
|
||||
/*!\brief Initialize an encoder instance
|
||||
|
||||
Reference in New Issue
Block a user