Merge "For thumbnail extraction make sure we instantiate a decoder that allows access to the framebuffer. Implement the samsung workaround to support this by reconfiguring the decoder." into gingerbread
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 2bb7783..1d94160 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -33,7 +33,11 @@
                   public MediaBufferObserver {
     enum CreationFlags {
         kPreferSoftwareCodecs    = 1,
-        kIgnoreCodecSpecificData = 2
+        kIgnoreCodecSpecificData = 2,
+
+        // The client wants to access the output buffer's video
+        // data for example for thumbnail extraction.
+        kClientNeedsFramebuffer  = 4,
     };
     static sp<MediaSource> Create(
             const sp<IOMX> &omx,
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4648ad3..9a49a9b 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -493,12 +493,29 @@
 
         LOGV("Attempting to allocate OMX node '%s'", componentName);
 
+        uint32_t quirks = getComponentQuirks(componentName, createEncoder);
+
+        if (!createEncoder
+                && (quirks & kOutputBuffersAreUnreadable)
+                && (flags & kClientNeedsFramebuffer)) {
+            if (strncmp(componentName, "OMX.SEC.", 8)) {
+                // For OMX.SEC.* decoders we can enable a special mode that
+                // gives the client access to the framebuffer contents.
+
+                LOGW("Component '%s' does not give the client access to "
+                     "the framebuffer contents. Skipping.",
+                     componentName);
+
+                continue;
+            }
+        }
+
         status_t err = omx->allocateNode(componentName, observer, &node);
         if (err == OK) {
             LOGV("Successfully allocated OMX node '%s'", componentName);
 
             sp<OMXCodec> codec = new OMXCodec(
-                    omx, node, getComponentQuirks(componentName, createEncoder),
+                    omx, node, quirks,
                     createEncoder, mime, componentName,
                     source);
 
@@ -681,6 +698,33 @@
 
     initOutputFormat(meta);
 
+    if ((flags & kClientNeedsFramebuffer)
+            && !strncmp(mComponentName, "OMX.SEC.", 8)) {
+        OMX_INDEXTYPE index;
+
+        status_t err =
+            mOMX->getExtensionIndex(
+                    mNode,
+                    "OMX.SEC.index.ThumbnailMode",
+                    &index);
+
+        if (err != OK) {
+            return err;
+        }
+
+        OMX_BOOL enable = OMX_TRUE;
+        err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
+
+        if (err != OK) {
+            CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
+                       "returned error 0x%08x", err);
+
+            return err;
+        }
+
+        mQuirks &= ~kOutputBuffersAreUnreadable;
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index af9c70c..a800a93 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -112,7 +112,7 @@
     sp<MediaSource> decoder =
         OMXCodec::Create(
                 client->interface(), source->getFormat(), false, source,
-                NULL, flags);
+                NULL, flags | OMXCodec::kClientNeedsFramebuffer);
 
     if (decoder.get() == NULL) {
         LOGV("unable to instantiate video decoder.");