Merge changes I58b03acd,I7d7eb086 into nyc-dev
am: 0d0a8b48d2

* commit '0d0a8b48d267a1980cfd9507b51d173756835f34':
  stagefright: untangle metadata-mode handling
  stagefright: add a way to update native handle in OMX buffers

Change-Id: I857573724b0a4f7b38832777b12caa8666ac210b
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index e5fbba0..9e15a81 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -39,7 +39,8 @@
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax
+	$(TOP)/frameworks/native/include/media/openmax \
+	$(TOP)/frameworks/native/include/media/hardware
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
@@ -63,7 +64,8 @@
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax
+	$(TOP)/frameworks/native/include/media/openmax \
+	$(TOP)/frameworks/native/include/media/hardware
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 19c7955..673c56a 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -118,6 +118,10 @@
             node_id node, OMX_U32 port_index,
             const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) = 0;
 
+    virtual status_t updateNativeHandleInMeta(
+            node_id node, OMX_U32 port_index,
+            const sp<NativeHandle> &nativeHandle, buffer_id buffer) = 0;
+
     // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
     // well as on success.
     virtual status_t createInputSurface(
@@ -272,17 +276,18 @@
     OMX_U32 mLevel;
 };
 
-}  // namespace android
-
-inline static const char *asString(android::MetadataBufferType i, const char *def = "??") {
+inline static const char *asString(MetadataBufferType i, const char *def = "??") {
     using namespace android;
     switch (i) {
         case kMetadataBufferTypeCameraSource:   return "CameraSource";
         case kMetadataBufferTypeGrallocSource:  return "GrallocSource";
         case kMetadataBufferTypeANWBuffer:      return "ANWBuffer";
+        case kMetadataBufferTypeNativeHandleSource: return "NativeHandleSource";
         case kMetadataBufferTypeInvalid:        return "Invalid";
         default:                                return def;
     }
 }
 
+}  // namespace android
+
 #endif  // ANDROID_IOMX_H_
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 399f363..c2e75a6 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -28,6 +28,7 @@
 #include <utils/List.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
