Merge "Use Cues to seek Matroska files"
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 14dc1b8..dfb845b 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -36,9 +36,22 @@
 
     ssize_t findCodecByName(const char *name) const;
 
+    size_t countCodecs() const;
     const char *getCodecName(size_t index) const;
+    bool isEncoder(size_t index) const;
     bool codecHasQuirk(size_t index, const char *quirkName) const;
 
+    status_t getSupportedTypes(size_t index, Vector<AString> *types) const;
+
+    struct ProfileLevel {
+        uint32_t mProfile;
+        uint32_t mLevel;
+    };
+    status_t getCodecCapabilities(
+            size_t index, const char *type,
+            Vector<ProfileLevel> *profileLevels,
+            Vector<uint32_t> *colorFormats) const;
+
 private:
     enum Section {
         SECTION_TOPLEVEL,
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 7d51dee..bf054ac 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -384,6 +384,11 @@
         const char *mimeType, bool queryDecoders,
         Vector<CodecCapabilities> *results);
 
+status_t QueryCodec(
+        const sp<IOMX> &omx,
+        const char *componentName, const char *mime,
+        bool isEncoder,
+        CodecCapabilities *caps);
 
 }  // namespace android
 
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index a31be0a..c39aa77 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -22,6 +22,8 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
 #include <utils/threads.h>
 
 #include <expat.h>
@@ -448,6 +450,10 @@
     return -ENOENT;
 }
 
+size_t MediaCodecList::countCodecs() const {
+    return mCodecInfos.size();
+}
+
 const char *MediaCodecList::getCodecName(size_t index) const {
     if (index >= mCodecInfos.size()) {
         return NULL;
@@ -457,6 +463,15 @@
     return info.mName.c_str();
 }
 
+bool MediaCodecList::isEncoder(size_t index) const {
+    if (index >= mCodecInfos.size()) {
+        return NULL;
+    }
+
+    const CodecInfo &info = mCodecInfos.itemAt(index);
+    return info.mIsEncoder;
+}
+
 bool MediaCodecList::codecHasQuirk(
         size_t index, const char *quirkName) const {
     if (index >= mCodecInfos.size()) {
@@ -475,4 +490,69 @@
     return false;
 }
 
+status_t MediaCodecList::getSupportedTypes(
+        size_t index, Vector<AString> *types) const {
+    types->clear();
+
+    if (index >= mCodecInfos.size()) {
+        return -ERANGE;
+    }
+
+    const CodecInfo &info = mCodecInfos.itemAt(index);
+
+    for (size_t i = 0; i < mTypes.size(); ++i) {
+        uint32_t typeMask = 1ul << mTypes.valueAt(i);
+
+        if (info.mTypes & typeMask) {
+            types->push(mTypes.keyAt(i));
+        }
+    }
+
+    return OK;
+}
+
+status_t MediaCodecList::getCodecCapabilities(
+        size_t index, const char *type,
+        Vector<ProfileLevel> *profileLevels,
+        Vector<uint32_t> *colorFormats) const {
+    profileLevels->clear();
+    colorFormats->clear();
+
+    if (index >= mCodecInfos.size()) {
+        return -ERANGE;
+    }
+
+    const CodecInfo &info = mCodecInfos.itemAt(index);
+
+    OMXClient client;
+    status_t err = client.connect();
+    if (err != OK) {
+        return err;
+    }
+
+    CodecCapabilities caps;
+    err = QueryCodec(
+            client.interface(),
+            info.mName.c_str(), type, info.mIsEncoder, &caps);
+
+    if (err != OK) {
+        return err;
+    }
+
+    for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
+        const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
+
+        ProfileLevel profileLevel;
+        profileLevel.mProfile = src.mProfile;
+        profileLevel.mLevel = src.mLevel;
+        profileLevels->push(profileLevel);
+    }
+
+    for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
+        colorFormats->push(caps.mColorFormats.itemAt(i));
+    }
+
+    return OK;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index e844e36..1c4b47e 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4509,70 +4509,84 @@
     for (size_t c = 0; c < matchingCodecs.size(); c++) {
         const char *componentName = matchingCodecs.itemAt(c).string();
 
-        if (strncmp(componentName, "OMX.", 4)) {
-            // Not an OpenMax component but a software codec.
-
-            results->push();
-            CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
-            caps->mComponentName = componentName;
-            continue;
-        }
-
-        sp<OMXCodecObserver> observer = new OMXCodecObserver;
-        IOMX::node_id node;
-        status_t err = omx->allocateNode(componentName, observer, &node);
-
-        if (err != OK) {
-            continue;
-        }
-
-        OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
-
         results->push();
         CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
-        caps->mComponentName = componentName;
 
-        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
-        InitOMXParams(&param);
+        status_t err =
+            QueryCodec(omx, componentName, mime, !queryDecoders, caps);
 
-        param.nPortIndex = queryDecoders ? 0 : 1;
-
-        for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
-            err = omx->getParameter(
-                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
-                    &param, sizeof(param));
-
-            if (err != OK) {
-                break;
-            }
-
-            CodecProfileLevel profileLevel;
-            profileLevel.mProfile = param.eProfile;
-            profileLevel.mLevel = param.eLevel;
-
-            caps->mProfileLevels.push(profileLevel);
+        if (err != OK) {
+            results->removeAt(results->size() - 1);
         }
-
-        // Color format query
-        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
-        InitOMXParams(&portFormat);
-        portFormat.nPortIndex = queryDecoders ? 1 : 0;
-        for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
-            err = omx->getParameter(
-                    node, OMX_IndexParamVideoPortFormat,
-                    &portFormat, sizeof(portFormat));
-            if (err != OK) {
-                break;
-            }
-            caps->mColorFormats.push(portFormat.eColorFormat);
-        }
-
-        CHECK_EQ(omx->freeNode(node), (status_t)OK);
     }
 
     return OK;
 }
 
