Use heif embedded thumbnail if available

Add plumbing to retieve the embedded thumbnail from
MPEG4Extractor/ItemTable.

bug: 74395267
Test: CTS MediaMetadataRetriever test; manual test of thumbnail
extraction by browsing new folders containing heif files in
Downloads app.
Change-Id: Ic49f6dfa47eddc229b9f4b0e1835d58df1dce9f8
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index 26b8251..a1f6e9a 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -1591,10 +1591,9 @@
 
     ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(masterImage.thumbnails[0]);
     if (thumbItemIndex < 0) {
-        ALOGW("%s: Thumbnail item id %d not found, use master instead",
-                __FUNCTION__, masterImage.thumbnails[0]);
-        *itemIndex = masterItemIndex;
-        return OK;
+        // Do not return the master image in this case, fail it so that the
+        // thumbnail extraction code knows we really don't have it.
+        return INVALID_OPERATION;
     }
 
     *itemIndex = thumbItemIndex;
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index f725c97..214117b 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -166,15 +166,16 @@
         return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
-    sp<IMemory> getImageAtIndex(int index, int colorFormat, bool metaOnly)
+    sp<IMemory> getImageAtIndex(int index, int colorFormat, bool metaOnly, bool thumbnail)
     {
-        ALOGV("getImageAtIndex: index %d, colorFormat(%d) metaOnly(%d)",
-                index, colorFormat, metaOnly);
+        ALOGV("getImageAtIndex: index %d, colorFormat(%d) metaOnly(%d) thumbnail(%d)",
+                index, colorFormat, metaOnly, thumbnail);
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
         data.writeInt32(index);
         data.writeInt32(colorFormat);
         data.writeInt32(metaOnly);
+        data.writeInt32(thumbnail);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
         sendSchedPolicy(data);
 #endif
@@ -356,12 +357,13 @@
             int index = data.readInt32();
             int colorFormat = data.readInt32();
             bool metaOnly = (data.readInt32() != 0);
-            ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
-                    index, colorFormat, metaOnly);
+            bool thumbnail = (data.readInt32() != 0);
+            ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
+                    index, colorFormat, metaOnly, thumbnail);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
             setSchedPolicy(data);
 #endif
-            sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly);
+            sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
                 reply->writeStrongBinder(IInterface::asBinder(bitmap));
diff --git a/media/libmedia/include/media/IMediaMetadataRetriever.h b/media/libmedia/include/media/IMediaMetadataRetriever.h
index 5491535..1a04552 100644
--- a/media/libmedia/include/media/IMediaMetadataRetriever.h
+++ b/media/libmedia/include/media/IMediaMetadataRetriever.h
@@ -45,7 +45,7 @@
     virtual sp<IMemory>     getFrameAtTime(
             int64_t timeUs, int option, int colorFormat, bool metaOnly) = 0;
     virtual sp<IMemory>     getImageAtIndex(
-            int index, int colorFormat, bool metaOnly) = 0;
+            int index, int colorFormat, bool metaOnly, bool thumbnail) = 0;
     virtual status_t        getFrameAtIndex(
             std::vector<sp<IMemory> > *frames,
             int frameIndex, int numFrames, int colorFormat, bool metaOnly) = 0;
diff --git a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
index 116b548..c45a964 100644
--- a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
+++ b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
@@ -46,7 +46,7 @@
     virtual VideoFrame* getFrameAtTime(
             int64_t timeUs, int option, int colorFormat, bool metaOnly) = 0;
     virtual VideoFrame* getImageAtIndex(
-            int index, int colorFormat, bool metaOnly) = 0;
+            int index, int colorFormat, bool metaOnly, bool thumbnail) = 0;
     virtual status_t getFrameAtIndex(
             std::vector<VideoFrame*>* frames,
             int frameIndex, int numFrames, int colorFormat, bool metaOnly) = 0;
