Merge "mediaextractor: Skip setting  memory limits on ASan builds"
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index a7eace1..6097f01 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -51,6 +51,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaMuxer.h>
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 
 #include "screenrecord.h"
 #include "Overlay.h"
@@ -328,7 +329,7 @@
 
     assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
 
-    Vector<sp<ABuffer> > buffers;
+    Vector<sp<MediaCodecBuffer> > buffers;
     err = encoder->getOutputBuffers(&buffers);
     if (err != NO_ERROR) {
         fprintf(stderr, "Unable to get output buffers (err=%d)\n", err);
@@ -411,7 +412,10 @@
                     // want to queue these up and do them on a different thread.
                     ATRACE_NAME("write sample");
                     assert(trackIdx != -1);
-                    err = muxer->writeSampleData(buffers[bufIndex], trackIdx,
+                    // TODO
+                    sp<ABuffer> buffer = new ABuffer(
+                            buffers[bufIndex]->data(), buffers[bufIndex]->size());
+                    err = muxer->writeSampleData(buffer, trackIdx,
                             ptsUsec, flags);
                     if (err != NO_ERROR) {
                         fprintf(stderr,
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 50913cd..afb7db3 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -25,6 +25,7 @@
 #include <media/AudioTrack.h>
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -355,7 +356,7 @@
             err = state->mCodec->dequeueInputBuffer(&index, -1ll);
             CHECK_EQ(err, (status_t)OK);
 
-            const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
+            const sp<MediaCodecBuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
 
             CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
             dstBuffer->setRange(0, srcBuffer->size());
@@ -482,11 +483,13 @@
             state->mAvailInputBufferIndices.erase(
                     state->mAvailInputBufferIndices.begin());
 
-            const sp<ABuffer> &dstBuffer =
+            const sp<MediaCodecBuffer> &dstBuffer =
                 state->mBuffers[0].itemAt(index);
+            sp<ABuffer> abuffer = new ABuffer(dstBuffer->base(), dstBuffer->capacity());
 
-            err = mExtractor->readSampleData(dstBuffer);
+            err = mExtractor->readSampleData(abuffer);
             CHECK_EQ(err, (status_t)OK);
+            dstBuffer->setRange(abuffer->offset(), abuffer->size());
 
             int64_t timeUs;
             CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
@@ -530,7 +533,7 @@
                     state->mCodec->releaseOutputBuffer(info->mIndex);
                 } else {
                     if (state->mAudioTrack != NULL) {
-                        const sp<ABuffer> &srcBuffer =
+                        const sp<MediaCodecBuffer> &srcBuffer =
                             state->mBuffers[1].itemAt(info->mIndex);
 
                         renderAudio(state, info, srcBuffer);
@@ -597,7 +600,7 @@
 }
 
 void SimplePlayer::renderAudio(
-        CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
+        CodecState *state, BufferInfo *info, const sp<MediaCodecBuffer> &buffer) {
     CHECK(state->mAudioTrack != NULL);
 
     if (state->mAudioTrack->stopped()) {
diff --git a/cmds/stagefright/SimplePlayer.h b/cmds/stagefright/SimplePlayer.h
index ae9dfd2..918fd24 100644
--- a/cmds/stagefright/SimplePlayer.h
+++ b/cmds/stagefright/SimplePlayer.h
@@ -25,6 +25,7 @@
 struct AudioTrack;
 class IGraphicBufferProducer;
 struct MediaCodec;
+class MediaCodecBuffer;
 struct NuMediaExtractor;
 class Surface;
 
@@ -73,7 +74,7 @@
     {
         sp<MediaCodec> mCodec;
         Vector<sp<ABuffer> > mCSD;
-        Vector<sp<ABuffer> > mBuffers[2];
+        Vector<sp<MediaCodecBuffer> > mBuffers[2];
 
         List<size_t> mAvailInputBufferIndices;
         List<BufferInfo> mAvailOutputBufferInfos;
@@ -101,7 +102,7 @@
     status_t onOutputFormatChanged(size_t trackIndex, CodecState *state);
 
     void renderAudio(
-            CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer);
+            CodecState *state, BufferInfo *info, const sp<MediaCodecBuffer> &buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer);
 };
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index dae9bbe..26135d7 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -26,6 +26,7 @@
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayerService.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -56,8 +57,8 @@
 
 struct CodecState {
     sp<MediaCodec> mCodec;
-    Vector<sp<ABuffer> > mInBuffers;
-    Vector<sp<ABuffer> > mOutBuffers;
+    Vector<sp<MediaCodecBuffer> > mInBuffers;
+    Vector<sp<MediaCodecBuffer> > mOutBuffers;
     bool mSignalledInputEOS;
     bool mSawOutputEOS;
     int64_t mNumBuffersDecoded;
@@ -174,10 +175,12 @@
                 if (err == OK) {
                     ALOGV("filling input buffer %zu", index);
 
-                    const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+                    const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
+                    sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
 
-                    err = extractor->readSampleData(buffer);
+                    err = extractor->readSampleData(abuffer);
                     CHECK_EQ(err, (status_t)OK);
+                    buffer->setRange(abuffer->offset(), abuffer->size());
 
                     int64_t timeUs;
                     err = extractor->getSampleTime(&timeUs);
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index d829df0..410dd69 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -26,6 +26,7 @@
 #include <gui/Surface.h>
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -131,8 +132,8 @@
 
 struct CodecState {
     sp<MediaCodec> mCodec;
-    Vector<sp<ABuffer> > mInBuffers;
-    Vector<sp<ABuffer> > mOutBuffers;
+    Vector<sp<MediaCodecBuffer> > mInBuffers;
+    Vector<sp<MediaCodecBuffer> > mOutBuffers;
     bool mSignalledInputEOS;
     bool mSawOutputEOS;
     int64_t mNumBuffersDecoded;
@@ -183,9 +184,9 @@
     }
     size_t outIndex = frame.index;
 
-    const sp<ABuffer> &srcBuffer =
+    const sp<MediaCodecBuffer> &srcBuffer =
         vidState->mOutBuffers.itemAt(outIndex);
-    const sp<ABuffer> &destBuffer =
+    const sp<MediaCodecBuffer> &destBuffer =
         filterState->mInBuffers.itemAt(filterIndex);
 
     sp<AMessage> srcFormat, destFormat;
@@ -532,10 +533,12 @@
                 if (err == OK) {
                     ALOGV("filling input buffer %zu", index);
 
-                    const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+                    const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
+                    sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
 
-                    err = extractor->readSampleData(buffer);
+                    err = extractor->readSampleData(abuffer);
                     CHECK(err == OK);
+                    buffer->setRange(abuffer->offset(), abuffer->size());
 
                     int64_t timeUs;
                     err = extractor->getSampleTime(&timeUs);
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index c0c48c1..f413fd7 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -36,6 +36,7 @@
 
 class IGraphicBufferSource;
 class IMemory;
+class IOMXNode;
 class IOMXObserver;
 class NativeHandle;
 struct omx_message;
@@ -45,12 +46,14 @@
     DECLARE_META_INTERFACE(OMX);
 
     typedef uint32_t buffer_id;
-    typedef uint32_t node_id;
 
-    // Given a node_id and the calling process' pid, returns true iff
-    // the implementation of the OMX interface lives in the same
-    // process.
-    virtual bool livesLocally(node_id node, pid_t pid) = 0;
+    enum {
+        kFenceTimeoutMs = 1000
+    };
+
+    // Returns true iff the implementation of the OMX interface
+    // lives in the same process.
+    virtual bool livesLocally() = 0;
 
     struct ComponentInfo {
         String8 mName;
@@ -60,85 +63,86 @@
 
     virtual status_t allocateNode(
             const char *name, const sp<IOMXObserver> &observer,
-            sp<IBinder> *nodeBinder,
-            node_id *node) = 0;
+            sp<IBinder> *nodeBinder, sp<IOMXNode> *omxNode) = 0;
 
-    virtual status_t freeNode(node_id node) = 0;
+    virtual status_t createPersistentInputSurface(
+            sp<IGraphicBufferProducer> *bufferProducer,
+            sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
+};
+
+class IOMXNode : public IInterface {
+public:
+    DECLARE_META_INTERFACE(OMXNode);
+
+    typedef IOMX::buffer_id buffer_id;
+
+    virtual status_t freeNode() = 0;
 
     virtual status_t sendCommand(
-            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
+            OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
 
     virtual status_t getParameter(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size) = 0;
+            OMX_INDEXTYPE index, void *params, size_t size) = 0;
 
     virtual status_t setParameter(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size) = 0;
+            OMX_INDEXTYPE index, const void *params, size_t size) = 0;
 
     virtual status_t getConfig(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size) = 0;
+            OMX_INDEXTYPE index, void *params, size_t size) = 0;
 
     virtual status_t setConfig(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size) = 0;
+            OMX_INDEXTYPE index, const void *params, size_t size) = 0;
 
-    virtual status_t getState(
-            node_id node, OMX_STATETYPE* state) = 0;
+    virtual status_t getState(OMX_STATETYPE* state) = 0;
 
     // This will set *type to previous metadata buffer type on OMX error (not on binder error), and
     // new metadata buffer type on success.
     virtual status_t storeMetaDataInBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
+            OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
 
     virtual status_t prepareForAdaptivePlayback(
-            node_id node, OMX_U32 portIndex, OMX_BOOL enable,
+            OMX_U32 portIndex, OMX_BOOL enable,
             OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0;
 
     virtual status_t configureVideoTunnelMode(
-            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+            OMX_U32 portIndex, OMX_BOOL tunneled,
             OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0;
 
     virtual status_t enableNativeBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) = 0;
+            OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) = 0;
 
     virtual status_t getGraphicBufferUsage(
-            node_id node, OMX_U32 port_index, OMX_U32* usage) = 0;
+            OMX_U32 port_index, OMX_U32* usage) = 0;
 
     // Use |params| as an OMX buffer, but limit the size of the OMX buffer to |allottedSize|.
     virtual status_t useBuffer(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+            OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer, OMX_U32 allottedSize) = 0;
 
     virtual status_t useGraphicBuffer(
-            node_id node, OMX_U32 port_index,
+            OMX_U32 port_index,
             const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) = 0;
 
     virtual status_t updateGraphicBufferInMeta(
-            node_id node, OMX_U32 port_index,
+            OMX_U32 port_index,
             const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) = 0;
 
     virtual status_t updateNativeHandleInMeta(
-            node_id node, OMX_U32 port_index,
+            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(
-            node_id node, OMX_U32 port_index, android_dataspace dataSpace,
+            OMX_U32 port_index, android_dataspace dataSpace,
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferSource> *bufferSource,
             MetadataBufferType *type = NULL) = 0;
 
-    virtual status_t createPersistentInputSurface(
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer) = 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 setInputSurface(
-            node_id node, OMX_U32 port_index,
+            OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer,
             sp<IGraphicBufferSource> *bufferSource,
             MetadataBufferType *type) = 0;
@@ -149,32 +153,28 @@
     // same process as the callee, i.e. is the media_server, as the returned "buffer_data"
     // pointer is just that, a pointer into local address space.
     virtual status_t allocateSecureBuffer(
-            node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) = 0;
+            OMX_U32 port_index, size_t size, buffer_id *buffer,
+            void **buffer_data, sp<NativeHandle> *native_handle) = 0;
 
     // Allocate an OMX buffer of size |allotedSize|. Use |params| as the backup buffer, which
     // may be larger.
     virtual status_t allocateBufferWithBackup(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+            OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer, OMX_U32 allottedSize) = 0;
 
     virtual status_t freeBuffer(
-            node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
+            OMX_U32 port_index, buffer_id buffer) = 0;
 
-    enum {
-        kFenceTimeoutMs = 1000
-    };
     // Calls OMX_FillBuffer on buffer, and passes |fenceFd| to component if it supports
     // fences. Otherwise, it waits on |fenceFd| before calling OMX_FillBuffer.
     // Takes ownership of |fenceFd| even if this call fails.
-    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd = -1) = 0;
+    virtual status_t fillBuffer(buffer_id buffer, int fenceFd = -1) = 0;
 
     // Calls OMX_EmptyBuffer on buffer (after updating buffer header with |range_offset|,
     // |range_length|, |flags| and |timestamp|). Passes |fenceFd| to component if it
     // supports fences. Otherwise, it waits on |fenceFd| before calling OMX_EmptyBuffer.
     // Takes ownership of |fenceFd| even if this call fails.
     virtual status_t emptyBuffer(
-            node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) = 0;
@@ -186,13 +186,11 @@
     // timestamp on the filled buffer corresponding to this frame will be modified to
     // |origTimestamp| after it's filled.
     virtual status_t emptyGraphicBuffer(
-            node_id node,
             buffer_id buffer,
             const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
             OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) = 0;
 
     virtual status_t getExtensionIndex(
-            node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) = 0;
 
@@ -207,7 +205,6 @@
         FRAME_RENDERED,
     } type;
 
-    IOMX::node_id node;
     int fenceFd; // used for EMPTY_BUFFER_DONE and FILL_BUFFER_DONE; client must close this
 
     union {
@@ -254,13 +251,24 @@
 
 class BnOMX : public BnInterface<IOMX> {
 public:
+    virtual bool livesLocally() {
+        return true;
+    }
+
+    virtual status_t onTransact(
+            uint32_t code, const Parcel &data, Parcel *reply,
+            uint32_t flags = 0);
+};
+
+class BnOMXNode : public BnInterface<IOMXNode> {
+public:
     virtual status_t onTransact(
             uint32_t code, const Parcel &data, Parcel *reply,
             uint32_t flags = 0);
 
 protected:
     // check if the codec is secure.
-    virtual bool isSecure(IOMX::node_id node) {
+    virtual bool isSecure() const {
         return false;
     }
 };
diff --git a/include/media/MediaCodecBuffer.h b/include/media/MediaCodecBuffer.h
new file mode 100644
index 0000000..2df81dd
--- /dev/null
+++ b/include/media/MediaCodecBuffer.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_CODEC_BUFFER_H_
+
+#define MEDIA_CODEC_BUFFER_H_
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+class MediaBufferBase;
+
+/**
+ * Buffers used by MediaCodec.
+ */
+class MediaCodecBuffer : public RefBase {
+public:
+    MediaCodecBuffer(const sp<AMessage> &format, const sp<ABuffer> &buffer);
+
+    /**
+     * MediaCodec will release all references to the buffer when it's done using
+     * it, so the destructor should return the buffer to the owner, such as OMX
+     * components, buffer allocators, surfaces, etc.
+     */
+    virtual ~MediaCodecBuffer() = default;
+
+    // ABuffer-like interface
+    uint8_t *base();
+    uint8_t *data();
+    size_t capacity() const;
+    size_t size() const;
+    size_t offset() const;
+    // Default implementation calls ABuffer::setRange() and returns OK.
+    virtual status_t setRange(size_t offset, size_t size);
+    // TODO: These can be removed if we finish replacing all MediaBuffer's.
+    MediaBufferBase *getMediaBufferBase();
+    void setMediaBufferBase(MediaBufferBase *mediaBuffer);
+
+    // TODO: Specify each field for meta/format.
+    sp<AMessage> meta();
+    sp<AMessage> format();
+
+private:
+    MediaCodecBuffer() = delete;
+
+    const sp<AMessage> mMeta;
+    const sp<AMessage> mFormat;
+    const sp<ABuffer> mBuffer;
+    MediaBufferBase *mMediaBufferBase;
+};
+
+}  // namespace android
+
+#endif  // MEDIA_CODEC_BUFFER_H_
diff --git a/include/media/audiohal/StreamHalInterface.h b/include/media/audiohal/StreamHalInterface.h
index 5a7b4b6..8f42fe7 100644
--- a/include/media/audiohal/StreamHalInterface.h
+++ b/include/media/audiohal/StreamHalInterface.h
@@ -102,7 +102,7 @@
     // Set the callback for notifying completion of non-blocking write and drain.
     // The callback must be owned by someone else. The output stream does not own it
     // to avoid strong pointer loops.
-    virtual status_t setCallback(sp<StreamOutHalInterfaceCallback> callback) = 0;
+    virtual status_t setCallback(wp<StreamOutHalInterfaceCallback> callback) = 0;
 
     // Returns whether pause and resume operations are supported.
     virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index faf62ad..e83a8f2 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -35,6 +35,7 @@
 namespace android {
 
 struct ABuffer;
+class MediaCodecBuffer;
 struct MemoryDealer;
 struct DescribeColorFormat2Params;
 struct DataConverter;
@@ -74,7 +75,7 @@
     struct PortDescription : public CodecBase::PortDescription {
         size_t countBuffers();
         IOMX::buffer_id bufferIDAt(size_t index) const;
-        sp<ABuffer> bufferAt(size_t index) const;
+        sp<MediaCodecBuffer> bufferAt(size_t index) const;
         sp<NativeHandle> handleAt(size_t index) const;
         sp<RefBase> memRefAt(size_t index) const;
 
@@ -82,13 +83,13 @@
         friend struct ACodec;
 
         Vector<IOMX::buffer_id> mBufferIDs;
-        Vector<sp<ABuffer> > mBuffers;
+        Vector<sp<MediaCodecBuffer>> mBuffers;
         Vector<sp<NativeHandle> > mHandles;
         Vector<sp<RefBase> > mMemRefs;
 
         PortDescription();
         void addBuffer(
-                IOMX::buffer_id id, const sp<ABuffer> &buffer,
+                IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer,
                 const sp<NativeHandle> &handle, const sp<RefBase> &memRef);
 
         DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
@@ -186,11 +187,12 @@
         Status mStatus;
         unsigned mDequeuedAt;
 
-        sp<ABuffer> mData;      // the client's buffer; if not using data conversion, this is the
-                                // codec buffer; otherwise, it is allocated separately
-        sp<RefBase> mMemRef;    // and a reference to the IMemory, so it does not go away
-        sp<ABuffer> mCodecData; // the codec's buffer
-        sp<RefBase> mCodecRef;  // and a reference to the IMemory
+        sp<MediaCodecBuffer> mData;  // the client's buffer; if not using data conversion, this is
+                                     // the codec buffer; otherwise, it is allocated separately
+        sp<RefBase> mMemRef;         // and a reference to the IMemory, so it does not go away
+        sp<MediaCodecBuffer> mCodecData;  // the codec's buffer
+        sp<RefBase> mCodecRef;            // and a reference to the IMemory
+
         sp<GraphicBuffer> mGraphicBuffer;
         sp<NativeHandle> mNativeHandle;
         int mFenceFd;
@@ -204,6 +206,8 @@
         // Log error, if the current fence is not a read/write fence.
         void checkReadFence(const char *dbg);
         void checkWriteFence(const char *dbg);
+
+        sp<MediaCodecBuffer> alloc(const sp<AMessage> &format);
     };
 
     static const char *_asString(BufferInfo::Status s);
@@ -240,8 +244,9 @@
     uint32_t mFlags;
     uint32_t mQuirks;
     sp<IOMX> mOMX;
+    sp<IOMXNode> mOMXNode;
     sp<IBinder> mNodeBinder;
-    IOMX::node_id mNode;
+    int32_t mNodeGeneration;
     sp<MemoryDealer> mDealer[2];
 
     bool mUsingNativeWindow;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index be2835d..92a5593 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -34,7 +34,7 @@
 
 namespace android {
 
-struct ABuffer;
+class MediaCodecBuffer;
 struct PersistentSurface;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
@@ -88,7 +88,7 @@
     struct PortDescription : public RefBase {
         virtual size_t countBuffers() = 0;
         virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
-        virtual sp<ABuffer> bufferAt(size_t index) const = 0;
+        virtual sp<MediaCodecBuffer> bufferAt(size_t index) const = 0;
         virtual sp<NativeHandle> handleAt(size_t index) const { return NULL; };
         virtual sp<RefBase> memRefAt(size_t index) const { return NULL; }
 
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 8291cec..e3e5c2d 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -33,15 +33,16 @@
 struct AReplyToken;
 struct AString;
 struct CodecBase;
-struct IBatteryStats;
+class IBatteryStats;
 struct ICrypto;
+class MediaCodecBuffer;
 class IMemory;
 struct MemoryDealer;
 class IResourceManagerClient;
 class IResourceManagerService;
 struct PersistentSurface;
 struct SoftwareRenderer;
-struct Surface;
+class Surface;
 
 struct MediaCodec : public AHandler {
     enum ConfigureFlags {
@@ -149,14 +150,14 @@
     status_t getOutputFormat(sp<AMessage> *format) const;
     status_t getInputFormat(sp<AMessage> *format) const;
 
-    status_t getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const;
+    status_t getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
 
-    status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
-    status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;
+    status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
+    status_t getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
 
-    status_t getOutputBuffer(size_t index, sp<ABuffer> *buffer);
+    status_t getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
     status_t getOutputFormat(size_t index, sp<AMessage> *format);
-    status_t getInputBuffer(size_t index, sp<ABuffer> *buffer);
+    status_t getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
 
     status_t setSurface(const sp<Surface> &nativeWindow);
 
@@ -253,10 +254,10 @@
 
     struct BufferInfo {
         uint32_t mBufferID;
-        sp<ABuffer> mData;
+        sp<MediaCodecBuffer> mData;
         sp<NativeHandle> mNativeHandle;
         sp<RefBase> mMemRef;
-        sp<ABuffer> mEncryptedData;
+        sp<MediaCodecBuffer> mEncryptedData;
         sp<IMemory> mSharedEncryptedBuffer;
         sp<AMessage> mNotify;
         sp<AMessage> mFormat;
@@ -367,7 +368,7 @@
 
     status_t getBufferAndFormat(
             size_t portIndex, size_t index,
-            sp<ABuffer> *buffer, sp<AMessage> *format);
+            sp<MediaCodecBuffer> *buffer, sp<AMessage> *format);
 
     bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
     bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
@@ -389,7 +390,7 @@
 
     status_t onSetParameters(const sp<AMessage> &params);
 
-    status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer);
+    status_t amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> &buffer);
     void updateBatteryStat();
     bool isExecuting() const;
 
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 44dbde0..430bc16 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -115,7 +115,6 @@
 
     Vector<sp<MediaCodecInfo> > mCodecInfos;
     sp<MediaCodecInfo> mCurrentInfo;
-    sp<IOMX> mOMX;
 
     MediaCodecList();
     ~MediaCodecList();
diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h
index d0a572c..6aa87e8 100644
--- a/include/media/stagefright/MediaFilter.h
+++ b/include/media/stagefright/MediaFilter.h
@@ -21,7 +21,6 @@
 
 namespace android {
 
-struct ABuffer;
 struct GraphicBufferListener;
 struct MemoryDealer;
 struct SimpleFilter;
@@ -51,7 +50,7 @@
     struct PortDescription : public CodecBase::PortDescription {
         virtual size_t countBuffers();
         virtual IOMX::buffer_id bufferIDAt(size_t index) const;
-        virtual sp<ABuffer> bufferAt(size_t index) const;
+        virtual sp<MediaCodecBuffer> bufferAt(size_t index) const;
 
     protected:
         PortDescription();
@@ -60,9 +59,9 @@
         friend struct MediaFilter;
 
         Vector<IOMX::buffer_id> mBufferIDs;
-        Vector<sp<ABuffer> > mBuffers;
+        Vector<sp<MediaCodecBuffer> > mBuffers;
 
-        void addBuffer(IOMX::buffer_id id, const sp<ABuffer> &buffer);
+        void addBuffer(IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer);
 
         DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
     };
@@ -82,7 +81,7 @@
         int32_t mOutputFlags;
         Status mStatus;
 
-        sp<ABuffer> mData;
+        sp<MediaCodecBuffer> mData;
     };
 
     enum State {
diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h
index 2f14d06..6973405 100644
--- a/include/media/stagefright/OMXClient.h
+++ b/include/media/stagefright/OMXClient.h
@@ -18,10 +18,10 @@
 
 #define OMX_CLIENT_H_
 
-#include <media/IOMX.h>
-
 namespace android {
 
+class IOMX;
+
 class OMXClient {
 public:
     OMXClient();
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
index 61f9949..0fb5690 100644
--- a/include/media/stagefright/SkipCutBuffer.h
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -18,6 +18,7 @@
 
 #define SKIP_CUT_BUFFER_H_
 
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 
@@ -39,6 +40,7 @@
     // After this, the caller should continue processing the buffer as usual.
     void submit(MediaBuffer *buffer);
     void submit(const sp<ABuffer>& buffer);    // same as above, but with an ABuffer
+    void submit(const sp<MediaCodecBuffer>& buffer);    // same as above, but with an ABuffer
     void clear();
     size_t size(); // how many bytes are currently stored in the buffer
 
@@ -48,6 +50,8 @@
  private:
     void write(const char *src, size_t num);
     size_t read(char *dst, size_t num);
+    template <typename T>
+    void submitInternal(const sp<T>& buffer);
     int32_t mSkip;
     int32_t mFrontPadding;
     int32_t mBackPadding;
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
index cd97cc8..59314eb 100644
--- a/media/libaudiohal/StreamHalLocal.cpp
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -140,7 +140,7 @@
     return mStream->get_next_write_timestamp(mStream, timestamp);
 }
 
-status_t StreamOutHalLocal::setCallback(sp<StreamOutHalInterfaceCallback> callback) {
+status_t StreamOutHalLocal::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
     if (mStream->set_callback == NULL) return INVALID_OPERATION;
     status_t result = mStream->set_callback(mStream, StreamOutHalLocal::asyncCallback, this);
     if (result == OK) {
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/StreamHalLocal.h
index 7144e65..5e6f41a 100644
--- a/media/libaudiohal/StreamHalLocal.h
+++ b/media/libaudiohal/StreamHalLocal.h
@@ -92,7 +92,7 @@
     virtual status_t getNextWriteTimestamp(int64_t *timestamp);
 
     // Set the callback for notifying completion of non-blocking write and drain.
-    virtual status_t setCallback(sp<StreamOutHalInterfaceCallback> callback);
+    virtual status_t setCallback(wp<StreamOutHalInterfaceCallback> callback);
 
     // Returns whether pause and resume operations are supported.
     virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 59cb28c..81232bb 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -43,6 +43,7 @@
     IResourceManagerClient.cpp \
     IResourceManagerService.cpp \
     IStreamSource.cpp \
+    MediaCodecBuffer.cpp \
     MediaCodecInfo.cpp \
     MediaDefs.cpp \
     MediaUtils.cpp \
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 5e6ac36..e25e56c 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -33,7 +33,6 @@
 
 enum {
     CONNECT = IBinder::FIRST_CALL_TRANSACTION,
-    LIVES_LOCALLY,
     LIST_NODES,
     ALLOCATE_NODE,
     FREE_NODE,
@@ -72,14 +71,8 @@
         : BpInterface<IOMX>(impl) {
     }
 
-    virtual bool livesLocally(node_id node, pid_t pid) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(pid);
-        remote()->transact(LIVES_LOCALLY, data, &reply);
-
-        return reply.readInt32() != 0;
+    virtual bool livesLocally() {
+        return false;
     }
 
     virtual status_t listNodes(List<ComponentInfo> *list) {
@@ -106,8 +99,7 @@
 
     virtual status_t allocateNode(
             const char *name, const sp<IOMXObserver> &observer,
-            sp<IBinder> *nodeBinder,
-            node_id *node) {
+            sp<IBinder> *nodeBinder, sp<IOMXNode> *omxNode) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeCString(name);
@@ -116,261 +108,17 @@
 
         status_t err = reply.readInt32();
         if (err == OK) {
-            *node = (node_id)reply.readInt32();
+            *omxNode = IOMXNode::asInterface(reply.readStrongBinder());
             if (nodeBinder != NULL) {
                 *nodeBinder = remote();
             }
         } else {
-            *node = 0;
+            omxNode->clear();
         }
 
         return err;
     }
 
-    virtual status_t freeNode(node_id node) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        remote()->transact(FREE_NODE, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t sendCommand(
-            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(cmd);
-        data.writeInt32(param);
-        remote()->transact(SEND_COMMAND, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getParameter(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(index);
-        data.writeInt64(size);
-        data.write(params, size);
-        remote()->transact(GET_PARAMETER, data, &reply);
-
-        status_t err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        reply.read(params, size);
-
-        return OK;
-    }
-
-    virtual status_t setParameter(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(index);
-        data.writeInt64(size);
-        data.write(params, size);
-        remote()->transact(SET_PARAMETER, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getConfig(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(index);
-        data.writeInt64(size);
-        data.write(params, size);
-        remote()->transact(GET_CONFIG, data, &reply);
-
-        status_t err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        reply.read(params, size);
-
-        return OK;
-    }
-
-    virtual status_t setConfig(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(index);
-        data.writeInt64(size);
-        data.write(params, size);
-        remote()->transact(SET_CONFIG, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getState(
-            node_id node, OMX_STATETYPE* state) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        remote()->transact(GET_STATE, data, &reply);
-
-        *state = static_cast<OMX_STATETYPE>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t enableNativeBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.writeInt32((uint32_t)graphic);
-        data.writeInt32((uint32_t)enable);
-        remote()->transact(ENABLE_NATIVE_BUFFERS, data, &reply);
-
-        status_t err = reply.readInt32();
-        return err;
-    }
-
-    virtual status_t getGraphicBufferUsage(
-            node_id node, OMX_U32 port_index, OMX_U32* usage) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
-
-        status_t err = reply.readInt32();
-        *usage = reply.readInt32();
-        return err;
-    }
-
-    virtual status_t useBuffer(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.writeStrongBinder(IInterface::asBinder(params));
-        data.writeInt32(allottedSize);
-        remote()->transact(USE_BUFFER, data, &reply);
-
-        status_t err = reply.readInt32();
-        if (err != OK) {
-            *buffer = 0;
-
-            return err;
-        }
-
-        *buffer = (buffer_id)reply.readInt32();
-
-        return err;
-    }
-
-
-    virtual status_t useGraphicBuffer(
-            node_id node, OMX_U32 port_index,
-            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.write(*graphicBuffer);
-        remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
-
-        status_t err = reply.readInt32();
-        if (err != OK) {
-            *buffer = 0;
-
-            return err;
-        }
-
-        *buffer = (buffer_id)reply.readInt32();
-
-        return err;
-    }
-
-    virtual status_t updateGraphicBufferInMeta(
-            node_id node, OMX_U32 port_index,
-            const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.write(*graphicBuffer);
-        data.writeInt32((int32_t)buffer);
-        remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply);
-
-        status_t err = reply.readInt32();
-        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,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) {
-        Parcel data, reply;
-        status_t err;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.writeInt32(dataSpace);
-        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
-        if (err != OK) {
-            ALOGW("binder transaction failed: %d", err);
-            return err;
-        }
-
-        // read type even if createInputSurface failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
-        err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        *bufferProducer = IGraphicBufferProducer::asInterface(
-                reply.readStrongBinder());
-        *bufferSource = IGraphicBufferSource::asInterface(
-                reply.readStrongBinder());
-
-        return err;
-    }
-
     virtual status_t createPersistentInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer) {
@@ -395,16 +143,252 @@
 
         return err;
     }
+};
+
+class BpOMXNode : public BpInterface<IOMXNode> {
+public:
+    explicit BpOMXNode(const sp<IBinder> &impl)
+        : BpInterface<IOMXNode>(impl) {
+    }
+
+    virtual status_t freeNode() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        remote()->transact(FREE_NODE, data, &reply);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t sendCommand(
+            OMX_COMMANDTYPE cmd, OMX_S32 param) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(cmd);
+        data.writeInt32(param);
+        remote()->transact(SEND_COMMAND, data, &reply);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t getParameter(
+            OMX_INDEXTYPE index,
+            void *params, size_t size) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(index);
+        data.writeInt64(size);
+        data.write(params, size);
+        remote()->transact(GET_PARAMETER, data, &reply);
+
+        status_t err = reply.readInt32();
+        if (err != OK) {
+            return err;
+        }
+
+        reply.read(params, size);
+
+        return OK;
+    }
+
+    virtual status_t setParameter(
+            OMX_INDEXTYPE index,
+            const void *params, size_t size) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(index);
+        data.writeInt64(size);
+        data.write(params, size);
+        remote()->transact(SET_PARAMETER, data, &reply);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t getConfig(
+            OMX_INDEXTYPE index,
+            void *params, size_t size) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(index);
+        data.writeInt64(size);
+        data.write(params, size);
+        remote()->transact(GET_CONFIG, data, &reply);
+
+        status_t err = reply.readInt32();
+        if (err != OK) {
+            return err;
+        }
+
+        reply.read(params, size);
+
+        return OK;
+    }
+
+    virtual status_t setConfig(
+            OMX_INDEXTYPE index,
+            const void *params, size_t size) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(index);
+        data.writeInt64(size);
+        data.write(params, size);
+        remote()->transact(SET_CONFIG, data, &reply);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t getState(
+            OMX_STATETYPE* state) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        remote()->transact(GET_STATE, data, &reply);
+
+        *state = static_cast<OMX_STATETYPE>(reply.readInt32());
+        return reply.readInt32();
+    }
+
+    virtual status_t enableNativeBuffers(
+            OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        data.writeInt32((uint32_t)graphic);
+        data.writeInt32((uint32_t)enable);
+        remote()->transact(ENABLE_NATIVE_BUFFERS, data, &reply);
+
+        status_t err = reply.readInt32();
+        return err;
+    }
+
+    virtual status_t getGraphicBufferUsage(
+            OMX_U32 port_index, OMX_U32* usage) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
+
+        status_t err = reply.readInt32();
+        *usage = reply.readInt32();
+        return err;
+    }
+
+    virtual status_t useBuffer(
+            OMX_U32 port_index, const sp<IMemory> &params,
+            buffer_id *buffer, OMX_U32 allottedSize) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        data.writeStrongBinder(IInterface::asBinder(params));
+        data.writeInt32(allottedSize);
+        remote()->transact(USE_BUFFER, data, &reply);
+
+        status_t err = reply.readInt32();
+        if (err != OK) {
+            *buffer = 0;
+
+            return err;
+        }
+
+        *buffer = (buffer_id)reply.readInt32();
+
+        return err;
+    }
+
+
+    virtual status_t useGraphicBuffer(
+            OMX_U32 port_index,
+            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        data.write(*graphicBuffer);
+        remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
+
+        status_t err = reply.readInt32();
+        if (err != OK) {
+            *buffer = 0;
+
+            return err;
+        }
+
+        *buffer = (buffer_id)reply.readInt32();
+
+        return err;
+    }
+
+    virtual status_t updateGraphicBufferInMeta(
+            OMX_U32 port_index,
+            const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        data.write(*graphicBuffer);
+        data.writeInt32((int32_t)buffer);
+        remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply);
+
+        status_t err = reply.readInt32();
+        return err;
+    }
+
+    virtual status_t updateNativeHandleInMeta(
+            OMX_U32 port_index,
+            const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        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(
+            OMX_U32 port_index, android_dataspace dataSpace,
+            sp<IGraphicBufferProducer> *bufferProducer,
+            sp<IGraphicBufferSource> *bufferSource,
+            MetadataBufferType *type) {
+        Parcel data, reply;
+        status_t err;
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+        data.writeInt32(port_index);
+        data.writeInt32(dataSpace);
+        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
+        if (err != OK) {
+            ALOGW("binder transaction failed: %d", err);
+            return err;
+        }
+
+        // read type even if createInputSurface failed
+        int negotiatedType = reply.readInt32();
+        if (type != NULL) {
+            *type = (MetadataBufferType)negotiatedType;
+        }
+
+        err = reply.readInt32();
+        if (err != OK) {
+            return err;
+        }
+
+        *bufferProducer = IGraphicBufferProducer::asInterface(
+                reply.readStrongBinder());
+        *bufferSource = IGraphicBufferSource::asInterface(
+                reply.readStrongBinder());
+
+        return err;
+    }
 
     virtual status_t setInputSurface(
-            node_id node, OMX_U32 port_index,
+            OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer,
             sp<IGraphicBufferSource> *bufferSource,
             MetadataBufferType *type) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         status_t err;
-        data.writeInt32((int32_t)node);
         data.writeInt32(port_index);
         data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
 
@@ -433,10 +417,9 @@
     }
 
     virtual status_t storeMetaDataInBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
+            OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
         data.writeInt32((int32_t)enable);
         data.writeInt32(type == NULL ? kMetadataBufferTypeANWBuffer : *type);
@@ -453,11 +436,10 @@
     }
 
     virtual status_t prepareForAdaptivePlayback(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable,
+            OMX_U32 port_index, OMX_BOOL enable,
             OMX_U32 max_width, OMX_U32 max_height) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
         data.writeInt32((int32_t)enable);
         data.writeInt32(max_width);
@@ -469,11 +451,10 @@
     }
 
     virtual status_t configureVideoTunnelMode(
-            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+            OMX_U32 portIndex, OMX_BOOL tunneled,
             OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(portIndex);
         data.writeInt32((int32_t)tunneled);
         data.writeInt32(audioHwSync);
@@ -488,11 +469,10 @@
 
 
     virtual status_t allocateSecureBuffer(
-            node_id node, OMX_U32 port_index, size_t size,
+            OMX_U32 port_index, size_t size,
             buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
         data.writeInt64(size);
         remote()->transact(ALLOC_SECURE_BUFFER, data, &reply);
@@ -517,11 +497,10 @@
     }
 
     virtual status_t allocateBufferWithBackup(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+            OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer, OMX_U32 allottedSize) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
         data.writeStrongBinder(IInterface::asBinder(params));
         data.writeInt32(allottedSize);
@@ -540,10 +519,9 @@
     }
 
     virtual status_t freeBuffer(
-            node_id node, OMX_U32 port_index, buffer_id buffer) {
+            OMX_U32 port_index, buffer_id buffer) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(port_index);
         data.writeInt32((int32_t)buffer);
         remote()->transact(FREE_BUFFER, data, &reply);
@@ -551,10 +529,9 @@
         return reply.readInt32();
     }
 
-    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
+    virtual status_t fillBuffer(buffer_id buffer, int fenceFd) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32((int32_t)buffer);
         data.writeInt32(fenceFd >= 0);
         if (fenceFd >= 0) {
@@ -566,13 +543,11 @@
     }
 
     virtual status_t emptyBuffer(
-            node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32((int32_t)buffer);
         data.writeInt32(range_offset);
         data.writeInt32(range_length);
@@ -588,13 +563,11 @@
     }
 
     virtual status_t emptyGraphicBuffer(
-            node_id node,
             buffer_id buffer,
             const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
             OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32((int32_t)buffer);
         data.write(*graphicBuffer);
         data.writeInt32(flags);
@@ -610,12 +583,10 @@
     }
 
     virtual status_t getExtensionIndex(
-            node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeCString(parameter_name);
 
         remote()->transact(GET_EXTENSION_INDEX, data, &reply);
@@ -632,8 +603,7 @@
 
     virtual status_t dispatchMessage(const omx_message &msg) {
         Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)msg.node);
+        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
         data.writeInt32(msg.fenceFd >= 0);
         if (msg.fenceFd >= 0) {
             data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
@@ -648,6 +618,7 @@
 };
 
 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
+IMPLEMENT_META_INTERFACE(OMXNode, "android.hardware.IOMXNode");
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -660,16 +631,6 @@
 status_t BnOMX::onTransact(
     uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
     switch (code) {
-        case LIVES_LOCALLY:
-        {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
-            node_id node = (node_id)data.readInt32();
-            pid_t pid = (pid_t)data.readInt32();
-            reply->writeInt32(livesLocally(node, pid));
-
-            return OK;
-        }
-
         case LIST_NODES:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
@@ -708,40 +669,64 @@
                 return NO_ERROR;
             }
 
-            node_id node;
+            sp<IOMXNode> omxNode;
 
-            status_t err = allocateNode(name, observer,
-                    NULL /* nodeBinder */, &node);
+            status_t err = allocateNode(
+                    name, observer, NULL /* nodeBinder */, &omxNode);
+
             reply->writeInt32(err);
             if (err == OK) {
-                reply->writeInt32((int32_t)node);
+                reply->writeStrongBinder(IInterface::asBinder(omxNode));
             }
 
             return NO_ERROR;
         }
 
-        case FREE_NODE:
+        case CREATE_PERSISTENT_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
 
-            node_id node = (node_id)data.readInt32();
+            sp<IGraphicBufferProducer> bufferProducer;
+            sp<IGraphicBufferConsumer> bufferConsumer;
+            status_t err = createPersistentInputSurface(
+                    &bufferProducer, &bufferConsumer);
 
-            reply->writeInt32(freeNode(node));
+            reply->writeInt32(err);
+
+            if (err == OK) {
+                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
+                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
+            }
+
+            return NO_ERROR;
+        }
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+status_t BnOMXNode::onTransact(
+    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch (code) {
+        case FREE_NODE:
+        {
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+
+            reply->writeInt32(freeNode());
 
             return NO_ERROR;
         }
 
         case SEND_COMMAND:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
-
-            node_id node = (node_id)data.readInt32();
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
             OMX_COMMANDTYPE cmd =
                 static_cast<OMX_COMMANDTYPE>(data.readInt32());
 
             OMX_S32 param = data.readInt32();
-            reply->writeInt32(sendCommand(node, cmd, param));
+            reply->writeInt32(sendCommand(cmd, param));
 
             return NO_ERROR;
         }
@@ -751,9 +736,8 @@
         case GET_CONFIG:
         case SET_CONFIG:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
             size_t size = data.readInt64();
@@ -800,16 +784,16 @@
                             } else {
                                 switch (code) {
                                     case GET_PARAMETER:
-                                        err = getParameter(node, index, params, size);
+                                        err = getParameter(index, params, size);
                                         break;
                                     case SET_PARAMETER:
-                                        err = setParameter(node, index, params, size);
+                                        err = setParameter(index, params, size);
                                         break;
                                     case GET_CONFIG:
-                                        err = getConfig(node, index, params, size);
+                                        err = getConfig(index, params, size);
                                         break;
                                     case SET_CONFIG:
-                                        err = setConfig(node, index, params, size);
+                                        err = setConfig(index, params, size);
                                         break;
                                     default:
                                         TRESPASS();
@@ -838,12 +822,11 @@
 
         case GET_STATE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_STATETYPE state = OMX_StateInvalid;
 
-            status_t err = getState(node, &state);
+            status_t err = getState(&state);
             reply->writeInt32(state);
             reply->writeInt32(err);
 
@@ -852,14 +835,13 @@
 
         case ENABLE_NATIVE_BUFFERS:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             OMX_BOOL graphic = (OMX_BOOL)data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();
 
-            status_t err = enableNativeBuffers(node, port_index, graphic, enable);
+            status_t err = enableNativeBuffers(port_index, graphic, enable);
             reply->writeInt32(err);
 
             return NO_ERROR;
@@ -867,13 +849,12 @@
 
         case GET_GRAPHIC_BUFFER_USAGE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
 
             OMX_U32 usage = 0;
-            status_t err = getGraphicBufferUsage(node, port_index, &usage);
+            status_t err = getGraphicBufferUsage(port_index, &usage);
             reply->writeInt32(err);
             reply->writeInt32(usage);
 
@@ -882,9 +863,8 @@
 
         case USE_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             sp<IMemory> params =
                 interface_cast<IMemory>(data.readStrongBinder());
@@ -897,7 +877,7 @@
             }
 
             buffer_id buffer;
-            status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
+            status_t err = useBuffer(port_index, params, &buffer, allottedSize);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -909,16 +889,15 @@
 
         case USE_GRAPHIC_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
             data.read(*graphicBuffer);
 
             buffer_id buffer;
             status_t err = useGraphicBuffer(
-                    node, port_index, graphicBuffer, &buffer);
+                    port_index, graphicBuffer, &buffer);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -930,16 +909,15 @@
 
         case UPDATE_GRAPHIC_BUFFER_IN_META:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
             data.read(*graphicBuffer);
             buffer_id buffer = (buffer_id)data.readInt32();
 
             status_t err = updateGraphicBufferInMeta(
-                    node, port_index, graphicBuffer, buffer);
+                    port_index, graphicBuffer, buffer);
             reply->writeInt32(err);
 
             return NO_ERROR;
@@ -947,9 +925,8 @@
 
         case UPDATE_NATIVE_HANDLE_IN_META:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             native_handle *handle = NULL;
             if (data.readInt32()) {
@@ -958,7 +935,7 @@
             buffer_id buffer = (buffer_id)data.readInt32();
 
             status_t err = updateNativeHandleInMeta(
-                    node, port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
+                    port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
             reply->writeInt32(err);
 
             return NO_ERROR;
@@ -966,9 +943,8 @@
 
         case CREATE_INPUT_SURFACE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             android_dataspace dataSpace = (android_dataspace)data.readInt32();
 
@@ -976,7 +952,7 @@
             sp<IGraphicBufferSource> bufferSource;
             MetadataBufferType type = kMetadataBufferTypeInvalid;
             status_t err = createInputSurface(
-                    node, port_index, dataSpace, &bufferProducer, &bufferSource, &type);
+                    port_index, dataSpace, &bufferProducer, &bufferSource, &type);
 
             if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                 android_errorWriteLog(0x534e4554, "26324358");
@@ -993,30 +969,10 @@
             return NO_ERROR;
         }
 
-        case CREATE_PERSISTENT_INPUT_SURFACE:
-        {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
-
-            sp<IGraphicBufferProducer> bufferProducer;
-            sp<IGraphicBufferConsumer> bufferConsumer;
-            status_t err = createPersistentInputSurface(
-                    &bufferProducer, &bufferConsumer);
-
-            reply->writeInt32(err);
-
-            if (err == OK) {
-                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
-                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
-            }
-
-            return NO_ERROR;
-        }
-
         case SET_INPUT_SURFACE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
 
             sp<IGraphicBufferConsumer> bufferConsumer =
@@ -1029,7 +985,7 @@
             if (bufferConsumer == NULL) {
                 ALOGE("b/26392700");
             } else {
-                err = setInputSurface(node, port_index, bufferConsumer, &bufferSource, &type);
+                err = setInputSurface(port_index, bufferConsumer, &bufferSource, &type);
 
                 if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                    android_errorWriteLog(0x534e4554, "26324358");
@@ -1046,14 +1002,13 @@
 
         case STORE_META_DATA_IN_BUFFERS:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();
 
             MetadataBufferType type = (MetadataBufferType)data.readInt32();
-            status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
+            status_t err = storeMetaDataInBuffers(port_index, enable, &type);
 
             reply->writeInt32(type);
             reply->writeInt32(err);
@@ -1063,16 +1018,15 @@
 
         case PREPARE_FOR_ADAPTIVE_PLAYBACK:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();
             OMX_U32 max_width = data.readInt32();
             OMX_U32 max_height = data.readInt32();
 
             status_t err = prepareForAdaptivePlayback(
-                    node, port_index, enable, max_width, max_height);
+                    port_index, enable, max_width, max_height);
             reply->writeInt32(err);
 
             return NO_ERROR;
@@ -1080,16 +1034,15 @@
 
         case CONFIGURE_VIDEO_TUNNEL_MODE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
             OMX_U32 audio_hw_sync = data.readInt32();
 
             native_handle_t *sideband_handle = NULL;
             status_t err = configureVideoTunnelMode(
-                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
+                    port_index, tunneled, audio_hw_sync, &sideband_handle);
             reply->writeInt32(err);
             if(err == OK){
                 reply->writeNativeHandle(sideband_handle);
@@ -1100,11 +1053,10 @@
 
         case ALLOC_SECURE_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
-            if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
+            if (!isSecure() || port_index != 0 /* kPortIndexInput */) {
                 ALOGE("b/24310423");
                 reply->writeInt32(INVALID_OPERATION);
                 return NO_ERROR;
@@ -1116,7 +1068,7 @@
             void *buffer_data = NULL;
             sp<NativeHandle> native_handle;
             status_t err = allocateSecureBuffer(
-                    node, port_index, size, &buffer, &buffer_data, &native_handle);
+                    port_index, size, &buffer, &buffer_data, &native_handle);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -1132,9 +1084,8 @@
 
         case ALLOC_BUFFER_WITH_BACKUP:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             sp<IMemory> params =
                 interface_cast<IMemory>(data.readStrongBinder());
@@ -1148,7 +1099,7 @@
 
             buffer_id buffer;
             status_t err = allocateBufferWithBackup(
-                    node, port_index, params, &buffer, allottedSize);
+                    port_index, params, &buffer, allottedSize);
 
             reply->writeInt32(err);
 
@@ -1161,34 +1112,31 @@
 
         case FREE_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
             buffer_id buffer = (buffer_id)data.readInt32();
-            reply->writeInt32(freeBuffer(node, port_index, buffer));
+            reply->writeInt32(freeBuffer(port_index, buffer));
 
             return NO_ERROR;
         }
 
         case FILL_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             buffer_id buffer = (buffer_id)data.readInt32();
             bool haveFence = data.readInt32();
             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
-            reply->writeInt32(fillBuffer(node, buffer, fenceFd));
+            reply->writeInt32(fillBuffer(buffer, fenceFd));
 
             return NO_ERROR;
         }
 
         case EMPTY_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             buffer_id buffer = (buffer_id)data.readInt32();
             OMX_U32 range_offset = data.readInt32();
             OMX_U32 range_length = data.readInt32();
@@ -1197,16 +1145,15 @@
             bool haveFence = data.readInt32();
             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
             reply->writeInt32(emptyBuffer(
-                    node, buffer, range_offset, range_length, flags, timestamp, fenceFd));
+                    buffer, range_offset, range_length, flags, timestamp, fenceFd));
 
             return NO_ERROR;
         }
 
         case EMPTY_GRAPHIC_BUFFER:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             buffer_id buffer = (buffer_id)data.readInt32();
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
             data.read(*graphicBuffer);
