Merge "Better tuning hooks for mediaformatshaper" into sc-dev
diff --git a/media/libmediaformatshaper/CodecProperties.cpp b/media/libmediaformatshaper/CodecProperties.cpp
index d733c57..961f676 100644
--- a/media/libmediaformatshaper/CodecProperties.cpp
+++ b/media/libmediaformatshaper/CodecProperties.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <string>
+#include <stdlib.h>
 
 #include <media/formatshaper/CodecProperties.h>
 
@@ -63,17 +64,12 @@
     ALOGD("setFeatureValue(%s,%d)", key.c_str(), value);
     mFeatures.insert({key, value});
 
-    if (!strcmp(key.c_str(), "vq-minimum-quality")) {
-        setSupportedMinimumQuality(value);
-    } else if (!strcmp(key.c_str(), "vq-supports-qp")) {      // key from prototyping
+    if (!strcmp(key.c_str(), "qp-bounds")) {               // official key
         setSupportsQp(1);
-    } else if (!strcmp(key.c_str(), "qp-bounds")) {           // official key
+    } else if (!strcmp(key.c_str(), "vq-supports-qp")) {   // key from prototyping
         setSupportsQp(1);
-    } else if (!strcmp(key.c_str(), "vq-target-qpmax")) {
-        setTargetQpMax(value);
-    } else if (!strcmp(key.c_str(), "vq-target-bppx100")) {
-        double bpp = value / 100.0;
-        setBpp(bpp);
+    } else if (!strcmp(key.c_str(), "vq-minimum-quality")) {
+        setSupportedMinimumQuality(1);
     }
 }
 
@@ -90,6 +86,63 @@
     return false;
 }
 
+// Tuning values (which differ from Features)
+// this is where we set up things like target bitrates and QP ranges
+// NB the tuning values arrive as a string, allowing us to convert it into an appropriate
+// format (int, float, ranges, other combinations)
+//
+void CodecProperties::setTuningValue(std::string key, std::string value) {
+    ALOGD("setTuningValue(%s,%s)", key.c_str(), value.c_str());
+    mTunings.insert({key, value});
+
+    bool legal = false;
+    // NB: old school strtol() because std::stoi() throws exceptions
+    if (!strcmp(key.c_str(), "vq-target-qpmax")) {
+        const char *p = value.c_str();
+        char *q;
+        int32_t iValue =  strtol(p, &q, 0);
+        if (q != p) {
+            setTargetQpMax(iValue);
+            legal = true;
+        }
+    } else if (!strcmp(key.c_str(), "vq-target-bpp")) {
+        const char *p = value.c_str();
+        char *q;
+        double bpp = strtod(p, &q);
+        if (q != p) {
+            setBpp(bpp);
+            legal = true;
+        }
+    } else if (!strcmp(key.c_str(), "vq-target-bppx100")) {
+        const char *p = value.c_str();
+        char *q;
+        int32_t iValue =  strtol(p, &q, 0);
+        if (q != p) {
+            double bpp = iValue / 100.0;
+            setBpp(bpp);
+            legal = true;
+        }
+    } else {
+        legal = true;
+    }
+
+    if (!legal) {
+        ALOGW("setTuningValue() unable to apply tuning '%s' with value '%s'",
+              key.c_str(), value.c_str());
+    }
+    return;
+}
+
+bool CodecProperties::getTuningValue(std::string key, std::string &value) {
+    ALOGV("getTuningValue(%s)", key.c_str());
+    auto mapped = mFeatures.find(key);
+    if (mapped != mFeatures.end()) {
+        value = mapped->second;
+        return true;
+    }
+    return false;
+}
+
 
 std::string CodecProperties::getMapping(std::string key, std::string kind) {
     ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str());
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/libmediaformatshaper/CodecSeeding.cpp
index 629b405..fde7833 100644
--- a/media/libmediaformatshaper/CodecSeeding.cpp
+++ b/media/libmediaformatshaper/CodecSeeding.cpp
@@ -26,56 +26,63 @@
 namespace mediaformatshaper {
 
 /*
- * a block of pre-loads; things the library seeds into the codecproperties based
+ * a block of pre-loaded tunings for codecs.
+ *
+ * things the library seeds into the codecproperties based
  * on the mediaType.
  * XXX: parsing from a file is likely better than embedding in code.
  */
 typedef struct {
+    bool overrideable;
     const char *key;
-    int32_t value;
-} preloadFeature_t;
+    const char *value;
+} preloadTuning_t;
 
 typedef struct {
     const char *mediaType;
-    preloadFeature_t *features;
-} preloadProperties_t;
+    preloadTuning_t *features;
+} preloadTunings_t;
 
 /*
  * 240 = 2.4 bits per pixel-per-second == 5mbps@1080, 2.3mbps@720p, which is about where
  * we want our initial floor for now.
  */
 
