Merge "Squashed commit of the following:"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index ad6540a..e65cdf1 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -34,12 +34,14 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/mediametadataretriever.h>
 
 using namespace android;
 
 static long gNumRepetitions;
 static long gMaxNumFrames;  // 0 means decode all available.
 static long gReproduceBug;  // if not -1.
+static bool gPreferSoftwareCodec;
 
 static int64_t getNowUs() {
     struct timeval tv;
@@ -59,7 +61,9 @@
         rawSource = source;
     } else {
         rawSource = OMXCodec::Create(
-            client->interface(), meta, false /* createEncoder */, source);
+            client->interface(), meta, false /* createEncoder */, source,
+            NULL /* matchComponentName */,
+            gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
 
         if (rawSource == NULL) {
             fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
@@ -219,6 +223,8 @@
     fprintf(stderr, "       -m max-number-of-frames-to-decode in each pass\n");
     fprintf(stderr, "       -b bug to reproduce\n");
     fprintf(stderr, "       -p(rofiles) dump decoder profiles supported\n");
+    fprintf(stderr, "       -t(humbnail) extract video thumbnail\n");
+    fprintf(stderr, "       -s(oftware) prefer software codec\n");
 }
 
 int main(int argc, char **argv) {
@@ -227,12 +233,14 @@
     bool audioOnly = false;
     bool listComponents = false;
     bool dumpProfiles = false;
+    bool extractThumbnail = false;
     gNumRepetitions = 1;
     gMaxNumFrames = 0;
     gReproduceBug = -1;
+    gPreferSoftwareCodec = false;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:p")) >= 0) {
+    while ((res = getopt(argc, argv, "han:lm:b:pts")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -274,6 +282,18 @@
                 break;
             }
 
+            case 't':
+            {
+                extractThumbnail = true;
+                break;
+            }
+
+            case 's':
+            {
+                gPreferSoftwareCodec = true;
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -288,6 +308,34 @@
     argc -= optind;
     argv += optind;
 
+    if (extractThumbnail) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->getService(String16("media.player"));
+        sp<IMediaPlayerService> service =
+            interface_cast<IMediaPlayerService>(binder);
+
+        CHECK(service.get() != NULL);
+
+        sp<IMediaMetadataRetriever> retriever =
+            service->createMetadataRetriever(getpid());
+
+        CHECK(retriever != NULL);
+
+        for (int k = 0; k < argc; ++k) {
+            const char *filename = argv[k];
+
+            CHECK_EQ(retriever->setDataSource(filename), OK);
+            CHECK_EQ(retriever->setMode(METADATA_MODE_FRAME_CAPTURE_ONLY), OK);
+
+            sp<IMemory> mem = retriever->captureFrame();
+
+            printf("captureFrame(%s) => %s\n",
+                   filename, mem != NULL ? "OK" : "FAILED");
+        }
+
+        return 0;
+    }
+
     if (dumpProfiles) {
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder = sm->getService(String16("media.player"));
@@ -389,7 +437,8 @@
             sp<MetaData> meta;
             size_t i;
             for (i = 0; i < numTracks; ++i) {
-                meta = extractor->getTrackMetaData(i);
+                meta = extractor->getTrackMetaData(
+                        i, MediaExtractor::kIncludeExtensiveMetaData);
 
                 const char *mime;
                 meta->findCString(kKeyMIMEType, &mime);
@@ -403,6 +452,12 @@
                 }
             }
 
+            int64_t thumbTimeUs;
+            if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
+                printf("thumbnailTime: %lld us (%.2f secs)\n",
+                       thumbTimeUs, thumbTimeUs / 1E6);
+            }
+
             mediaSource = extractor->getTrack(i);
         }
 
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 8c3f252..0d617a5 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -135,50 +135,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-class BufferMeta {
-public:
-    BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false)
-        : mOwner(owner),
-          mMem(mem),
-          mIsBackup(is_backup) {
-    }
-
-    BufferMeta(OMX *owner, size_t size)
-        : mOwner(owner),
-          mSize(size),
-          mIsBackup(false) {
-    }
-
-    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
-        if (!mIsBackup) {
-            return;
-        }
-
-        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
-               header->pBuffer + header->nOffset,
-               header->nFilledLen);
-    }
-
-    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
-        if (!mIsBackup) {
-            return;
-        }
-
-        memcpy(header->pBuffer + header->nOffset,
-               (const OMX_U8 *)mMem->pointer() + header->nOffset,
-               header->nFilledLen);
-    }
-
-private:
-    OMX *mOwner;
-    sp<IMemory> mMem;
-    size_t mSize;
-    bool mIsBackup;
-
-    BufferMeta(const BufferMeta &);
-    BufferMeta &operator=(const BufferMeta &);
-};
-
 OMX::OMX()
     : mMaster(new OMXMaster),
       mDispatcher(new CallbackDispatcher(this)),
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 2e23899..5b45c1c 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -586,14 +586,14 @@
 
         double r = uniform_rand();
 
-        if (r < 0.5) {
+        if (i > 0 && r < 0.5) {
             // 50% chance of just continuing to decode from last position.
 
             requestedSeekTimeUs = -1;
 
             LOGI("requesting linear read");
         } else {
-            if (r < 0.55) {
+            if (i > 0 && r < 0.55) {
                 // 5% chance of seeking beyond end of stream.
 
                 requestedSeekTimeUs = durationUs;