@@ -1216,7 +1163,7 @@
             bool haveFence = data.readInt32();
             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
             reply->writeInt32(emptyGraphicBuffer(
-                    node, buffer, graphicBuffer, flags,
+                    buffer, graphicBuffer, flags,
                     timestamp, origTimestamp, fenceFd));
 
             return NO_ERROR;
@@ -1224,9 +1171,8 @@
 
         case GET_EXTENSION_INDEX:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            node_id node = (node_id)data.readInt32();
             const char *parameter_name = data.readCString();
 
             if (parameter_name == NULL) {
@@ -1236,7 +1182,7 @@
             }
 
             OMX_INDEXTYPE index;
-            status_t err = getExtensionIndex(node, parameter_name, &index);
+            status_t err = getExtensionIndex(parameter_name, &index);
 
             reply->writeInt32(err);
 
@@ -1249,9 +1195,8 @@
 
         case DISPATCH_MESSAGE:
         {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
+            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
             omx_message msg;
-            msg.node = data.readInt32();
             int haveFence = data.readInt32();
             msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
             msg.type = (typeof(msg.type))data.readInt32();
@@ -1281,14 +1226,12 @@
     virtual void onMessages(const std::list<omx_message> &messages) {
         Parcel data, reply;
         std::list<omx_message>::const_iterator it = messages.cbegin();
-        bool first = true;
+        if (messages.empty()) {
+            return;
+        }
+        data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
         while (it != messages.cend()) {
             const omx_message &msg = *it++;
-            if (first) {
-                data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
-                data.writeInt32(msg.node);
-                first = false;
-            }
             data.writeInt32(msg.fenceFd >= 0);
             if (msg.fenceFd >= 0) {
                 data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
@@ -1297,10 +1240,8 @@
             data.write(&msg.u, sizeof(msg.u));
             ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
         }
-        if (!first) {
-            data.writeInt32(-1); // mark end
-            remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
-        }
+        data.writeInt32(-1); // mark end
+        remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -1312,7 +1253,6 @@
         case OBSERVER_ON_MSG:
         {
             CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
-            IOMX::node_id node = data.readInt32();
             std::list<omx_message> messages;
             status_t err = FAILED_TRANSACTION; // must receive at least one message
             do {
@@ -1321,7 +1261,6 @@
                     break;
                 }
                 omx_message msg;
-                msg.node = node;
                 msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
                 msg.type = (typeof(msg.type))data.readInt32();
                 err = data.read(&msg.u, sizeof(msg.u));
diff --git a/media/libmedia/MediaCodecBuffer.cpp b/media/libmedia/MediaCodecBuffer.cpp
new file mode 100644
index 0000000..2d255be
--- /dev/null
+++ b/media/libmedia/MediaCodecBuffer.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaCodecBuffer"
+#include <utils/Log.h>
+
+#include <media/MediaCodecBuffer.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/MediaBufferBase.h>
+
+namespace android {
+
+MediaCodecBuffer::MediaCodecBuffer(const sp<AMessage> &format, const sp<ABuffer> &buffer)
+    : mMeta(new AMessage),
+      mFormat(format),
+      mBuffer(buffer),
+      mMediaBufferBase(nullptr) {
+}
+
+// ABuffer-like interface
+uint8_t *MediaCodecBuffer::base() {
+    return mBuffer->base();
+}
+
+uint8_t *MediaCodecBuffer::data() {
+    return mBuffer->data();
+}
+
+size_t MediaCodecBuffer::capacity() const {
+    return mBuffer->capacity();
+}
+
+size_t MediaCodecBuffer::size() const {
+    return mBuffer->size();
+}
+
+size_t MediaCodecBuffer::offset() const {
+    return mBuffer->offset();
+}
+
+status_t MediaCodecBuffer::setRange(size_t offset, size_t size) {
+    mBuffer->setRange(offset, size);
+    return OK;
+}
+
+MediaBufferBase *MediaCodecBuffer::getMediaBufferBase() {
+    if (mMediaBufferBase != NULL) {
+        mMediaBufferBase->add_ref();
+    }
+    return mMediaBufferBase;
+}
+
+void MediaCodecBuffer::setMediaBufferBase(MediaBufferBase *mediaBuffer) {
+    if (mMediaBufferBase != NULL) {
+        mMediaBufferBase->release();
+    }
+    mMediaBufferBase = mediaBuffer;
+}
+
+sp<AMessage> MediaCodecBuffer::meta() {
+    return mMeta;
+}
+
+sp<AMessage> MediaCodecBuffer::format() {
+    return mFormat;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 95c91d1..d45dbcd 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -684,10 +684,18 @@
 
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("media.extractor"));
+    if (binder == NULL) {
+        ALOGE("extractor service not available");
+        return NULL;
+    }
     mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
     binder->linkToDeath(mExtractorDeathListener);
 
     binder = sm->getService(String16("media.codec"));
+    if (binder == NULL) {
+        ALOGE("codec service not available");
+        return NULL;
+    }
     mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
     binder->linkToDeath(mCodecDeathListener);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e370c2b..ac49993 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -39,6 +39,7 @@
 
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
+#include <media/MediaCodecBuffer.h>
 
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -1657,12 +1658,12 @@
 
     // allocate buffers to decrypt widevine source buffers
     if (!audio && (mSourceFlags & Source::FLAG_SECURE)) {
-        Vector<sp<ABuffer> > inputBufs;
+        Vector<sp<MediaCodecBuffer> > inputBufs;
         CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK);
 
         Vector<MediaBuffer *> mediaBufs;
         for (size_t i = 0; i < inputBufs.size(); i++) {
-            const sp<ABuffer> &buffer = inputBufs[i];
+            const sp<MediaCodecBuffer> &buffer = inputBufs[i];
             MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size());
             mediaBufs.push(mbuf);
         }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index cf38efc..822f154 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -28,6 +28,7 @@
 
 #include <cutils/properties.h>
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -417,7 +418,7 @@
 }
 
 void NuPlayer::Decoder::onGetInputBuffers(
-        Vector<sp<ABuffer> > *dstBuffers) {
+        Vector<sp<MediaCodecBuffer> > *dstBuffers) {
     CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers));
 }
 
@@ -561,7 +562,7 @@
         return false;
     }
 
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
     mCodec->getInputBuffer(index, &buffer);
 
     if (buffer == NULL) {
@@ -628,7 +629,7 @@
         int64_t timeUs,
         int32_t flags) {
 //    CHECK_LT(bufferIx, mOutputBuffers.size());
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
     mCodec->getOutputBuffer(index, &buffer);
 
     if (index >= mOutputBuffers.size()) {
@@ -865,10 +866,11 @@
     size_t bufferIx;
     CHECK(msg->findSize("buffer-ix", &bufferIx));
     CHECK_LT(bufferIx, mInputBuffers.size());
-    sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
+    sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
 
     sp<ABuffer> buffer;
     bool hasBuffer = msg->findBuffer("buffer", &buffer);
+    bool needsCopy = true;
 
     // handle widevine classic source - that fills an arbitrary input buffer
     MediaBuffer *mediaBuffer = NULL;
@@ -878,7 +880,7 @@
             // likely filled another buffer than we requested: adjust buffer index
             size_t ix;
             for (ix = 0; ix < mInputBuffers.size(); ix++) {
-                const sp<ABuffer> &buf = mInputBuffers[ix];
+                const sp<MediaCodecBuffer> &buf = mInputBuffers[ix];
                 if (buf->data() == mediaBuffer->data()) {
                     // all input buffers are dequeued on start, hence the check
                     if (!mInputBufferIsDequeued[ix]) {
@@ -891,11 +893,12 @@
                     // TRICKY: need buffer for the metadata, so instead, set
                     // codecBuffer to the same (though incorrect) buffer to
                     // avoid a memcpy into the codecBuffer
-                    codecBuffer = buffer;
+                    codecBuffer = new MediaCodecBuffer(codecBuffer->format(), buffer);
                     codecBuffer->setRange(
                             mediaBuffer->range_offset(),
                             mediaBuffer->range_length());
                     bufferIx = ix;
+                    needsCopy = false;
                     break;
                 }
             }
@@ -955,7 +958,7 @@
         }
 
         // copy into codec buffer
-        if (buffer != codecBuffer) {
+        if (needsCopy) {
             if (buffer->size() > codecBuffer->capacity()) {
                 handleError(ERROR_BUFFER_TOO_SMALL);
                 mDequeuedInputBuffers.push_back(bufferIx);
@@ -998,7 +1001,7 @@
 
     if (!mIsAudio) {
         int64_t timeUs;
-        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
+        sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
         buffer->meta()->findInt64("timeUs", &timeUs);
 
         if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 0c619ed..8186862 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -23,6 +23,8 @@
 
 namespace android {
 
+class MediaCodecBuffer;
+
 struct NuPlayer::Decoder : public DecoderBase {
     Decoder(const sp<AMessage> &notify,
             const sp<Source> &source,
@@ -44,7 +46,7 @@
     virtual void onConfigure(const sp<AMessage> &format);
     virtual void onSetParameters(const sp<AMessage> &params);
     virtual void onSetRenderer(const sp<Renderer> &renderer);
-    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
+    virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers);
     virtual void onResume(bool notifyComplete);
     virtual void onFlush();
     virtual void onShutdown(bool notifyComplete);
@@ -74,8 +76,8 @@
 
     List<sp<AMessage> > mPendingInputMessages;
 
-    Vector<sp<ABuffer> > mInputBuffers;
-    Vector<sp<ABuffer> > mOutputBuffers;
+    Vector<sp<MediaCodecBuffer> > mInputBuffers;
+    Vector<sp<MediaCodecBuffer> > mOutputBuffers;
     Vector<sp<ABuffer> > mCSDsForCurrentFormat;
     Vector<sp<ABuffer> > mCSDsToSubmit;
     Vector<bool> mInputBufferIsDequeued;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
index 04bb61c..9c007ae 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -23,6 +23,7 @@
 
 #include "NuPlayerRenderer.h"
 
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -91,7 +92,7 @@
     PostAndAwaitResponse(msg, &response);
 }
 
-status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
     sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, this);
     msg->setPointer("buffers", buffers);
 
@@ -170,7 +171,7 @@
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
-            Vector<sp<ABuffer> > *dstBuffers;
+            Vector<sp<MediaCodecBuffer> > *dstBuffers;
             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
 
             onGetInputBuffers(dstBuffers);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
index 9966144..6f4ead6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -27,6 +27,7 @@
 struct ABuffer;
 struct MediaCodec;
 class MediaBuffer;
+class MediaCodecBuffer;
 class Surface;
 
 struct NuPlayer::DecoderBase : public AHandler {
@@ -42,7 +43,7 @@
     void setRenderer(const sp<Renderer> &renderer);
     virtual status_t setVideoSurface(const sp<Surface> &) { return INVALID_OPERATION; }
 
-    status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
+    status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers) const;
     void signalFlush();
     void signalResume(bool notifyComplete);
     void initiateShutdown();
@@ -70,7 +71,7 @@
     virtual void onConfigure(const sp<AMessage> &format) = 0;
     virtual void onSetParameters(const sp<AMessage> &params) = 0;
     virtual void onSetRenderer(const sp<Renderer> &renderer) = 0;
-    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers) = 0;
+    virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers) = 0;
     virtual void onResume(bool notifyComplete) = 0;
     virtual void onFlush() = 0;
     virtual void onShutdown(bool notifyComplete) = 0;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index f224635..ffeea86 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -25,6 +25,7 @@
 #include "NuPlayerSource.h"
 
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -93,7 +94,7 @@
 }
 
 void NuPlayer::DecoderPassThrough::onGetInputBuffers(
-        Vector<sp<ABuffer> > * /* dstBuffers */) {
+        Vector<sp<MediaCodecBuffer> > * /* dstBuffers */) {
     ALOGE("onGetInputBuffers() called unexpectedly");
 }
 
@@ -289,8 +290,12 @@
         return;
     }
 
-    sp<ABuffer> buffer;
-    bool hasBuffer = msg->findBuffer("buffer", &buffer);
+    sp<RefBase> obj;
+    bool hasBuffer = msg->findObject("buffer", &obj);
+    sp<MediaCodecBuffer> buffer;
+    if (hasBuffer) {
+        buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    }
     if (buffer == NULL) {
         int32_t streamErr = ERROR_END_OF_STREAM;
         CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index 5850efa..9af25ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -38,7 +38,7 @@
     virtual void onConfigure(const sp<AMessage> &format);
     virtual void onSetParameters(const sp<AMessage> &params);
     virtual void onSetRenderer(const sp<Renderer> &renderer);
-    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
+    virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers);
     virtual void onResume(bool notifyComplete);
     virtual void onFlush();
     virtual void onShutdown(bool notifyComplete);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index b742762..b78bdfb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -21,7 +21,6 @@
 #include "NuPlayerRenderer.h"
 #include <algorithm>
 #include <cutils/properties.h>
-#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -31,6 +30,7 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/VideoFrameScheduler.h>
+#include <media/MediaCodecBuffer.h>
 
 #include <inttypes.h>
 
@@ -156,12 +156,12 @@
 
 void NuPlayer::Renderer::queueBuffer(
         bool audio,
-        const sp<ABuffer> &buffer,
+        const sp<MediaCodecBuffer> &buffer,
         const sp<AMessage> &notifyConsumed) {
     sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
     msg->setInt32("queueGeneration", getQueueGeneration(audio));
     msg->setInt32("audio", static_cast<int32_t>(audio));
-    msg->setBuffer("buffer", buffer);
+    msg->setObject("buffer", buffer);
     msg->setMessage("notifyConsumed", notifyConsumed);
     msg->post();
 }
@@ -1368,8 +1368,9 @@
         }
     }
 