-static preloadFeature_t featuresAvc[] = {
-      {"vq-target-bppx100", 240},
-      {nullptr, 0}
+static preloadTuning_t featuresAvc[] = {
+      {true, "vq-target-bpp", "2.45"},
+      {true, "vq-target-qpmax", "41"},
+      {true, nullptr, 0}
 };
 
-static preloadFeature_t featuresHevc[] = {
-      {"vq-target-bppx100", 240},
-      {nullptr, 0}
+static preloadTuning_t featuresHevc[] = {
+      {true, "vq-target-bpp", "2.30"},
+      {true, "vq-target-qpmax", "42"}, // nop, since hevc codecs don't declare qp support
+      {true, nullptr, 0}
 };
 
-static preloadFeature_t featuresGenericVideo[] = {
-      {"vq-target-bppx100", 240},
-      {nullptr, 0}
+static preloadTuning_t featuresGenericVideo[] = {
+      {true, "vq-target-bpp", "2.40"},
+      {true, nullptr, 0}
 };
 
-static preloadProperties_t preloadProperties[] = {
+static preloadTunings_t preloadTunings[] = {
     { "video/avc", featuresAvc},
     { "video/hevc", &featuresHevc[0]},
 
     // wildcard for any video format not already captured
     { "video/*", &featuresGenericVideo[0]},
+
     { nullptr, nullptr}
 };
 
-void CodecProperties::Seed() {
-    ALOGV("Seed: for codec %s, mediatype %s", mName.c_str(), mMediaType.c_str());
+void CodecProperties::addMediaDefaults(bool overrideable) {
+    ALOGD("Seed: codec %s, mediatype %s, overrideable %d",
+          mName.c_str(), mMediaType.c_str(), overrideable);
 
     // load me up with initial configuration data
     int count = 0;
-    for (int i=0;; i++) {
-        preloadProperties_t *p = &preloadProperties[i];
+    for (int i = 0; ; i++) {
+        preloadTunings_t *p = &preloadTunings[i];
         if (p->mediaType == nullptr) {
             break;
         }
@@ -100,11 +107,14 @@
         // walk through, filling things
         if (p->features != nullptr) {
             for (int j=0;; j++) {
-                preloadFeature_t *q = &p->features[j];
+                preloadTuning_t *q = &p->features[j];
                 if (q->key == nullptr) {
                     break;
                 }
-                setFeatureValue(q->key, q->value);
+                if (q->overrideable != overrideable) {
+                    continue;
+                }
+                setTuningValue(q->key, q->value);
                 count++;
             }
             break;
@@ -113,13 +123,18 @@
     ALOGV("loaded %d preset values", count);
 }
 
-// a chance, as we register the codec and accept no further updates, to
-// override any poor configuration that arrived from the device's XML files.
+// a chance, as we create the codec to inject any default behaviors we want.
+// XXX: consider whether we need pre/post or just post. it affects what can be
+// overridden by way of the codec XML
 //
+void CodecProperties::Seed() {
+    ALOGV("Seed: for codec %s, mediatype %s", mName.c_str(), mMediaType.c_str());
+    addMediaDefaults(true);
+}
+
 void CodecProperties::Finish() {
     ALOGV("Finish: for codec %s, mediatype %s", mName.c_str(), mMediaType.c_str());
-
-    // currently a no-op
+    addMediaDefaults(false);
 }
 
 } // namespace mediaformatshaper
diff --git a/media/libmediaformatshaper/FormatShaper.cpp b/media/libmediaformatshaper/FormatShaper.cpp
index a52edc2..42502e0 100644
--- a/media/libmediaformatshaper/FormatShaper.cpp
+++ b/media/libmediaformatshaper/FormatShaper.cpp
@@ -99,6 +99,23 @@
     return 0;
 }
 
+int setTuning(shaperHandle_t shaper, const char *tuning, const char *value) {
+    ALOGV("setTuning: tuning %s value %s", tuning, value);
+    CodecProperties *codec = (CodecProperties*) shaper;
+    if (codec == nullptr) {
+        return -1;
+    }
+    // must not yet be registered
+    if (codec->isRegistered()) {
+        return -1;
+    }
+
+    // save a map of all features
+    codec->setTuningValue(tuning, value);
+
+    return 0;
+}
+
 /*
  * The routines that manage finding, creating, and registering the shapers.
  */
@@ -176,6 +193,8 @@
     .shapeFormat = shapeFormat,
     .getMappings = getMappings,
     .getReverseMappings = getReverseMappings,
+
+    .setTuning = setTuning,
 };
 
 }  // namespace mediaformatshaper
diff --git a/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h b/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
index e5cc9cf..84268b9 100644
--- a/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
+++ b/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
@@ -56,6 +56,10 @@
     void setFeatureValue(std::string key, int32_t value);
     bool getFeatureValue(std::string key, int32_t *valuep);
 
+    // keep a map of all tunings and their parameters
+    void setTuningValue(std::string key, std::string value);
+    bool getTuningValue(std::string key, std::string &value);
+
     // does the codec support the Android S minimum quality rules
     void setSupportedMinimumQuality(int vmaf);
     int supportedMinimumQuality();
@@ -97,6 +101,10 @@
     std::map<std::string, std::string> mMappings /*GUARDED_BY(mMappingLock)*/ ;
 
     std::map<std::string, int32_t> mFeatures /*GUARDED_BY(mMappingLock)*/ ;
+    std::map<std::string, std::string> mTunings /*GUARDED_BY(mMappingLock)*/ ;
+
+    // Seed() and Finish() use this as the underlying implementation
+    void addMediaDefaults(bool overrideable);
 
     bool mIsRegistered = false;
 
diff --git a/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h b/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
index 8ad81cd..a1747cc 100644
--- a/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
+++ b/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
@@ -84,6 +84,12 @@
 typedef int (*setFeature_t)(shaperHandle_t shaper, const char *feature, int value);
 
 /*
+ * establishes that codec "codecName" encoding for "mediaType" supports the indicated
+ * tuning at the indicated value
+ */
+typedef int (*setTuning_t)(shaperHandle_t shaper, const char *feature, const char * value);
+
+/*
  * The expectation is that the client will implement a flow similar to the following when
  * setting up an encoding.
  *
@@ -118,6 +124,10 @@
     shapeFormat_t shapeFormat;
     getMappings_t getMappings;
     getMappings_t getReverseMappings;
+
+    setTuning_t setTuning;
+
+    // additions happen at the end of the structure
 } FormatShaperOps_t;
 
 // versioninf information
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 26cdec8..16cd5ca 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -109,6 +109,7 @@
 static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
 static const char *kCodecBitrateMode = "android.media.mediacodec.bitrate_mode";  /* CQ/VBR/CBR */
 static const char *kCodecBitrate = "android.media.mediacodec.bitrate";  /* 0..n */
+static const char *kCodecOriginalBitrate = "android.media.mediacodec.original.bitrate";  /* 0..n */
 static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
 static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
 static const char *kCodecError = "android.media.mediacodec.errcode";
@@ -139,6 +140,8 @@
 static const char *kCodecRecentLatencyCount = "android.media.mediacodec.recent.n";
 static const char *kCodecRecentLatencyHist = "android.media.mediacodec.recent.hist";    /* in us */
 
+static const char *kCodecShapingEnhanced = "android.media.mediacodec.shaped";    /* 0/1 */
+
 // XXX suppress until we get our representation right
 static bool kEmitHistogram = false;
 
@@ -1556,18 +1559,7 @@
 static bool connectFormatShaper() {
     static std::once_flag sCheckOnce;
 
-#if 0
-    // an early return if the property says disabled means we skip loading.
-    // that saves memory.
-
-    // apply framework level modifications to the mediaformat for encoding
-    // XXX: default off for a while during dogfooding
-    int8_t enableShaping = property_get_bool(enableMediaFormatShapingProperty, 0);
-
-    if (!enableShaping) {
-        return true;
-    }
-#endif
+    ALOGV("connectFormatShaper...");
 
     std::call_once(sCheckOnce, [&](){
 
@@ -1672,6 +1664,8 @@
             //
             static const char *featurePrefix = "feature-";
             static const int featurePrefixLen = strlen(featurePrefix);
+            static const char *tuningPrefix = "tuning-";
+            static const int tuningPrefixLen = strlen(tuningPrefix);
             static const char *mappingPrefix = "mapping-";
             static const int mappingPrefixLen = strlen(mappingPrefix);
 
@@ -1685,6 +1679,14 @@
                                                    intValue);
                 }
                 continue;
+            } else if (!strncmp(mapSrc, tuningPrefix, tuningPrefixLen)) {
+                AString value;
+                if (details->findString(mapSrc, &value)) {
+                    ALOGV("-- tuning '%s' -> '%s'", mapSrc, value.c_str());
+                    (void)(sShaperOps->setTuning)(shaperHandle, &mapSrc[tuningPrefixLen],
+                                                   value.c_str());
+                }
+                continue;
             } else if (!strncmp(mapSrc, mappingPrefix, mappingPrefixLen)) {
                 AString target;
                 if (details->findString(mapSrc, &target)) {
@@ -1801,10 +1803,20 @@
         AMediaFormat_getFormat(updatedNdkFormat, &updatedFormat);
 
         sp<AMessage> deltas = updatedFormat->changesFrom(format, false /* deep */);
-        ALOGD("shapeMediaFormat: deltas: %s", deltas->debugString(2).c_str());
-
-        // note that this means that for anything in both, the copy in deltas wins
-        format->extend(deltas);
+        size_t changeCount = deltas->countEntries();
+        ALOGD("shapeMediaFormat: deltas(%zu): %s", changeCount, deltas->debugString(2).c_str());
+        if (changeCount > 0) {
+            if (mMetricsHandle != 0) {
+                mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, changeCount);
+                // save some old properties before we fold in the new ones
+                int32_t bitrate;
+                if (format->findInt32(KEY_BIT_RATE, &bitrate)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalBitrate, bitrate);
+                }
+            }
+            // NB: for any field in both format and deltas, the deltas copy wins
+            format->extend(deltas);
+        }
     }
 
     AMediaFormat_delete(updatedNdkFormat);
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 5a9760d..67c6102 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -146,7 +146,10 @@
         };
     static std::vector<std::string> names = {
             prefixes[0] + variants[0] + ".xml",
-            prefixes[1] + variants[1] + ".xml"
+            prefixes[1] + variants[1] + ".xml",
+
+            // shaping information is not currently variant specific.
+            "media_codecs_shaping.xml"
         };
     return names;
 }
@@ -347,6 +350,7 @@
         status_t addFeature(const char **attrs);
         status_t addLimit(const char **attrs);
         status_t addMapping(const char **attrs);
+        status_t addTuning(const char **attrs);
         status_t addQuirk(const char **attrs, const char *prefix = nullptr);
         status_t addSetting(const char **attrs, const char *prefix = nullptr);
         status_t enterMediaCodec(const char **attrs, bool encoder);
@@ -429,7 +433,7 @@
         if (findFileInDirs(searchDirs, fileName, &path)) {
             err = parseXmlPath(path);
         } else {
-            ALOGD("Cannot find %s in search path", fileName.c_str());
+            ALOGI("Did not find %s in search path", fileName.c_str());
         }
         res = combineStatus(res, err);
     }
