Fix in ctrl_set_svc_params for use_svc
In the set_svc_params control: the use_svc should be set
after the invalid param exit check, otherwise if the
ctrl_set_svc_params fails due to invalid params after use_svc
is set to 1, av1_free_svc_cyclic_refresh() will be called in
dealloc_compressor_data() causing a failure, as shown in the
issue below.
Added unittest to reproduce the issue.
Bug: b:449341177
Change-Id: Id5b3ad3b2ec36a77e5415633a5ebfb2d970ec615
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 89d9b92..4eff4e9 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -4013,7 +4013,6 @@
unsigned int sl, tl;
// Disable svc for lag_in_frames > 0.
if (cpi->oxcf.gf_cfg.lag_in_frames > 0) return AOM_CODEC_INVALID_PARAM;
- ctx->ppi->use_svc = 1;
const int num_layers =
ppi->number_spatial_layers * ppi->number_temporal_layers;
for (int layer = 0; layer < num_layers; ++layer) {
@@ -4024,6 +4023,7 @@
}
}
if (!av1_alloc_layer_context(cpi, num_layers)) return AOM_CODEC_MEM_ERROR;
+ ppi->use_svc = 1;
for (sl = 0; sl < ppi->number_spatial_layers; ++sl) {
for (tl = 0; tl < ppi->number_temporal_layers; ++tl) {
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index 3bf2205..252b1bf 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -1685,4 +1685,46 @@
ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK);
}
+// This test is based on the issue:449341177. The issue occurs in the
+// codec_destroy after invalid params (quantizer out of range) are passed
+// to the set_svc_params control. The issue can occur for realtime mode
+// with lag_in_frames = 0.
+TEST(EncodeAPI, Issue449341177) {
+ aom_codec_iface_t *iface = aom_codec_av1_cx();
+ aom_codec_enc_cfg_t cfg;
+ ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME),
+ AOM_CODEC_OK);
+ cfg.g_w = 320;
+ cfg.g_h = 240;
+ cfg.rc_target_bitrate = 500;
+ cfg.g_timebase.num = 1;
+ cfg.g_timebase.den = 30;
+ cfg.rc_end_usage = AOM_CBR;
+ cfg.g_lag_in_frames = 0;
+ aom_codec_ctx_t enc;
+ ASSERT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK);
+ // AV1E_SET_SVC_PARAMS
+ aom_svc_params_t svc_params = {};
+ svc_params.number_spatial_layers = 3;
+ svc_params.number_temporal_layers = 2;
+ for (int i = 0; i < AOM_MAX_LAYERS; i++) {
+ // Set quantizer out of range.
+ svc_params.max_quantizers[i] = 80;
+ svc_params.min_quantizers[i] = 0;
+ svc_params.layer_target_bitrate[i] = 1000;
+ }
+ for (int i = 0; i < AOM_MAX_SS_LAYERS; i++) {
+ svc_params.scaling_factor_num[i] = 1;
+ svc_params.scaling_factor_den[i] = 1;
+ }
+ for (int i = 0; i < AOM_MAX_TS_LAYERS; i++) {
+ svc_params.framerate_factor[i] = 1;
+ }
+ // set_svc_params should fail because svc_params.max_quantizer[i] is set out
+ // of range.
+ EXPECT_NE(aom_codec_control(&enc, AV1E_SET_SVC_PARAMS, &svc_params),
+ AOM_CODEC_OK);
+ ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK);
+}
+
} // namespace