+#include <MetadataBufferType.h>
 
 namespace android {
 
@@ -118,11 +119,11 @@
      * Tell whether this camera source stores meta data or real YUV
      * frame data in video buffers.
      *
-     * @return true if meta data is stored in the video
-     *      buffers; false if real YUV data is stored in
+     * @return a valid type if meta data is stored in the video
+     *      buffers; kMetadataBufferTypeInvalid if real YUV data is stored in
      *      the video buffers.
      */
-    bool isMetaDataStoredInVideoBuffers() const;
+    MetadataBufferType metaDataStoredInVideoBuffers() const;
 
     virtual void signalBufferReturned(MediaBuffer* buffer);
 
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 035e8ae..cc62786 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -37,7 +37,6 @@
                           public MediaBufferObserver {
     enum FlagBits {
         FLAG_USE_SURFACE_INPUT      = 1,
-        FLAG_USE_METADATA_INPUT     = 2,
         FLAG_PREFER_SOFTWARE_CODEC  = 4,  // used for testing only
     };
 
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 2177c00..ca3a3bf 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -25,6 +25,8 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 
+#include <MetadataBufferType.h>
+
 #include "foundation/ABase.h"
 
 namespace android {
@@ -109,9 +111,9 @@
     void dump(String8& result, const char* prefix, char* buffer,
                                                     size_t SIZE) const;
 
-    // isMetaDataStoredInVideoBuffers tells the encoder whether we will
-    // pass metadata through the buffers. Currently, it is force set to true
-    bool isMetaDataStoredInVideoBuffers() const;
+    // metaDataStoredInVideoBuffers tells the encoder what kind of metadata
+    // is passed through the buffers. Currently, it is set to ANWBuffer
+    MetadataBufferType metaDataStoredInVideoBuffers() const;
 
     sp<IGraphicBufferProducer> getProducer() const { return mProducer; }
 
@@ -234,6 +236,9 @@
 
     Condition mMediaBuffersAvailableCondition;
 
+    // Allocate and return a new MediaBuffer and pass the ANW buffer as metadata into it.
+    void passMetadataBuffer_l(MediaBuffer **buffer, ANativeWindowBuffer *bufferHandle) const;
+
     // Avoid copying and equating and default constructor
     DISALLOW_EVIL_CONSTRUCTORS(SurfaceMediaSource);
 };
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index daffb48..797a5f7 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -25,6 +25,7 @@
 #include <media/IOMX.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/openmax/OMX_IndexExt.h>
+#include <utils/NativeHandle.h>
 
 namespace android {
 
@@ -60,6 +61,7 @@
     SET_INTERNAL_OPTION,
     UPDATE_GRAPHIC_BUFFER_IN_META,
     CONFIGURE_VIDEO_TUNNEL_MODE,
+    UPDATE_NATIVE_HANDLE_IN_META,
 };
 
 class BpOMX : public BpInterface<IOMX> {
@@ -313,6 +315,24 @@
         return err;
     }
 
+    virtual status_t updateNativeHandleInMeta(
+            node_id node, OMX_U32 port_index,
+            const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+        data.writeInt32((int32_t)node);
+        data.writeInt32(port_index);
+        data.writeInt32(nativeHandle != NULL);
+        if (nativeHandle != NULL) {
+            data.writeNativeHandle(nativeHandle->handle());
+        }
+        data.writeInt32((int32_t)buffer);
+        remote()->transact(UPDATE_NATIVE_HANDLE_IN_META, data, &reply);
+
+        status_t err = reply.readInt32();
+        return err;
+    }
+
     virtual status_t createInputSurface(
             node_id node, OMX_U32 port_index, android_dataspace dataSpace,
             sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
@@ -416,7 +436,9 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeInt32((int32_t)node);
         data.writeInt32(port_index);
-        data.writeInt32((uint32_t)enable);
+        data.writeInt32((int32_t)enable);
+        data.writeInt32(type == NULL ? kMetadataBufferTypeANWBuffer : *type);
+
         remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
 
         // read type even storeMetaDataInBuffers failed
@@ -908,6 +930,25 @@
             return NO_ERROR;
         }
 
+        case UPDATE_NATIVE_HANDLE_IN_META:
+        {
+            CHECK_OMX_INTERFACE(IOMX, data, reply);
+
+            node_id node = (node_id)data.readInt32();
+            OMX_U32 port_index = data.readInt32();
+            native_handle *handle = NULL;
+            if (data.readInt32()) {
+                handle = data.readNativeHandle();
+            }
+            buffer_id buffer = (buffer_id)data.readInt32();
+
+            status_t err = updateNativeHandleInMeta(
+                    node, port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
+            reply->writeInt32(err);
+
+            return NO_ERROR;
+        }
+
         case CREATE_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
@@ -1001,7 +1042,7 @@
             OMX_U32 port_index = data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();
 
-            MetadataBufferType type = kMetadataBufferTypeInvalid;
+            MetadataBufferType type = (MetadataBufferType)data.readInt32();
             status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
 
             reply->writeInt32(type);
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f6a6f83..31a6992 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -53,6 +53,7 @@
     $(TOP)/frameworks/av/include/media                              \
     $(TOP)/frameworks/av/include/camera                             \
     $(TOP)/frameworks/native/include/media/openmax                  \
+    $(TOP)/frameworks/native/include/media/hardware                 \
     $(TOP)/external/tremolo/Tremolo                                 \
     libcore/include                                                 \
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3f7367f..6114af8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1474,8 +1474,8 @@
 
     CHECK(mFrameRate != -1);
 
-    mIsMetaDataStoredInVideoBuffers =
-        (*cameraSource)->isMetaDataStoredInVideoBuffers();
+    mMetaDataStoredInVideoBuffers =
+        (*cameraSource)->metaDataStoredInVideoBuffers();
 
     return OK;
 }
@@ -1565,11 +1565,11 @@
         format->setFloat("operating-rate", mCaptureFps);
     }
 
-    uint32_t flags = 0;
-    if (mIsMetaDataStoredInVideoBuffers) {
-        flags |= MediaCodecSource::FLAG_USE_METADATA_INPUT;
+    if (mMetaDataStoredInVideoBuffers != kMetadataBufferTypeInvalid) {
+        format->setInt32("android._input-metadata-buffer-type", mMetaDataStoredInVideoBuffers);
     }
 
+    uint32_t flags = 0;
     if (cameraSource == NULL) {
         flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT;
     } else {
@@ -1866,7 +1866,7 @@
     mCaptureFps = 0.0f;
     mTimeBetweenCaptureUs = -1;
     mCameraSourceTimeLapse = NULL;
-    mIsMetaDataStoredInVideoBuffers = false;
+    mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
     mEncoderProfiles = MediaProfiles::getInstance();
     mRotationDegrees = 0;
     mLatitudex10000 = -3600000;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index a73197f..d7f43bc 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -24,6 +24,8 @@
 
 #include <system/audio.h>
 
+#include <MetadataBufferType.h>
+
 namespace android {
 
 class Camera;
@@ -121,7 +123,7 @@
 
     String8 mParams;
 
-    bool mIsMetaDataStoredInVideoBuffers;
+    MetadataBufferType mMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     int64_t mPauseStartTimeUs;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3841876..27c1a64 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -794,10 +794,10 @@
             MetadataBufferType type =
                 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
             size_t bufSize = def.nBufferSize;
-            if (type == kMetadataBufferTypeGrallocSource) {
-                bufSize = sizeof(VideoGrallocMetadata);
-            } else if (type == kMetadataBufferTypeANWBuffer) {
+            if (type == kMetadataBufferTypeANWBuffer) {
                 bufSize = sizeof(VideoNativeMetadata);
+            } else if (type == kMetadataBufferTypeNativeHandleSource) {
+                bufSize = sizeof(VideoNativeHandleMetadata);
             }
 
             // If using gralloc or native source input metadata buffers, allocate largest
@@ -805,7 +805,7 @@
             // may require gralloc source. For camera source, allocate at least enough
             // size for native metadata buffers.
             size_t allottedSize = bufSize;
-            if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) {
+            if (portIndex == kPortIndexInput && type == kMetadataBufferTypeANWBuffer) {
                 bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
             } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
                 bufSize = max(bufSize, sizeof(VideoNativeMetadata));
@@ -1726,19 +1726,20 @@
 
     int32_t storeMeta;
     if (encoder
-            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
-            && storeMeta != 0) {
-        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
+            && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
+            && storeMeta != kMetadataBufferTypeInvalid) {
+        mInputMetadataType = (MetadataBufferType)storeMeta;
+        err = mOMX->storeMetaDataInBuffers(
+                mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
         if (err != OK) {
             ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
                     mComponentName.c_str(), err);
 
             return err;
-        }
-        // For this specific case we could be using camera source even if storeMetaDataInBuffers
-        // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
-        if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            mInputMetadataType = kMetadataBufferTypeCameraSource;
+        } else if (storeMeta == kMetadataBufferTypeANWBuffer
+                && mInputMetadataType == kMetadataBufferTypeGrallocSource) {
+            // IOMX translates ANWBuffers to gralloc source already.
+            mInputMetadataType = (MetadataBufferType)storeMeta;
         }
 
         uint32_t usageBits;
@@ -1784,9 +1785,10 @@
     mIsVideo = video;
     if (encoder && video) {
         OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
-            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
+            && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
             && storeMeta != 0);
 
+        mOutputMetadataType = kMetadataBufferTypeNativeHandleSource;
         err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
         if (err != OK) {
             ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
@@ -1915,6 +1917,7 @@
             }
 
             // Always try to enable dynamic output buffers on native surface
+            mOutputMetadataType = kMetadataBufferTypeANWBuffer;
             err = mOMX->storeMetaDataInBuffers(
                     mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
             if (err != OK) {
@@ -5967,18 +5970,15 @@
 
             if (mCodec->usingMetadataOnEncoderOutput()) {
                 native_handle_t *handle = NULL;
-                VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
-                VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
-                if (info->mData->size() >= sizeof(grallocMeta)
-                        && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
-                    handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;
-                } else if (info->mData->size() >= sizeof(nativeMeta)
-                        && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
+                VideoNativeHandleMetadata &nativeMeta =
+                    *(VideoNativeHandleMetadata *)info->mData->data();
+                if (info->mData->size() >= sizeof(nativeMeta)
+                        && nativeMeta.eType == kMetadataBufferTypeNativeHandleSource) {
 #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
-                    // ANativeWindowBuffer is only valid on 32-bit/mediaserver process
+                    // handle is only valid on 32-bit/mediaserver process
                     handle = NULL;
 #else
-                    handle = (native_handle_t *)nativeMeta.pBuffer->handle;
+                    handle = (native_handle_t *)nativeMeta.pHandle;
 #endif
                 }
                 info->mData->meta()->setPointer("handle", handle);
@@ -6665,8 +6665,14 @@
 
     sp<IGraphicBufferProducer> bufferProducer;
     if (err == OK) {
+        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
         err = mCodec->mOMX->createInputSurface(
-                mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType);
+                mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer,
+                &mCodec->mInputMetadataType);
+        // framework uses ANW buffers internally instead of gralloc handles
+        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
+            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+        }
     }
 
     if (err == OK) {
@@ -6705,9 +6711,14 @@
     notify->setMessage("output-format", mCodec->mOutputFormat);
 
     if (err == OK) {
+        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
         err = mCodec->mOMX->setInputSurface(
                 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
                 &mCodec->mInputMetadataType);
+        // framework uses ANW buffers internally instead of gralloc handles
+        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
+            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+        }
     }
 
     if (err == OK) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index e213581..5fc9237 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -1244,13 +1244,19 @@
     mFrameAvailableCondition.signal();
 }
 
-bool CameraSource::isMetaDataStoredInVideoBuffers() const {
-    ALOGV("isMetaDataStoredInVideoBuffers");
+MetadataBufferType CameraSource::metaDataStoredInVideoBuffers() const {
+    ALOGV("metaDataStoredInVideoBuffers");
 
     // Output buffers will contain metadata if camera sends us buffer in metadata mode or via
     // buffer queue.
-    return (mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA ||
-            mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE);
+    switch (mVideoBufferMode) {
+        case hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA:
+            return kMetadataBufferTypeNativeHandleSource;
+        case hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE:
+            return kMetadataBufferTypeANWBuffer;
+        default:
+            return kMetadataBufferTypeInvalid;
+    }
 }
 
 CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index f77d762..d7cf1e9 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -449,10 +449,6 @@
     mCodecLooper->setName("codec_looper");
     mCodecLooper->start();
 
-    if (mFlags & FLAG_USE_METADATA_INPUT) {
-        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
-    }
-
     if (mFlags & FLAG_USE_SURFACE_INPUT) {
         mOutputFormat->setInt32("create-input-buffers-suspended", 1);
     }
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index a523d0e..e19c9f6 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -111,6 +111,10 @@
             node_id node, OMX_U32 port_index,
             const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
 
+    virtual status_t updateNativeHandleInMeta(
+            node_id node, OMX_U32 port_index,
+            const sp<NativeHandle> &nativeHandle, buffer_id buffer);
+
     virtual status_t createInputSurface(
             node_id node, OMX_U32 port_index, android_dataspace dataSpace,
             sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type);
@@ -387,6 +391,13 @@
             node, port_index, graphicBuffer, buffer);
 }
 
+status_t MuxOMX::updateNativeHandleInMeta(
+        node_id node, OMX_U32 port_index,
+        const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
+    return getOMX(node)->updateNativeHandleInMeta(
+            node, port_index, nativeHandle, buffer);
+}
+
 status_t MuxOMX::createInputSurface(
         node_id node, OMX_U32 port_index, android_dataspace dataSpace,
         sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index e4bf67a..15ff569 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -23,6 +23,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <OMX_IVCommon.h>
+#include <media/hardware/HardwareAPI.h>
 #include <media/hardware/MetadataBufferType.h>
 
 #include <ui/GraphicBuffer.h>
@@ -126,9 +127,9 @@
     return OK;
 }
 
-bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
+MetadataBufferType SurfaceMediaSource::metaDataStoredInVideoBuffers() const {
     ALOGV("isMetaDataStoredInVideoBuffers");
-    return true;
+    return kMetadataBufferTypeANWBuffer;
 }
 
 int32_t SurfaceMediaSource::getFrameRate( ) const {
@@ -250,29 +251,19 @@
 }
 
 // Pass the data to the MediaBuffer. Pass in only the metadata
-// The metadata passed consists of two parts:
-// 1. First, there is an integer indicating that it is a GRAlloc
-// source (kMetadataBufferTypeGrallocSource)
-// 2. This is followed by the buffer_handle_t that is a handle to the
-// GRalloc buffer. The encoder needs to interpret this GRalloc handle
-// and encode the frames.
-// --------------------------------------------------------------
-// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
-// --------------------------------------------------------------
 // Note: Call only when you have the lock
-static void passMetadataBuffer(MediaBuffer **buffer,
-        buffer_handle_t bufferHandle) {
-    *buffer = new MediaBuffer(4 + sizeof(buffer_handle_t));
-    char *data = (char *)(*buffer)->data();
+void SurfaceMediaSource::passMetadataBuffer_l(MediaBuffer **buffer,
+        ANativeWindowBuffer *bufferHandle) const {
+    *buffer = new MediaBuffer(sizeof(VideoNativeMetadata));
+    VideoNativeMetadata *data = (VideoNativeMetadata *)(*buffer)->data();
     if (data == NULL) {
         ALOGE("Cannot allocate memory for metadata buffer!");
         return;
     }
-    OMX_U32 type = kMetadataBufferTypeGrallocSource;
-    memcpy(data, &type, 4);
-    memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t));
-
-    ALOGV("handle = %p, , offset = %zu, length = %zu",
+    data->eType = metaDataStoredInVideoBuffers();
+    data->pBuffer = bufferHandle;
+    data->nFenceFd = -1;
+    ALOGV("handle = %p, offset = %zu, length = %zu",
             bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset());
 }
 
@@ -361,7 +352,7 @@
     mNumFramesEncoded++;
     // Pass the data to the MediaBuffer. Pass in only the metadata
 
-    passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);
+    passMetadataBuffer_l(buffer, mSlots[mCurrentSlot].mGraphicBuffer->getNativeBuffer());
 
     (*buffer)->setObserver(this);
     (*buffer)->add_ref();
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 9726741..53bf5d6 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -93,6 +93,10 @@
             node_id node, OMX_U32 port_index,
             const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
 
+    virtual status_t updateNativeHandleInMeta(
+            node_id node, OMX_U32 port_index,
+            const sp<NativeHandle> &nativeHandle, buffer_id buffer);
+
     virtual status_t createInputSurface(
             node_id node, OMX_U32 port_index, android_dataspace dataSpace,
             sp<IGraphicBufferProducer> *bufferProducer,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 25c3773..736718c 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -79,6 +79,10 @@
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
             OMX::buffer_id buffer);
 
+    status_t updateNativeHandleInMeta(
+            OMX_U32 portIndex, const sp<NativeHandle> &nativeHandle,
+            OMX::buffer_id buffer);
+
     status_t createInputSurface(
             OMX_U32 portIndex, android_dataspace dataSpace,
             sp<IGraphicBufferProducer> *bufferProducer,
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 4cc857e..7121ac4 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -488,6 +488,19 @@
             port_index, graphicBuffer, buffer);
 }
 
+status_t OMX::updateNativeHandleInMeta(
+        node_id node, OMX_U32 port_index,
+        const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->updateNativeHandleInMeta(
+            port_index, nativeHandle, buffer);
+}
+
 status_t OMX::createInputSurface(
         node_id node, OMX_U32 port_index, android_dataspace dataSpace,
         sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index e23ceed..70c5cb1 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -38,6 +38,7 @@
 #include <media/stagefright/MediaErrors.h>
 
 #include <utils/misc.h>
+#include <utils/NativeHandle.h>
 
 static const OMX_U32 kPortIndexInput = 0;
 static const OMX_U32 kPortIndexOutput = 1;
@@ -152,8 +153,13 @@
         mGraphicBuffer = graphicBuffer;
     }
 
+    void setNativeHandle(const sp<NativeHandle> &nativeHandle) {
+        mNativeHandle = nativeHandle;
+    }
+
 private:
     sp<GraphicBuffer> mGraphicBuffer;
+    sp<NativeHandle> mNativeHandle;
     sp<IMemory> mMem;
     size_t mSize;
     bool mIsBackup;
@@ -523,6 +529,9 @@
         OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
     if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
         android_errorWriteLog(0x534e4554, "26324358");
+        if (type != NULL) {
+            *type = kMetadataBufferTypeInvalid;
+        }
         return BAD_VALUE;
     }
 
@@ -533,26 +542,32 @@
     OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
             "OMX.google.android.index.storeANWBufferInMetadata");
     MetadataBufferType negotiatedType;
+    MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;
 
     StoreMetaDataInBuffersParams params;
     InitOMXParams(&params);
     params.nPortIndex = portIndex;
     params.bStoreMetaData = enable;
 
-    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, nativeBufferName, &index);
+    OMX_ERRORTYPE err =
+        requestedType == kMetadataBufferTypeANWBuffer
+                ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index)
+                : OMX_ErrorUnsupportedIndex;
     OMX_ERRORTYPE xerr = err;
     if (err == OMX_ErrorNone) {
         err = OMX_SetParameter(mHandle, index, &params);
         if (err == OMX_ErrorNone) {
             name = nativeBufferName; // set name for debugging
-            negotiatedType = kMetadataBufferTypeANWBuffer;
+            negotiatedType = requestedType;
         }
     }
     if (err != OMX_ErrorNone) {
         err = OMX_GetExtensionIndex(mHandle, name, &index);
         xerr = err;
         if (err == OMX_ErrorNone) {
-            negotiatedType = kMetadataBufferTypeGrallocSource;
+            negotiatedType =
+                requestedType == kMetadataBufferTypeANWBuffer
+                        ? kMetadataBufferTypeGrallocSource : requestedType;
             err = OMX_SetParameter(mHandle, index, &params);
         }
     }
