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 = {};