Update mediaformatshaper library

better default handling
defer library load until time of use (memory vs latency)

Bug: 182827840
Test: manual
Change-Id: I557ea3d82814dd5758396181210fd46524a26a30
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/libmediaformatshaper/VQApply.cpp
index 6f6f33c..39a5e19 100644
--- a/media/libmediaformatshaper/VQApply.cpp
+++ b/media/libmediaformatshaper/VQApply.cpp
@@ -44,42 +44,60 @@
 #define	AMEDIAFORMAT_VIDEO_QP_P_MAX	"video-qp-p-max"
 #define	AMEDIAFORMAT_VIDEO_QP_P_MIN	"video-qp-p-min"
 
+// defined in the SDK, but not in the NDK
+//
+static const int BITRATE_MODE_VBR = 1;
+
 //
 // Caller retains ownership of and responsibility for inFormat
 //
 int VQApply(CodecProperties *codec, vqOps_t *info, AMediaFormat* inFormat, int flags) {
     ALOGV("codecName %s inFormat %p flags x%x", codec->getName().c_str(), inFormat, flags);
 
-    if (codec->supportedMinimumQuality() > 0) {
-        // allow the codec provided minimum quality behavior to work at it
-        ALOGD("minquality(codec): codec says %d", codec->supportedMinimumQuality());
+    int32_t bitRateMode = -1;
+    if (AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_BITRATE_MODE, &bitRateMode)
+        && bitRateMode != BITRATE_MODE_VBR) {
+        ALOGD("minquality: applies only to VBR encoding");
         return 0;
     }
 
-    ALOGD("considering other ways to improve quality...");
+    if (codec->supportedMinimumQuality() > 0) {
+        // allow the codec provided minimum quality behavior to work at it
+        ALOGD("minquality: codec claims to implement minquality=%d",
+              codec->supportedMinimumQuality());
+        return 0;
+    }
 
     //
     // apply any and all tools that we have.
     // -- qp
     // -- minimum bits-per-pixel
     //
-    if (codec->supportsQp()) {
+    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
         //
-        // XXX: augment this so that we don't lower an existing QP setting
-        // (e.g. if user set it to 40, we don't want to set it back to 45)
-        int qpmax = codec->targetQpMax();
-        if (qpmax <= 0) {
-                qpmax = 45;
-                ALOGD("use default substitute QpMax == %d", qpmax);
+        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");
         }
-        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);
-    } else {
-        ALOGD("codec %s: no qp bounding", codec->getName().c_str());
+        // 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);
+        }
     }
 
     double bpp = codec->getBpp();
@@ -108,7 +126,7 @@
               bitrateConfigured, bitrateFloor, codec->getBpp(), height, width);
 
         if (bitrateConfigured < bitrateFloor) {
-            ALOGD("minquality/target bitrate raised from %d to %" PRId64 " to maintain quality",
+            ALOGD("minquality/target bitrate raised from %d to %" PRId64 " bps",
                   bitrateConfigured, bitrateFloor);
             AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)bitrateFloor);
         }
@@ -121,16 +139,16 @@
 bool hasQpPerFrameType(AMediaFormat *format) {
     int32_t value;
 
-    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_I_MAX, &value)
-        || !AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_I_MIN, &value)) {
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_I_MAX, &value)
+        || AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_I_MIN, &value)) {
         return true;
     }
-    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_P_MAX, &value)
-        || !AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_P_MIN, &value)) {
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_P_MAX, &value)
+        || AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_P_MIN, &value)) {
         return true;
     }
-    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_B_MAX, &value)
-        || !AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_B_MIN, &value)) {
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_B_MAX, &value)
+        || AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_B_MIN, &value)) {
         return true;
     }
     return false;
@@ -138,8 +156,8 @@
 
 bool hasQp(AMediaFormat *format) {
     int32_t value;
-    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_MAX, &value)
-        || !AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_MIN, &value)) {
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_MAX, &value)
+        || AMediaFormat_getInt32(format, AMEDIAFORMAT_VIDEO_QP_MIN, &value)) {
         return true;
     }
     return hasQpPerFrameType(format);