@@ -65,7 +65,7 @@
             int64_t /*timeUs*/, int /*option*/, int /*colorFormat*/, bool /*metaOnly*/)
     { return NULL; }
     virtual VideoFrame* getImageAtIndex(
-            int /*index*/, int /*colorFormat*/, bool /*metaOnly*/)
+            int /*index*/, int /*colorFormat*/, bool /*metaOnly*/, bool /*thumbnail*/)
     { return NULL; }
     virtual status_t getFrameAtIndex(
             std::vector<VideoFrame*>* /*frames*/,
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 3511253..bd23161 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -88,7 +88,7 @@
     sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
             int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
     sp<IMemory> getImageAtIndex(int index,
-            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false, bool thumbnail = false);
     status_t getFrameAtIndex(
             std::vector<sp<IMemory> > *frames, int frameIndex, int numFrames = 1,
             int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 6a4204b..c10a907 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -155,15 +155,15 @@
 }
 
 sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
-        int index, int colorFormat, bool metaOnly) {
-    ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d)",
-            index, colorFormat, metaOnly);
+        int index, int colorFormat, bool metaOnly, bool thumbnail) {
+    ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
+            index, colorFormat, metaOnly, thumbnail);
     Mutex::Autolock _l(mLock);
     if (mRetriever == 0) {
         ALOGE("retriever is not initialized");
         return NULL;
     }
-    return mRetriever->getImageAtIndex(index, colorFormat, metaOnly);
+    return mRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
 }
 
 status_t MediaMetadataRetriever::getFrameAtIndex(
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 16ed530..3b3ac29 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -234,9 +234,9 @@
 }
 
 sp<IMemory> MetadataRetrieverClient::getImageAtIndex(
-        int index, int colorFormat, bool metaOnly) {
-    ALOGV("getFrameAtTime: index(%d) colorFormat(%d), metaOnly(%d)",
-            index, colorFormat, metaOnly);
+        int index, int colorFormat, bool metaOnly, bool thumbnail) {
+    ALOGV("getFrameAtTime: index(%d) colorFormat(%d), metaOnly(%d) thumbnail(%d)",
+            index, colorFormat, metaOnly, thumbnail);
     Mutex::Autolock lock(mLock);
     Mutex::Autolock glock(sLock);
     mThumbnail.clear();
@@ -244,7 +244,7 @@
         ALOGE("retriever is not initialized");
         return NULL;
     }
-    VideoFrame *frame = mRetriever->getImageAtIndex(index, colorFormat, metaOnly);
+    VideoFrame *frame = mRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
     if (frame == NULL) {
         ALOGE("failed to extract image");
         return NULL;
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index f71891a..e774c8f 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -53,7 +53,7 @@
     virtual sp<IMemory>             getFrameAtTime(
             int64_t timeUs, int option, int colorFormat, bool metaOnly);
     virtual sp<IMemory>             getImageAtIndex(
-            int index, int colorFormat, bool metaOnly);
+            int index, int colorFormat, bool metaOnly, bool thumbnail);
     virtual status_t getFrameAtIndex(
                 std::vector<sp<IMemory> > *frames,
                 int frameIndex, int numFrames, int colorFormat, bool metaOnly);
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 3d0aad1..a00d13a 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -42,30 +42,30 @@
 static const int64_t kBufferTimeOutUs = 30000ll; // 30 msec
 static const size_t kRetryCount = 20; // must be >0
 