@@ -439,7 +443,7 @@
 status_t MediaCodecsXmlParser::Impl::parseXmlPath(const std::string &path) {
     std::lock_guard<std::mutex> guard(mLock);
     if (!fileExists(path)) {
-        ALOGD("Cannot find %s", path.c_str());
+        ALOGV("Cannot find %s", path.c_str());
         mParsingStatus = combineStatus(mParsingStatus, NAME_NOT_FOUND);
         return NAME_NOT_FOUND;
     }
@@ -743,7 +747,8 @@
             // ignore limits and features specified outside of type
             if (!mState->inType()
                     && (strEq(name, "Limit") || strEq(name, "Feature")
-                        || strEq(name, "Variant") || strEq(name, "Mapping"))) {
+                        || strEq(name, "Variant") || strEq(name, "Mapping")
+                        || strEq(name, "Tuning"))) {
                 PLOGD("ignoring %s specified outside of a Type", name);
                 return;
             } else if (strEq(name, "Limit")) {
@@ -752,6 +757,8 @@
                 err = addFeature(attrs);
             } else if (strEq(name, "Mapping")) {
                 err = addMapping(attrs);
+            } else if (strEq(name, "Tuning")) {
+                err = addTuning(attrs);
             } else if (strEq(name, "Variant") && section != SECTION_VARIANT) {
                 err = limitVariants(attrs);
                 mState->enterSection(err == OK ? SECTION_VARIANT : SECTION_UNKNOWN);
@@ -1445,6 +1452,45 @@
     return OK;
 }
 
