Rework how QP bounds are passed

Pass via an (variable length) set of settings for picture types
instead of the fixed I/P/B types. Also makes it possible to
pass a max without also passing a min.

Bug: 181830609
Test: vq testing, ALOG
Change-Id: I69bba8e35f0eda234530df92706230dc898b4ae9
(cherry picked from commit a0ae69790a8e96a5a386260b5197f4472b930dac)
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 8e8a08b..f8aa672 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -187,7 +187,7 @@
     kParamIndexPictureType,
     kParamIndexHdr10PlusMetadata,
 
-    kParamIndexQuantization,
+    kParamIndexPictureQuantization,
 
     /* ------------------------------------ video components ------------------------------------ */
 
@@ -710,38 +710,6 @@
         C2StreamProfileLevelInfo;
 constexpr char C2_PARAMKEY_PROFILE_LEVEL[] = "coded.pl";
 
-struct C2QuantizationStruct {
-    int32_t iMax;  ///< max/min for I frames
-    int32_t iMin;
-    int32_t pMax;  ///< max/min for P frames
-    int32_t pMin;
-    int32_t bMax;  ///< max/min for B frames
-    int32_t bMin;
-
-    C2QuantizationStruct(
-            int32_t iMax_ = INT32_MAX,
-            int32_t iMin_ = INT32_MIN,
-            int32_t pMax_ = INT32_MAX,
-            int32_t pMin_ = INT32_MIN,
-            int32_t bMax_ = INT32_MAX,
-            int32_t bMin_ = INT32_MIN)
-        : iMax(iMax_), iMin(iMin_),
-          pMax(pMax_), pMin(pMin_),
-          bMax(bMax_), bMin(bMin_) { }
-
-    DEFINE_AND_DESCRIBE_C2STRUCT(Quantization)          // reference?
-    C2FIELD(iMax, "i-max")
-    C2FIELD(iMin, "i-min")
-    C2FIELD(pMax, "p-max")
-    C2FIELD(pMin, "p-min")
-    C2FIELD(bMax, "b-max")
-    C2FIELD(bMin, "b-min")
-};
-
-typedef C2StreamParam<C2Info, C2QuantizationStruct, kParamIndexQuantization>
-        C2StreamQuantizationInfo;
-constexpr char C2_PARAMKEY_QUANTIZATION[] = "coded.qp";
-
 /**
  * Codec-specific initialization data.
  *
@@ -1733,6 +1701,31 @@
 constexpr char C2_PARAMKEY_GOP[] = "coding.gop";
 
 /**
+ * Quantization
+ * min/max for each picture type
+ *
+ */
+struct C2PictureQuantizationStruct {
+    C2PictureQuantizationStruct() : type_((C2Config::picture_type_t)0),
+                                         min(INT32_MIN), max(INT32_MAX) {}
+    C2PictureQuantizationStruct(C2Config::picture_type_t type, int32_t min_, int32_t max_)
+        : type_(type), min(min_), max(max_) { }
+
+    C2Config::picture_type_t type_;
+    int32_t min;      // INT32_MIN == 'no lower bound specified'
+    int32_t max;      // INT32_MAX == 'no upper bound specified'
+
+    DEFINE_AND_DESCRIBE_C2STRUCT(PictureQuantization)
+    C2FIELD(type_, "type")
+    C2FIELD(min, "min")
+    C2FIELD(max, "max")
+};
+
+typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2PictureQuantizationStruct>,
+        kParamIndexPictureQuantization> C2StreamPictureQuantizationTuning;
+constexpr char C2_PARAMKEY_PICTURE_QUANTIZATION[] = "coding.qp";
+
+/**
  * Sync frame can be requested on demand by the client.
  *
  * If true, the next I frame shall be encoded as a sync frame. This config can be passed
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index f7564f6..f869691 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1085,6 +1085,45 @@
             configUpdate.push_back(std::move(gop));
         }
 
+        if ((config->mDomain & Config::IS_ENCODER)
+                && (config->mDomain & Config::IS_VIDEO)) {
+            // we may not use all 3 of these entries
+            std::unique_ptr<C2StreamPictureQuantizationTuning::output> qp =
+                C2StreamPictureQuantizationTuning::output::AllocUnique(3 /* flexCount */,
+                                                                       0u /* stream */);
+
+            int ix = 0;
+
+            int32_t iMax = INT32_MAX;
+            int32_t iMin = INT32_MIN;
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MAX, &iMax);
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MIN, &iMin);
+            if (iMax != INT32_MAX || iMin != INT32_MIN) {
+                qp->m.values[ix++] = {I_FRAME, iMin, iMax};
+            }
+
+            int32_t pMax = INT32_MAX;
+            int32_t pMin = INT32_MIN;
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MAX, &pMax);
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MIN, &pMin);
+            if (pMax != INT32_MAX || pMin != INT32_MIN) {
+                qp->m.values[ix++] = {P_FRAME, pMin, pMax};
+            }
+
+            int32_t bMax = INT32_MAX;
+            int32_t bMin = INT32_MIN;
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MAX, &bMax);
+            (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MIN, &bMin);
+            if (bMax != INT32_MAX || bMin != INT32_MIN) {
+                qp->m.values[ix++] = {B_FRAME, bMin, bMax};
+            }
+
+            // adjust to reflect actual use.
+            qp->setFlexCount(ix);
+
+            configUpdate.push_back(std::move(qp));
+        }
+
         err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK);
         if (err != OK) {
             ALOGW("failed to configure c2 params");
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5de7539..f5cc98e 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -729,19 +729,6 @@
             return C2Value();
         }));
 
-    add(ConfigMapper(KEY_VIDEO_QP_I_MAX, C2_PARAMKEY_QUANTIZATION, "i-max")
-        .limitTo(D::VIDEO & D::ENCODER));
-    add(ConfigMapper(KEY_VIDEO_QP_I_MIN, C2_PARAMKEY_QUANTIZATION, "i-min")
-        .limitTo(D::VIDEO & D::ENCODER));
-    add(ConfigMapper(KEY_VIDEO_QP_P_MAX, C2_PARAMKEY_QUANTIZATION, "p-max")
-        .limitTo(D::VIDEO & D::ENCODER));
-    add(ConfigMapper(KEY_VIDEO_QP_P_MIN, C2_PARAMKEY_QUANTIZATION, "p-min")
-        .limitTo(D::VIDEO & D::ENCODER));
-    add(ConfigMapper(KEY_VIDEO_QP_B_MAX, C2_PARAMKEY_QUANTIZATION, "b-max")
-        .limitTo(D::VIDEO & D::ENCODER));
-    add(ConfigMapper(KEY_VIDEO_QP_B_MIN, C2_PARAMKEY_QUANTIZATION, "b-min")
-        .limitTo(D::VIDEO & D::ENCODER));
-
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
         .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))