am 2637cb17: Merge "Allow OMXCodec to specify an output color format for OMX decoder component" into jb-mr1-dev

* commit '2637cb172105939052d8a02f4eea693a90549518':
  Allow OMXCodec to specify an output color format for OMX decoder component
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index e6739ae..583c3b3 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -276,7 +276,7 @@
             CodecProfileLevel& profileLevel);
 
     status_t setVideoOutputFormat(
-            const char *mime, OMX_U32 width, OMX_U32 height);
+            const char *mime, const sp<MetaData>& meta);
 
     void setImageOutputFormat(
             OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d0e306c..233a733 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -546,12 +546,8 @@
         if (mIsEncoder) {
             setVideoInputFormat(mMIME, meta);
         } else {
-            int32_t width, height;
-            bool success = meta->findInt32(kKeyWidth, &width);
-            success = success && meta->findInt32(kKeyHeight, &height);
-            CHECK(success);
             status_t err = setVideoOutputFormat(
-                    mMIME, width, height);
+                    mMIME, meta);
 
             if (err != OK) {
                 return err;
@@ -1172,7 +1168,13 @@
 }
 
 status_t OMXCodec::setVideoOutputFormat(
-        const char *mime, OMX_U32 width, OMX_U32 height) {
+        const char *mime, const sp<MetaData>& meta) {
+
+    int32_t width, height;
+    bool success = meta->findInt32(kKeyWidth, &width);
+    success = success && meta->findInt32(kKeyHeight, &height);
+    CHECK(success);
+
     CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
 
     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
@@ -1218,6 +1220,26 @@
                || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
                || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka);
 
+        int32_t colorFormat;
+        if (meta->findInt32(kKeyColorFormat, &colorFormat)
+                && colorFormat != OMX_COLOR_FormatUnused
+                && colorFormat != format.eColorFormat) {
+
+            while (OMX_ErrorNoMore != err) {
+                format.nIndex++;
+                err = mOMX->getParameter(
+                        mNode, OMX_IndexParamVideoPortFormat,
+                            &format, sizeof(format));
+                if (format.eColorFormat == colorFormat) {
+                    break;
+                }
+            }
+            if (format.eColorFormat != colorFormat) {
+                CODEC_LOGE("Color format %d is not supported", colorFormat);
+                return ERROR_UNSUPPORTED;
+            }
+        }
+
         err = mOMX->setParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c9ef4d9..a2f3f13 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -110,6 +110,31 @@
     return OK;
 }
 
+static bool isYUV420PlanarSupported(
+            OMXClient *client,
+            const sp<MetaData> &trackMeta) {
+
+    const char *mime;
+    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+
+    Vector<CodecCapabilities> caps;
+    if (QueryCodecs(client->interface(), mime,
+                    true, /* queryDecoders */
+                    true, /* hwCodecOnly */
+                    &caps) == OK) {
+
+        for (size_t j = 0; j < caps.size(); ++j) {
+            CodecCapabilities cap = caps[j];
+            for (size_t i = 0; i < cap.mColorFormats.size(); ++i) {
+                if (cap.mColorFormats[i] == OMX_COLOR_FormatYUV420Planar) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
 static VideoFrame *extractVideoFrameWithCodecFlags(
         OMXClient *client,
         const sp<MetaData> &trackMeta,
@@ -117,9 +142,19 @@
         uint32_t flags,
         int64_t frameTimeUs,
         int seekMode) {
+
+    sp<MetaData> format = source->getFormat();
+
+    // XXX:
+    // Once all vendors support OMX_COLOR_FormatYUV420Planar, we can
+    // remove this check and always set the decoder output color format
+    if (isYUV420PlanarSupported(client, trackMeta)) {
+        format->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+    }
+
     sp<MediaSource> decoder =
         OMXCodec::Create(
-                client->interface(), source->getFormat(), false, source,
+                client->interface(), format, false, source,
                 NULL, flags | OMXCodec::kClientNeedsFramebuffer);
 
     if (decoder.get() == NULL) {