-    sp<ABuffer> buffer;
-    CHECK(msg->findBuffer("buffer", &buffer));
+    sp<RefBase> obj;
+    CHECK(msg->findObject("buffer", &obj));
+    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
 
     sp<AMessage> notifyConsumed;
     CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
@@ -1395,8 +1396,8 @@
         return;
     }
 
-    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
-    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
+    sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
+    sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
 
     if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
         // EOS signalled on either queue.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index fe7f8fa..0bd3aa1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -25,9 +25,9 @@
 
 namespace android {
 
-struct ABuffer;
 class  AWakeLock;
 struct MediaClock;
+class MediaCodecBuffer;
 struct VideoFrameScheduler;
 
 struct NuPlayer::Renderer : public AHandler {
@@ -46,7 +46,7 @@
 
     void queueBuffer(
             bool audio,
-            const sp<ABuffer> &buffer,
+            const sp<MediaCodecBuffer> &buffer,
             const sp<AMessage> &notifyConsumed);
 
     void queueEOS(bool audio, status_t finalResult);
@@ -125,7 +125,7 @@
     };
 
     struct QueueEntry {
-        sp<ABuffer> mBuffer;
+        sp<MediaCodecBuffer> mBuffer;
         sp<AMessage> mNotifyConsumed;
         size_t mOffset;
         status_t mFinalResult;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 62ebb3f..162ae22 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -53,6 +53,7 @@
 
 #include "include/avc_utils.h"
 #include "include/DataConverter.h"
+#include "include/SharedMemoryBuffer.h"
 #include "omx/OMXUtils.h"
 
 #include <android/IGraphicBufferSource.h>
@@ -155,15 +156,10 @@
         }
 
         sp<AMessage> notify = mNotify->dup();
-        bool first = true;
         sp<MessageList> msgList = new MessageList();
         for (std::list<omx_message>::const_iterator it = messages.cbegin();
               it != messages.cend(); ++it) {
             const omx_message &omx_msg = *it;
-            if (first) {
-                notify->setInt32("node", omx_msg.node);
-                first = false;
-            }
 
             sp<AMessage> msg = new AMessage;
             msg->setInt32("type", omx_msg.type);
@@ -515,7 +511,7 @@
 ACodec::ACodec()
     : mSampleRate(0),
       mQuirks(0),
-      mNode(0),
+      mNodeGeneration(0),
       mUsingNativeWindow(false),
       mNativeWindowUsageBits(0),
       mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
@@ -812,8 +808,8 @@
         InitOMXParams(&def);
         def.nPortIndex = portIndex;
 
-        err = mOMX->getParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->getParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         if (err == OK) {
             MetadataBufferType type =
@@ -872,6 +868,7 @@
             size_t totalSize = def.nBufferCountActual * (alignedSize + alignedConvSize);
             mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
 
+            const sp<AMessage> &format = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
             for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
                 sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
                 if (mem == NULL || mem->pointer() == NULL) {
@@ -894,8 +891,8 @@
 
                     void *ptr = NULL;
                     sp<NativeHandle> native_handle;
-                    err = mOMX->allocateSecureBuffer(
-                            mNode, portIndex, bufSize, &info.mBufferID,
+                    err = mOMXNode->allocateSecureBuffer(
+                            portIndex, bufSize, &info.mBufferID,
                             &ptr, &native_handle);
 
                     // TRICKY: this representation is unorthodox, but ACodec requires
@@ -908,19 +905,19 @@
                     // because Widevine source only receives these base addresses.
                     const native_handle_t *native_handle_ptr =
                         native_handle == NULL ? NULL : native_handle->handle();
-                    info.mData = new ABuffer(
-                            ptr != NULL ? ptr : (void *)native_handle_ptr, bufSize);
+                    info.mData = new MediaCodecBuffer(format,
+                            new ABuffer(ptr != NULL ? ptr : (void *)native_handle_ptr, bufSize));
                     info.mNativeHandle = native_handle;
                     info.mCodecData = info.mData;
                 } else if (mQuirks & requiresAllocateBufferBit) {
-                    err = mOMX->allocateBufferWithBackup(
-                            mNode, portIndex, mem, &info.mBufferID, allottedSize);
+                    err = mOMXNode->allocateBufferWithBackup(
+                            portIndex, mem, &info.mBufferID, allottedSize);
                 } else {
-                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
+                    err = mOMXNode->useBuffer(portIndex, mem, &info.mBufferID, allottedSize);
                 }
 
                 if (mem != NULL) {
-                    info.mCodecData = new ABuffer(mem->pointer(), bufSize);
+                    info.mCodecData = new SharedMemoryBuffer(format, mem);
                     info.mCodecRef = mem;
 
                     if (type == kMetadataBufferTypeANWBuffer) {
@@ -935,7 +932,7 @@
                         if (mem == NULL|| mem->pointer() == NULL) {
                             return NO_MEMORY;
                         }
-                        info.mData = new ABuffer(mem->pointer(), conversionBufferSize);
+                        info.mData = new SharedMemoryBuffer(format, mem);
                         info.mMemRef = mem;
                     } else {
                         info.mData = info.mCodecData;
@@ -977,15 +974,15 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
     }
 
     OMX_U32 usage = 0;
-    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
+    err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
     if (err != 0) {
         ALOGW("querying usage flags from OMX IL component failed: %d", err);
         // XXX: Currently this error is logged, but not fatal.
@@ -1022,8 +1019,8 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err == OK) {
         err = setupNativeWindowSizeFormatAndUsage(
@@ -1040,8 +1037,8 @@
     if (mTunneled) {
         ALOGV("Tunneled Playback: skipping native window buffer allocation.");
         def.nBufferCountActual = 0;
-        err = mOMX->setParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->setParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         *minUndequeuedBuffers = 0;
         *bufferCount = 0;
@@ -1076,8 +1073,8 @@
         OMX_U32 newBufferCount =
             def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
         def.nBufferCountActual = newBufferCount;
-        err = mOMX->setParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->setParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         if (err == OK) {
             *minUndequeuedBuffers += extraBuffers;
@@ -1139,14 +1136,12 @@
         info.mFenceFd = fenceFd;
         info.mIsReadFence = false;
         info.mRenderInfo = NULL;
-        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
-        info.mCodecData = info.mData;
         info.mGraphicBuffer = graphicBuffer;
         mBuffers[kPortIndexOutput].push(info);
 
         IOMX::buffer_id bufferId;
-        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
-                &bufferId);
+        err = mOMXNode->useGraphicBuffer(
+                kPortIndexOutput, graphicBuffer, &bufferId);
         if (err != 0) {
             ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
                  "%d", i, err);
@@ -1225,14 +1220,14 @@
         if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
             ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
         }
-        info.mData = new ABuffer(mem->pointer(), mem->size());
+        info.mData = new SharedMemoryBuffer(mOutputFormat, mem);
         info.mMemRef = mem;
         info.mCodecData = info.mData;
         info.mCodecRef = mem;
 
         // we use useBuffer for metadata regardless of quirks
-        err = mOMX->useBuffer(
-                mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
+        err = mOMXNode->useBuffer(
+                kPortIndexOutput, mem, &info.mBufferID, mem->size());
         mBuffers[kPortIndexOutput].push(info);
 
         ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
@@ -1261,8 +1256,8 @@
             }
 
             sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
-            mOMX->updateGraphicBufferInMeta(
-                    mNode, kPortIndexOutput, graphicBuffer, info->mBufferID);
+            mOMXNode->updateGraphicBufferInMeta(
+                    kPortIndexOutput, graphicBuffer, info->mBufferID);
             info->mStatus = BufferInfo::OWNED_BY_US;
             info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy");
             info->mGraphicBuffer = graphicBuffer;
@@ -1301,7 +1296,7 @@
 
     --mMetadataBuffersToSubmit;
     info->checkWriteFence("submitOutputMetadataBuffer");
-    status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd);
+    status_t err = mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
     info->mFenceFd = -1;
     if (err == OK) {
         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
@@ -1499,26 +1494,25 @@
     mRenderTracker.untrackFrame(oldest->mRenderInfo);
     oldest->mRenderInfo = NULL;
 
-    mOMX->updateGraphicBufferInMeta(
-            mNode, kPortIndexOutput, oldest->mGraphicBuffer,
-            oldest->mBufferID);
+    mOMXNode->updateGraphicBufferInMeta(
+            kPortIndexOutput, oldest->mGraphicBuffer, oldest->mBufferID);
 
     if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
         VideoGrallocMetadata *grallocMeta =
-            reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
+            reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->data());
         ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
                 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
                 mDequeueCounter - oldest->mDequeuedAt,
                 (void *)(uintptr_t)grallocMeta->pHandle,
-                oldest->mGraphicBuffer->handle, oldest->mData->base());
+                oldest->mGraphicBuffer->handle, oldest->mData->data());
     } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
         VideoNativeMetadata *nativeMeta =
-            reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
+            reinterpret_cast<VideoNativeMetadata *>(oldest->mData->data());
         ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
                 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
                 mDequeueCounter - oldest->mDequeuedAt,
                 (void *)(uintptr_t)nativeMeta->pBuffer,
-                oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
+                oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->data());
     }
 
     updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
@@ -1585,7 +1579,7 @@
             // fall through
 
         case BufferInfo::OWNED_BY_NATIVE_WINDOW:
-            err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
+            err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
             break;
 
         default:
@@ -1603,7 +1597,7 @@
         info->mRenderInfo = NULL;
     }
 
-    // remove buffer even if mOMX->freeBuffer fails
+    // remove buffer even if mOMXNode->freeBuffer fails
     mBuffers[portIndex].removeAt(i);
     return err;
 }
@@ -1631,7 +1625,7 @@
     if (role == NULL) {
         return BAD_VALUE;
     }