+status_t MediaCodecsXmlParser::Impl::Parser::addTuning(const char **attrs) {
+    CHECK(mState->inType());
+    size_t i = 0;
+    const char *a_name = nullptr;
+    const char *a_value = nullptr;
+
+    while (attrs[i] != nullptr) {
+        CHECK((i & 1) == 0);
+        if (attrs[i + 1] == nullptr) {
+            PLOGD("Mapping: attribute '%s' is null", attrs[i]);
+            return BAD_VALUE;
+        }
+
+        if (strEq(attrs[i], "name")) {
+            a_name = attrs[++i];
+        } else if (strEq(attrs[i], "value")) {
+            a_value = attrs[++i];
+        } else {
+            PLOGD("Tuning: ignoring unrecognized attribute '%s'", attrs[i]);
+            ++i;
+        }
+        ++i;
+    }
+
+    // Every tuning must have both fields
+    if (a_name == nullptr) {
+        PLOGD("Tuning with no 'name' attribute");
+        return BAD_VALUE;
+    }
+
+    if (a_value == nullptr) {
+        PLOGD("Tuning with no 'value' attribute");
+        return BAD_VALUE;
+    }
+
+    mState->addDetail(std::string("tuning-") + a_name, a_value);
+    return OK;
+}
+
 status_t MediaCodecsXmlParser::Impl::Parser::addAlias(const char **attrs) {
     CHECK(mState->inCodec());
     size_t i = 0;
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index 6f55dc0..ecfd85e 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -87,6 +87,7 @@
     method public String getName();
     method public java.util.List<media.codecs.Quirk> getQuirk_optional();
     method public String getRank();
+    method public java.util.List<media.codecs.Tuning> getTuning_optional();
     method public String getType();
     method public java.util.List<media.codecs.Type> getType_optional();
     method public String getUpdate();
@@ -136,6 +137,14 @@
     method public java.util.List<media.codecs.Setting> getVariant_optional();
   }
 