+status_t QueryCodec(
+        const sp<IOMX> &omx,
+        const char *componentName, const char *mime,
+        bool isEncoder,
+        CodecCapabilities *caps) {
+    if (strncmp(componentName, "OMX.", 4)) {
+        // Not an OpenMax component but a software codec.
+
+        caps->mComponentName = componentName;
+        return OK;
+    }
+
+    sp<OMXCodecObserver> observer = new OMXCodecObserver;
+    IOMX::node_id node;
+    status_t err = omx->allocateNode(componentName, observer, &node);
+
+    if (err != OK) {
+        return err;
+    }
+
+    OMXCodec::setComponentRole(omx, node, isEncoder, mime);
+
+    caps->mComponentName = componentName;
+
+    OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+    InitOMXParams(&param);
+
+    param.nPortIndex = !isEncoder ? 0 : 1;
+
+    for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+        err = omx->getParameter(
+                node, OMX_IndexParamVideoProfileLevelQuerySupported,
+                &param, sizeof(param));
+
+        if (err != OK) {
+            break;
+        }
+
+        CodecProfileLevel profileLevel;
+        profileLevel.mProfile = param.eProfile;
+        profileLevel.mLevel = param.eLevel;
+
+        caps->mProfileLevels.push(profileLevel);
+    }
+
+    // Color format query
+    OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+    InitOMXParams(&portFormat);
+    portFormat.nPortIndex = !isEncoder ? 1 : 0;
+    for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
+        err = omx->getParameter(
+                node, OMX_IndexParamVideoPortFormat,
+                &portFormat, sizeof(portFormat));
+        if (err != OK) {
+            break;
+        }
+        caps->mColorFormats.push(portFormat.eColorFormat);
+    }
+
+    CHECK_EQ(omx->freeNode(node), (status_t)OK);
+
+    return OK;
+}
+
 status_t QueryCodecs(
         const sp<IOMX> &omx,
         const char *mimeType, bool queryDecoders,