@@ -574,8 +589,9 @@
         }
         mMetadataType[portIndex] = negotiatedType;
     }
-    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u negotiated %s:%d",
-            portString(portIndex), portIndex, asString(negotiatedType), negotiatedType);
+    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d",
+            portString(portIndex), portIndex, enable ? "" : "UN",
+            asString(requestedType), requestedType, asString(negotiatedType), negotiatedType);
 
     if (type != NULL) {
         *type = negotiatedType;
@@ -871,6 +887,43 @@
     return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header);
 }
 
+status_t OMXNodeInstance::updateNativeHandleInMeta(
+        OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle, OMX::buffer_id buffer) {
+    Mutex::Autolock autoLock(mLock);
+    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+    // No need to check |nativeHandle| since NULL is valid for it as below.
+    if (header == NULL) {
+        ALOGE("b/25884056");
+        return BAD_VALUE;
+    }
+
+    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+        return BAD_VALUE;
+    }
+
+    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
+    // update backup buffer for input, codec buffer for output
+    sp<ABuffer> data = bufferMeta->getBuffer(
+            header, portIndex == kPortIndexInput /* backup */, false /* limit */);
+    bufferMeta->setNativeHandle(nativeHandle);
+    if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
+            && data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
+        VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data());
+        metadata.eType = mMetadataType[portIndex];
+        metadata.pHandle =
+            nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle());
+    } else {
+        CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)",
+            portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity());
+        return BAD_VALUE;
+    }
+
+    CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p",
+            portString(portIndex), portIndex, buffer,
+            nativeHandle == NULL ? NULL : nativeHandle->handle());
+    return OK;
+}
+
 status_t OMXNodeInstance::createGraphicBufferSource(
         OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) {
     status_t err;
@@ -884,6 +937,9 @@
     }
 
     // Input buffers will hold meta-data (ANativeWindowBuffer references).