+  public class Tuning {
+    ctor public Tuning();
+    method public String getName();
+    method public String getValue();
+    method public void setName(String);
+    method public void setValue(String);
+  }
+
   public class Type {
     ctor public Type();
     method public java.util.List<media.codecs.Alias> getAlias();
diff --git a/media/libstagefright/xmlparser/media_codecs.xsd b/media/libstagefright/xmlparser/media_codecs.xsd
index 30974f6..c9a7efc 100644
--- a/media/libstagefright/xmlparser/media_codecs.xsd
+++ b/media/libstagefright/xmlparser/media_codecs.xsd
@@ -64,6 +64,7 @@
             <xs:element name="Limit" type="Limit" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="Feature" type="Feature" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="Mapping" type="Mapping" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="Tuning" type="Tuning" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="Variant" type="Variant" minOccurs="0" maxOccurs="unbounded"/>
         </xs:choice>
         <xs:attribute name="name" type="xs:string"/>
@@ -128,6 +129,10 @@
         <xs:attribute name="kind" type="xs:string"/>
         <xs:attribute name="value" type="xs:string"/>
     </xs:complexType>
+    <xs:complexType name="Tuning">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="value" type="xs:string"/>
+    </xs:complexType>
     <xs:complexType name="Include">
         <xs:attribute name="href" type="xs:string"/>
     </xs:complexType>
diff --git a/media/libstagefright/xmlparser/test/XMLParserTest.cpp b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
index c411c8d..7629d97 100644
--- a/media/libstagefright/xmlparser/test/XMLParserTest.cpp
+++ b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
@@ -138,6 +138,12 @@
                    pair<string, string>("mapping-fire-from", "to"),
            },
            {}, "");
+    setCodecProperties("test11.encoder", true, 11, {}, {}, {}, "video/av01",
+           {
+                   pair<string, string>("tuning-hungry", "yes"),
+                   pair<string, string>("tuning-pi", "3.1415"),
+           },
+           {}, "");
 
     setRoleProperties("audio_decoder.mp3", false, 1, "audio/mpeg", "test1.decoder",
                       {pair<string, string>("attribute::disabled", "present"),
@@ -180,6 +186,11 @@
     setRoleProperties("video_encoder.hevc", true, 10, "video/hevc", "test10.encoder",
                        { pair<string, string>("mapping-fire-from", "to")});
 
+    setRoleProperties("video_encoder.av01", true, 11, "video/av01", "test11.encoder",
+                       {pair<string, string>("tuning-hungry", "yes"),
+                        pair<string, string>("tuning-pi", "3.1415")
+                       });
+
     setServiceAttribute(
             {pair<string, string>("domain-telephony", "0"), pair<string, string>("domain-tv", "0"),
              pair<string, string>("setting2", "0"), pair<string, string>("variant-variant1", "0")});
diff --git a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
index c8913e5..8cae423 100644
--- a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
+++ b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
@@ -83,5 +83,10 @@
         <MediaCodec name="test10.encoder" type="video/hevc" >
             <Mapping kind="fire" name="from" value="to"/>
         </MediaCodec>
+        <!-- entry for testing Tuning -->
+        <MediaCodec name="test11.encoder" type="video/av01" >
+            <Tuning name="hungry" value="yes"/>
+            <Tuning name="pi" value="3.1415"/>
+        </MediaCodec>
     </Encoders>
 </Included>