-    status_t err = SetComponentRole(mOMX, mNode, role);
+    status_t err = SetComponentRole(mOMXNode, role);
     if (err != OK) {
         ALOGW("[%s] Failed to set standard component role '%s'.",
              mComponentName.c_str(), role);
@@ -1681,8 +1675,8 @@
             && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
             && storeMeta != kMetadataBufferTypeInvalid) {
         mInputMetadataType = (MetadataBufferType)storeMeta;
-        err = mOMX->storeMetaDataInBuffers(
-                mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
+        err = mOMXNode->storeMetaDataInBuffers(
+                kPortIndexInput, OMX_TRUE, &mInputMetadataType);
         if (err != OK) {
             ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
                     mComponentName.c_str(), err);
@@ -1695,8 +1689,8 @@
         }
 
         uint32_t usageBits;
-        if (mOMX->getParameter(
-                mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+        if (mOMXNode->getParameter(
+                (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
                 &usageBits, sizeof(usageBits)) == OK) {
             inputFormat->setInt32(
                     "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
@@ -1708,18 +1702,15 @@
             && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
             && prependSPSPPS != 0) {
         OMX_INDEXTYPE index;
-        err = mOMX->getExtensionIndex(
-                mNode,
-                "OMX.google.android.index.prependSPSPPSToIDRFrames",
-                &index);
+        err = mOMXNode->getExtensionIndex(
+                "OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
 
         if (err == OK) {
             PrependSPSPPSToIDRFramesParams params;
             InitOMXParams(&params);
             params.bEnable = OMX_TRUE;
 
-            err = mOMX->setParameter(
-                    mNode, index, &params, sizeof(params));
+            err = mOMXNode->setParameter(index, &params, sizeof(params));
         }
 
         if (err != OK) {
@@ -1741,7 +1732,7 @@
             && storeMeta != 0);
 
         mOutputMetadataType = kMetadataBufferTypeNativeHandleSource;
-        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
+        err = mOMXNode->storeMetaDataInBuffers(kPortIndexOutput, enable, &mOutputMetadataType);
         if (err != OK) {
             ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
                 mComponentName.c_str(), err);
@@ -1793,8 +1784,8 @@
 
         if (mFlags & kFlagIsSecure) {
             // use native_handles for secure input buffers
-            err = mOMX->enableNativeBuffers(
-                    mNode, kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
+            err = mOMXNode->enableNativeBuffers(
+                    kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
             ALOGI_IF(err != OK, "falling back to non-native_handles");
             err = OK; // ignore error for now
         }
@@ -1810,8 +1801,8 @@
             OMX_CONFIG_BOOLEANTYPE config;
             InitOMXParams(&config);
             config.bEnabled = (OMX_BOOL)enabled;
-            status_t temp = mOMX->setConfig(
-                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
+            status_t temp = mOMXNode->setConfig(
+                    (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
                     &config, sizeof(config));
             if (temp == OK) {
                 outputFormat->setInt32("auto-frc", enabled);
@@ -1842,8 +1833,8 @@
             if (msg->findInt32("max-width", &maxWidth) &&
                     msg->findInt32("max-height", &maxHeight)) {
 
-                err = mOMX->prepareForAdaptivePlayback(
-                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
+                err = mOMXNode->prepareForAdaptivePlayback(
+                        kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
                 if (err != OK) {
                     ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
                             mComponentName.c_str(), err);
@@ -1870,8 +1861,8 @@
 
             // Always try to enable dynamic output buffers on native surface
             mOutputMetadataType = kMetadataBufferTypeANWBuffer;
-            err = mOMX->storeMetaDataInBuffers(
-                    mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
+            err = mOMXNode->storeMetaDataInBuffers(
+                    kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
             if (err != OK) {
                 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
                         mComponentName.c_str(), err);
@@ -1905,9 +1896,8 @@
                     ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
                             mComponentName.c_str(), maxWidth, maxHeight);
 
-                    err = mOMX->prepareForAdaptivePlayback(
-                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
-                            maxHeight);
+                    err = mOMXNode->prepareForAdaptivePlayback(
+                            kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
                     ALOGW_IF(err != OK,
                             "[%s] prepareForAdaptivePlayback failed w/ err %d",
                             mComponentName.c_str(), err);
@@ -1996,7 +1986,7 @@
                 ALOGD("[%s] Requested output format %#x and got %#x.",
                         mComponentName.c_str(), requestedColorFormat, colorFormat);
                 if (!IsFlexibleColorFormat(
-                                mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
+                        mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
                         || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
                     // device did not handle flex-YUV request for native window, fall back
                     // to SW renderer
@@ -2006,16 +1996,16 @@
                     haveNativeWindow = false;
                     usingSwRenderer = true;
                     if (storingMetadataInDecodedBuffers()) {
-                        err = mOMX->storeMetaDataInBuffers(
-                                mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
+                        err = mOMXNode->storeMetaDataInBuffers(
+                                kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
                         mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
                         // TODO: implement adaptive-playback support for bytebuffer mode.
                         // This is done by SW codecs, but most HW codecs don't support it.
                         inputFormat->setInt32("adaptive-playback", false);
                     }
                     if (err == OK) {
-                        err = mOMX->enableNativeBuffers(
-                                mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
+                        err = mOMXNode->enableNativeBuffers(
+                                kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
                     }
                     if (mFlags & kFlagIsGrallocUsageProtected) {
                         // fallback is not supported for protected playback
@@ -2257,8 +2247,8 @@
     OMX_PARAM_U32TYPE config;
     InitOMXParams(&config);
     config.nU32 = (OMX_U32)priority;
-    status_t temp = mOMX->setConfig(
-            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
+    status_t temp = mOMXNode->setConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigPriority,
             &config, sizeof(config));
     if (temp != OK) {
         ALOGI("codec does not support config priority (err %d)", temp);
@@ -2285,8 +2275,8 @@
     OMX_PARAM_U32TYPE config;
     InitOMXParams(&config);
     config.nU32 = rate;
-    status_t err = mOMX->setConfig(
-            mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
+    status_t err = mOMXNode->setConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
             &config, sizeof(config));
     if (err != OK) {
         ALOGI("codec does not support config operating rate (err %d)", err);
@@ -2298,8 +2288,8 @@
     OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
     InitOMXParams(&params);
     params.nPortIndex = kPortIndexOutput;
-    status_t err = mOMX->getConfig(
-            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
+    status_t err = mOMXNode->getConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
     if (err == OK) {
         *intraRefreshPeriod = params.nRefreshPeriod;
         return OK;
@@ -2310,8 +2300,8 @@
     InitOMXParams(&refreshParams);
     refreshParams.nPortIndex = kPortIndexOutput;
     refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
     if (err != OK || refreshParams.nCirMBs == 0) {
         *intraRefreshPeriod = 0;
         return OK;
@@ -2323,8 +2313,8 @@
     InitOMXParams(&def);
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
     def.nPortIndex = kPortIndexOutput;
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
     if (err != OK) {
         *intraRefreshPeriod = 0;
         return err;
@@ -2342,8 +2332,8 @@
     InitOMXParams(&params);
     params.nPortIndex = kPortIndexOutput;
     params.nRefreshPeriod = intraRefreshPeriod;
-    status_t err = mOMX->setConfig(
-            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
+    status_t err = mOMXNode->setConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
     if (err == OK) {
         return OK;
     }
@@ -2370,8 +2360,8 @@
         InitOMXParams(&def);
         OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
         def.nPortIndex = kPortIndexOutput;
-        err = mOMX->getParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->getParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
         if (err != OK) {
             return err;
         }
@@ -2381,8 +2371,9 @@
         refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
     }
 
-    err = mOMX->setParameter(mNode, OMX_IndexParamVideoIntraRefresh,
-                             &refreshParams, sizeof(refreshParams));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamVideoIntraRefresh,
+            &refreshParams, sizeof(refreshParams));
     if (err != OK) {
         return err;
     }
@@ -2425,9 +2416,9 @@
     InitOMXParams(&layerParams);
     layerParams.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-        mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
-        &layerParams, sizeof(layerParams));
+    status_t err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+            &layerParams, sizeof(layerParams));
 
     if (err != OK) {
         return err;
@@ -2447,8 +2438,8 @@
         layerConfig.nBLayerCountActual = numBLayers;
         layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
 
-        err = mOMX->setConfig(
-                mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
+        err = mOMXNode->setConfig(
+                (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
                 &layerConfig, sizeof(layerConfig));
     } else {
         layerParams.ePattern = pattern;
@@ -2456,8 +2447,8 @@
         layerParams.nBLayerCountActual = numBLayers;
         layerParams.bBitrateRatiosSpecified = OMX_FALSE;
 
-        err = mOMX->setParameter(
-                mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+        err = mOMXNode->setParameter(
+                (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
                 &layerParams, sizeof(layerParams));
     }
 
@@ -2474,8 +2465,8 @@
         return err;
     }
 
-    err = mOMX->getParameter(
-            mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+    err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
             &layerParams, sizeof(layerParams));
 
     if (err == OK) {
@@ -2498,8 +2489,8 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2511,15 +2502,15 @@
 
     def.nBufferSize = size;
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
     }
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2541,9 +2532,8 @@
     format.nPortIndex = portIndex;
     for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
         format.nIndex = index;
-        status_t err = mOMX->getParameter(
-                mNode, OMX_IndexParamAudioPortFormat,
-                &format, sizeof(format));
+        status_t err = mOMXNode->getParameter(
+                OMX_IndexParamAudioPortFormat, &format, sizeof(format));
 
         if (err != OK) {
             return err;
@@ -2561,8 +2551,8 @@
         }
     }
 
-    return mOMX->setParameter(
-            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
+    return mOMXNode->setParameter(
+            OMX_IndexParamAudioPortFormat, &format, sizeof(format));
 }
 
 status_t ACodec::setupAACCodec(
@@ -2594,8 +2584,8 @@
         InitOMXParams(&def);
         def.nPortIndex = kPortIndexOutput;
 
-        err = mOMX->getParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->getParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         if (err != OK) {
             return err;
@@ -2604,8 +2594,8 @@
         def.format.audio.bFlagErrorConcealment = OMX_TRUE;
         def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
 
-        err = mOMX->setParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+        err = mOMXNode->setParameter(
+                OMX_IndexParamPortDefinition, &def, sizeof(def));
 
         if (err != OK) {
             return err;
@@ -2615,8 +2605,8 @@
         InitOMXParams(&profile);
         profile.nPortIndex = kPortIndexOutput;
 
-        err = mOMX->getParameter(
-                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+        err = mOMXNode->getParameter(
+                OMX_IndexParamAudioAac, &profile, sizeof(profile));
 
         if (err != OK) {
             return err;
@@ -2663,8 +2653,8 @@
         }
 
 
-        err = mOMX->setParameter(
-                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+        err = mOMXNode->setParameter(
+                OMX_IndexParamAudioAac, &profile, sizeof(profile));
 
         if (err != OK) {
             return err;
@@ -2677,8 +2667,8 @@
     InitOMXParams(&profile);
     profile.nPortIndex = kPortIndexInput;
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamAudioAac, &profile, sizeof(profile));
 
     if (err != OK) {
         return err;
@@ -2702,10 +2692,12 @@
     presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
     presentation.nPCMLimiterEnable = pcmLimiterEnable;
 
-    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+    status_t res = mOMXNode->setParameter(
+            OMX_IndexParamAudioAac, &profile, sizeof(profile));
     if (res == OK) {
         // optional parameters, will not cause configuration failure
-        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
+        mOMXNode->setParameter(
+                (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
                 &presentation, sizeof(presentation));
     } else {
         ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
@@ -2732,11 +2724,8 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    err = mOMX->getParameter(
-            mNode,
-            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
-            &def,
-            sizeof(def));
+    err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2745,11 +2734,8 @@
     def.nChannels = numChannels;
     def.nSampleRate = sampleRate;
 
-    return mOMX->setParameter(
-            mNode,
-            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
-            &def,
-            sizeof(def));
+    return mOMXNode->setParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
 }
 
 status_t ACodec::setupEAC3Codec(
@@ -2770,11 +2756,8 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    err = mOMX->getParameter(
-            mNode,
-            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
-            &def,
-            sizeof(def));
+    err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2783,11 +2766,8 @@
     def.nChannels = numChannels;
     def.nSampleRate = sampleRate;
 
-    return mOMX->setParameter(
-            mNode,
-            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
-            &def,
-            sizeof(def));
+    return mOMXNode->setParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
 }
 
 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
@@ -2840,8 +2820,8 @@
     InitOMXParams(&def);
     def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
 
-    status_t err =
-        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamAudioAmr, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2850,8 +2830,8 @@
     def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
     def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamAudioAmr, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2881,13 +2861,13 @@
         def.nPortIndex = kPortIndexOutput;
 
         // configure compression level
-        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
+        status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
         if (err != OK) {
             ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
             return err;
         }
         def.nCompressionLevel = compressionLevel;
-        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
+        err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
         if (err != OK) {
             ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
             return err;
@@ -2906,8 +2886,8 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2915,8 +2895,8 @@
 
     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -2926,8 +2906,8 @@
     InitOMXParams(&pcmParams);
     pcmParams.nPortIndex = portIndex;
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     if (err != OK) {
         return err;
@@ -2958,15 +2938,15 @@
         return OMX_ErrorNone;
     }
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
     // if we could not set up raw format to non-16-bit, try with 16-bit
     // NOTE: we will also verify this via readback, in case codec ignores these fields
     if (err != OK && encoding != kAudioEncodingPcm16bit) {
         pcmParams.eNumData = OMX_NumericalDataSigned;
         pcmParams.nBitPerSample = 16;
-        err = mOMX->setParameter(
-                mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+        err = mOMXNode->setParameter(
+                OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
     }
     return err;
 }
@@ -2975,8 +2955,8 @@
         int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
     native_handle_t* sidebandHandle;
 
-    status_t err = mOMX->configureVideoTunnelMode(
-            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
+    status_t err = mOMXNode->configureVideoTunnelMode(
+            kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
     if (err != OK) {
         ALOGE("configureVideoTunnelMode failed! (err %d).", err);
         return err;
@@ -3005,8 +2985,8 @@
 
     for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
         format.nIndex = index;
-        status_t err = mOMX->getParameter(
-                mNode, OMX_IndexParamVideoPortFormat,
+        status_t err = mOMXNode->getParameter(
+                OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
 
         if (err != OK) {
@@ -3017,7 +2997,7 @@
         OMX_U32 flexibleEquivalent;
         if (compressionFormat == OMX_VIDEO_CodingUnused
                 && IsFlexibleColorFormat(
-                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
+                        mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
                 && colorFormat == flexibleEquivalent) {
             ALOGI("[%s] using color format %#x in place of %#x",
                     mComponentName.c_str(), format.eColorFormat, colorFormat);
@@ -3060,9 +3040,8 @@
         return UNKNOWN_ERROR;
     }
 
-    status_t err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoPortFormat,
-            &format, sizeof(format));
+    status_t err = mOMXNode->setParameter(
+            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
 
     return err;
 }
@@ -3092,9 +3071,8 @@
 
     for (OMX_U32 index = 0; ; ++index) {
         format.nIndex = index;
-        status_t err = mOMX->getParameter(
-                mNode, OMX_IndexParamVideoPortFormat,
-                &format, sizeof(format));
+        status_t err = mOMXNode->getParameter(
+                OMX_IndexParamVideoPortFormat, &format, sizeof(format));
         if (err != OK) {
             // no more formats, pick legacy format if found
             if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
@@ -3121,15 +3099,14 @@
         OMX_U32 flexibleEquivalent;
         if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
                 && IsFlexibleColorFormat(
-                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
+                        mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
                         &flexibleEquivalent)
                 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
             memcpy(&legacyFormat, &format, sizeof(format));
         }
     }
-    return mOMX->setParameter(
-            mNode, OMX_IndexParamVideoPortFormat,
-            &format, sizeof(format));
+    return mOMXNode->setParameter(
+            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
 }
 
 static const struct VideoCodingMapEntry {
@@ -3185,14 +3162,14 @@
     status_t err;
     ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
             portIndex == kPortIndexInput ? "input" : "output", bufferNum);
-    err = mOMX->getParameter(
-        mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->getParameter(
+        OMX_IndexParamPortDefinition, &def, sizeof(def));
     if (err != OK) {
         return err;
     }
     def.nBufferCountActual = bufferNum;
-    err = mOMX->setParameter(
-        mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+        OMX_IndexParamPortDefinition, &def, sizeof(def));
     if (err != OK) {
         // Component could reject this request.
         ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
@@ -3223,11 +3200,9 @@
         params.nPortIndex = kPortIndexInput;
         // Check if VP9 decoder advertises supported profiles.
         params.nProfileIndex = 0;
-        status_t err = mOMX->getParameter(
-                mNode,
+        status_t err = mOMXNode->getParameter(
                 OMX_IndexParamVideoProfileLevelQuerySupported,
-                &params,
-                sizeof(params));
+                &params, sizeof(params));
         mIsLegacyVP9Decoder = err != OK;
     }
 
@@ -3316,8 +3291,8 @@
 }
 
 status_t ACodec::initDescribeColorAspectsIndex() {
-    status_t err = mOMX->getExtensionIndex(
-            mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
+    status_t err = mOMXNode->getExtensionIndex(
+            "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
     if (err != OK) {
         mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
     }
@@ -3327,7 +3302,7 @@
 status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams &params, bool verify) {
     status_t err = ERROR_UNSUPPORTED;
     if (mDescribeColorAspectsIndex) {
-        err = mOMX->setConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
+        err = mOMXNode->setConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
     }
     ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
             mComponentName.c_str(),
@@ -3372,7 +3347,7 @@
 status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams &params) {
     status_t err = ERROR_UNSUPPORTED;
     if (mDescribeColorAspectsIndex) {
-        err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
+        err = mOMXNode->getConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
     }
     ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
             mComponentName.c_str(),
@@ -3594,8 +3569,8 @@
 }
 
 status_t ACodec::initDescribeHDRStaticInfoIndex() {
-    status_t err = mOMX->getExtensionIndex(
-            mNode, "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
+    status_t err = mOMXNode->getExtensionIndex(
+            "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
     if (err != OK) {
         mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
     }
@@ -3605,7 +3580,7 @@
 status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams &params) {
     status_t err = ERROR_UNSUPPORTED;
     if (mDescribeHDRStaticInfoIndex) {
-        err = mOMX->setConfig(mNode, mDescribeHDRStaticInfoIndex, &params, sizeof(params));
+        err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
     }
 
     const HDRStaticInfo *info = &params.sInfo;
@@ -3626,7 +3601,7 @@
 status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams &params) {
     status_t err = ERROR_UNSUPPORTED;
     if (mDescribeHDRStaticInfoIndex) {
-        err = mOMX->getConfig(mNode, mDescribeHDRStaticInfoIndex, &params, sizeof(params));
+        err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
     }
 
     ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
@@ -3665,8 +3640,8 @@
 
     def.nPortIndex = kPortIndexInput;
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -3716,8 +3691,8 @@
         video_def->eColorFormat = colorFormat;
     }
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         ALOGE("[%s] failed to set input port definition parameters.",
@@ -3747,8 +3722,8 @@
 
     def.nPortIndex = kPortIndexOutput;
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         return err;
@@ -3761,8 +3736,8 @@
     video_def->eCompressionFormat = compressionFormat;
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
         ALOGE("[%s] failed to set output port definition parameters.",
@@ -3891,9 +3866,8 @@
         params.nAirRef = ref;
     }
 
-    status_t err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoIntraRefresh,
-            &params, sizeof(params));
+    status_t err = mOMXNode->setParameter(
+            OMX_IndexParamVideoIntraRefresh, &params, sizeof(params));
     return err;
 }
 
@@ -3956,8 +3930,8 @@
     InitOMXParams(&mpeg4type);
     mpeg4type.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
 
     if (err != OK) {
         return err;
@@ -3999,8 +3973,8 @@
         mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
     }
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
 
     if (err != OK) {
         return err;
@@ -4038,8 +4012,8 @@
     InitOMXParams(&h263type);
     h263type.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
 
     if (err != OK) {
         return err;
@@ -4076,8 +4050,8 @@
     h263type.nPictureHeaderRepetition = 0;
     h263type.nGOBHeaderInterval = 0;
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
 
     if (err != OK) {
         return err;
@@ -4178,8 +4152,8 @@
     InitOMXParams(&h264type);
     h264type.nPortIndex = kPortIndexOutput;
 
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+    err = mOMXNode->getParameter(
+            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
 
     if (err != OK) {
         return err;
@@ -4268,8 +4242,8 @@
     h264type.bMBAFF = OMX_FALSE;
     h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
 
     if (err != OK) {
         return err;
@@ -4285,8 +4259,8 @@
         OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
         InitOMXParams(&layering);
         layering.nPortIndex = kPortIndexOutput;
-        if (mOMX->getParameter(
-                        mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+        if (mOMXNode->getParameter(
+                        (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
                         &layering, sizeof(layering)) == OK
                 && layering.eSupportedPatterns
                 && layering.nBLayerCountMax == 0) {
@@ -4294,8 +4268,8 @@
             h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
             h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
             ALOGI("disabling B-frames");
-            err = mOMX->setParameter(
-                    mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+            err = mOMXNode->setParameter(
+                    OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
 
             if (err != OK) {
                 return err;
@@ -4330,8 +4304,8 @@
     hevcType.nPortIndex = kPortIndexOutput;
 
     status_t err = OK;
-    err = mOMX->getParameter(
-            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
+    err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
     if (err != OK) {
         return err;
     }
@@ -4354,8 +4328,8 @@
     // TODO: finer control?
     hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
 
-    err = mOMX->setParameter(
-            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
+    err = mOMXNode->setParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
     if (err != OK) {
         return err;
     }
@@ -4423,8 +4397,8 @@
     OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
     InitOMXParams(&vp8type);
     vp8type.nPortIndex = kPortIndexOutput;
-    status_t err = mOMX->getParameter(
-            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+    status_t err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
             &vp8type, sizeof(vp8type));
 
     if (err == OK) {
@@ -4444,8 +4418,8 @@
             vp8type.nMaxQuantizer = 63;
         }
 
-        err = mOMX->setParameter(
-                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+        err = mOMXNode->setParameter(
+                (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
                 &vp8type, sizeof(vp8type));
         if (err != OK) {
             ALOGW("Extended VP8 parameters set failed: %d", err);
@@ -4469,11 +4443,9 @@
 
     for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
         params.nProfileIndex = index;
-        status_t err = mOMX->getParameter(
-                mNode,
+        status_t err = mOMXNode->getParameter(
                 OMX_IndexParamVideoProfileLevelQuerySupported,
-                &params,
-                sizeof(params));
+                &params, sizeof(params));
 
         if (err != OK) {
             return err;
@@ -4501,9 +4473,8 @@
     InitOMXParams(&bitrateType);
     bitrateType.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
 
     if (err != OK) {
         return err;
@@ -4512,9 +4483,8 @@
     bitrateType.eControlRate = bitrateMode;
     bitrateType.nTargetBitrate = bitrate;
 
-    return mOMX->setParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
+    return mOMXNode->setParameter(
+            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
 }
 
 status_t ACodec::setupErrorCorrectionParameters() {
@@ -4522,8 +4492,8 @@
     InitOMXParams(&errorCorrectionType);
     errorCorrectionType.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoErrorCorrection,
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamVideoErrorCorrection,
             &errorCorrectionType, sizeof(errorCorrectionType));
 
     if (err != OK) {
@@ -4536,8 +4506,8 @@
     errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
     errorCorrectionType.bEnableRVLC = OMX_FALSE;
 
-    return mOMX->setParameter(
-            mNode, OMX_IndexParamVideoErrorCorrection,
+    return mOMXNode->setParameter(
+            OMX_IndexParamVideoErrorCorrection,
             &errorCorrectionType, sizeof(errorCorrectionType));
 }
 
@@ -4551,8 +4521,8 @@
 
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
     if (err != OK) {
         return err;
     }
@@ -4581,18 +4551,18 @@
         }
     }
 
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    err = mOMXNode->setParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     return err;
 }
 
 status_t ACodec::initNativeWindow() {
     if (mNativeWindow != NULL) {
-        return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
+        return mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
     }
 
-    mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
+    mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
     return OK;
 }
 
@@ -4680,7 +4650,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
     if (err != OK) {
         return err;
     }
@@ -4714,7 +4684,7 @@
                         describeParams.nSliceHeight = videoDef->nSliceHeight;
                         describeParams.bUsingNativeBuffers = OMX_FALSE;
 
-                        if (DescribeColorFormat(mOMX, mNode, describeParams)) {
+                        if (DescribeColorFormat(mOMXNode, describeParams)) {
                             notify->setBuffer(
                                     "image-data",
                                     ABuffer::CreateAsCopy(
@@ -4739,8 +4709,7 @@
                         InitOMXParams(&rect);
                         rect.nPortIndex = portIndex;
 
-                        if (mOMX->getConfig(
-                                    mNode,
+                        if (mOMXNode->getConfig(
                                     (portIndex == kPortIndexOutput ?
                                             OMX_IndexConfigCommonOutputCrop :
                                             OMX_IndexConfigCommonInputCrop),
@@ -4796,8 +4765,7 @@
                     OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
                     InitOMXParams(&vp8type);
                     vp8type.nPortIndex = kPortIndexOutput;
-                    status_t err = mOMX->getParameter(
-                            mNode,
+                    status_t err = mOMXNode->getParameter(
                             (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
                             &vp8type,
                             sizeof(vp8type));
@@ -4866,8 +4834,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioPcm, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -4914,8 +4882,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioAac, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -4932,8 +4900,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioAmr, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -4955,8 +4923,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioFlac, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -4973,8 +4941,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioMp3, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -4991,8 +4959,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            OMX_IndexParamAudioVorbis, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -5009,8 +4977,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+                    err = mOMXNode->getParameter(
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
                             &params, sizeof(params));
                     if (err != OK) {
                         return err;
@@ -5028,8 +4996,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+                    err = mOMXNode->getParameter(
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
                             &params, sizeof(params));
                     if (err != OK) {
                         return err;
@@ -5047,8 +5015,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
+                    err = mOMXNode->getParameter(
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
                             &params, sizeof(params));
                     if (err != OK) {
                         return err;
@@ -5066,8 +5034,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -5093,8 +5061,8 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    err = mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    err = mOMXNode->getParameter(
+                                OMX_IndexParamAudioPcm, &params, sizeof(params));
                     if (err != OK) {
                         return err;
                     }
@@ -5267,11 +5235,6 @@
     notify->post();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-
-ACodec::PortDescription::PortDescription() {
-}
-
 status_t ACodec::requestIDRFrame() {
     if (!mIsEncoder) {
         return ERROR_UNSUPPORTED;
@@ -5283,15 +5246,19 @@
     params.nPortIndex = kPortIndexOutput;
     params.IntraRefreshVOP = OMX_TRUE;
 
-    return mOMX->setConfig(
-            mNode,
+    return mOMXNode->setConfig(
             OMX_IndexConfigVideoIntraVOPRefresh,
             &params,
             sizeof(params));
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::PortDescription::PortDescription() {
+}
+
 void ACodec::PortDescription::addBuffer(
-        IOMX::buffer_id id, const sp<ABuffer> &buffer,
+        IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer,
         const sp<NativeHandle> &handle, const sp<RefBase> &memRef) {
     mBufferIDs.push_back(id);
     mBuffers.push_back(buffer);
@@ -5307,7 +5274,7 @@
     return mBufferIDs.itemAt(index);
 }
 
-sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
+sp<MediaCodecBuffer> ACodec::PortDescription::bufferAt(size_t index) const {
     return mBuffers.itemAt(index);
 }
 
@@ -5400,7 +5367,7 @@
         {
             ALOGI("[%s] forcing the release of codec",
                     mCodec->mComponentName.c_str());
-            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
+            status_t err = mCodec->mOMXNode->freeNode();
             ALOGE_IF("[%s] failed to release codec instance: err=%d",
                        mCodec->mComponentName.c_str(), err);
             sp<AMessage> notify = mCodec->mNotify->dup();
@@ -5419,16 +5386,17 @@
 bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
     // there is a possibility that this is an outstanding message for a
     // codec that we have already destroyed
-    if (mCodec->mNode == 0) {
+    if (mCodec->mOMXNode == NULL) {
         ALOGI("ignoring message as already freed component: %s",
                 msg->debugString().c_str());
         return false;
     }
 
-    IOMX::node_id nodeID;
-    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
-    if (nodeID != mCodec->mNode) {
-        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
+    int32_t generation;
+    CHECK(msg->findInt32("generation", (int32_t*)&generation));
+    if (generation != mCodec->mNodeGeneration) {
+        ALOGW("Unexpected message for component: %s, gen %u, cur %u",
+                msg->debugString().c_str(), generation, mCodec->mNodeGeneration);
         return false;
     }
     return true;
@@ -5633,7 +5601,7 @@
     notify->setInt32("buffer-id", info->mBufferID);
 
     info->mData->meta()->clear();
-    notify->setBuffer("buffer", info->mData);
+    notify->setObject("buffer", info->mData);
 
     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
     reply->setInt32("buffer-id", info->mBufferID);
@@ -5648,12 +5616,13 @@
 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
     IOMX::buffer_id bufferID;
     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
     int32_t err = OK;
     bool eos = false;
     PortMode mode = getPortMode(kPortIndexInput);
 
-    if (!msg->findBuffer("buffer", &buffer)) {
+    sp<RefBase> obj;
+    if (!msg->findObject("buffer", &obj)) {
         /* these are unfilled buffers returned by client */
         CHECK(msg->findInt32("err", &err));
 
@@ -5667,6 +5636,8 @@
         }
 
         buffer.clear();
+    } else {
+        buffer = static_cast<MediaCodecBuffer *>(obj.get());
     }
 
     int32_t tmp;
@@ -5792,8 +5763,8 @@
                     if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
                         VideoNativeHandleMetadata *vnhmd =
                             (VideoNativeHandleMetadata*)info->mCodecData->base();
-                        err2 = mCodec->mOMX->updateNativeHandleInMeta(
-                                mCodec->mNode, kPortIndexInput,
+                        err2 = mCodec->mOMXNode->updateNativeHandleInMeta(
+                                mCodec->kPortIndexInput,
                                 NativeHandle::create(vnhmd->pHandle, false /* ownsHandle */),
                                 bufferID);
                     }
@@ -5801,8 +5772,8 @@
                 case kMetadataBufferTypeANWBuffer:
                     if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
                         VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
-                        err2 = mCodec->mOMX->updateGraphicBufferInMeta(
-                                mCodec->mNode, kPortIndexInput,
+                        err2 = mCodec->mOMXNode->updateGraphicBufferInMeta(
+                                mCodec->kPortIndexInput,
                                 new GraphicBuffer(vnmd->pBuffer, false /* keepOwnership */),
                                 bufferID);
                     }
@@ -5817,8 +5788,7 @@
                 }
 
                 if (err2 == OK) {
-                    err2 = mCodec->mOMX->emptyBuffer(
-                        mCodec->mNode,
+                    err2 = mCodec->mOMXNode->emptyBuffer(
                         bufferID,
                         0,
                         info->mCodecData->size(),
@@ -5855,8 +5825,7 @@
                      mCodec->mComponentName.c_str(), bufferID);
 
                 info->checkReadFence("onInputBufferFilled");
-                status_t err2 = mCodec->mOMX->emptyBuffer(
-                        mCodec->mNode,
+                status_t err2 = mCodec->mOMXNode->emptyBuffer(
                         bufferID,
                         0,
                         0,
@@ -5986,7 +5955,7 @@
                 ALOGV("[%s] calling fillBuffer %u",
                      mCodec->mComponentName.c_str(), info->mBufferID);
 
-                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
+                err = mCodec->mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
                 info->mFenceFd = -1;
                 if (err != OK) {
                     mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
@@ -5999,6 +5968,7 @@
 
             sp<AMessage> reply =
                 new AMessage(kWhatOutputBufferDrained, mCodec);
+            sp<MediaCodecBuffer> buffer = info->mData;
 
             if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
                 // pretend that output format has changed on the first frame (we used to do this)
@@ -6016,8 +5986,8 @@
             if (mCodec->usingMetadataOnEncoderOutput()) {
                 native_handle_t *handle = NULL;
                 VideoNativeHandleMetadata &nativeMeta =
-                    *(VideoNativeHandleMetadata *)info->mData->data();
-                if (info->mData->size() >= sizeof(nativeMeta)
+                    *(VideoNativeHandleMetadata *)buffer->data();
+                if (buffer->size() >= sizeof(nativeMeta)
                         && nativeMeta.eType == kMetadataBufferTypeNativeHandleSource) {
 #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
                     // handle is only valid on 32-bit/mediaserver process
@@ -6026,16 +5996,16 @@
                     handle = (native_handle_t *)nativeMeta.pHandle;
 #endif
                 }
-                info->mData->meta()->setPointer("handle", handle);
-                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
-                info->mData->meta()->setInt32("rangeLength", rangeLength);
-            } else if (info->mData == info->mCodecData) {
-                info->mData->setRange(rangeOffset, rangeLength);
+                buffer->meta()->setPointer("handle", handle);
+                buffer->meta()->setInt32("rangeOffset", rangeOffset);
+                buffer->meta()->setInt32("rangeLength", rangeLength);
+            } else if (buffer == info->mCodecData) {
+                buffer->setRange(rangeOffset, rangeLength);
             } else {
                 info->mCodecData->setRange(rangeOffset, rangeLength);
                 // in this case we know that mConverter is not null
                 status_t err = mCodec->mConverter[kPortIndexOutput]->convert(
-                        info->mCodecData, info->mData);
+                        info->mCodecData, buffer);
                 if (err != OK) {
                     mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
                     return true;
@@ -6050,14 +6020,14 @@
 #endif
 
             if (mCodec->mSkipCutBuffer != NULL) {
-                mCodec->mSkipCutBuffer->submit(info->mData);
+                mCodec->mSkipCutBuffer->submit(buffer);
             }
-            info->mData->meta()->setInt64("timeUs", timeUs);
+            buffer->meta()->setInt64("timeUs", timeUs);
 
             sp<AMessage> notify = mCodec->mNotify->dup();
             notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
             notify->setInt32("buffer-id", info->mBufferID);
-            notify->setBuffer("buffer", info->mData);
+            notify->setObject("buffer", buffer);
             notify->setInt32("flags", flags);
 
             reply->setInt32("buffer-id", info->mBufferID);
@@ -6100,6 +6070,11 @@
 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
     IOMX::buffer_id bufferID;
     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
+    sp<RefBase> obj;
+    sp<MediaCodecBuffer> buffer = nullptr;
+    if (msg->findObject("buffer", &obj)) {
+        buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    }
     ssize_t index;
     BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
     BufferInfo::Status status = BufferInfo::getSafeStatus(info);
@@ -6130,13 +6105,13 @@
     int32_t render;
     if (mCodec->mNativeWindow != NULL
             && msg->findInt32("render", &render) && render != 0
-            && info->mData != NULL && info->mData->size() != 0) {
+            && buffer != NULL && buffer->size() != 0) {
         ATRACE_NAME("render");
         // The client wants this buffer to be rendered.
 
         // save buffers sent to the surface so we can get render time when they return
         int64_t mediaTimeUs = -1;
-        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
+        buffer->meta()->findInt64("timeUs", &mediaTimeUs);
         if (mediaTimeUs >= 0) {
             mCodec->mRenderTracker.onFrameQueued(
                     mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
@@ -6145,7 +6120,7 @@
         int64_t timestampNs = 0;
         if (!msg->findInt64("timestampNs", &timestampNs)) {
             // use media timestamp if client did not request a specific render timestamp
-            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
+            if (buffer->meta()->findInt64("timeUs", &timestampNs)) {
                 ALOGV("using buffer PTS of %lld", (long long)timestampNs);
                 timestampNs *= 1000;
             }
@@ -6170,7 +6145,7 @@
         }
     } else {
         if (mCodec->mNativeWindow != NULL &&
-            (info->mData == NULL || info->mData->size() != 0)) {
+            (buffer == NULL || buffer->size() != 0)) {
             // move read fence into write fence to avoid clobbering
             info->mIsReadFence = false;
             ATRACE_NAME("frame-drop");
@@ -6208,8 +6183,8 @@
                     ALOGV("[%s] calling fillBuffer %u",
                          mCodec->mComponentName.c_str(), info->mBufferID);
                     info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
-                    status_t err = mCodec->mOMX->fillBuffer(
-                            mCodec->mNode, info->mBufferID, info->mFenceFd);
+                    status_t err = mCodec->mOMXNode->fillBuffer(
+                            info->mBufferID, info->mFenceFd);
                     info->mFenceFd = -1;
                     if (err == OK) {
                         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
@@ -6253,8 +6228,8 @@
     mCodec->mUsingNativeWindow = false;
     mCodec->mNativeWindow.clear();
     mCodec->mNativeWindowUsageBits = 0;
-    mCodec->mNode = 0;
     mCodec->mOMX.clear();
+    mCodec->mOMXNode.clear();
     mCodec->mQuirks = 0;
     mCodec->mFlags = 0;
     mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
@@ -6334,7 +6309,7 @@
 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
     ALOGV("onAllocateComponent");
 
-    CHECK(mCodec->mNode == 0);
+    CHECK(mCodec->mOMXNode == NULL);
 
     OMXClient client;
     if (client.connect() != OK) {
@@ -6373,7 +6348,7 @@
     }
 
     sp<CodecObserver> observer = new CodecObserver;
-    IOMX::node_id node = 0;
+    sp<IOMXNode> omxNode;
 
     status_t err = NAME_NOT_FOUND;
     for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
@@ -6384,7 +6359,7 @@
         pid_t tid = gettid();
         int prevPriority = androidGetThreadPriority(tid);
         androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
-        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
+        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &omxNode);
         androidSetThreadPriority(tid, prevPriority);
 
         if (err == OK) {
@@ -6393,10 +6368,10 @@
             ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
         }
 
-        node = 0;
+        omxNode = NULL;
     }
 
-    if (node == 0) {
+    if (omxNode == NULL) {
         if (!mime.empty()) {
             ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
                     encoder ? "en" : "de", mime.c_str(), err);
@@ -6417,6 +6392,7 @@
     }
 
     notify = new AMessage(kWhatOMXMessageList, mCodec);
+    notify->setInt32("generation", ++mCodec->mNodeGeneration);
     observer->setNotificationMessage(notify);
 
     mCodec->mComponentName = componentName;
@@ -6431,7 +6407,7 @@
 
     mCodec->mQuirks = quirks;
     mCodec->mOMX = omx;
-    mCodec->mNode = node;
+    mCodec->mOMXNode = omxNode;
 
     {
         sp<AMessage> notify = mCodec->mNotify->dup();
@@ -6482,7 +6458,7 @@
 
 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
     if (!keepComponentAllocated) {
-        (void)mCodec->mOMX->freeNode(mCodec->mNode);
+        (void)mCodec->mOMXNode->freeNode();
 
         mCodec->changeState(mCodec->mUninitializedState);
     }
@@ -6561,7 +6537,7 @@
         const sp<AMessage> &msg) {
     ALOGV("onConfigureComponent");
 
-    CHECK(mCodec->mNode != 0);
+    CHECK(mCodec->mOMXNode != NULL);
 
     status_t err = OK;
     AString mime;
@@ -6653,8 +6629,8 @@
     }
 
     uint32_t usageBits;
-    if (mCodec->mOMX->getParameter(
-            mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+    if (mCodec->mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
             &usageBits, sizeof(usageBits)) == OK) {
         mCodec->mInputFormat->setInt32(
                 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
@@ -6695,8 +6671,8 @@
     sp<IGraphicBufferProducer> bufferProducer;
     if (err == OK) {
         mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMX->createInputSurface(
-                mCodec->mNode, kPortIndexInput, dataSpace,
+        err = mCodec->mOMXNode->createInputSurface(
+                mCodec->kPortIndexInput, dataSpace,
                 &bufferProducer, &mCodec->mGraphicBufferSource,
                 &mCodec->mInputMetadataType);
         // framework uses ANW buffers internally instead of gralloc handles
@@ -6742,8 +6718,8 @@
 
     if (err == OK) {
         mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMX->setInputSurface(
-                mCodec->mNode, kPortIndexInput,
+        err = mCodec->mOMXNode->setInputSurface(
+                mCodec->kPortIndexInput,
                 surface->getBufferConsumer(),
                 &mCodec->mGraphicBufferSource,
                 &mCodec->mInputMetadataType);
@@ -6772,7 +6748,7 @@
 void ACodec::LoadedState::onStart() {
     ALOGV("onStart");
 
-    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+    status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
     if (err != OK) {
         mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
     } else {
@@ -6797,8 +6773,8 @@
 
         mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
 
-        mCodec->mOMX->sendCommand(
-                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+        mCodec->mOMXNode->sendCommand(
+                OMX_CommandStateSet, OMX_StateLoaded);
         if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
             mCodec->freeBuffersOnPort(kPortIndexInput);
         }
@@ -6870,8 +6846,8 @@
             }
 
             if (err == OK) {
-                err = mCodec->mOMX->sendCommand(
-                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
+                err = mCodec->mOMXNode->sendCommand(
+                    OMX_CommandStateSet, OMX_StateExecuting);
             }
 
             if (err != OK) {
@@ -7014,7 +6990,7 @@
         ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
 
         info->checkWriteFence("submitRegularOutputBuffers");
-        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
+        status_t err = mCodec->mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
         info->mFenceFd = -1;
         if (err != OK) {
             failed = true;
@@ -7082,8 +7058,8 @@
 
             mActive = false;
 
-            status_t err = mCodec->mOMX->sendCommand(
-                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+            status_t err = mCodec->mOMXNode->sendCommand(
+                    OMX_CommandStateSet, OMX_StateIdle);
             if (err != OK) {
                 if (keepComponentAllocated) {
                     mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
@@ -7109,7 +7085,7 @@
 
             mActive = false;
 
-            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
+            status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL);
             if (err != OK) {
                 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
             } else {
@@ -7192,8 +7168,7 @@
         configParams.nPortIndex = kPortIndexOutput;
         configParams.nEncodeBitrate = videoBitrate;
 
-        status_t err = mOMX->setConfig(
-                mNode,
+        status_t err = mOMXNode->setConfig(
                 OMX_IndexConfigVideoBitrate,
                 &configParams,
                 sizeof(configParams));
@@ -7327,8 +7302,7 @@
 
             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
                 mCodec->mMetadataBuffersToSubmit = 0;
-                CHECK_EQ(mCodec->mOMX->sendCommand(
-                            mCodec->mNode,
+                CHECK_EQ(mCodec->mOMXNode->sendCommand(
                             OMX_CommandPortDisable, kPortIndexOutput),
                          (status_t)OK);
 
@@ -7433,8 +7407,8 @@
                 }
 
                 if (err == OK) {
-                    err = mCodec->mOMX->sendCommand(
-                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
+                    err = mCodec->mOMXNode->sendCommand(
+                            OMX_CommandPortEnable, kPortIndexOutput);
                 }
 
                 if (err == OK) {
@@ -7559,8 +7533,8 @@
 
 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
     if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
-        status_t err = mCodec->mOMX->sendCommand(
-                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+        status_t err = mCodec->mOMXNode->sendCommand(
+                OMX_CommandStateSet, OMX_StateLoaded);
         if (err == OK) {
             err = mCodec->freeBuffersOnPort(kPortIndexInput);
             status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
@@ -7746,7 +7720,7 @@
         {
             sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
             msg->setInt32("type", omx_message::EVENT);
-            msg->setInt32("node", mCodec->mNode);
+            msg->setInt32("generation", mCodec->mNodeGeneration);
             msg->setInt32("event", event);
             msg->setInt32("data1", data1);
             msg->setInt32("data2", data2);
@@ -7822,17 +7796,17 @@
 
     sp<IOMX> omx = client.interface();
     sp<CodecObserver> observer = new CodecObserver;
-    IOMX::node_id node = 0;
+    sp<IOMXNode> omxNode;
 
-    err = omx->allocateNode(name.c_str(), observer, NULL, &node);
+    err = omx->allocateNode(name.c_str(), observer, NULL, &omxNode);
     if (err != OK) {
         client.disconnect();
         return err;
     }
 
-    err = SetComponentRole(omx, node, role);
+    err = SetComponentRole(omxNode, role);
     if (err != OK) {
-        omx->freeNode(node);
+        omxNode->freeNode();
         client.disconnect();
         return err;
     }
@@ -7847,8 +7821,8 @@
 
         for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
             param.nProfileIndex = index;
-            status_t err = omx->getParameter(
-                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
+            status_t err = omxNode->getParameter(
+                    OMX_IndexParamVideoProfileLevelQuerySupported,
                     &param, sizeof(param));
             if (err != OK) {
                 break;
@@ -7871,8 +7845,8 @@
         Vector<uint32_t> supportedColors; // shadow copy to check for duplicates
         for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
             portFormat.nIndex = index;
-            status_t err = omx->getParameter(
-                    node, OMX_IndexParamVideoPortFormat,
+            status_t err = omxNode->getParameter(
+                    OMX_IndexParamVideoPortFormat,
                     &portFormat, sizeof(portFormat));
             if (err != OK) {
                 break;
@@ -7880,7 +7854,7 @@
 
             OMX_U32 flexibleEquivalent;
             if (IsFlexibleColorFormat(
-                    omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
+                    omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
                     &flexibleEquivalent)) {
                 bool marked = false;
                 for (size_t i = 0; i < supportedColors.size(); ++i) {
@@ -7910,8 +7884,8 @@
         param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
         for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
             param.nProfileIndex = index;
-            status_t err = omx->getParameter(
-                    node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
+            status_t err = omxNode->getParameter(
+                    (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
                     &param, sizeof(param));
             if (err != OK) {
                 break;
@@ -7935,15 +7909,15 @@
 
     if (isVideo && !isEncoder) {
         native_handle_t *sidebandHandle = NULL;
-        if (omx->configureVideoTunnelMode(
-                node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
+        if (omxNode->configureVideoTunnelMode(
+                kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
             // tunneled playback includes adaptive playback
             builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
                     | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
-        } else if (omx->storeMetaDataInBuffers(
-                node, kPortIndexOutput, OMX_TRUE) == OK ||
-            omx->prepareForAdaptivePlayback(
-                node, kPortIndexOutput, OMX_TRUE,
+        } else if (omxNode->storeMetaDataInBuffers(
+                kPortIndexOutput, OMX_TRUE) == OK ||
+                omxNode->prepareForAdaptivePlayback(
+                kPortIndexOutput, OMX_TRUE,
                 1280 /* width */, 720 /* height */) == OK) {
             builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
         }
@@ -7954,15 +7928,15 @@
         InitOMXParams(&params);
         params.nPortIndex = kPortIndexOutput;
         // TODO: should we verify if fallback is supported?
-        if (omx->getConfig(
-                node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
+        if (omxNode->getConfig(
+                (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
                 &params, sizeof(params)) == OK) {
             builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
         }
     }
 
     *caps = builder;
-    omx->freeNode(node);
+    omxNode->freeNode();
     client.disconnect();
     return OK;
 }
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index b07d914..54f3c08 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -10,6 +10,7 @@
         AMRWriter.cpp                     \
         AudioPlayer.cpp                   \
         AudioSource.cpp                   \
+        BufferImpl.cpp                    \
         CallbackDataSource.cpp            \
         CameraSource.cpp                  \
         CameraSourceTimeLapse.cpp         \
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
new file mode 100644
index 0000000..7d195d3
--- /dev/null
+++ b/media/libstagefright/BufferImpl.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BufferImpl"
+#include <utils/Log.h>
+
+#include <binder/IMemory.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include "include/SharedMemoryBuffer.h"
+
+namespace android {
+
+SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem)
+    : MediaCodecBuffer(format, new ABuffer(mem->pointer(), mem->size())),
+      mMemory(mem) {
+}
+
+}  // namespace android
diff --git a/media/libstagefright/DataConverter.cpp b/media/libstagefright/DataConverter.cpp
index aea47f3..52be054 100644
--- a/media/libstagefright/DataConverter.cpp
+++ b/media/libstagefright/DataConverter.cpp
@@ -21,13 +21,13 @@
 
 #include <audio_utils/primitives.h>
 
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
 
 namespace android {
 
-status_t DataConverter::convert(const sp<ABuffer> &source, sp<ABuffer> &target) {
+status_t DataConverter::convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
     CHECK(source->base() != target->base());
     size_t size = targetSize(source->size());
     status_t err = OK;
@@ -43,7 +43,8 @@
     return err;
 }
 
-status_t DataConverter::safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target) {
+status_t DataConverter::safeConvert(
+        const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
     memcpy(target->base(), source->data(), source->size());
     return OK;
 }
@@ -101,7 +102,7 @@
     return NULL;
 }
 
-status_t AudioConverter::safeConvert(const sp<ABuffer> &src, sp<ABuffer> &tgt) {
+status_t AudioConverter::safeConvert(const sp<MediaCodecBuffer> &src, sp<MediaCodecBuffer> &tgt) {
     if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcm16bit) {
         memcpy_to_u8_from_i16((uint8_t*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
     } else if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcmFloat) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f6763a0..fc9f644 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,7 @@
 #include <inttypes.h>
 
 #include "include/avc_utils.h"
+#include "include/SharedMemoryBuffer.h"
 #include "include/SoftwareRenderer.h"
 
 #include <binder/IMemory.h>
@@ -30,6 +31,7 @@
 #include <media/ICrypto.h>
 #include <media/IOMX.h>
 #include <media/IResourceManagerService.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -860,7 +862,7 @@
     return OK;
 }
 
-status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
     msg->setInt32("portIndex", kPortIndexInput);
     msg->setPointer("buffers", buffers);
@@ -870,7 +872,7 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
-status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
     msg->setInt32("portIndex", kPortIndexInput);
     msg->setPointer("buffers", buffers);
@@ -879,7 +881,7 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
-status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
     msg->setInt32("portIndex", kPortIndexOutput);
     msg->setPointer("buffers", buffers);
@@ -888,17 +890,17 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
-status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
+status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
     sp<AMessage> format;
     return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
 }
 
 status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
     return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
 }
 
-status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
+status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
     sp<AMessage> format;
     return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
 }
@@ -909,7 +911,7 @@
 
 status_t MediaCodec::getBufferAndFormat(
         size_t portIndex, size_t index,
-        sp<ABuffer> *buffer, sp<AMessage> *format) {
+        sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
     // use mutex instead of a context switch
     if (mReleasedByResourceManager) {
         ALOGE("getBufferAndFormat - resource already released");
@@ -917,7 +919,7 @@
     }
 
     if (buffer == NULL) {
-        ALOGE("getBufferAndFormat - null ABuffer");
+        ALOGE("getBufferAndFormat - null MediaCodecBuffer");
         return INVALID_OPERATION;
     }
 
@@ -956,7 +958,6 @@
     *buffer = (portIndex == kPortIndexInput && mCrypto != NULL) ?
                   info.mEncryptedData :
                   info.mData;
-
     *format = info.mFormat;
 
     return OK;
@@ -1046,7 +1047,7 @@
             return false;
         }
 
-        const sp<ABuffer> &buffer =
+        const sp<MediaCodecBuffer> &buffer =
             mPortBuffers[kPortIndexOutput].itemAt(index).mData;
 
         response->setSize("index", index);
@@ -1377,7 +1378,7 @@
                         if (portIndex == kPortIndexInput && mCrypto != NULL) {
                             sp<IMemory> mem = mDealer->allocate(info.mData->capacity());
                             info.mEncryptedData =
-                                new ABuffer(mem->pointer(), info.mData->capacity());
+                                new SharedMemoryBuffer(mInputFormat, mem);
                             info.mSharedEncryptedBuffer = mem;
                         }
 
@@ -1484,6 +1485,9 @@
                         break;
                     }
 
+                    // TODO: hold reference of buffer from downstream when
+                    // mPortBuffers is removed.
+
                     if (!mCSD.empty()) {
                         ssize_t index = dequeuePortBuffer(kPortIndexInput);
                         CHECK_GE(index, 0);
@@ -1539,8 +1543,10 @@
                         break;
                     }
 
-                    sp<ABuffer> buffer;
-                    CHECK(msg->findBuffer("buffer", &buffer));
+                    sp<RefBase> obj;
+                    CHECK(msg->findObject("buffer", &obj));
+                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+                    // TODO: hold buffer's reference when we remove mPortBuffers
 
                     int32_t omxFlags;
                     CHECK(msg->findInt32("flags", &omxFlags));
@@ -2156,7 +2162,7 @@
             int32_t portIndex;
             CHECK(msg->findInt32("portIndex", &portIndex));
 
-            Vector<sp<ABuffer> > *dstBuffers;
+            Vector<sp<MediaCodecBuffer> > *dstBuffers;
             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
 
             dstBuffers->clear();
@@ -2306,7 +2312,7 @@
     sp<ABuffer> csd = *mCSD.begin();
     mCSD.erase(mCSD.begin());
 
-    const sp<ABuffer> &codecInputData =
+    const sp<MediaCodecBuffer> &codecInputData =
         (mCrypto != NULL) ? info->mEncryptedData : info->mData;
 
     if (csd->size() > codecInputData->capacity()) {
@@ -2553,13 +2559,14 @@
 
         info->mData->setRange(0, result);
     }
+    // TODO: release buffer reference.
 
     // synchronization boundary for getBufferAndFormat
     {
         Mutex::Autolock al(mBufferLock);
         info->mOwnedByClient = false;
     }
-    reply->setBuffer("buffer", info->mData);
+    reply->setObject("buffer", info->mData);
     reply->post();
 
     info->mNotify = NULL;
@@ -2644,8 +2651,10 @@
         }
     }
 
+    info->mNotify->setObject("buffer", info->mData);
+    // TODO: release buffer reference.
     info->mNotify->post();
-    info->mNotify = NULL;
+    info->mNotify.clear();
 
     return OK;
 }
@@ -2765,7 +2774,7 @@
 void MediaCodec::onOutputBufferAvailable() {
     int32_t index;
     while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
-        const sp<ABuffer> &buffer =
+        const sp<MediaCodecBuffer> &buffer =
             mPortBuffers[kPortIndexOutput].itemAt(index).mData;
         sp<AMessage> msg = mCallback->dup();
         msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
@@ -2866,7 +2875,7 @@
 }
 
 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
-        const sp<ABuffer> &buffer) {
+        const sp<MediaCodecBuffer> &buffer) {
     AString mime;
     CHECK(mOutputFormat->findString("mime", &mime));
 
@@ -2900,7 +2909,10 @@
     } else {
         // For everything else we just stash the codec specific data into
         // the output format as a single piece of csd under "csd-0".
-        mOutputFormat->setBuffer("csd-0", buffer);
+        sp<ABuffer> csd = new ABuffer(buffer->size());
+        memcpy(csd->data(), buffer->data(), buffer->size());
+        csd->setRange(0, buffer->size());
+        mOutputFormat->setBuffer("csd-0", csd);
     }
 
     return OK;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 8afb7e9..1f869b1 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -196,9 +196,7 @@
     if (mInitCheck != OK) {
         return;  // this may fail if IMediaPlayerService is not available.
     }
-    mOMX = client.interface();
     parseXMLFile(codecs_xml);
-    mOMX.clear();
 
     if (mInitCheck != OK) {
         if (ignore_errors) {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 30b078f..030c505 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -24,6 +24,7 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -689,7 +690,7 @@
 #endif // DEBUG_DRIFT_TIME
             }
 
-            sp<ABuffer> inbuf;
+            sp<MediaCodecBuffer> inbuf;
             status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
             if (err != OK || inbuf == NULL) {
                 mbuf->release();
@@ -851,7 +852,7 @@
                 break;
             }
 
-            sp<ABuffer> outbuf;
+            sp<MediaCodecBuffer> outbuf;
             status_t err = mEncoder->getOutputBuffer(index, &outbuf);
             if (err != OK || outbuf == NULL) {
                 signalEOS();
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 05ad2e8..a29aff0 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -24,513 +24,18 @@
 #include <utils/Log.h>
 
 #include <binder/IServiceManager.h>
-#include <media/IMediaPlayerService.h>
 #include <media/IMediaCodecService.h>
-#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/OMXClient.h>
-#include <cutils/properties.h>
-#include <utils/KeyedVector.h>
 
 #include "include/OMX.h"
 
 namespace android {
 
-static bool sCodecProcessEnabled = true;
-
-struct MuxOMX : public IOMX {
-    MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
-    virtual ~MuxOMX();
-
-    // Nobody should be calling this. In case someone does anyway, just
-    // return the media server IOMX.
-    // TODO: return NULL
-    virtual IBinder *onAsBinder() {
-        ALOGE("MuxOMX::onAsBinder should not be called");
-        return IInterface::asBinder(mMediaServerOMX).get();
-    }
-
-    virtual bool livesLocally(node_id node, pid_t pid);
-
-    virtual status_t listNodes(List<ComponentInfo> *list);
-
-    virtual status_t allocateNode(
-            const char *name, const sp<IOMXObserver> &observer,
-            sp<IBinder> *nodeBinder,
-            node_id *node);
-
-    virtual status_t freeNode(node_id node);
-
-    virtual status_t sendCommand(
-            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
-
-    virtual status_t getParameter(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size);
-
-    virtual status_t setParameter(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size);
-
-    virtual status_t getConfig(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size);
-
-    virtual status_t setConfig(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size);
-
-    virtual status_t getState(
-            node_id node, OMX_STATETYPE* state);
-
-    virtual status_t storeMetaDataInBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
-
-    virtual status_t prepareForAdaptivePlayback(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable,
-            OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
-
-    virtual status_t configureVideoTunnelMode(
-            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
-            OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
-
-    virtual status_t enableNativeBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable);
-
-    virtual status_t getGraphicBufferUsage(
-            node_id node, OMX_U32 port_index, OMX_U32* usage);
-
-    virtual status_t useBuffer(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize);
-
-    virtual status_t useGraphicBuffer(
-            node_id node, OMX_U32 port_index,
-            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
-
-    virtual status_t updateGraphicBufferInMeta(
-            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,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
-
-    virtual status_t createPersistentInputSurface(
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer);
-
-    virtual status_t setInputSurface(
-            node_id node, OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
-
-    virtual status_t allocateSecureBuffer(
-            node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle);
-
-    virtual status_t allocateBufferWithBackup(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize);
-
-    virtual status_t freeBuffer(
-            node_id node, OMX_U32 port_index, buffer_id buffer);
-
-    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
-
-    virtual status_t emptyBuffer(
-            node_id node,
-            buffer_id buffer,
-            OMX_U32 range_offset, OMX_U32 range_length,
-            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
-
-    virtual status_t emptyGraphicBuffer(
-            node_id node,
-            buffer_id buffer,
-            const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
-            OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd);
-
-    virtual status_t getExtensionIndex(
-            node_id node,
-            const char *parameter_name,
-            OMX_INDEXTYPE *index);
-
-    virtual status_t dispatchMessage(const omx_message &msg);
-
-private:
-    mutable Mutex mLock;
-
-    sp<IOMX> mMediaServerOMX;
-    sp<IOMX> mMediaCodecOMX;
-    sp<IOMX> mLocalOMX;
-
-    typedef enum {
-        LOCAL,
-        MEDIAPROCESS,
-        CODECPROCESS
-    } node_location;
-
-    KeyedVector<node_id, node_location> mNodeLocation;
-
-    bool isLocalNode(node_id node) const;
-    bool isLocalNode_l(node_id node) const;
-    const sp<IOMX> &getOMX(node_id node) const;
-    const sp<IOMX> &getOMX_l(node_id node) const;
-
-    static node_location getPreferredCodecLocation(const char *name);
-
-    DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
-};
-
-MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
-    : mMediaServerOMX(mediaServerOMX),
-      mMediaCodecOMX(mediaCodecOMX) {
-    ALOGI("MuxOMX ctor");
-}
-
-MuxOMX::~MuxOMX() {
-}
-
-bool MuxOMX::isLocalNode(node_id node) const {
-    Mutex::Autolock autoLock(mLock);
-
-    return isLocalNode_l(node);
-}
-
-bool MuxOMX::isLocalNode_l(node_id node) const {
-    return mNodeLocation.valueFor(node) == LOCAL;
-}
-
-// static
-MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
-    if (sCodecProcessEnabled) {
-        // all codecs go to codec process unless excluded using system property, in which case
-        // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process
-        // (non-OMX.google.* encoders can be excluded using system property.)
-        if ((strcasestr(name, "decoder")
-                        && strcasestr(name, ".secure") != name + strlen(name) - 7)
-                || (strcasestr(name, "encoder")
-                        && !property_get_bool("media.stagefright.legacyencoder", false))
-                || !property_get_bool("media.stagefright.less-secure", false)
-                || !strncasecmp(name, "OMX.google.", 11)) {
-            return CODECPROCESS;
-        }
-        // everything else runs in the media server
-        return MEDIAPROCESS;
-    } else {
-#ifdef __LP64__
-        // 64 bit processes always run OMX remote on MediaServer
-        return MEDIAPROCESS;
-#else
-        // 32 bit processes run only OMX.google.* components locally
-        if (!strncasecmp(name, "OMX.google.", 11)) {
-            return LOCAL;
-        }
-        return MEDIAPROCESS;
-#endif
-    }
-}
-
-const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
-    Mutex::Autolock autoLock(mLock);
-    return getOMX_l(node);
-}
-
-const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
-    node_location loc = mNodeLocation.valueFor(node);
-    if (loc == LOCAL) {
-        return mLocalOMX;
-    } else if (loc == MEDIAPROCESS) {
-        return mMediaServerOMX;
-    } else if (loc == CODECPROCESS) {
-        return mMediaCodecOMX;
-    }
-    ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
-    return mLocalOMX;
-}
-
-bool MuxOMX::livesLocally(node_id node, pid_t pid) {
-    return getOMX(node)->livesLocally(node, pid);
-}
-
-status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mLocalOMX == NULL) {
-        mLocalOMX = new OMX;
-    }
-
-    return mLocalOMX->listNodes(list);
-}
-
-status_t MuxOMX::allocateNode(
-        const char *name, const sp<IOMXObserver> &observer,
-        sp<IBinder> *nodeBinder,
-        node_id *node) {
-    Mutex::Autolock autoLock(mLock);
-
-    sp<IOMX> omx;
-
-    node_location loc = getPreferredCodecLocation(name);
-    if (loc == CODECPROCESS) {
-        omx = mMediaCodecOMX;
-    } else if (loc == MEDIAPROCESS) {
-        omx = mMediaServerOMX;
-    } else {
-        if (mLocalOMX == NULL) {
-            mLocalOMX = new OMX;
-        }
-        omx = mLocalOMX;
-    }
-
-    status_t err = omx->allocateNode(name, observer, nodeBinder, node);
-    ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
-            omx == mMediaServerOMX ? "mediaserver" : "local");
-
-
-    if (err != OK) {
-        return err;
-    }
-
-    mNodeLocation.add(*node, loc);
-
-    return OK;
-}
-
-status_t MuxOMX::freeNode(node_id node) {
-    Mutex::Autolock autoLock(mLock);
-
-    // exit if we have already freed the node
-    if (mNodeLocation.indexOfKey(node) < 0) {
-        ALOGD("MuxOMX::freeNode: node %d seems to be released already --- ignoring.", node);
-        return OK;
-    }
-
-    status_t err = getOMX_l(node)->freeNode(node);
-
-    if (err != OK) {
-        return err;
-    }
-
-    mNodeLocation.removeItem(node);
-
-    return OK;
-}
-
-status_t MuxOMX::sendCommand(
-        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-    return getOMX(node)->sendCommand(node, cmd, param);
-}
-
-status_t MuxOMX::getParameter(
-        node_id node, OMX_INDEXTYPE index,
-        void *params, size_t size) {
-    return getOMX(node)->getParameter(node, index, params, size);
-}
-
-status_t MuxOMX::setParameter(
-        node_id node, OMX_INDEXTYPE index,
-        const void *params, size_t size) {
-    return getOMX(node)->setParameter(node, index, params, size);
-}
-
-status_t MuxOMX::getConfig(
-        node_id node, OMX_INDEXTYPE index,
-        void *params, size_t size) {
-    return getOMX(node)->getConfig(node, index, params, size);
-}
-
-status_t MuxOMX::setConfig(
-        node_id node, OMX_INDEXTYPE index,
-        const void *params, size_t size) {
-    return getOMX(node)->setConfig(node, index, params, size);
-}
-
-status_t MuxOMX::getState(
-        node_id node, OMX_STATETYPE* state) {
-    return getOMX(node)->getState(node, state);
-}
-
-status_t MuxOMX::storeMetaDataInBuffers(
-        node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
-    return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type);
-}
-
-status_t MuxOMX::prepareForAdaptivePlayback(
-        node_id node, OMX_U32 port_index, OMX_BOOL enable,
-        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
-    return getOMX(node)->prepareForAdaptivePlayback(
-            node, port_index, enable, maxFrameWidth, maxFrameHeight);
-}
-
-status_t MuxOMX::configureVideoTunnelMode(
-        node_id node, OMX_U32 portIndex, OMX_BOOL enable,
-        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
-    return getOMX(node)->configureVideoTunnelMode(
-            node, portIndex, enable, audioHwSync, sidebandHandle);
-}
-
-status_t MuxOMX::enableNativeBuffers(
-        node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
-    return getOMX(node)->enableNativeBuffers(node, port_index, graphic, enable);
-}
-
-status_t MuxOMX::getGraphicBufferUsage(
-        node_id node, OMX_U32 port_index, OMX_U32* usage) {
-    return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
-}
-
-status_t MuxOMX::useBuffer(
-        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-        buffer_id *buffer, OMX_U32 allottedSize) {
-    return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
-}
-
-status_t MuxOMX::useGraphicBuffer(
-        node_id node, OMX_U32 port_index,
-        const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
-    return getOMX(node)->useGraphicBuffer(
-            node, port_index, graphicBuffer, buffer);
-}
-
-status_t MuxOMX::updateGraphicBufferInMeta(
-        node_id node, OMX_U32 port_index,
-        const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
-    return getOMX(node)->updateGraphicBufferInMeta(
-            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,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    status_t err = getOMX(node)->createInputSurface(
-            node, port_index, dataSpace, bufferProducer, bufferSource, type);
-    return err;
-}
-
-status_t MuxOMX::createPersistentInputSurface(
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferConsumer> *bufferConsumer) {
-    sp<IOMX> omx;
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (property_get_bool("media.stagefright.legacyencoder", false)) {
-            omx = mMediaServerOMX;
-        } else {
-            omx = mMediaCodecOMX;
-        }
-    }
-    return omx->createPersistentInputSurface(
-            bufferProducer, bufferConsumer);
-}
-
-status_t MuxOMX::setInputSurface(
-        node_id node, OMX_U32 port_index,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, bufferSource, type);
-}
-
-status_t MuxOMX::allocateSecureBuffer(
-        node_id node, OMX_U32 port_index, size_t size,
-        buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
-    return getOMX(node)->allocateSecureBuffer(
-            node, port_index, size, buffer, buffer_data, native_handle);
-}
-
-status_t MuxOMX::allocateBufferWithBackup(
-        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-        buffer_id *buffer, OMX_U32 allottedSize) {
-    return getOMX(node)->allocateBufferWithBackup(
-            node, port_index, params, buffer, allottedSize);
-}
-
-status_t MuxOMX::freeBuffer(
-        node_id node, OMX_U32 port_index, buffer_id buffer) {
-    return getOMX(node)->freeBuffer(node, port_index, buffer);
-}
-
-status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
-    return getOMX(node)->fillBuffer(node, buffer, fenceFd);
-}
-
-status_t MuxOMX::emptyBuffer(
-        node_id node,
-        buffer_id buffer,
-        OMX_U32 range_offset, OMX_U32 range_length,
-        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    return getOMX(node)->emptyBuffer(
-            node, buffer, range_offset, range_length, flags, timestamp, fenceFd);
-}
-
-status_t MuxOMX::emptyGraphicBuffer(
-        node_id node,
-        buffer_id buffer,
-        const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
-        OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
-    return getOMX(node)->emptyGraphicBuffer(
-            node, buffer, graphicBuffer, flags, timestamp, origTimestamp, fenceFd);
-}
-
-status_t MuxOMX::getExtensionIndex(
-        node_id node,
-        const char *parameter_name,
-        OMX_INDEXTYPE *index) {
-    return getOMX(node)->getExtensionIndex(node, parameter_name, index);
-}
-
-status_t MuxOMX::dispatchMessage(const omx_message &msg) {
-    return getOMX(msg.node)->dispatchMessage(msg);
-}
-
 OMXClient::OMXClient() {
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.codecremote", value, NULL)
-            && (!strcmp("0", value) || !strcasecmp("false", value))) {
-        sCodecProcessEnabled = false;
-    }
 }
 
 status_t OMXClient::connect() {
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> playerbinder = sm->getService(String16("media.player"));
-    sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
-
-    if (mediaservice.get() == NULL) {
-        ALOGE("Cannot obtain IMediaPlayerService");
-        return NO_INIT;
-    }
-
-    sp<IOMX> mediaServerOMX = mediaservice->getOMX();
-    if (mediaServerOMX.get() == NULL) {
-        ALOGE("Cannot obtain mediaserver IOMX");
-        return NO_INIT;
-    }
-
-    // If we don't want to use the codec process, and the media server OMX
-    // is local, use it directly instead of going through MuxOMX
-    if (!sCodecProcessEnabled &&
-            mediaServerOMX->livesLocally(0 /* node */, getpid())) {
-        mOMX = mediaServerOMX;
-        return OK;
-    }
-
     sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
     sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
 
@@ -539,22 +44,17 @@
         return NO_INIT;
     }
 
-    sp<IOMX> mediaCodecOMX = codecservice->getOMX();
-    if (mediaCodecOMX.get() == NULL) {
+    mOMX = codecservice->getOMX();
+    if (mOMX.get() == NULL) {
         ALOGE("Cannot obtain mediacodec IOMX");
         return NO_INIT;
     }
 
-    mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
-
     return OK;
 }
 
 void OMXClient::disconnect() {
-    if (mOMX.get() != NULL) {
-        mOMX.clear();
-        mOMX = NULL;
-    }
+    mOMX.clear();
 }
 
 }  // namespace android
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index de21c5e..4c4d93e 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -17,7 +17,7 @@
 #include <gui/Surface.h>
 
 #include <media/ICrypto.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -225,7 +225,7 @@
                 break;
             }
 
-            sp<ABuffer> in_buffer;
+            sp<MediaCodecBuffer> in_buffer;
             if (res == OK) {
                 res = mCodec->getInputBuffer(in_ix, &in_buffer);
             }
@@ -330,7 +330,7 @@
             return res;
         }
 
-        sp<ABuffer> out_buffer;
+        sp<MediaCodecBuffer> out_buffer;
         res = mCodec->getOutputBuffer(out_ix, &out_buffer);
         if (res != OK) {
             ALOGW("[%s] could not get output buffer #%zu",
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
index d30be88..ee9016d 100644
--- a/media/libstagefright/SkipCutBuffer.cpp
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -88,7 +88,8 @@
     buffer->set_range(0, copied);
 }
 
-void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
+template <typename T>
+void SkipCutBuffer::submitInternal(const sp<T>& buffer) {
     if (mCutBuffer == NULL) {
         // passthrough mode
         return;
@@ -120,6 +121,14 @@
     buffer->setRange(0, copied);
 }
 
+void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
+    submitInternal(buffer);
+}
+
+void SkipCutBuffer::submit(const sp<MediaCodecBuffer>& buffer) {
+    submitInternal(buffer);
+}
+
 void SkipCutBuffer::clear() {
     mWriteHead = mReadHead = 0;
     mFrontPadding = mSkip;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index be5067d..773f3ed 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -27,8 +27,8 @@
 
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
 
-#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/ColorConverter.h>
@@ -223,7 +223,7 @@
         return NULL;
     }
 
-    Vector<sp<ABuffer> > inputBuffers;
+    Vector<sp<MediaCodecBuffer> > inputBuffers;
     err = decoder->getInputBuffers(&inputBuffers);
     if (err != OK) {
         ALOGW("failed to get input buffers: %d (%s)", err, asString(err));
@@ -232,7 +232,7 @@
         return NULL;
     }
 
-    Vector<sp<ABuffer> > outputBuffers;
+    Vector<sp<MediaCodecBuffer> > outputBuffers;
     err = decoder->getOutputBuffers(&outputBuffers);
     if (err != OK) {
         ALOGW("failed to get output buffers: %d (%s)", err, asString(err));
@@ -264,7 +264,7 @@
         size_t inputIndex = -1;
         int64_t ptsUs = 0ll;
         uint32_t flags = 0;
-        sp<ABuffer> codecBuffer = NULL;
+        sp<MediaCodecBuffer> codecBuffer = NULL;
 
         while (haveMoreInputs) {
             err = decoder->dequeueInputBuffer(&inputIndex, kBufferTimeOutUs);
@@ -376,7 +376,7 @@
     }
 
     ALOGV("successfully decoded video frame.");
-    sp<ABuffer> videoFrameBuffer = outputBuffers.itemAt(index);
+    sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index);
 
     if (thumbNailTime >= 0) {
         if (timeUs != thumbNailTime) {
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 15ff569..4f1ef30 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -112,7 +112,7 @@
     Mutex::Autolock lock(mMutex);
 
     result.append(buffer);
-    mConsumer->dump(result, "");
+    mConsumer->dumpState(result, "");
 }
 
 status_t SurfaceMediaSource::setFrameRate(int32_t fps)
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 0396dc6..9f15cf7 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -447,7 +447,8 @@
     return meta;
 }
 
-bool IsIDR(const sp<ABuffer> &buffer) {
+template <typename T>
+bool IsIDRInternal(const sp<T> &buffer) {
     const uint8_t *data = buffer->data();
     size_t size = buffer->size();
 
@@ -469,6 +470,14 @@
     return foundIDR;
 }
 
+bool IsIDR(const sp<ABuffer> &buffer) {
+    return IsIDRInternal(buffer);
+}
+
+bool IsIDR(const sp<MediaCodecBuffer> &buffer) {
+    return IsIDRInternal(buffer);
+}
+
 bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
     const uint8_t *data = accessUnit->data();
     size_t size = accessUnit->size();
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.cpp b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
index cbcf699..e00afd9 100644
--- a/media/libstagefright/filters/IntrinsicBlurFilter.cpp
+++ b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
@@ -19,7 +19,7 @@
 
 #include <utils/Log.h>
 
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -88,7 +88,7 @@
 }
 
 status_t IntrinsicBlurFilter::processBuffers(
-        const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
     mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
     mBlur->forEach(mAllocOut);
     mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/IntrinsicBlurFilter.h
index 4707ab7..a2aabfa 100644
--- a/media/libstagefright/filters/IntrinsicBlurFilter.h
+++ b/media/libstagefright/filters/IntrinsicBlurFilter.h
@@ -31,7 +31,7 @@
     virtual void reset();
     virtual status_t setParameters(const sp<AMessage> &msg);
     virtual status_t processBuffers(
-            const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
 
 protected:
     virtual ~IntrinsicBlurFilter() {};
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index cd69418..f26c840 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -31,6 +31,8 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaFilter.h>
 
+#include <media/MediaCodecBuffer.h>
+
 #include <gui/BufferItem.h>
 
 #include "ColorConvert.h"
@@ -40,6 +42,8 @@
 #include "SaturationFilter.h"
 #include "ZeroFilter.h"
 
+#include "../include/SharedMemoryBuffer.h"
+
 namespace android {
 
 // parameter: number of input and output buffers
@@ -195,7 +199,7 @@
 }
 
 void MediaFilter::PortDescription::addBuffer(
-        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
+        IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer) {
     mBufferIDs.push_back(id);
     mBuffers.push_back(buffer);
 }
@@ -208,7 +212,7 @@
     return mBufferIDs.itemAt(index);
 }
 
-sp<ABuffer> MediaFilter::PortDescription::bufferAt(size_t index) const {
+sp<MediaCodecBuffer> MediaFilter::PortDescription::bufferAt(size_t index) const {
     return mBuffers.itemAt(index);
 }
 
@@ -250,7 +254,8 @@
         info.mBufferID = i;
         info.mGeneration = mGeneration;
         info.mOutputFlags = 0;
-        info.mData = new ABuffer(mem->pointer(), bufferSize);
+        info.mData = new SharedMemoryBuffer(
+                isInput ? mInputFormat : mOutputFormat, mem);
         info.mData->meta()->setInt64("timeUs", 0);
 
         mBuffers[portIndex].push_back(info);
@@ -314,7 +319,7 @@
     notify->setInt32("buffer-id", info->mBufferID);
 
     info->mData->meta()->clear();
-    notify->setBuffer("buffer", info->mData);
+    notify->setObject("buffer", info->mData);
 
     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
     reply->setInt32("buffer-id", info->mBufferID);
@@ -334,7 +339,7 @@
     notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
     notify->setInt32("buffer-id", info->mBufferID);
     notify->setInt32("flags", info->mOutputFlags);
-    notify->setBuffer("buffer", info->mData);
+    notify->setObject("buffer", info->mData);
 
     sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
     reply->setInt32("buffer-id", info->mBufferID);
@@ -597,11 +602,12 @@
     CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
     info->mStatus = BufferInfo::OWNED_BY_US;
 
-    sp<ABuffer> buffer;
+    sp<MediaCodecBuffer> buffer;
     int32_t err = OK;
     bool eos = false;
 
-    if (!msg->findBuffer("buffer", &buffer)) {
+    sp<RefBase> obj;
+    if (!msg->findObject("buffer", &obj)) {
         // these are unfilled buffers returned by client
         CHECK(msg->findInt32("err", &err));
 
@@ -616,6 +622,8 @@
         }
 
         buffer.clear();
+    } else {
+        buffer = static_cast<MediaCodecBuffer *>(obj.get());
     }
 
     int32_t isCSD;
@@ -768,7 +776,8 @@
     // TODO: check input format and convert only if necessary
     // copy RGBA graphic buffer into temporary ARGB input buffer
     BufferInfo *inputInfo = new BufferInfo;
-    inputInfo->mData = new ABuffer(buf->getWidth() * buf->getHeight() * 4);
+    inputInfo->mData = new MediaCodecBuffer(
+            mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
     ALOGV("Copying surface data into temp buffer.");
     convertRGBAToARGB(
             (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
diff --git a/media/libstagefright/filters/RSFilter.cpp b/media/libstagefright/filters/RSFilter.cpp
index b569945..225a375 100644
--- a/media/libstagefright/filters/RSFilter.cpp
+++ b/media/libstagefright/filters/RSFilter.cpp
@@ -19,7 +19,7 @@
 
 #include <utils/Log.h>
 
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -85,7 +85,7 @@
 }
 
 status_t RSFilter::processBuffers(
-        const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
     mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
     mCallback->processBuffers(mAllocIn.get(), mAllocOut.get());
     mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/RSFilter.h b/media/libstagefright/filters/RSFilter.h
index c5b5074..3326284 100644
--- a/media/libstagefright/filters/RSFilter.h
+++ b/media/libstagefright/filters/RSFilter.h
@@ -35,7 +35,7 @@
     virtual void reset();
     virtual status_t setParameters(const sp<AMessage> &msg);
     virtual status_t processBuffers(
-            const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
 
 protected:
     virtual ~RSFilter();
diff --git a/media/libstagefright/filters/SaturationFilter.cpp b/media/libstagefright/filters/SaturationFilter.cpp
index ba5f75a..0a1df05 100644
--- a/media/libstagefright/filters/SaturationFilter.cpp
+++ b/media/libstagefright/filters/SaturationFilter.cpp
@@ -19,7 +19,7 @@
 
 #include <utils/Log.h>
 
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -88,7 +88,7 @@
 }
 
 status_t SaturationFilter::processBuffers(
-        const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
     mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
     mScript->forEach_root(mAllocIn, mAllocOut);
     mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/SaturationFilter.h b/media/libstagefright/filters/SaturationFilter.h
index 0545021..317e469 100644
--- a/media/libstagefright/filters/SaturationFilter.h
+++ b/media/libstagefright/filters/SaturationFilter.h
@@ -33,7 +33,7 @@
     virtual void reset();
     virtual status_t setParameters(const sp<AMessage> &msg);
     virtual status_t processBuffers(
-            const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
 
 protected:
     virtual ~SaturationFilter() {};
diff --git a/media/libstagefright/filters/SimpleFilter.h b/media/libstagefright/filters/SimpleFilter.h
index 4cd37ef..a3c2d76 100644
--- a/media/libstagefright/filters/SimpleFilter.h
+++ b/media/libstagefright/filters/SimpleFilter.h
@@ -21,11 +21,11 @@
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
-struct ABuffer;
-struct AMessage;
-
 namespace android {
 
+struct AMessage;
+class MediaCodecBuffer;
+
 struct SimpleFilter : public RefBase {
 public:
     SimpleFilter() : mWidth(0), mHeight(0), mStride(0), mSliceHeight(0),
@@ -37,7 +37,7 @@
     virtual void reset() = 0;
     virtual status_t setParameters(const sp<AMessage> &msg) = 0;
     virtual status_t processBuffers(
-            const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) = 0;
+            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) = 0;
 
 protected:
     int32_t mWidth, mHeight;
diff --git a/media/libstagefright/filters/ZeroFilter.cpp b/media/libstagefright/filters/ZeroFilter.cpp
index 3f1243c..74b94b7 100644
--- a/media/libstagefright/filters/ZeroFilter.cpp
+++ b/media/libstagefright/filters/ZeroFilter.cpp
@@ -17,7 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ZeroFilter"
 
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -38,7 +38,7 @@
 }
 
 status_t ZeroFilter::processBuffers(
-        const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
     // assuming identical input & output buffers, since we're a copy filter
     if (mInvertData) {
         uint32_t* src = (uint32_t*)srcBuffer->data();
diff --git a/media/libstagefright/filters/ZeroFilter.h b/media/libstagefright/filters/ZeroFilter.h
index bd34dfb..f941cc8 100644
--- a/media/libstagefright/filters/ZeroFilter.h
+++ b/media/libstagefright/filters/ZeroFilter.h
@@ -29,7 +29,7 @@
     virtual void reset() {};
     virtual status_t setParameters(const sp<AMessage> &msg);
     virtual status_t processBuffers(
-            const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
 
 protected:
     virtual ~ZeroFilter() {};
diff --git a/media/libstagefright/include/DataConverter.h b/media/libstagefright/include/DataConverter.h
index 8d67921..60ebad1 100644
--- a/media/libstagefright/include/DataConverter.h
+++ b/media/libstagefright/include/DataConverter.h
@@ -24,18 +24,18 @@
 
 namespace android {
 
-struct ABuffer;
+class MediaCodecBuffer;
 
 // DataConverter base class, defaults to memcpy
 struct DataConverter : public RefBase {
     virtual size_t sourceSize(size_t targetSize); // will clamp to SIZE_MAX
     virtual size_t targetSize(size_t sourceSize); // will clamp to SIZE_MAX
 
-    status_t convert(const sp<ABuffer> &source, sp<ABuffer> &target);
+    status_t convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
     virtual ~DataConverter();
 
 protected:
-    virtual status_t safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target);
+    virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
 };
 
 // SampleConverterBase uses a ratio to calculate the source and target sizes
@@ -45,7 +45,7 @@
     virtual size_t targetSize(size_t sourceSize);
 
 protected:
-    virtual status_t safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target) = 0;
+    virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) = 0;
 
     // sourceSize = sourceSampleSize / targetSampleSize * targetSize
     SampleConverterBase(uint32_t sourceSampleSize, uint32_t targetSampleSize)
@@ -61,7 +61,7 @@
     static AudioConverter *Create(AudioEncoding source, AudioEncoding target);
 
 protected:
-    virtual status_t safeConvert(const sp<ABuffer> &src, sp<ABuffer> &tgt);
+    virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
 
 private:
     AudioConverter(
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 3af59ae..1ef180f 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -31,159 +31,28 @@
 public:
     OMX();
 
-    virtual bool livesLocally(node_id node, pid_t pid);
-
     virtual status_t listNodes(List<ComponentInfo> *list);
 
     virtual status_t allocateNode(
             const char *name, const sp<IOMXObserver> &observer,
-            sp<IBinder> *nodeBinder,
-            node_id *node);
-
-    virtual status_t freeNode(node_id node);
-
-    virtual status_t sendCommand(
-            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
-
-    virtual status_t getParameter(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size);
-
-    virtual status_t setParameter(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size);
-
-    virtual status_t getConfig(
-            node_id node, OMX_INDEXTYPE index,
-            void *params, size_t size);
-
-    virtual status_t setConfig(
-            node_id node, OMX_INDEXTYPE index,
-            const void *params, size_t size);
-
-    virtual status_t getState(
-            node_id node, OMX_STATETYPE* state);
-
-    virtual status_t enableNativeBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable);
-
-    virtual status_t getGraphicBufferUsage(
-            node_id node, OMX_U32 port_index, OMX_U32* usage);
-
-    virtual status_t storeMetaDataInBuffers(
-            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
-
-    virtual status_t prepareForAdaptivePlayback(
-            node_id node, OMX_U32 portIndex, OMX_BOOL enable,
-            OMX_U32 max_frame_width, OMX_U32 max_frame_height);
-
-    virtual status_t configureVideoTunnelMode(
-            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
-            OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
-
-    virtual status_t useBuffer(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize);
-
-    virtual status_t useGraphicBuffer(
-            node_id node, OMX_U32 port_index,
-            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
-
-    virtual status_t updateGraphicBufferInMeta(
-            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,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
+            sp<IBinder> *nodeBinder, sp<IOMXNode> *omxNode);
 
     virtual status_t createPersistentInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer);
 
-    virtual status_t setInputSurface(
-            node_id node, OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
-
-    virtual status_t allocateSecureBuffer(
-            node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle);
-
-    virtual status_t allocateBufferWithBackup(
-            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-            buffer_id *buffer, OMX_U32 allottedSize);
-
-    virtual status_t freeBuffer(
-            node_id node, OMX_U32 port_index, buffer_id buffer);
-
-    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
-
-    virtual status_t emptyBuffer(
-            node_id node,
-            buffer_id buffer,
-            OMX_U32 range_offset, OMX_U32 range_length,
-            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
-
-    virtual status_t emptyGraphicBuffer(
-            node_id node,
-            buffer_id buffer,
-            const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
-            OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd);
-
-    virtual status_t getExtensionIndex(
-            node_id node,
-            const char *parameter_name,
-            OMX_INDEXTYPE *index);
-
-    virtual status_t dispatchMessage(const omx_message &msg);
-
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
-    virtual bool isSecure(IOMX::node_id node);
-
-    OMX_ERRORTYPE OnEvent(
-            node_id node,
-            OMX_IN OMX_EVENTTYPE eEvent,
-            OMX_IN OMX_U32 nData1,
-            OMX_IN OMX_U32 nData2,
-            OMX_IN OMX_PTR pEventData);
-
-    OMX_ERRORTYPE OnEmptyBufferDone(
-            node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd);
-
-    OMX_ERRORTYPE OnFillBufferDone(
-            node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd);
-
-    void invalidateNodeID(node_id node);
+    status_t freeNode(const sp<OMXNodeInstance>& instance);
 
 protected:
     virtual ~OMX();
 
 private:
-    struct CallbackDispatcherThread;
-    struct CallbackDispatcher;
-
     Mutex mLock;
     OMXMaster *mMaster;
-    size_t mNodeCounter;
 
-    KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
-    KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
-    KeyedVector<node_id, sp<CallbackDispatcher> > mDispatchers;
-
-    node_id makeNodeID_l(OMXNodeInstance *instance);
-    OMXNodeInstance *findInstance(node_id node);
-    sp<CallbackDispatcher> findDispatcher(node_id node);
-
-    void invalidateNodeID_l(node_id node);
+    KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
 
     OMX(const OMX &);
     OMX &operator=(const OMX &);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index e4f204e..79643d6 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -30,17 +30,16 @@
 class IOMXObserver;
 struct OMXMaster;
 
-struct OMXNodeInstance {
+struct OMXNodeInstance : public BnOMXNode {
     OMXNodeInstance(
             OMX *owner, const sp<IOMXObserver> &observer, const char *name);
 
-    void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
+    void setHandle(OMX_HANDLETYPE handle);
 
-    OMX *owner();
+    OMX_HANDLETYPE handle();
     sp<IOMXObserver> observer();
-    OMX::node_id nodeID();
 
-    status_t freeNode(OMXMaster *master);
+    status_t freeNode() override;
 
     status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
     status_t getParameter(OMX_INDEXTYPE index, void *params, size_t size);
@@ -129,21 +128,25 @@
         return mIsSecure;
     }
 
+    status_t dispatchMessage(const omx_message &msg) override;
+
     // handles messages and removes them from the list
     void onMessages(std::list<omx_message> &messages);
-    void onObserverDied(OMXMaster *master);
-    void onGetHandleFailed();
+    void onObserverDied();
     void onEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2);
 
     static OMX_CALLBACKTYPE kCallbacks;
 
 private:
+    struct CallbackDispatcherThread;
+    struct CallbackDispatcher;
+
     Mutex mLock;
 
     OMX *mOwner;
-    OMX::node_id mNodeID;
     OMX_HANDLETYPE mHandle;
     sp<IOMXObserver> mObserver;
+    sp<CallbackDispatcher> mDispatcher;
     bool mDying;
     bool mSailed;  // configuration is set (no more meta-mode changes)
     bool mQueriedProhibitedExtensions;
diff --git a/media/libstagefright/include/SharedMemoryBuffer.h b/media/libstagefright/include/SharedMemoryBuffer.h
new file mode 100644
index 0000000..1d7f7a6
--- /dev/null
+++ b/media/libstagefright/include/SharedMemoryBuffer.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SHARED_MEMORY_BUFFER_H_
+
+#define SHARED_MEMORY_BUFFER_H_
+
+#include <media/MediaCodecBuffer.h>
+
+namespace android {
+
+struct AMessage;
+class IMemory;
+
+/**
+ * MediaCodecBuffer implementation based on IMemory.
+ */
+class SharedMemoryBuffer : public MediaCodecBuffer {
+public:
+    SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem);
+
+    virtual ~SharedMemoryBuffer() = default;
+
+private:
+    SharedMemoryBuffer() = delete;
+
+    const sp<IMemory> mMemory;
+};
+
+}  // namespace android
+
+#endif  // SHARED_MEMORY_BUFFER_H_
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index b2ef360..d05906a 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -18,6 +18,7 @@
 
 #define AVC_UTILS_H_
 
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <utils/Errors.h>
 
@@ -84,6 +85,7 @@
 sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
 
 bool IsIDR(const sp<ABuffer> &accessUnit);
+bool IsIDR(const sp<MediaCodecBuffer> &accessUnit);
 bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit);
 uint32_t FindAVCLayerId(const uint8_t *data, size_t size);
 
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 334c5d3..25bc41c 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -105,16 +105,14 @@
 }
 
 GraphicBufferSource::GraphicBufferSource(
-        const sp<IOMX> &omx,
-        IOMX::node_id nodeID,
+        const sp<IOMXNode> &omxNode,
         uint32_t bufferWidth,
         uint32_t bufferHeight,
         uint32_t bufferCount,
         uint32_t consumerUsage,
         const sp<IGraphicBufferConsumer> &consumer) :
     mInitCheck(UNKNOWN_ERROR),
-    mOMX(omx),
-    mNodeID(nodeID),
+    mOMXNode(omxNode),
     mExecuting(false),
     mSuspended(false),
     mLastDataSpace(HAL_DATASPACE_UNKNOWN),
@@ -427,14 +425,13 @@
     if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
         omx_message msg;
         msg.type = omx_message::EVENT;
-        msg.node = mNodeID;
         msg.fenceFd = -1;
         msg.u.event_data.event = OMX_EventDataSpaceChanged;
         msg.u.event_data.data1 = mLastDataSpace;
         msg.u.event_data.data2 = ColorUtils::packToU32(mColorAspects);
         msg.u.event_data.data3 = pixelFormat;
 
-        mOMX->dispatchMessage(msg);
+        mOMXNode->dispatchMessage(msg);
     }
 }
 
@@ -702,8 +699,8 @@
     const sp<GraphicBuffer> &buffer = codecBuffer.mGraphicBuffer;
     int fenceID = item.mFence->isValid() ? item.mFence->dup() : -1;
 
-    status_t err = mOMX->emptyGraphicBuffer(
-            mNodeID, bufferID, buffer, OMX_BUFFERFLAG_ENDOFFRAME,
+    status_t err = mOMXNode->emptyGraphicBuffer(
+            bufferID, buffer, OMX_BUFFERFLAG_ENDOFFRAME,
             codecTimeUs, origTimeUs, fenceID);
 
     if (err != OK) {
@@ -736,8 +733,8 @@
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
     IOMX::buffer_id bufferID = codecBuffer.mBufferID;
 
-    status_t err = mOMX->emptyGraphicBuffer(
-            mNodeID, bufferID, NULL /* buffer */,
+    status_t err = mOMXNode->emptyGraphicBuffer(
+            bufferID, NULL /* buffer */,
             OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
             0 /* timestamp */, -1ll /* origTimestamp */, -1 /* fenceFd */);
     if (err != OK) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 16fefc4..88fab02 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -59,8 +59,7 @@
                             public BufferQueue::ConsumerListener {
 public:
     GraphicBufferSource(
-            const sp<IOMX> &omx,
-            IOMX::node_id nodeID,
+            const sp<IOMXNode> &omxNode,
             uint32_t bufferWidth,
             uint32_t bufferHeight,
             uint32_t bufferCount,
@@ -261,9 +260,8 @@
     // Used to report constructor failure.
     status_t mInitCheck;
 
-    // Pointer back to the IOMX that created us.  We send buffers here.
-    sp<IOMX> mOMX;
-    IOMX::node_id mNodeID;
+    // Pointer back to the IOMXNode that created us.  We send buffers here.
+    sp<IOMXNode> mOMXNode;
 
     // Set by omxExecuting() / omxIdling().
     bool mExecuting;
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index d867fe4..81e03ba 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -26,149 +26,18 @@
 
 #include "../include/OMXNodeInstance.h"
 
-#include <binder/IMemory.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <utils/threads.h>
 
 #include "OMXMaster.h"
 #include "OMXUtils.h"
 
-#include <OMX_AsString.h>
-#include <OMX_Component.h>
-#include <OMX_VideoExt.h>
-
 namespace android {
 
 // node ids are created by concatenating the pid with a 16-bit counter
 static size_t kMaxNodeInstances = (1 << 16);
 
-////////////////////////////////////////////////////////////////////////////////
-
-// This provides the underlying Thread used by CallbackDispatcher.
-// Note that deriving CallbackDispatcher from Thread does not work.
-
-struct OMX::CallbackDispatcherThread : public Thread {
-    explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
-        : mDispatcher(dispatcher) {
-    }
-
-private:
-    CallbackDispatcher *mDispatcher;
-
-    bool threadLoop();
-
-    CallbackDispatcherThread(const CallbackDispatcherThread &);
-    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct OMX::CallbackDispatcher : public RefBase {
-    explicit CallbackDispatcher(OMXNodeInstance *owner);
-
-    // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
-    // that a new message is available on the queue. Otherwise, the message stays on the queue, but
-    // the listener is not notified of it. It will process this message when a subsequent message
-    // is posted with |realTime| set to true.
-    void post(const omx_message &msg, bool realTime = true);
-
-    bool loop();
-
-protected:
-    virtual ~CallbackDispatcher();
-
-private:
-    Mutex mLock;
-
-    OMXNodeInstance *mOwner;
-    bool mDone;
-    Condition mQueueChanged;
-    std::list<omx_message> mQueue;
-
-    sp<CallbackDispatcherThread> mThread;
-
-    void dispatch(std::list<omx_message> &messages);
-
-    CallbackDispatcher(const CallbackDispatcher &);
-    CallbackDispatcher &operator=(const CallbackDispatcher &);
-};
-
-OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
-    : mOwner(owner),
-      mDone(false) {
-    mThread = new CallbackDispatcherThread(this);
-    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
-}
-
-OMX::CallbackDispatcher::~CallbackDispatcher() {
-    {
-        Mutex::Autolock autoLock(mLock);
-
-        mDone = true;
-        mQueueChanged.signal();
-    }
-
-    // A join on self can happen if the last ref to CallbackDispatcher
-    // is released within the CallbackDispatcherThread loop
-    status_t status = mThread->join();
-    if (status != WOULD_BLOCK) {
-        // Other than join to self, the only other error return codes are
-        // whatever readyToRun() returns, and we don't override that
-        CHECK_EQ(status, (status_t)NO_ERROR);
-    }
-}
-
-void OMX::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
-    Mutex::Autolock autoLock(mLock);
-
-    mQueue.push_back(msg);
-    if (realTime) {
-        mQueueChanged.signal();
-    }
-}
-
-void OMX::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
-    if (mOwner == NULL) {
-        ALOGV("Would have dispatched a message to a node that's already gone.");
-        return;
-    }
-    mOwner->onMessages(messages);
-}
-
-bool OMX::CallbackDispatcher::loop() {
-    for (;;) {
-        std::list<omx_message> messages;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-            while (!mDone && mQueue.empty()) {
-                mQueueChanged.wait(mLock);
-            }
-
-            if (mDone) {
-                break;
-            }
-
-            messages.swap(mQueue);
-        }
-
-        dispatch(messages);
-    }
-
-    return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool OMX::CallbackDispatcherThread::threadLoop() {
-    return mDispatcher->loop();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 OMX::OMX()
-    : mMaster(new OMXMaster),
-      mNodeCounter(0) {
+    : mMaster(new OMXMaster) {
 }
 
 OMX::~OMX() {
@@ -177,7 +46,7 @@
 }
 
 void OMX::binderDied(const wp<IBinder> &the_late_who) {
-    OMXNodeInstance *instance;
+    sp<OMXNodeInstance> instance;
 
     {
         Mutex::Autolock autoLock(mLock);
@@ -192,24 +61,9 @@
 
         instance = mLiveNodes.editValueAt(index);
         mLiveNodes.removeItemsAt(index);
-
-        index = mDispatchers.indexOfKey(instance->nodeID());
-        CHECK(index >= 0);
-        mDispatchers.removeItemsAt(index);
-
-        invalidateNodeID_l(instance->nodeID());
     }
 
-    instance->onObserverDied(mMaster);
-}
-
-bool OMX::isSecure(node_id node) {
-    OMXNodeInstance *instance = findInstance(node);
-    return (instance == NULL ? false : instance->isSecure());
-}
-
-bool OMX::livesLocally(node_id /* node */, pid_t pid) {
-    return pid == getpid();
+    instance->onObserverDied();
 }
 
 status_t OMX::listNodes(List<ComponentInfo> *list) {
@@ -242,48 +96,41 @@
 
 status_t OMX::allocateNode(
         const char *name, const sp<IOMXObserver> &observer,
-        sp<IBinder> *nodeBinder, node_id *node) {
+        sp<IBinder> *nodeBinder, sp<IOMXNode> *omxNode) {
     Mutex::Autolock autoLock(mLock);
 
-    *node = 0;
+    omxNode->clear();
     if (nodeBinder != NULL) {
         *nodeBinder = NULL;
     }
 
-    if (mNodeIDToInstance.size() == kMaxNodeInstances) {
-        // all possible node IDs are in use
+    if (mLiveNodes.size() == kMaxNodeInstances) {
         return NO_MEMORY;
     }
 
-    OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
+    sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
 
     OMX_COMPONENTTYPE *handle;
     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
             name, &OMXNodeInstance::kCallbacks,
-            instance, &handle);
+            instance.get(), &handle);
 
     if (err != OMX_ErrorNone) {
         ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
 
-        instance->onGetHandleFailed();
-
         return StatusFromOMXError(err);
     }
-
-    *node = makeNodeID_l(instance);
-    mDispatchers.add(*node, new CallbackDispatcher(instance));
-
-    instance->setHandle(*node, handle);
+    instance->setHandle(handle);
 
     mLiveNodes.add(IInterface::asBinder(observer), instance);
     IInterface::asBinder(observer)->linkToDeath(this);
 
+    *omxNode = instance;
+
     return OK;
 }
 
-status_t OMX::freeNode(node_id node) {
-    OMXNodeInstance *instance = findInstance(node);
-
+status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
     if (instance == NULL) {
         return OK;
     }
@@ -301,219 +148,13 @@
 
     IInterface::asBinder(instance->observer())->unlinkToDeath(this);
 
-    status_t err = instance->freeNode(mMaster);
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        ssize_t index = mDispatchers.indexOfKey(node);
-        CHECK(index >= 0);
-        mDispatchers.removeItemsAt(index);
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    if (instance->handle() != NULL) {
+        err = mMaster->destroyComponentInstance(
+                static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
     }
 
-    return err;
-}
-
-status_t OMX::sendCommand(
-        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->sendCommand(cmd, param);
-}
-
-status_t OMX::getParameter(
-        node_id node, OMX_INDEXTYPE index,
-        void *params, size_t size) {
-    ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size);
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->getParameter(
-            index, params, size);
-}
-
-status_t OMX::setParameter(
-        node_id node, OMX_INDEXTYPE index,
-        const void *params, size_t size) {
-    ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size);
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->setParameter(
-            index, params, size);
-}
-
-status_t OMX::getConfig(
-        node_id node, OMX_INDEXTYPE index,
-        void *params, size_t size) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->getConfig(
-            index, params, size);
-}
-
-status_t OMX::setConfig(
-        node_id node, OMX_INDEXTYPE index,
-        const void *params, size_t size) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->setConfig(
-            index, params, size);
-}
-
-status_t OMX::getState(
-        node_id node, OMX_STATETYPE* state) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->getState(
-            state);
-}
-
-status_t OMX::enableNativeBuffers(
-        node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->enableNativeBuffers(port_index, graphic, enable);
-}
-
-status_t OMX::getGraphicBufferUsage(
-        node_id node, OMX_U32 port_index, OMX_U32* usage) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->getGraphicBufferUsage(port_index, usage);
-}
-
-status_t OMX::storeMetaDataInBuffers(
-        node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->storeMetaDataInBuffers(port_index, enable, type);
-}
-
-status_t OMX::prepareForAdaptivePlayback(
-        node_id node, OMX_U32 portIndex, OMX_BOOL enable,
-        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->prepareForAdaptivePlayback(
-            portIndex, enable, maxFrameWidth, maxFrameHeight);
-}
-
-status_t OMX::configureVideoTunnelMode(
-        node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
-        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->configureVideoTunnelMode(
-            portIndex, tunneled, audioHwSync, sidebandHandle);
-}
-
-status_t OMX::useBuffer(
-        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-        buffer_id *buffer, OMX_U32 allottedSize) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->useBuffer(
-            port_index, params, buffer, allottedSize);
-}
-
-status_t OMX::useGraphicBuffer(
-        node_id node, OMX_U32 port_index,
-        const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->useGraphicBuffer(
-            port_index, graphicBuffer, buffer);
-}
-
-status_t OMX::updateGraphicBufferInMeta(
-        node_id node, OMX_U32 port_index,
-        const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->updateGraphicBufferInMeta(
-            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,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->createInputSurface(
-            port_index, dataSpace, bufferProducer, bufferSource, type);
+    return StatusFromOMXError(err);
 }
 
 status_t OMX::createPersistentInputSurface(
@@ -523,249 +164,4 @@
             bufferProducer, bufferConsumer);
 }
 
-status_t OMX::setInputSurface(
-        node_id node, OMX_U32 port_index,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->setInputSurface(port_index, bufferConsumer, bufferSource, type);
-}
-
-status_t OMX::allocateSecureBuffer(
-        node_id node, OMX_U32 port_index, size_t size,
-        buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->allocateSecureBuffer(
-            port_index, size, buffer, buffer_data, native_handle);
-}
-
-status_t OMX::allocateBufferWithBackup(
-        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
-        buffer_id *buffer, OMX_U32 allottedSize) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->allocateBufferWithBackup(
-            port_index, params, buffer, allottedSize);
-}
-
-status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->freeBuffer(
-            port_index, buffer);
-}
-
-status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->fillBuffer(buffer, fenceFd);
-}
-
-status_t OMX::emptyBuffer(
-        node_id node,
-        buffer_id buffer,
-        OMX_U32 range_offset, OMX_U32 range_length,
-        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->emptyBuffer(
-            buffer, range_offset, range_length, flags, timestamp, fenceFd);
-}
-
-status_t OMX::emptyGraphicBuffer(
-        node_id node,
-        buffer_id buffer,
-        const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
-        OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->emptyGraphicBuffer(
-            buffer, graphicBuffer, flags, timestamp, origTimestamp, fenceFd);
-}
-
-status_t OMX::getExtensionIndex(
-        node_id node,
-        const char *parameter_name,
-        OMX_INDEXTYPE *index) {
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return instance->getExtensionIndex(
-            parameter_name, index);
-}
-
-status_t OMX::dispatchMessage(const omx_message &msg) {
-    sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(msg.node);
-
-    if (dispatcher == NULL) {
-        return OMX_ErrorComponentNotFound;
-    }
-
-    dispatcher->post(msg, true /*realTime*/);
-
-    return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE OMX::OnEvent(
-        node_id node,
-        OMX_IN OMX_EVENTTYPE eEvent,
-        OMX_IN OMX_U32 nData1,
-        OMX_IN OMX_U32 nData2,
-        OMX_IN OMX_PTR pEventData) {
-    ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
-    OMXNodeInstance *instance = findInstance(node);
-
-    if (instance == NULL) {
-        return OMX_ErrorComponentNotFound;
-    }
-
-    // Forward to OMXNodeInstance.
-    instance->onEvent(eEvent, nData1, nData2);
-
-    sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
-
-    // output rendered events are not processed as regular events until they hit the observer
-    if (eEvent == OMX_EventOutputRendered) {
-        if (pEventData == NULL) {
-            return OMX_ErrorBadParameter;
-        }
-
-        // process data from array
-        OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
-        for (size_t i = 0; i < nData1; ++i) {
-            omx_message msg;
-            msg.type = omx_message::FRAME_RENDERED;
-            msg.node = node;
-            msg.fenceFd = -1;
-            msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
-            msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
-
-            dispatcher->post(msg, false /* realTime */);
-        }
-        return OMX_ErrorNone;
-    }
-
-    omx_message msg;
-    msg.type = omx_message::EVENT;
-    msg.node = node;
-    msg.fenceFd = -1;
-    msg.u.event_data.event = eEvent;
-    msg.u.event_data.data1 = nData1;
-    msg.u.event_data.data2 = nData2;
-
-    dispatcher->post(msg, true /* realTime */);
-
-    return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE OMX::OnEmptyBufferDone(
-        node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
-    ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
-
-    omx_message msg;
-    msg.type = omx_message::EMPTY_BUFFER_DONE;
-    msg.node = node;
-    msg.fenceFd = fenceFd;
-    msg.u.buffer_data.buffer = buffer;
-
-    findDispatcher(node)->post(msg);
-
-    return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE OMX::OnFillBufferDone(
-        node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
-    ALOGV("OnFillBufferDone buffer=%p", pBuffer);
-
-    omx_message msg;
-    msg.type = omx_message::FILL_BUFFER_DONE;
-    msg.node = node;
-    msg.fenceFd = fenceFd;
-    msg.u.extended_buffer_data.buffer = buffer;
-    msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
-    msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
-    msg.u.extended_buffer_data.flags = pBuffer->nFlags;
-    msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
-
-    findDispatcher(node)->post(msg);
-
-    return OMX_ErrorNone;
-}
-
-OMX::node_id OMX::makeNodeID_l(OMXNodeInstance *instance) {
-    // mLock is already held.
-
-    node_id prefix = node_id(getpid() << 16);
-    node_id node = 0;
-    do  {
-        if (++mNodeCounter >= kMaxNodeInstances) {
-            mNodeCounter = 0; // OK to use because we're combining with the pid
-        }
-        node = node_id(prefix | mNodeCounter);
-    } while (mNodeIDToInstance.indexOfKey(node) >= 0);
-    mNodeIDToInstance.add(node, instance);
-
-    return node;
-}
-
-OMXNodeInstance *OMX::findInstance(node_id node) {
-    Mutex::Autolock autoLock(mLock);
-
-    ssize_t index = mNodeIDToInstance.indexOfKey(node);
-
-    return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
-}
-
-sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
-    Mutex::Autolock autoLock(mLock);
-
-    ssize_t index = mDispatchers.indexOfKey(node);
-
-    return index < 0 ? NULL : mDispatchers.valueAt(index);
-}
-
-void OMX::invalidateNodeID(node_id node) {
-    Mutex::Autolock autoLock(mLock);
-    invalidateNodeID_l(node);
-}
-
-void OMX::invalidateNodeID_l(node_id node) {
-    // mLock is held.
-    mNodeIDToInstance.removeItem(node);
-}
-
 }  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 997cc13..72e7375 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -29,6 +29,7 @@
 
 #include <OMX_Component.h>
 #include <OMX_IndexExt.h>
+#include <OMX_VideoExt.h>
 #include <OMX_AsString.h>
 
 #include <binder/IMemory.h>
@@ -45,19 +46,19 @@
 static const OMX_U32 kPortIndexInput = 0;
 static const OMX_U32 kPortIndexOutput = 1;
 
-#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__)
+#define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__)
 
 #define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
-    ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \
-    mNodeID, mName, ##__VA_ARGS__, asString(err), err)
+    ALOGE_IF(cond, #fn "(%p:%s, " fmt ") ERROR: %s(%#x)", \
+    mHandle, mName, ##__VA_ARGS__, asString(err), err)
 #define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
 #define CLOG_IF_ERROR(fn, err, fmt, ...) \
     CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
 
 #define CLOGI_(level, fn, fmt, ...) \
-    ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+    ALOGI_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
 #define CLOGD_(level, fn, fmt, ...) \
-    ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+    ALOGD_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
 
 #define CLOG_LIFE(fn, fmt, ...)     CLOGI_(ADebug::kDebugLifeCycle,     fn, fmt, ##__VA_ARGS__)
 #define CLOG_STATE(fn, fmt, ...)    CLOGI_(ADebug::kDebugState,         fn, fmt, ##__VA_ARGS__)
@@ -65,7 +66,7 @@
 #define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
 
 #define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
-    ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__)
+    ALOGD_IF(cond, #fn "(%p, " fmt ")", mHandle, ##__VA_ARGS__)
 
 #define CLOG_BUFFER(fn, fmt, ...) \
     CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
@@ -206,10 +207,133 @@
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+// This provides the underlying Thread used by CallbackDispatcher.
+// Note that deriving CallbackDispatcher from Thread does not work.
+
+struct OMXNodeInstance::CallbackDispatcherThread : public Thread {
+    explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+        : mDispatcher(dispatcher) {
+    }
+
+private:
+    CallbackDispatcher *mDispatcher;
+
+    bool threadLoop();
+
+    CallbackDispatcherThread(const CallbackDispatcherThread &);
+    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct OMXNodeInstance::CallbackDispatcher : public RefBase {
+    explicit CallbackDispatcher(const sp<OMXNodeInstance> &owner);
+
+    // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
+    // that a new message is available on the queue. Otherwise, the message stays on the queue, but
+    // the listener is not notified of it. It will process this message when a subsequent message
+    // is posted with |realTime| set to true.
+    void post(const omx_message &msg, bool realTime = true);
+
+    bool loop();
+
+protected:
+    virtual ~CallbackDispatcher();
+
+private:
+    Mutex mLock;
+
+    sp<OMXNodeInstance> const mOwner;
+    bool mDone;
+    Condition mQueueChanged;
+    std::list<omx_message> mQueue;
+
+    sp<CallbackDispatcherThread> mThread;
+
+    void dispatch(std::list<omx_message> &messages);
+
+    CallbackDispatcher(const CallbackDispatcher &);
+    CallbackDispatcher &operator=(const CallbackDispatcher &);
+};
+
+OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner)
+    : mOwner(owner),
+      mDone(false) {
+    mThread = new CallbackDispatcherThread(this);
+    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
+}
+
+OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        mDone = true;
+        mQueueChanged.signal();
+    }
+
+    // A join on self can happen if the last ref to CallbackDispatcher
+    // is released within the CallbackDispatcherThread loop
+    status_t status = mThread->join();
+    if (status != WOULD_BLOCK) {
+        // Other than join to self, the only other error return codes are
+        // whatever readyToRun() returns, and we don't override that
+        CHECK_EQ(status, (status_t)NO_ERROR);
+    }
+}
+
+void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
+    Mutex::Autolock autoLock(mLock);
+
+    mQueue.push_back(msg);
+    if (realTime) {
+        mQueueChanged.signal();
+    }
+}
+
+void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
+    if (mOwner == NULL) {
+        ALOGV("Would have dispatched a message to a node that's already gone.");
+        return;
+    }
+    mOwner->onMessages(messages);
+}
+
+bool OMXNodeInstance::CallbackDispatcher::loop() {
+    for (;;) {
+        std::list<omx_message> messages;
+
+        {
+            Mutex::Autolock autoLock(mLock);
+            while (!mDone && mQueue.empty()) {
+                mQueueChanged.wait(mLock);
+            }
+
+            if (mDone) {
+                break;
+            }
+
+            messages.swap(mQueue);
+        }
+
+        dispatch(messages);
+    }
+
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool OMXNodeInstance::CallbackDispatcherThread::threadLoop() {
+    return mDispatcher->loop();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 OMXNodeInstance::OMXNodeInstance(
         OMX *owner, const sp<IOMXObserver> &observer, const char *name)
     : mOwner(owner),
-      mNodeID(0),
       mHandle(NULL),
       mObserver(observer),
       mDying(false),
@@ -239,11 +363,13 @@
     CHECK(mHandle == NULL);
 }
 
-void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
-    mNodeID = node_id;
+void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) {
     CLOG_LIFE(allocateNode, "handle=%p", handle);
     CHECK(mHandle == NULL);
     mHandle = handle;
+    if (handle != NULL) {
+        mDispatcher = new CallbackDispatcher(this);
+    }
 }
 
 sp<IOMXBufferSource> OMXNodeInstance::getBufferSource() {
@@ -257,25 +383,22 @@
     mOMXBufferSource = bufferSource;
 }
 
-OMX *OMXNodeInstance::owner() {
-    return mOwner;
+OMX_HANDLETYPE OMXNodeInstance::handle() {
+    return mHandle;
 }
 
 sp<IOMXObserver> OMXNodeInstance::observer() {
     return mObserver;
 }
 
-OMX::node_id OMXNodeInstance::nodeID() {
-    return mNodeID;
-}
+status_t OMXNodeInstance::freeNode() {
 
-status_t OMXNodeInstance::freeNode(OMXMaster *master) {
     CLOG_LIFE(freeNode, "handle=%p", mHandle);
     static int32_t kMaxNumIterations = 10;
 
     // exit if we have already freed the node
     if (mHandle == NULL) {
-        return OK;
+        return mOwner->freeNode(this);
     }
 
     // Transition the node from its current state all the way down
@@ -354,23 +477,18 @@
             LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
             break;
     }
+    status_t err = mOwner->freeNode(this);
 
-    ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName);
-    OMX_ERRORTYPE err = master->destroyComponentInstance(
-            static_cast<OMX_COMPONENTTYPE *>(mHandle));
+    mDispatcher.clear();
 
     mHandle = NULL;
     CLOG_IF_ERROR(freeNode, err, "");
     free(mName);
     mName = NULL;
 
-    mOwner->invalidateNodeID(mNodeID);
-    mNodeID = 0;
-
     ALOGV("OMXNodeInstance going away.");
-    delete this;
 
-    return StatusFromOMXError(err);
+    return err;
 }
 
 status_t OMXNodeInstance::sendCommand(
@@ -1133,8 +1251,7 @@
     }
 
     sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(
-            mOwner,
-            mNodeID,
+            this,
             def.format.video.nFrameWidth,
             def.format.video.nFrameHeight,
             def.nBufferCountActual,
@@ -1621,6 +1738,11 @@
     return StatusFromOMXError(err);
 }
 
+status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) {
+    mDispatcher->post(msg, true /*realTime*/);
+    return OMX_ErrorNone;
+}
+
 bool OMXNodeInstance::handleMessage(omx_message &msg) {
     if (msg.type == omx_message::FILL_BUFFER_DONE) {
         OMX_BUFFERHEADERTYPE *buffer =
@@ -1776,15 +1898,11 @@
     }
 }
 
-void OMXNodeInstance::onObserverDied(OMXMaster *master) {
+void OMXNodeInstance::onObserverDied() {
     ALOGE("!!! Observer died. Quickly, do something, ... anything...");
 
     // Try to force shutdown of the node and hope for the best.
-    freeNode(master);
-}
-
-void OMXNodeInstance::onGetHandleFailed() {
-    delete this;
+    freeNode();
 }
 
 // OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
@@ -1861,8 +1979,39 @@
     if (instance->mDying) {
         return OMX_ErrorNone;
     }
-    return instance->owner()->OnEvent(
-            instance->nodeID(), eEvent, nData1, nData2, pEventData);
+
+    instance->onEvent(eEvent, nData1, nData2);
+
+    // output rendered events are not processed as regular events until they hit the observer
+    if (eEvent == OMX_EventOutputRendered) {
+        if (pEventData == NULL) {
+            return OMX_ErrorBadParameter;
+        }
+
+        // process data from array
+        OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
+        for (size_t i = 0; i < nData1; ++i) {
+            omx_message msg;
+            msg.type = omx_message::FRAME_RENDERED;
+            msg.fenceFd = -1;
+            msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
+            msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
+
+            instance->mDispatcher->post(msg, false /* realTime */);
+        }
+        return OMX_ErrorNone;
+    }
+
+    omx_message msg;
+    msg.type = omx_message::EVENT;
+    msg.fenceFd = -1;
+    msg.u.event_data.event = eEvent;
+    msg.u.event_data.data1 = nData1;
+    msg.u.event_data.data2 = nData2;
+
+    instance->mDispatcher->post(msg, true /* realTime */);
+
+    return OMX_ErrorNone;
 }
 
 // static
@@ -1879,8 +2028,14 @@
         return OMX_ErrorNone;
     }
     int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
-    return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
-            instance->findBufferID(pBuffer), pBuffer, fenceFd);
+
+    omx_message msg;
+    msg.type = omx_message::EMPTY_BUFFER_DONE;
+    msg.fenceFd = fenceFd;
+    msg.u.buffer_data.buffer = instance->findBufferID(pBuffer);
+    instance->mDispatcher->post(msg);
+
+    return OMX_ErrorNone;
 }
 
 // static
@@ -1897,8 +2052,18 @@
         return OMX_ErrorNone;
     }
     int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
-    return instance->owner()->OnFillBufferDone(instance->nodeID(),
-            instance->findBufferID(pBuffer), pBuffer, fenceFd);
+
+    omx_message msg;
+    msg.type = omx_message::FILL_BUFFER_DONE;
+    msg.fenceFd = fenceFd;
+    msg.u.extended_buffer_data.buffer = instance->findBufferID(pBuffer);
+    msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
+    msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
+    msg.u.extended_buffer_data.flags = pBuffer->nFlags;
+    msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
+    instance->mDispatcher->post(msg);
+
+    return OMX_ErrorNone;
 }
 
 void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index c5879b8..38aad39 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -178,7 +178,7 @@
                   : kMimeToRole[i].decoderRole;
 }
 
-status_t SetComponentRole(const sp<IOMX> &omx, IOMX::node_id node, const char *role) {
+status_t SetComponentRole(const sp<IOMXNode> &omxNode, const char *role) {
     OMX_PARAM_COMPONENTROLETYPE roleParams;
     InitOMXParams(&roleParams);
 
@@ -187,8 +187,8 @@
 
     roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
 
-    return omx->setParameter(
-            node, OMX_IndexParamStandardComponentRole,
+    return omxNode->setParameter(
+            OMX_IndexParamStandardComponentRole,
             &roleParams, sizeof(roleParams));
 }
 
@@ -305,24 +305,24 @@
 }
 
 bool DescribeColorFormat(
-        const sp<IOMX> &omx, IOMX::node_id node,
+        const sp<IOMXNode> &omxNode,
         DescribeColorFormat2Params &describeParams)
 {
     OMX_INDEXTYPE describeColorFormatIndex;
-    if (omx->getExtensionIndex(
-            node, "OMX.google.android.index.describeColorFormat",
+    if (omxNode->getExtensionIndex(
+            "OMX.google.android.index.describeColorFormat",
             &describeColorFormatIndex) == OK) {
         DescribeColorFormatParams describeParamsV1(describeParams);
-        if (omx->getParameter(
-                node, describeColorFormatIndex,
+        if (omxNode->getParameter(
+                describeColorFormatIndex,
                 &describeParamsV1, sizeof(describeParamsV1)) == OK) {
             describeParams.initFromV1(describeParamsV1);
             return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
         }
-    } else if (omx->getExtensionIndex(
-            node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
-               && omx->getParameter(
-            node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
+    } else if (omxNode->getExtensionIndex(
+            "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
+               && omxNode->getParameter(
+                       describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
         return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
     }
 
@@ -331,7 +331,7 @@
 
 // static
 bool IsFlexibleColorFormat(
-         const sp<IOMX> &omx, IOMX::node_id node,
+         const sp<IOMXNode> &omxNode,
          uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
     DescribeColorFormat2Params describeParams;
     InitOMXParams(&describeParams);
@@ -345,7 +345,7 @@
 
     CHECK(flexibleEquivalent != NULL);
 
-    if (!DescribeColorFormat(omx, node, describeParams)) {
+    if (!DescribeColorFormat(omxNode, describeParams)) {
         return false;
     }
 
diff --git a/media/libstagefright/omx/OMXUtils.h b/media/libstagefright/omx/OMXUtils.h
index 315f118..3f533ff 100644
--- a/media/libstagefright/omx/OMXUtils.h
+++ b/media/libstagefright/omx/OMXUtils.h
@@ -39,16 +39,16 @@
 status_t StatusFromOMXError(OMX_ERRORTYPE err);
 
 const char *GetComponentRole(bool isEncoder, const char *mime);
-status_t SetComponentRole(const sp<IOMX> &omx, IOMX::node_id node, const char *role);
+status_t SetComponentRole(const sp<IOMXNode> &omxNode, const char *role);
 
 struct DescribeColorFormat2Params;
 
 bool IsFlexibleColorFormat(
-        const sp<IOMX> &omx, IOMX::node_id node,
-        uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
+        const sp<IOMXNode> &omxNode, uint32_t colorFormat,
+        bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
 bool DescribeDefaultColorFormat(DescribeColorFormat2Params &describeParams);
 bool DescribeColorFormat(
-        const sp<IOMX> &omx, IOMX::node_id node,
+        const sp<IOMXNode> &omxNode,
         DescribeColorFormat2Params &describeParams);
 
 }  // namespace android
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 50bb0de..277af63 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -43,6 +43,25 @@
 
 namespace android {
 
+/////////////////////////////////////////////////////////////////////
+
+struct Harness::CodecObserver : public BnOMXObserver {
+    CodecObserver(const sp<Harness> &harness, int32_t gen)
+            : mHarness(harness), mGeneration(gen) {}
+
+    void onMessages(const std::list<omx_message> &messages) override;
+
+private:
+    sp<Harness> mHarness;
+    int32_t mGeneration;
+};
+
+void Harness::CodecObserver::onMessages(const std::list<omx_message> &messages) {
+    mHarness->handleMessages(mGeneration, messages);
+}
+
+/////////////////////////////////////////////////////////////////////
+
 Harness::Harness()
     : mInitCheck(NO_INIT) {
     mInitCheck = initOMX();
@@ -64,18 +83,17 @@
     return mOMX != 0 ? OK : NO_INIT;
 }
 
-void Harness::onMessages(const std::list<omx_message> &messages) {
+void Harness::handleMessages(int32_t gen, const std::list<omx_message> &messages) {
     Mutex::Autolock autoLock(mLock);
     for (std::list<omx_message>::const_iterator it = messages.cbegin(); it != messages.cend(); ) {
         mMessageQueue.push_back(*it++);
+        mLastMsgGeneration = gen;
     }
     mMessageAddedCondition.signal();
 }
 
-status_t Harness::dequeueMessageForNode(
-        IOMX::node_id node, omx_message *msg, int64_t timeoutUs) {
-    return dequeueMessageForNodeIgnoringBuffers(
-            node, NULL, NULL, msg, timeoutUs);
+status_t Harness::dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
+    return dequeueMessageForNodeIgnoringBuffers(NULL, NULL, msg, timeoutUs);
 }
 
 // static
@@ -120,7 +138,6 @@
 }
 
 status_t Harness::dequeueMessageForNodeIgnoringBuffers(
-        IOMX::node_id node,
         Vector<Buffer> *inputBuffers,
         Vector<Buffer> *outputBuffers,
         omx_message *msg, int64_t timeoutUs) {
@@ -128,21 +145,22 @@
 
     for (;;) {
         Mutex::Autolock autoLock(mLock);
+        // Messages are queued in batches, if the last batch queued is
+        // from a node that already expired, discard those messages.
+        if (mLastMsgGeneration < mCurGeneration) {
+            mMessageQueue.clear();
+        }
         List<omx_message>::iterator it = mMessageQueue.begin();
         while (it != mMessageQueue.end()) {
-            if ((*it).node == node) {
-                if (handleBufferMessage(*it, inputBuffers, outputBuffers)) {
-                    it = mMessageQueue.erase(it);
-                    continue;
-                }
-
-                *msg = *it;
-                mMessageQueue.erase(it);
-
-                return OK;
+            if (handleBufferMessage(*it, inputBuffers, outputBuffers)) {
+                it = mMessageQueue.erase(it);
+                continue;
             }
 
-            ++it;
+            *msg = *it;
+            mMessageQueue.erase(it);
+
+            return OK;
         }
 
         status_t err = (timeoutUs < 0)
@@ -158,16 +176,15 @@
 }
 
 status_t Harness::getPortDefinition(
-        IOMX::node_id node, OMX_U32 portIndex,
-        OMX_PARAM_PORTDEFINITIONTYPE *def) {
+        OMX_U32 portIndex, OMX_PARAM_PORTDEFINITIONTYPE *def) {
     def->nSize = sizeof(*def);
     def->nVersion.s.nVersionMajor = 1;
     def->nVersion.s.nVersionMinor = 0;
     def->nVersion.s.nRevision = 0;
     def->nVersion.s.nStep = 0;
     def->nPortIndex = portIndex;
-    return mOMX->getParameter(
-            node, OMX_IndexParamPortDefinition, def, sizeof(*def));
+    return mOMXNode->getParameter(
+            OMX_IndexParamPortDefinition, def, sizeof(*def));
 }
 
 #define EXPECT(condition, info) \
@@ -180,12 +197,11 @@
 
 status_t Harness::allocatePortBuffers(
         const sp<MemoryDealer> &dealer,
-        IOMX::node_id node, OMX_U32 portIndex,
-        Vector<Buffer> *buffers) {
+        OMX_U32 portIndex, Vector<Buffer> *buffers) {
     buffers->clear();
 
     OMX_PARAM_PORTDEFINITIONTYPE def;
-    status_t err = getPortDefinition(node, portIndex, &def);
+    status_t err = getPortDefinition(portIndex, &def);
     EXPECT_SUCCESS(err, "getPortDefinition");
 
     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
@@ -194,8 +210,8 @@
         buffer.mFlags = 0;
         CHECK(buffer.mMemory != NULL);
 
-        err = mOMX->allocateBufferWithBackup(
-                node, portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
+        err = mOMXNode->allocateBufferWithBackup(
+                portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
         EXPECT_SUCCESS(err, "allocateBuffer");
 
         buffers->push(buffer);
@@ -204,7 +220,7 @@
     return OK;
 }
 
-status_t Harness::setRole(IOMX::node_id node, const char *role) {
+status_t Harness::setRole(const char *role) {
     OMX_PARAM_COMPONENTROLETYPE params;
     params.nSize = sizeof(params);
     params.nVersion.s.nVersionMajor = 1;
@@ -214,31 +230,31 @@
     strncpy((char *)params.cRole, role, OMX_MAX_STRINGNAME_SIZE - 1);
     params.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
 
-    return mOMX->setParameter(
-            node, OMX_IndexParamStandardComponentRole,
+    return mOMXNode->setParameter(
+            OMX_IndexParamStandardComponentRole,
             &params, sizeof(params));
 }
 
 struct NodeReaper {
-    NodeReaper(const sp<Harness> &harness, IOMX::node_id node)
+    NodeReaper(const sp<Harness> &harness, const sp<IOMXNode> &omxNode)
         : mHarness(harness),
-          mNode(node) {
+          mOMXNode(omxNode) {
     }
 
     ~NodeReaper() {
-        if (mNode != 0) {
-            mHarness->mOMX->freeNode(mNode);
-            mNode = 0;
+        if (mOMXNode != 0) {
+            mOMXNode->freeNode();
+            mOMXNode = NULL;
         }
     }
 
     void disarm() {
-        mNode = 0;
+        mOMXNode = NULL;
     }
 
 private:
     sp<Harness> mHarness;
-    IOMX::node_id mNode;
+    sp<IOMXNode> mOMXNode;
 
     NodeReaper(const NodeReaper &);
     NodeReaper &operator=(const NodeReaper &);
@@ -264,23 +280,24 @@
     }
 
     sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
-    IOMX::node_id node;
+
+    sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
 
     status_t err =
-        mOMX->allocateNode(componentName, this, NULL, &node);
+        mOMX->allocateNode(componentName, observer, NULL, &mOMXNode);
     EXPECT_SUCCESS(err, "allocateNode");
 
-    NodeReaper reaper(this, node);
+    NodeReaper reaper(this, mOMXNode);
 
-    err = setRole(node, componentRole);
+    err = setRole(componentRole);
     EXPECT_SUCCESS(err, "setRole");
 
     // Initiate transition Loaded->Idle
-    err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+    err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
     EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
 
     omx_message msg;
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     // Make sure node doesn't just transition to idle before we are done
     // allocating all input and output buffers.
     EXPECT(err == TIMED_OUT,
@@ -289,17 +306,17 @@
 
     // Now allocate buffers.
     Vector<Buffer> inputBuffers;
-    err = allocatePortBuffers(dealer, node, 0, &inputBuffers);
+    err = allocatePortBuffers(dealer, 0, &inputBuffers);
     EXPECT_SUCCESS(err, "allocatePortBuffers(input)");
 
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     CHECK_EQ(err, (status_t)TIMED_OUT);
 
     Vector<Buffer> outputBuffers;
-    err = allocatePortBuffers(dealer, node, 1, &outputBuffers);
+    err = allocatePortBuffers(dealer, 1, &outputBuffers);
     EXPECT_SUCCESS(err, "allocatePortBuffers(output)");
 
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     EXPECT(err == OK
             && msg.type == omx_message::EVENT
             && msg.u.event_data.event == OMX_EventCmdComplete
@@ -309,10 +326,10 @@
            "after all input and output buffers were allocated.");
 
     // Initiate transition Idle->Executing
-    err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateExecuting);
+    err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateExecuting);
     EXPECT_SUCCESS(err, "sendCommand(go-to-Executing)");
 
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     EXPECT(err == OK
             && msg.type == omx_message::EVENT
             && msg.u.event_data.event == OMX_EventCmdComplete
@@ -322,17 +339,17 @@
            "executing state.");
 
     for (size_t i = 0; i < outputBuffers.size(); ++i) {
-        err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+        err = mOMXNode->fillBuffer(outputBuffers[i].mID);
         EXPECT_SUCCESS(err, "fillBuffer");
 
         outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
     }
 
-    err = mOMX->sendCommand(node, OMX_CommandFlush, 1);
+    err = mOMXNode->sendCommand(OMX_CommandFlush, 1);
     EXPECT_SUCCESS(err, "sendCommand(flush-output-port)");
 
     err = dequeueMessageForNodeIgnoringBuffers(
-            node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+            &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
     EXPECT(err == OK
             && msg.type == omx_message::EVENT
             && msg.u.event_data.event == OMX_EventCmdComplete
@@ -347,18 +364,18 @@
     }
 
     for (size_t i = 0; i < outputBuffers.size(); ++i) {
-        err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+        err = mOMXNode->fillBuffer(outputBuffers[i].mID);
         EXPECT_SUCCESS(err, "fillBuffer");
 
         outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
     }
 
     // Initiate transition Executing->Idle
-    err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+    err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
     EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
 
     err = dequeueMessageForNodeIgnoringBuffers(
-            node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+            &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
     EXPECT(err == OK
             && msg.type == omx_message::EVENT
             && msg.u.event_data.event == OMX_EventCmdComplete
@@ -382,28 +399,28 @@
     }
 
     // Initiate transition Idle->Loaded
-    err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateLoaded);
+    err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
     EXPECT_SUCCESS(err, "sendCommand(go-to-Loaded)");
 
     // Make sure node doesn't just transition to loaded before we are done
     // freeing all input and output buffers.
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     CHECK_EQ(err, (status_t)TIMED_OUT);
 
     for (size_t i = 0; i < inputBuffers.size(); ++i) {
-        err = mOMX->freeBuffer(node, 0, inputBuffers[i].mID);
+        err = mOMXNode->freeBuffer(0, inputBuffers[i].mID);
         EXPECT_SUCCESS(err, "freeBuffer");
     }
 
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     CHECK_EQ(err, (status_t)TIMED_OUT);
 
     for (size_t i = 0; i < outputBuffers.size(); ++i) {
-        err = mOMX->freeBuffer(node, 1, outputBuffers[i].mID);
+        err = mOMXNode->freeBuffer(1, outputBuffers[i].mID);
         EXPECT_SUCCESS(err, "freeBuffer");
     }
 
-    err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
     EXPECT(err == OK
             && msg.type == omx_message::EVENT
             && msg.u.event_data.event == OMX_EventCmdComplete
@@ -412,12 +429,12 @@
            "Component did not properly transition to from idle to "
            "loaded state after freeing all input and output buffers.");
 
-    err = mOMX->freeNode(node);
+    err = mOMXNode->freeNode();
     EXPECT_SUCCESS(err, "freeNode");
 
     reaper.disarm();
 
-    node = 0;
+    mOMXNode = NULL;
 
     return OK;
 }
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 1ebf3aa..0fe00a6 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -29,7 +29,7 @@
 
 class MemoryDealer;
 
-struct Harness : public BnOMXObserver {
+struct Harness : public RefBase {
     enum BufferFlags {
         kBufferBusy = 1
     };
@@ -43,25 +43,21 @@
 
     status_t initCheck() const;
 
-    status_t dequeueMessageForNode(
-            IOMX::node_id node, omx_message *msg, int64_t timeoutUs = -1);
+    status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs = -1);
 
     status_t dequeueMessageForNodeIgnoringBuffers(
-            IOMX::node_id node,
             Vector<Buffer> *inputBuffers,
             Vector<Buffer> *outputBuffers,
             omx_message *msg, int64_t timeoutUs = -1);
 
     status_t getPortDefinition(
-            IOMX::node_id node, OMX_U32 portIndex,
-            OMX_PARAM_PORTDEFINITIONTYPE *def);
+            OMX_U32 portIndex, OMX_PARAM_PORTDEFINITIONTYPE *def);
 
     status_t allocatePortBuffers(
             const sp<MemoryDealer> &dealer,
-            IOMX::node_id node, OMX_U32 portIndex,
-            Vector<Buffer> *buffers);
+            OMX_U32 portIndex, Vector<Buffer> *buffers);
 
-    status_t setRole(IOMX::node_id node, const char *role);
+    status_t setRole(const char *role);
 
     status_t testStateTransitions(
             const char *componentName, const char *componentRole);
@@ -74,20 +70,22 @@
 
     status_t testAll();
 
-    virtual void onMessages(const std::list<omx_message> &messages);
-
 protected:
     virtual ~Harness();
 
 private:
     friend struct NodeReaper;
+    struct CodecObserver;
 
     Mutex mLock;
 
     status_t mInitCheck;
     sp<IOMX> mOMX;
+    sp<IOMXNode> mOMXNode;
     List<omx_message> mMessageQueue;
     Condition mMessageAddedCondition;
+    int32_t mLastMsgGeneration;
+    int32_t mCurGeneration;
 
     status_t initOMX();
 
@@ -96,6 +94,8 @@
             Vector<Buffer> *inputBuffers,
             Vector<Buffer> *outputBuffers);
 
+    void handleMessages(int32_t gen, const std::list<omx_message> &messages);
+
     Harness(const Harness &);
     Harness &operator=(const Harness &);
 };
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 471152e..273af18 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -26,6 +26,7 @@
 #include <cutils/properties.h>
 #include <gui/Surface.h>
 #include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -720,7 +721,7 @@
 #endif
 
             sp<ABuffer> buffer;
-            sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
+            sp<MediaCodecBuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
 
             if (outbuf->meta()->findPointer("handle", (void**)&handle) &&
                     handle != NULL) {
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index b182990..ad95ab5 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -25,6 +25,7 @@
 struct ABuffer;
 class IGraphicBufferProducer;
 struct MediaCodec;
+class MediaCodecBuffer;
 
 #define ENABLE_SILENCE_DETECTION        0
 
@@ -106,8 +107,8 @@
 
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
 
-    Vector<sp<ABuffer> > mEncoderInputBuffers;
-    Vector<sp<ABuffer> > mEncoderOutputBuffers;
+    Vector<sp<MediaCodecBuffer> > mEncoderInputBuffers;
+    Vector<sp<MediaCodecBuffer> > mEncoderOutputBuffers;
 
     List<size_t> mAvailEncoderInputIndices;
 
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 3d1eca1..22c90e2 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -30,10 +30,10 @@
 
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/ABuffer.h>
 
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/MediaCodecBuffer.h>
 
 using namespace android;
 
@@ -268,13 +268,17 @@
 
 EXPORT
 uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
-    android::Vector<android::sp<android::ABuffer> > abufs;
+    android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
     if (mData->mCodec->getInputBuffers(&abufs) == 0) {
         size_t n = abufs.size();
         if (idx >= n) {
             ALOGE("buffer index %zu out of range", idx);
             return NULL;
         }
+        if (abufs[idx] == NULL) {
+            ALOGE("buffer index %zu is NULL", idx);
+            return NULL;
+        }
         if (out_size != NULL) {
             *out_size = abufs[idx]->capacity();
         }
@@ -286,7 +290,7 @@
 
 EXPORT
 uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
-    android::Vector<android::sp<android::ABuffer> > abufs;
+    android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
     if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
         size_t n = abufs.size();
         if (idx >= n) {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 2b66c81..5445413 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -95,7 +95,9 @@
 
     sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
 
-    uint32_t activeInputsCount() const;
+    // count active capture sessions using one of the specified devices.
+    // ignore devices if AUDIO_DEVICE_IN_DEFAULT is passed
+    uint32_t activeInputsCountOnDevices(audio_devices_t devices = AUDIO_DEVICE_IN_DEFAULT) const;
 
     /**
      * return io handle of active input or 0 if no input is active
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 1164607..44f9637 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -241,12 +241,14 @@
     return inputDesc;
 }
 
-uint32_t AudioInputCollection::activeInputsCount() const
+uint32_t AudioInputCollection::activeInputsCountOnDevices(audio_devices_t devices) const
 {
     uint32_t count = 0;
     for (size_t i = 0; i < size(); i++) {
         const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
-        if (inputDescriptor->isActive()) {
+        if (inputDescriptor->isActive() &&
+                ((devices == AUDIO_DEVICE_IN_DEFAULT) ||
+                 ((inputDescriptor->mDevice & devices & ~AUDIO_DEVICE_BIT_IN) != 0))) {
             count++;
         }
     }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 39d156c..5dcd41c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1727,7 +1727,7 @@
     if (isInCall()) {
         *concurrency |= API_INPUT_CONCURRENCY_CALL;
     }
-    if (mInputs.activeInputsCount() != 0) {
+    if (mInputs.activeInputsCountOnDevices() != 0) {
         *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
     }
 
@@ -1739,8 +1739,10 @@
     mInputRoutes.incRouteActivity(session);
 
     if (audioSession->activeCount() == 1 || mInputRoutes.hasRouteChanged(session)) {
-
-        setInputDevice(input, getNewInputDevice(inputDesc), true /* force */);
+        // indicate active capture to sound trigger service if starting capture from a mic on
+        // primary HW module
+        audio_devices_t device = getNewInputDevice(inputDesc);
+        setInputDevice(input, device, true /* force */);
 
         if (inputDesc->getAudioSessionCount(true/*activeOnly*/) == 1) {
             // if input maps to a dynamic policy with an activity listener, notify of state change
@@ -1750,7 +1752,9 @@
                         MIX_STATE_MIXING);
             }
 
-            if (mInputs.activeInputsCount() == 0) {
+            audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+            if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+                    mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
                 SoundTrigger::setCaptureState(true);
             }
 
@@ -1833,9 +1837,14 @@
                 }
             }
 
+            audio_devices_t device = inputDesc->mDevice;
             resetInputDevice(input);
 
-            if (mInputs.activeInputsCount() == 0) {
+            // indicate inactive capture to sound trigger service if stopping capture from a mic on
+            // primary HW module
+            audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+            if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+                    mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
                 SoundTrigger::setCaptureState(false);
             }
             inputDesc->clearPreemptedSessions();