Updated shaping algorithm

-- bitrate > 2x floor => no changes
        so 1st party camera (with high bitrates) is unchanged
-- if QP desired, but not supported by codec -> +20% bitrate
        try to compensate for missing QP capabilities

Bug: 183211971
Test: video quality tests
Change-Id: Ibdff3c6d73af6372f265ccb945066272ac4097d9
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/libmediaformatshaper/VQApply.cpp
index 39a5e19..08e23cc 100644
--- a/media/libmediaformatshaper/VQApply.cpp
+++ b/media/libmediaformatshaper/VQApply.cpp
@@ -48,6 +48,15 @@
 //
 static const int BITRATE_MODE_VBR = 1;
 
+
+// constants we use within the calculations
+//
+constexpr double BITRATE_LEAVE_UNTOUCHED = 2.0;
+constexpr double BITRATE_QP_UNAVAILABLE = 1.20;
+// 10% didn't work so hot on bonito (with no QP support)
+// 15% is next.. still leaves a few short
+// 20% ? this is on the edge of what I want do do
+
 //
 // Caller retains ownership of and responsibility for inFormat
 //
@@ -69,69 +78,82 @@
     }
 
     //
-    // apply any and all tools that we have.
+    // consider any and all tools available
     // -- qp
     // -- minimum bits-per-pixel
     //
-    if (!codec->supportsQp()) {
-        ALOGD("minquality: no qp bounding in codec %s", codec->getName().c_str());
-    } else {
-        // use a (configurable) QP value to force better quality
-        //
+    int64_t bitrateChosen = 0;
+    int32_t qpChosen = INT32_MAX;
+
+    int64_t bitrateConfigured = 0;
+    int32_t bitrateConfiguredTmp = 0;
+    (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrateConfiguredTmp);
+    bitrateConfigured = bitrateConfiguredTmp;
+    bitrateChosen = bitrateConfigured;
+
+    int32_t width = 0;
+    (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
+    int32_t height = 0;
+    (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
+    int64_t pixels = ((int64_t)width) * height;
+    double minimumBpp = codec->getBpp(width, height);
+
+    int64_t bitrateFloor = pixels * minimumBpp;
+    if (bitrateFloor > INT32_MAX) bitrateFloor = INT32_MAX;
+
+    // if we are far enough above the target bpp, leave it alone
+    //
+    ALOGV("bitrate: configured %" PRId64 " floor %" PRId64, bitrateConfigured, bitrateFloor);
+    if (bitrateConfigured >= BITRATE_LEAVE_UNTOUCHED * bitrateFloor) {
+        ALOGV("high enough bitrate: configured %" PRId64 " >= %f * floor %" PRId64,
+                bitrateConfigured, BITRATE_LEAVE_UNTOUCHED, bitrateFloor);
+        return 0;
+    }
+
+    // raise anything below the bitrate floor
+    if (bitrateConfigured < bitrateFloor) {
+        ALOGD("raise bitrate: configured %" PRId64 " to floor %" PRId64,
+                bitrateConfigured, bitrateFloor);
+        bitrateChosen = bitrateFloor;
+    }
+
+    bool qpPresent = hasQp(inFormat);
+
+    // add QP, if not already present
+    if (!qpPresent) {
         int32_t qpmax = codec->targetQpMax();
-        int32_t qpmaxUser = INT32_MAX;
-        if (hasQp(inFormat)) {
-            (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, &qpmaxUser);
-            ALOGD("minquality by QP: format already sets QP");
-        }
-
-        // if the system didn't do one, use what the user provided
-        if (qpmax == 0 && qpmaxUser != INT32_MAX) {
-                qpmax = qpmaxUser;
-        }
-        // XXX: if both said something, how do we want to reconcile that
-
-        if (qpmax > 0) {
-            ALOGD("minquality by QP: inject %s=%d", AMEDIAFORMAT_VIDEO_QP_MAX, qpmax);
-            AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, qpmax);
-
-            // force spreading the QP across frame types, since we imposing a value
-            qpSpreadMaxPerFrameType(inFormat, info->qpDelta, info->qpMax, /* override */ true);
+        if (qpmax != INT32_MAX) {
+            ALOGV("choosing qp=%d", qpmax);
+            qpChosen = qpmax;
         }
     }
 
-    double bpp = codec->getBpp();
-    if (bpp > 0.0) {
-        // if we've decided to use bits-per-pixel (per second) to drive the quality
-        //
-        // (properly phrased as 'bits per second per pixel' so that it's resolution
-        // and framerate agnostic
-        //
-        // all of these is structured so that a missing value cleanly gets us to a
-        // non-faulting value of '0' for the minimum bits-per-pixel.
-        //
-        int32_t width = 0;
-        (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
-        int32_t height = 0;
-        (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
-        int32_t bitrateConfigured = 0;
-        (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrateConfigured);
-
-        int64_t pixels = ((int64_t)width) * height;
-        int64_t bitrateFloor = pixels * bpp;
-
-        if (bitrateFloor > INT32_MAX) bitrateFloor = INT32_MAX;
-
-        ALOGD("minquality/bitrate: target %d floor %" PRId64 "(%.3f bpp * (%d w * %d h)",
-              bitrateConfigured, bitrateFloor, codec->getBpp(), height, width);
-
-        if (bitrateConfigured < bitrateFloor) {
-            ALOGD("minquality/target bitrate raised from %d to %" PRId64 " bps",
-                  bitrateConfigured, bitrateFloor);
-            AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)bitrateFloor);
+    // if QP is desired but not supported, compensate with additional bits
+    if (!codec->supportsQp()) {
+        if (qpPresent || qpChosen != INT32_MAX) {
+            ALOGD("minquality: desired QP, but unsupported, boost bitrate %" PRId64 " to %" PRId64,
+                bitrateChosen, (int64_t)(bitrateChosen * BITRATE_QP_UNAVAILABLE));
+            bitrateChosen =  bitrateChosen * BITRATE_QP_UNAVAILABLE;
+            qpChosen = INT32_MAX;
         }
     }
 
+    // apply our chosen values
+    //
+    if (qpChosen != INT32_MAX) {
+        ALOGD("minquality by QP: inject %s=%d", AMEDIAFORMAT_VIDEO_QP_MAX, qpChosen);
+        AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, qpChosen);
+
+        // force spreading the QP across frame types, since we are imposing a value
+        qpSpreadMaxPerFrameType(inFormat, info->qpDelta, info->qpMax, /* override */ true);
+    }
+
+    if (bitrateChosen != bitrateConfigured) {
+        ALOGD("minquality/target bitrate raised from %" PRId64 " to %" PRId64 " bps",
+              bitrateConfigured, bitrateChosen);
+        AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)bitrateChosen);
+    }
+
     return 0;
 }