Squashed commit of the following:

commit cb11364feefc200f10af6a01f776803acba2792a
Author: Andreas Huber <andih@google.com>
Date:   Thu Jan 14 14:05:36 2010 -0800

    Even if the decoder didn't extract the thumbnail at the specified time, accept it for now.

commit a54c0244b305caf11e67db49b7d3d8dba5f77751
Author: Andreas Huber <andih@google.com>
Date:   Thu Jan 14 11:37:15 2010 -0800

    Add some checks to make sure we extract the correct thumbnail frame, also revert to the hardware decoders for thumnbail extraction if the software decoders failed.
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c7877a9..020887c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -107,6 +107,104 @@
     return OK;
 }
 
+static VideoFrame *extractVideoFrameWithCodecFlags(
+        OMXClient *client,
+        const sp<MetaData> &trackMeta,
+        const sp<MediaSource> &source, uint32_t flags) {
+    sp<MediaSource> decoder =
+        OMXCodec::Create(
+                client->interface(), source->getFormat(), false, source,
+                NULL, flags);
+
+    if (decoder.get() == NULL) {
+        LOGV("unable to instantiate video decoder.");
+
+        return NULL;
+    }
+
+    decoder->start();
+
+    // Read one output buffer, ignore format change notifications
+    // and spurious empty buffers.
+
+    MediaSource::ReadOptions options;
+    int64_t thumbNailTime;
+    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+        options.setSeekTo(thumbNailTime);
+    } else {
+        thumbNailTime = -1;
+    }
+
+    MediaBuffer *buffer = NULL;
+    status_t err;
+    do {
+        if (buffer != NULL) {
+            buffer->release();
+            buffer = NULL;
+        }
+        err = decoder->read(&buffer, &options);
+        options.clearSeekTo();
+    } while (err == INFO_FORMAT_CHANGED
+             || (buffer != NULL && buffer->range_length() == 0));
+
+    if (err != OK) {
+        CHECK_EQ(buffer, NULL);
+
+        LOGV("decoding frame failed.");
+        decoder->stop();
+
+        return NULL;
+    }
+
+    LOGV("successfully decoded video frame.");
+
+    int64_t timeUs;
+    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+    if (thumbNailTime >= 0) {
+        if (timeUs != thumbNailTime) {
+            const char *mime;
+            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+
+            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
+                 thumbNailTime, timeUs, mime);
+        }
+    }
+
+    sp<MetaData> meta = decoder->getFormat();
+
+    int32_t width, height;
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+
+    VideoFrame *frame = new VideoFrame;
+    frame->mWidth = width;
+    frame->mHeight = height;
+    frame->mDisplayWidth = width;
+    frame->mDisplayHeight = height;
+    frame->mSize = width * height * 2;
+    frame->mData = new uint8_t[frame->mSize];
+
+    int32_t srcFormat;
+    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
+
+    ColorConverter converter(
+            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
+    CHECK(converter.isValid());
+
+    converter.convert(
+            width, height,
+            (const uint8_t *)buffer->data() + buffer->range_offset(),
+            0,
+            frame->mData, width * 2);
+
+    buffer->release();
+    buffer = NULL;
+
+    decoder->stop();
+
+    return frame;
+}
+
 VideoFrame *StagefrightMetadataRetriever::captureFrame() {
     LOGV("captureFrame");
 
@@ -143,85 +241,17 @@
         return NULL;
     }
 
-    sp<MetaData> meta = source->getFormat();
+    VideoFrame *frame =
+        extractVideoFrameWithCodecFlags(
+                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
 
-    sp<MediaSource> decoder =
-        OMXCodec::Create(
-                mClient.interface(), meta, false, source,
-                NULL, OMXCodec::kPreferSoftwareCodecs);
+    if (frame == NULL) {
+        LOGV("Software decoder failed to extract thumbnail, "
+             "trying hardware decoder.");
 
-    if (decoder.get() == NULL) {
-        LOGV("unable to instantiate video decoder.");
-
-        return NULL;
+        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
     }
 
-    decoder->start();
-
-    // Read one output buffer, ignore format change notifications
-    // and spurious empty buffers.
-
-    MediaSource::ReadOptions options;
-    int64_t thumbNailTime;
-    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
-        options.setSeekTo(thumbNailTime);
-    }
-
-    MediaBuffer *buffer = NULL;
-    status_t err;
-    do {
-        if (buffer != NULL) {
-            buffer->release();
-            buffer = NULL;
-        }
-        err = decoder->read(&buffer, &options);
-        options.clearSeekTo();
-    } while (err == INFO_FORMAT_CHANGED
-             || (buffer != NULL && buffer->range_length() == 0));
-
-    if (err != OK) {
-        CHECK_EQ(buffer, NULL);
-
-        LOGV("decoding frame failed.");
-        decoder->stop();
-
-        return NULL;
-    }
-
-    LOGV("successfully decoded video frame.");
-
-    meta = decoder->getFormat();
-
-    int32_t width, height;
-    CHECK(meta->findInt32(kKeyWidth, &width));
-    CHECK(meta->findInt32(kKeyHeight, &height));
-
-    VideoFrame *frame = new VideoFrame;
-    frame->mWidth = width;
-    frame->mHeight = height;
-    frame->mDisplayWidth = width;
-    frame->mDisplayHeight = height;
-    frame->mSize = width * height * 2;
-    frame->mData = new uint8_t[frame->mSize];
-
-    int32_t srcFormat;
-    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
-
-    ColorConverter converter(
-            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
-    CHECK(converter.isValid());
-
-    converter.convert(
-            width, height,
-            (const uint8_t *)buffer->data() + buffer->range_offset(),
-            0,
-            frame->mData, width * 2);
-
-    buffer->release();
-    buffer = NULL;
-
-    decoder->stop();
-
     return frame;
 }