-VideoFrame *FrameDecoder::allocVideoFrame(
-        int32_t width, int32_t height, bool metaOnly) {
+//static
+VideoFrame *allocVideoFrame(const sp<MetaData> &trackMeta,
+        int32_t width, int32_t height, int32_t dstBpp, bool metaOnly = false) {
     int32_t rotationAngle;
-    if (!mTrackMeta->findInt32(kKeyRotation, &rotationAngle)) {
+    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
         rotationAngle = 0;  // By default, no rotation
     }
-
     uint32_t type;
     const void *iccData;
     size_t iccSize;
-    if (!mTrackMeta->findData(kKeyIccProfile, &type, &iccData, &iccSize)){
+    if (!trackMeta->findData(kKeyIccProfile, &type, &iccData, &iccSize)){
         iccData = NULL;
         iccSize = 0;
     }
 
     int32_t sarWidth, sarHeight;
     int32_t displayWidth, displayHeight;
-    if (mTrackMeta->findInt32(kKeySARWidth, &sarWidth)
-            && mTrackMeta->findInt32(kKeySARHeight, &sarHeight)
+    if (trackMeta->findInt32(kKeySARWidth, &sarWidth)
+            && trackMeta->findInt32(kKeySARHeight, &sarHeight)
             && sarHeight != 0) {
         displayWidth = (width * sarWidth) / sarHeight;
         displayHeight = height;
-    } else if (mTrackMeta->findInt32(kKeyDisplayWidth, &displayWidth)
-                && mTrackMeta->findInt32(kKeyDisplayHeight, &displayHeight)
+    } else if (trackMeta->findInt32(kKeyDisplayWidth, &displayWidth)
+                && trackMeta->findInt32(kKeyDisplayHeight, &displayHeight)
                 && displayWidth > 0 && displayHeight > 0
                 && width > 0 && height > 0) {
         ALOGV("found display size %dx%d", displayWidth, displayHeight);
@@ -75,27 +75,66 @@
     }
 
     return new VideoFrame(width, height, displayWidth, displayHeight,
-            rotationAngle, mDstBpp, !metaOnly, iccData, iccSize);
+            rotationAngle, dstBpp, !metaOnly, iccData, iccSize);
 }
 
-bool FrameDecoder::setDstColorFormat(android_pixel_format_t colorFormat) {
+//static
+bool findThumbnailInfo(
+        const sp<MetaData> &trackMeta, int32_t *width, int32_t *height,
+        uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) {
+    uint32_t dummyType;
+    const void *dummyData;
+    size_t dummySize;
+    return trackMeta->findInt32(kKeyThumbnailWidth, width)
+        && trackMeta->findInt32(kKeyThumbnailHeight, height)
+        && trackMeta->findData(kKeyThumbnailHVCC,
+                type ?: &dummyType, data ?: &dummyData, size ?: &dummySize);
+}
+
+//static
+VideoFrame* FrameDecoder::getMetadataOnly(
+        const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) {
+    OMX_COLOR_FORMATTYPE dstFormat;
+    int32_t dstBpp;
+    if (!getDstColorFormat(
+            (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) {
+        return NULL;
+    }
+
+    int32_t width, height;
+    if (thumbnail) {
+        if (!findThumbnailInfo(trackMeta, &width, &height)) {
+            return NULL;
+        }
+    } else {
+        CHECK(trackMeta->findInt32(kKeyWidth, &width));
+        CHECK(trackMeta->findInt32(kKeyHeight, &height));
+    }
+    return allocVideoFrame(trackMeta, width, height, dstBpp, true /*metaOnly*/);
+}
+
+//static
+bool FrameDecoder::getDstColorFormat(
+        android_pixel_format_t colorFormat,
+        OMX_COLOR_FORMATTYPE *dstFormat,
+        int32_t *dstBpp) {
     switch (colorFormat) {
         case HAL_PIXEL_FORMAT_RGB_565:
         {
-            mDstFormat = OMX_COLOR_Format16bitRGB565;
-            mDstBpp = 2;
+            *dstFormat = OMX_COLOR_Format16bitRGB565;
+            *dstBpp = 2;
             return true;
         }
         case HAL_PIXEL_FORMAT_RGBA_8888:
         {
-            mDstFormat = OMX_COLOR_Format32BitRGBA8888;
-            mDstBpp = 4;
+            *dstFormat = OMX_COLOR_Format32BitRGBA8888;
+            *dstBpp = 4;
             return true;
         }
         case HAL_PIXEL_FORMAT_BGRA_8888:
         {
-            mDstFormat = OMX_COLOR_Format32bitBGRA8888;
-            mDstBpp = 4;
+            *dstFormat = OMX_COLOR_Format32bitBGRA8888;
+            *dstBpp = 4;
             return true;
         }
         default:
@@ -108,18 +147,12 @@
 }
 
 VideoFrame* FrameDecoder::extractFrame(
-        int64_t frameTimeUs, int option, int colorFormat, bool metaOnly) {
-    if (!setDstColorFormat((android_pixel_format_t)colorFormat)) {
+        int64_t frameTimeUs, int option, int colorFormat) {
+    if (!getDstColorFormat(
+            (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) {
         return NULL;
     }
 
-    if (metaOnly) {
-        int32_t width, height;
-        CHECK(trackMeta()->findInt32(kKeyWidth, &width));
-        CHECK(trackMeta()->findInt32(kKeyHeight, &height));
-        return allocVideoFrame(width, height, true);
-    }
-
     status_t err = extractInternal(frameTimeUs, 1, option);
     if (err != OK) {
         return NULL;
@@ -131,7 +164,8 @@
 status_t FrameDecoder::extractFrames(
         int64_t frameTimeUs, size_t numFrames, int option, int colorFormat,
         std::vector<VideoFrame*>* frames) {
-    if (!setDstColorFormat((android_pixel_format_t)colorFormat)) {
+    if (!getDstColorFormat(
+            (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) {
         return ERROR_UNSUPPORTED;
     }
 
@@ -435,9 +469,10 @@
     }
 
     VideoFrame *frame = allocVideoFrame(
+            trackMeta(),
             (crop_right - crop_left + 1),
             (crop_bottom - crop_top + 1),
-            false /*metaOnly*/);
+            dstBpp());
     addFrame(frame);
 
     int32_t srcFormat;
@@ -466,28 +501,28 @@
         int64_t frameTimeUs, size_t /*numFrames*/,
         int /*seekMode*/, MediaSource::ReadOptions *options) {
     sp<MetaData> overrideMeta;
+    mThumbnail = false;
     if (frameTimeUs < 0) {
         uint32_t type;
         const void *data;
         size_t size;
-        int64_t thumbNailTime = 0;
-        int32_t thumbnailWidth, thumbnailHeight;
+        int32_t thumbWidth, thumbHeight;
 
         // if we have a stand-alone thumbnail, set up the override meta,
         // and set seekTo time to -1.
-        if (trackMeta()->findInt32(kKeyThumbnailWidth, &thumbnailWidth)
-         && trackMeta()->findInt32(kKeyThumbnailHeight, &thumbnailHeight)
-         && trackMeta()->findData(kKeyThumbnailHVCC, &type, &data, &size)){
-            overrideMeta = new MetaData(*(trackMeta()));
-            overrideMeta->remove(kKeyDisplayWidth);
-            overrideMeta->remove(kKeyDisplayHeight);
-            overrideMeta->setInt32(kKeyWidth, thumbnailWidth);
-            overrideMeta->setInt32(kKeyHeight, thumbnailHeight);
-            overrideMeta->setData(kKeyHVCC, type, data, size);
-            thumbNailTime = -1ll;
-            ALOGV("thumbnail: %dx%d", thumbnailWidth, thumbnailHeight);
+        if (!findThumbnailInfo(trackMeta(),
+                &thumbWidth, &thumbHeight, &type, &data, &size)) {
+            ALOGE("Thumbnail not available");
+            return NULL;
         }
-        options->setSeekTo(thumbNailTime);
+        overrideMeta = new MetaData(*(trackMeta()));
+        overrideMeta->remove(kKeyDisplayWidth);
+        overrideMeta->remove(kKeyDisplayHeight);
+        overrideMeta->setInt32(kKeyWidth, thumbWidth);
+        overrideMeta->setInt32(kKeyHeight, thumbHeight);
+        overrideMeta->setData(kKeyHVCC, type, data, size);
+        options->setSeekTo(-1);
+        mThumbnail = true;
     } else {
         options->setSeekTo(frameTimeUs);
     }
@@ -552,11 +587,16 @@
     CHECK(outputFormat->findInt32("height", &height));
 
     int32_t imageWidth, imageHeight;
-    CHECK(trackMeta()->findInt32(kKeyWidth, &imageWidth));
-    CHECK(trackMeta()->findInt32(kKeyHeight, &imageHeight));
+    if (mThumbnail) {
+        CHECK(trackMeta()->findInt32(kKeyThumbnailWidth, &imageWidth));
+        CHECK(trackMeta()->findInt32(kKeyThumbnailHeight, &imageHeight));
+    } else {
+        CHECK(trackMeta()->findInt32(kKeyWidth, &imageWidth));
+        CHECK(trackMeta()->findInt32(kKeyHeight, &imageHeight));
+    }
 
     if (mFrame == NULL) {
-        mFrame = allocVideoFrame(imageWidth, imageHeight, false /*metaOnly*/);
+        mFrame = allocVideoFrame(trackMeta(), imageWidth, imageHeight, dstBpp());
 
         addFrame(mFrame);
     }
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 179e0e6..e086bea 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -125,10 +125,10 @@
 }
 
 VideoFrame* StagefrightMetadataRetriever::getImageAtIndex(
-        int index, int colorFormat, bool metaOnly) {
+        int index, int colorFormat, bool metaOnly, bool thumbnail) {
 
-    ALOGV("getImageAtIndex: index: %d colorFormat: %d, metaOnly: %d",
-            index, colorFormat, metaOnly);
+    ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
+            index, colorFormat, metaOnly, thumbnail);
 
     if (mExtractor.get() == NULL) {
         ALOGE("no extractor.");
@@ -163,6 +163,10 @@
 
     sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
 
+    if (metaOnly) {
+        return FrameDecoder::getMetadataOnly(trackMeta, colorFormat, thumbnail);
+    }
+
     sp<IMediaSource> source = mExtractor->getTrack(i);
 
     if (source.get() == NULL) {
@@ -190,7 +194,7 @@
         const AString &componentName = matchingCodecs[i];
         ImageDecoder decoder(componentName, trackMeta, source);
         VideoFrame* frame = decoder.extractFrame(
-                0 /*frameTimeUs*/, 0 /*seekMode*/, colorFormat, metaOnly);
+                thumbnail ? -1 : 0 /*frameTimeUs*/, 0 /*seekMode*/, colorFormat);
 
         if (frame != NULL) {
             return frame;
@@ -265,6 +269,16 @@
     sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
             i, MediaExtractor::kIncludeExtensiveMetaData);
 
+    if (metaOnly) {
+        if (outFrame != NULL) {
+            *outFrame = FrameDecoder::getMetadataOnly(trackMeta, colorFormat);
+            if (*outFrame != NULL) {
+                return OK;
+            }
+        }
+        return UNKNOWN_ERROR;
+    }
+
     sp<IMediaSource> source = mExtractor->getTrack(i);
 
     if (source.get() == NULL) {
@@ -294,8 +308,7 @@
         const AString &componentName = matchingCodecs[i];
         VideoFrameDecoder decoder(componentName, trackMeta, source);
         if (outFrame != NULL) {
-            *outFrame = decoder.extractFrame(
-                    timeUs, option, colorFormat, metaOnly);
+            *outFrame = decoder.extractFrame(timeUs, option, colorFormat);
             if (*outFrame != NULL) {
                 return OK;
             }
diff --git a/media/libstagefright/include/FrameDecoder.h b/media/libstagefright/include/FrameDecoder.h
index dfbe2cd..b67e928 100644
--- a/media/libstagefright/include/FrameDecoder.h
+++ b/media/libstagefright/include/FrameDecoder.h
@@ -44,11 +44,7 @@
                 mDstFormat(OMX_COLOR_Format16bitRGB565),
                 mDstBpp(2) {}
 
-    VideoFrame* extractFrame(
-            int64_t frameTimeUs,
-            int option,
-            int colorFormat,
-            bool metaOnly);
+    VideoFrame* extractFrame(int64_t frameTimeUs, int option, int colorFormat);
 
     status_t extractFrames(
             int64_t frameTimeUs,
@@ -57,6 +53,9 @@
             int colorFormat,
             std::vector<VideoFrame*>* frames);
 
+    static VideoFrame* getMetadataOnly(
+            const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false);
+
 protected:
     virtual ~FrameDecoder() {}
 
@@ -78,8 +77,6 @@
             int64_t timeUs,
             bool *done) = 0;
 
-    VideoFrame *allocVideoFrame(int32_t width, int32_t height, bool metaOnly);
-
     sp<MetaData> trackMeta()     const      { return mTrackMeta; }
     OMX_COLOR_FORMATTYPE dstFormat() const  { return mDstFormat; }
     int32_t dstBpp()             const      { return mDstBpp; }
@@ -96,7 +93,11 @@
     int32_t mDstBpp;
     std::vector<std::unique_ptr<VideoFrame> > mFrames;
 
-    bool setDstColorFormat(android_pixel_format_t colorFormat);
+    static bool getDstColorFormat(
+            android_pixel_format_t colorFormat,
+            OMX_COLOR_FORMATTYPE *dstFormat,
+            int32_t *dstBpp);
+
     status_t extractInternal(int64_t frameTimeUs, size_t numFrames, int option);
 
     DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder);
@@ -147,7 +148,8 @@
             const sp<MetaData> &trackMeta,
             const sp<IMediaSource> &source) :
                 FrameDecoder(componentName, trackMeta, source),
-                mFrame(NULL), mGridRows(1), mGridCols(1), mTilesDecoded(0) {}
+                mFrame(NULL), mGridRows(1), mGridCols(1),
+                mTilesDecoded(0), mThumbnail(false) {}
 
 protected:
     virtual sp<AMessage> onGetFormatAndSeekOptions(
@@ -173,6 +175,7 @@
     int32_t mGridRows;
     int32_t mGridCols;
     int32_t mTilesDecoded;
+    bool mThumbnail;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index 58442fe..8443fbe 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -43,7 +43,7 @@
     virtual VideoFrame* getFrameAtTime(
             int64_t timeUs, int option, int colorFormat, bool metaOnly);
     virtual VideoFrame* getImageAtIndex(
-            int index, int colorFormat, bool metaOnly);
+            int index, int colorFormat, bool metaOnly, bool thumbnail);
     virtual status_t getFrameAtIndex(
             std::vector<VideoFrame*>* frames,
             int frameIndex, int numFrames, int colorFormat, bool metaOnly);