Commit 2f0bbb582b for aom
commit 2f0bbb582bd124265bde19b77bba4d4e3e8b67eb
Author: Marco Paniconi <marpan@google.com>
Date: Fri Apr 17 16:17:32 2026 -0700
Add check for svc input scaling_factor_den
Spatial scaling factors should be such that
scaling_factor_den[sl] >= scaling_factor_num[sl].
Return AOM_CODEC_INVALID_PARAM if this is not
satisfied.
Bug: 503171639
Change-Id: I63c9df9c8f0b6f1516547e6b5eafb64c7b3e5c85
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 8d14b41034..7c7ad7bebd 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -1843,10 +1843,14 @@ typedef struct aom_svc_params {
* \li When \em not using #AV1E_SET_SVC_REF_FRAME_CONFIG: [1, 3]
*/
int number_temporal_layers;
- int max_quantizers[AOM_MAX_LAYERS]; /**< Max Q for each layer */
- int min_quantizers[AOM_MAX_LAYERS]; /**< Min Q for each layer */
- int scaling_factor_num[AOM_MAX_SS_LAYERS]; /**< Scaling factor-numerator */
- int scaling_factor_den[AOM_MAX_SS_LAYERS]; /**< Scaling factor-denominator */
+ int max_quantizers[AOM_MAX_LAYERS]; /**< Max Q for each layer */
+ int min_quantizers[AOM_MAX_LAYERS]; /**< Min Q for each layer */
+ /*! Scaling factor-numerator */
+ int scaling_factor_num[AOM_MAX_SS_LAYERS];
+ /*! Scaling factor-denominator: must be greater than or equal to the
+ * scaling_factor_num[].
+ */
+ int scaling_factor_den[AOM_MAX_SS_LAYERS];
/*! Target bitrate for each layer, in kilobits per second */
int layer_target_bitrate[AOM_MAX_LAYERS];
/*! Frame rate factor for each temporal layer */
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 120f6f7e8b..3b63df5740 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -4142,8 +4142,14 @@ static aom_codec_err_t ctrl_set_svc_params(aom_codec_alg_priv_t *ctx,
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
lc->max_q = params->max_quantizers[layer];
lc->min_q = params->min_quantizers[layer];
- lc->scaling_factor_num = AOMMAX(1, params->scaling_factor_num[sl]);
- lc->scaling_factor_den = AOMMAX(1, params->scaling_factor_den[sl]);
+ // spatial scaling (scaling_factor_num[]/den[]) is always to a lower
+ // resolution, so den must be >= num.
+ if (params->scaling_factor_den[sl] < params->scaling_factor_num[sl]) {
+ return AOM_CODEC_INVALID_PARAM;
+ } else {
+ lc->scaling_factor_num = AOMMAX(1, params->scaling_factor_num[sl]);
+ lc->scaling_factor_den = AOMMAX(1, params->scaling_factor_den[sl]);
+ }
const int layer_target_bitrate = params->layer_target_bitrate[layer];
if (layer_target_bitrate > INT_MAX / 1000) {
lc->layer_target_bitrate = INT_MAX;
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index 239d29af1c..4b75ece6ff 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -171,6 +171,25 @@ TEST(EncodeAPI, InvalidSvcParams) {
svc_params.framerate_factor[1] = 1;
svc_params.layer_target_bitrate[0] = 60 * cfg.rc_target_bitrate / 100;
svc_params.layer_target_bitrate[1] = cfg.rc_target_bitrate;
+ // Check scale factors.
+ for (int i = 0; i < AOM_MAX_SS_LAYERS; i++) {
+ svc_params.scaling_factor_num[i] = 1;
+ svc_params.scaling_factor_den[i] = 1;
+ }
+ svc_params.number_spatial_layers = 2;
+ svc_params.number_temporal_layers = 1;
+ // Set invalid factors.
+ svc_params.scaling_factor_num[0] = 2;
+ svc_params.scaling_factor_den[0] = 1;
+ EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_SVC_PARAMS, &svc_params),
+ AOM_CODEC_INVALID_PARAM);
+ // Set valid factors.
+ svc_params.scaling_factor_num[0] = 1;
+ svc_params.scaling_factor_den[0] = 2;
+ EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_SVC_PARAMS, &svc_params),
+ AOM_CODEC_OK);
+ svc_params.scaling_factor_num[0] = 1;
+ svc_params.scaling_factor_den[0] = 1;
for (const bool use_flexible_mode : { false, true }) {
if (use_flexible_mode) {
aom_svc_ref_frame_config_t ref_frame_config = {};