+    if (type != NULL) {
+        *type = kMetadataBufferTypeANWBuffer;
+    }
     err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
     if (err != OK) {
         return err;
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index 111e6c5..d1c9d36 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -30,6 +30,7 @@
 	frameworks/av/media/libstagefright \
 	frameworks/av/media/libstagefright/include \
 	$(TOP)/frameworks/native/include/media/openmax \
+	$(TOP)/frameworks/native/include/media/hardware \
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index 5bd6e5c..ae4ac90 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -17,6 +17,7 @@
 LOCAL_C_INCLUDES:= \
         $(TOP)/frameworks/av/media/libstagefright \
         $(TOP)/frameworks/native/include/media/openmax \
+        $(TOP)/frameworks/native/include/media/hardware \
         $(TOP)/frameworks/av/media/libstagefright/mpeg2ts \
 
 LOCAL_SHARED_LIBRARIES:= \
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 3ecb52b..3587cb9 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -948,8 +948,9 @@
 
     if (isVideo) {
         format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
-        format->setInt32("store-metadata-in-buffers", true);
-        format->setInt32("store-metadata-in-buffers-output", (mHDCP != NULL)
+        format->setInt32(
+                "android._input-metadata-buffer-type", kMetadataBufferTypeANWBuffer);
+        format->setInt32("android._store-metadata-in-buffers-output", (mHDCP != NULL)
                 && (mHDCP->getCaps() & HDCPModule::HDCP_CAPS_ENCRYPT_NATIVE));
         format->setInt32(
                 "color-format", OMX_COLOR_FormatAndroidOpaque);