Reimplement the OMX backend for stagefright.

Besides a major cleanup and refactoring, OMX is now a singleton living in the media server, it listens for death notifications of node observers/clients that allocated OMX nodes and performs/attempts cleanup.

Changed APIs to conform to the rest of the system.
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 4d4d013..7dc99c1 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -273,7 +273,7 @@
 
         CHECK(service.get() != NULL);
 
-        sp<IOMX> omx = service->createOMX();
+        sp<IOMX> omx = service->getOMX();
         CHECK(omx.get() != NULL);
 
         const char *kMimeTypes[] = {
@@ -319,11 +319,11 @@
 
         CHECK(service.get() != NULL);
 
-        sp<IOMX> omx = service->createOMX();
+        sp<IOMX> omx = service->getOMX();
         CHECK(omx.get() != NULL);
 
         List<String8> list;
-        omx->list_nodes(&list);
+        omx->listNodes(&list);
 
         for (List<String8>::iterator it = list.begin();
              it != list.end(); ++it) {
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 303444c..d5c1594 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -42,7 +42,7 @@
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
-    virtual sp<IOMX>            createOMX() = 0;
+    virtual sp<IOMX>            getOMX() = 0;
 
     // Take a peek at currently playing audio, for visualization purposes.
     // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index e551d17..6f3ba1c 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -42,57 +42,57 @@
     typedef void *buffer_id;
     typedef void *node_id;
 
-    virtual status_t list_nodes(List<String8> *list) = 0;
+    virtual status_t listNodes(List<String8> *list) = 0;
 
-    virtual status_t allocate_node(const char *name, node_id *node) = 0;
-    virtual status_t free_node(node_id node) = 0;
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer,
+            node_id *node) = 0;
 
-    virtual status_t send_command(
+    virtual status_t freeNode(node_id node) = 0;
+
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) = 0;
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) = 0;
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) = 0;
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) = 0;
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) = 0;
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer) = 0;
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) = 0;
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer) = 0;
+    virtual status_t fillBuffer(node_id node, buffer_id buffer) = 0;
 
-    virtual status_t fill_buffer(node_id node, buffer_id buffer) = 0;
-
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp) = 0;
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) = 0;
@@ -162,7 +162,7 @@
 public:
     DECLARE_META_INTERFACE(OMXObserver);
 
-    virtual void on_message(const omx_message &msg) = 0;
+    virtual void onMessage(const omx_message &msg) = 0;
 };
 
 class IOMXRenderer : public IInterface {
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 98f7ef1..cca3e9b 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -35,7 +35,7 @@
     DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
-    CREATE_OMX,
+    GET_OMX,
     SNOOP
 };
 
@@ -123,10 +123,10 @@
         return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
-    virtual sp<IOMX> createOMX() {
+    virtual sp<IOMX> getOMX() {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        remote()->transact(CREATE_OMX, data, &reply);
+        remote()->transact(GET_OMX, data, &reply);
         return interface_cast<IOMX>(reply.readStrongBinder());
     }
 };
@@ -207,9 +207,9 @@
             reply->writeStrongBinder(retriever->asBinder());
             return NO_ERROR;
         } break;
-        case CREATE_OMX: {
+        case GET_OMX: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IOMX> omx = createOMX();
+            sp<IOMX> omx = getOMX();
             reply->writeStrongBinder(omx->asBinder());
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index e74f1a9..76a9e7d 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -24,7 +24,6 @@
     ALLOC_BUFFER,
     ALLOC_BUFFER_WITH_BACKUP,
     FREE_BUFFER,
-    OBSERVE_NODE,
     FILL_BUFFER,
     EMPTY_BUFFER,
     GET_EXTENSION_INDEX,
@@ -76,7 +75,7 @@
         : BpInterface<IOMX>(impl) {
     }
 
-    virtual status_t list_nodes(List<String8> *list) {
+    virtual status_t listNodes(List<String8> *list) {
         list->clear();
 
         Parcel data, reply;
@@ -93,10 +92,12 @@
         return OK;
     }
 
-    virtual status_t allocate_node(const char *name, node_id *node) {
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer, node_id *node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeCString(name);
+        data.writeStrongBinder(observer->asBinder());
         remote()->transact(ALLOCATE_NODE, data, &reply);
 
         status_t err = reply.readInt32();
@@ -109,7 +110,7 @@
         return err;
     }
 
-    virtual status_t free_node(node_id node) {
+    virtual status_t freeNode(node_id node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
@@ -118,7 +119,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t send_command(
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -130,7 +131,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) {
         Parcel data, reply;
@@ -151,7 +152,7 @@
         return OK;
     }
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) {
         Parcel data, reply;
@@ -165,7 +166,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) {
         Parcel data, reply;
@@ -186,7 +187,7 @@
         return OK;
     }
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) {
         Parcel data, reply;
@@ -200,7 +201,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -222,7 +223,7 @@
         return err;
     }
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -244,7 +245,7 @@
         return err;
     }
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -266,7 +267,7 @@
         return err;
     }
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -278,18 +279,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeIntPtr((intptr_t)node);
-        data.writeStrongBinder(observer->asBinder());
-        remote()->transact(OBSERVE_NODE, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t fill_buffer(node_id node, buffer_id buffer) {
+    virtual status_t fillBuffer(node_id node, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
@@ -299,7 +289,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
@@ -317,7 +307,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) {
@@ -379,7 +369,7 @@
             CHECK_INTERFACE(IOMX, data, reply);
 
             List<String8> list;
-            list_nodes(&list);
+            listNodes(&list);
 
             reply->writeInt32(list.size());
             for (List<String8>::iterator it = list.begin();
@@ -394,8 +384,14 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
+            const char *name = data.readCString();
+
+            sp<IOMXObserver> observer =
+                interface_cast<IOMXObserver>(data.readStrongBinder());
+
             node_id node;
-            status_t err = allocate_node(data.readCString(), &node);
+
+            status_t err = allocateNode(name, observer, &node);
             reply->writeInt32(err);
             if (err == OK) {
                 reply->writeIntPtr((intptr_t)node);
@@ -410,7 +406,7 @@
 
             node_id node = (void*)data.readIntPtr();
 
-            reply->writeInt32(free_node(node));
+            reply->writeInt32(freeNode(node));
                 
             return NO_ERROR;
         }
@@ -425,7 +421,7 @@
                 static_cast<OMX_COMMANDTYPE>(data.readInt32());
 
             OMX_S32 param = data.readInt32();
-            reply->writeInt32(send_command(node, cmd, param));
+            reply->writeInt32(sendCommand(node, cmd, param));
 
             return NO_ERROR;
         }
@@ -443,7 +439,7 @@
             void *params = malloc(size);
             data.read(params, size);
 
-            status_t err = get_parameter(node, index, params, size);
+            status_t err = getParameter(node, index, params, size);
 
             reply->writeInt32(err);
 
@@ -467,7 +463,7 @@
             size_t size = data.readInt32();
             void *params = const_cast<void *>(data.readInplace(size));
 
-            reply->writeInt32(set_parameter(node, index, params, size));
+            reply->writeInt32(setParameter(node, index, params, size));
 
             return NO_ERROR;
         }
@@ -485,7 +481,7 @@
             void *params = malloc(size);
             data.read(params, size);
 
-            status_t err = get_config(node, index, params, size);
+            status_t err = getConfig(node, index, params, size);
 
             reply->writeInt32(err);
 
@@ -509,7 +505,7 @@
             size_t size = data.readInt32();
             void *params = const_cast<void *>(data.readInplace(size));
 
-            reply->writeInt32(set_config(node, index, params, size));
+            reply->writeInt32(setConfig(node, index, params, size));
 
             return NO_ERROR;
         }
@@ -524,7 +520,7 @@
                 interface_cast<IMemory>(data.readStrongBinder());
 
             buffer_id buffer;
-            status_t err = use_buffer(node, port_index, params, &buffer);
+            status_t err = useBuffer(node, port_index, params, &buffer);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -543,7 +539,7 @@
             size_t size = data.readInt32();
 
             buffer_id buffer;
-            status_t err = allocate_buffer(node, port_index, size, &buffer);
+            status_t err = allocateBuffer(node, port_index, size, &buffer);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -563,7 +559,7 @@
                 interface_cast<IMemory>(data.readStrongBinder());
 
             buffer_id buffer;
-            status_t err = allocate_buffer_with_backup(
+            status_t err = allocateBufferWithBackup(
                     node, port_index, params, &buffer);
 
             reply->writeInt32(err);
@@ -582,19 +578,7 @@
             node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
             buffer_id buffer = (void*)data.readIntPtr();
-            reply->writeInt32(free_buffer(node, port_index, buffer));
-
-            return NO_ERROR;
-        }
-
-        case OBSERVE_NODE:
-        {
-            CHECK_INTERFACE(IOMX, data, reply);
-
-            node_id node = (void*)data.readIntPtr();
-            sp<IOMXObserver> observer =
-                interface_cast<IOMXObserver>(data.readStrongBinder());
-            reply->writeInt32(observe_node(node, observer));
+            reply->writeInt32(freeBuffer(node, port_index, buffer));
 
             return NO_ERROR;
         }
@@ -605,7 +589,7 @@
 
             node_id node = (void*)data.readIntPtr();
             buffer_id buffer = (void*)data.readIntPtr();
-            reply->writeInt32(fill_buffer(node, buffer));
+            reply->writeInt32(fillBuffer(node, buffer));
 
             return NO_ERROR;
         }
@@ -622,7 +606,7 @@
             OMX_TICKS timestamp = data.readInt64();
 
             reply->writeInt32(
-                    empty_buffer(
+                    emptyBuffer(
                         node, buffer, range_offset, range_length,
                         flags, timestamp));
 
@@ -637,7 +621,7 @@
             const char *parameter_name = data.readCString();
             
             OMX_INDEXTYPE index;
-            status_t err = get_extension_index(node, parameter_name, &index);
+            status_t err = getExtensionIndex(node, parameter_name, &index);
 
             reply->writeInt32(err);
 
@@ -688,7 +672,7 @@
         : BpInterface<IOMXObserver>(impl) {
     }
 
-    virtual void on_message(const omx_message &msg) {
+    virtual void onMessage(const omx_message &msg) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
         data.write(&msg, sizeof(msg));
@@ -710,7 +694,7 @@
             data.read(&msg, sizeof(msg));
 
             // XXX Could use readInplace maybe?
-            on_message(msg);
+            onMessage(msg);
 
             return NO_ERROR;
         }
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index ef41225..6fc9fa2 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -51,7 +51,7 @@
 	$(JNI_H_INCLUDE)                                                \
 	$(call include-path-for, graphics corecg)                       \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
-	$(TOP)/frameworks/base/media/libstagefright/omx
+	$(TOP)/frameworks/base/media/libstagefright/include
 
 LOCAL_MODULE:= libmediaplayerservice
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 84be874..ab759df 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -274,8 +274,14 @@
     return c;
 }
 
-sp<IOMX> MediaPlayerService::createOMX() {
-    return new OMX;
+sp<IOMX> MediaPlayerService::getOMX() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mOMX.get() == NULL) {
+        mOMX = new OMX;
+    }
+
+    return mOMX;
 }
 
 status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 7d2e611..931667e 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -183,7 +183,7 @@
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         snoop();
-    virtual sp<IOMX>            createOMX();
+    virtual sp<IOMX>            getOMX();
 
     virtual status_t            dump(int fd, const Vector<String16>& args);
 
@@ -281,6 +281,7 @@
     mutable     Mutex                       mLock;
                 SortedVector< wp<Client> >  mClients;
                 int32_t                     mNextConnId;
+                sp<IOMX>                    mOMX;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index dba7a2a..9de873e 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -35,7 +35,7 @@
 
     CHECK(service.get() != NULL);
 
-    mOMX = service->createOMX();
+    mOMX = service->getOMX();
     CHECK(mOMX.get() != NULL);
 
     return OK;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 5201c5a..83d3b13 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -88,12 +88,15 @@
 #define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
 
 struct OMXCodecObserver : public BnOMXObserver {
-    OMXCodecObserver(const wp<OMXCodec> &target)
-        : mTarget(target) {
+    OMXCodecObserver() {
+    }
+
+    void setCodec(const sp<OMXCodec> &target) {
+        mTarget = target;
     }
 
     // from IOMXObserver
-    virtual void on_message(const omx_message &msg) {
+    virtual void onMessage(const omx_message &msg) {
         sp<OMXCodec> codec = mTarget.promote();
 
         if (codec.get() != NULL) {
@@ -180,6 +183,7 @@
     CHECK(success);
 
     const char *componentName = NULL;
+    sp<OMXCodecObserver> observer = new OMXCodecObserver;
     IOMX::node_id node = 0;
     for (int index = 0;; ++index) {
         if (createEncoder) {
@@ -203,7 +207,7 @@
 
         LOGV("Attempting to allocate OMX node '%s'", componentName);
 
-        status_t err = omx->allocate_node(componentName, &node);
+        status_t err = omx->allocateNode(componentName, observer, &node);
         if (err == OK) {
             LOGV("Successfully allocated OMX node '%s'", componentName);
             break;
@@ -245,6 +249,8 @@
             omx, node, quirks, createEncoder, mime, componentName,
             source);
 
+    observer->setCodec(codec);
+
     uint32_t type;
     const void *data;
     size_t size;
@@ -325,15 +331,15 @@
         LOGV("AVC profile = %d (%s), level = %d",
              (int)profile, AVCProfileToString(profile), (int)level / 10);
 
-#if 0
         if (!strcmp(componentName, "OMX.TI.Video.Decoder")
             && (profile != kAVCProfileBaseline || level > 39)) {
-            // This stream exceeds the decoder's capabilities.
+            // This stream exceeds the decoder's capabilities. The decoder
+            // does not handle this gracefully and would clobber the heap
+            // and wreak havoc instead...
 
             LOGE("Profile and/or level exceed the decoder's capabilities.");
             return NULL;
         }
-#endif
     }
 
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
@@ -404,7 +410,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -413,7 +419,7 @@
 
     }
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -431,7 +437,7 @@
     OMX_U32 index = 0;
     for (;;) {
         format.nIndex = index;
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
 
@@ -477,7 +483,7 @@
     }
 
     CODEC_LOGV("found a match.");
-    status_t err = mOMX->set_parameter(
+    status_t err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoPortFormat,
             &format, sizeof(format));
 
@@ -520,7 +526,7 @@
 
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     CHECK_EQ(err, OK);
@@ -532,7 +538,7 @@
     video_def->eCompressionFormat = compressionFormat;
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -541,7 +547,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    err = mOMX->get_parameter(
+    err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -555,7 +561,7 @@
     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
     video_def->eColorFormat = colorFormat;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -586,7 +592,7 @@
         format.nPortIndex = kPortIndexOutput;
         format.nIndex = 0;
 
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
         CHECK_EQ(err, OK);
@@ -599,7 +605,7 @@
                || format.eColorFormat == OMX_COLOR_FormatCbYCrY
                || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
 
-        err = mOMX->set_parameter(
+        err = mOMX->setParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
         CHECK_EQ(err, OK);
@@ -612,7 +618,7 @@
 
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     CHECK_EQ(err, OK);
@@ -632,7 +638,7 @@
 
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -641,7 +647,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    err = mOMX->get_parameter(
+    err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
@@ -654,7 +660,7 @@
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -683,9 +689,6 @@
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
 
-    mObserver = new OMXCodecObserver(this);
-    mOMX->observe_node(mNode, mObserver);
-
     setComponentRole();
 }
 
@@ -743,7 +746,7 @@
 
         roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
 
-        status_t err = omx->set_parameter(
+        status_t err = omx->setParameter(
                 node, OMX_IndexParamStandardComponentRole,
                 &roleParams, sizeof(roleParams));
 
@@ -760,10 +763,7 @@
 OMXCodec::~OMXCodec() {
     CHECK(mState == LOADED || mState == ERROR);
 
-    status_t err = mOMX->observe_node(mNode, NULL);
-    CHECK_EQ(err, OK);
-
-    err = mOMX->free_node(mNode);
+    status_t err = mOMX->freeNode(mNode);
     CHECK_EQ(err, OK);
 
     mNode = NULL;
@@ -785,7 +785,7 @@
 
     status_t err;
     if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
-        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
         CHECK_EQ(err, OK);
         setState(LOADED_TO_IDLE);
     }
@@ -794,7 +794,7 @@
     CHECK_EQ(err, OK);
 
     if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
-        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
         CHECK_EQ(err, OK);
 
         setState(LOADED_TO_IDLE);
@@ -831,7 +831,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
@@ -848,14 +848,14 @@
         IOMX::buffer_id buffer;
         if (portIndex == kPortIndexInput
                 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
-            err = mOMX->allocate_buffer_with_backup(
+            err = mOMX->allocateBufferWithBackup(
                     mNode, portIndex, mem, &buffer);
         } else if (portIndex == kPortIndexOutput
                 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
-            err = mOMX->allocate_buffer_with_backup(
+            err = mOMX->allocateBufferWithBackup(
                     mNode, portIndex, mem, &buffer);
         } else {
-            err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
+            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
         }
 
         if (err != OK) {
@@ -922,7 +922,7 @@
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
 
                 status_t err =
-                    mOMX->free_buffer(mNode, kPortIndexInput, buffer);
+                    mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
                 CHECK_EQ(err, OK);
 
                 buffers->removeAt(i);
@@ -968,7 +968,7 @@
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
 
                 status_t err =
-                    mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
+                    mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
                 CHECK_EQ(err, OK);
 
                 buffers->removeAt(i);
@@ -1137,7 +1137,7 @@
                     mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
 
                     status_t err =
-                        mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+                        mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
                     CHECK_EQ(err, OK);
                 }
             } else {
@@ -1177,7 +1177,7 @@
         {
             CODEC_LOGV("Now Idle.");
             if (mState == LOADED_TO_IDLE) {
-                status_t err = mOMX->send_command(
+                status_t err = mOMX->sendCommand(
                         mNode, OMX_CommandStateSet, OMX_StateExecuting);
 
                 CHECK_EQ(err, OK);
@@ -1194,7 +1194,7 @@
                     countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
                     mPortBuffers[kPortIndexOutput].size());
 
-                status_t err = mOMX->send_command(
+                status_t err = mOMX->sendCommand(
                         mNode, OMX_CommandStateSet, OMX_StateLoaded);
 
                 CHECK_EQ(err, OK);
@@ -1277,7 +1277,7 @@
         CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
 
         status_t err =
-            mOMX->free_buffer(mNode, portIndex, info->mBuffer);
+            mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
 
         if (err != OK) {
             stickyErr = err;
@@ -1337,7 +1337,7 @@
     }
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
     CHECK_EQ(err, OK);
 
     return true;
@@ -1350,7 +1350,7 @@
     mPortStatus[portIndex] = DISABLING;
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
     CHECK_EQ(err, OK);
 
     freeBuffersOnPort(portIndex, true);
@@ -1363,7 +1363,7 @@
     mPortStatus[portIndex] = ENABLING;
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
     CHECK_EQ(err, OK);
 }
 
@@ -1415,7 +1415,7 @@
             memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
         }
 
-        status_t err = mOMX->empty_buffer(
+        status_t err = mOMX->emptyBuffer(
                 mNode, info->mBuffer, 0, size,
                 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
                 0);
@@ -1461,9 +1461,9 @@
                srcLength);
 
         if (srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs)) {
-            CODEC_LOGV("Calling empty_buffer on buffer %p (length %d)",
+            CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d)",
                  info->mBuffer, srcLength);
-            CODEC_LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
+            CODEC_LOGV("Calling emptyBuffer with timestamp %lld us (%.2f secs)",
                  timestampUs, timestampUs / 1E6);
         }
     }
@@ -1473,7 +1473,7 @@
         srcBuffer = NULL;
     }
 
-    err = mOMX->empty_buffer(
+    err = mOMX->emptyBuffer(
             mNode, info->mBuffer, 0, srcLength,
             flags, timestampUs);
 
@@ -1495,7 +1495,7 @@
     }
 
     CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
-    status_t err = mOMX->fill_buffer(mNode, info->mBuffer);
+    status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
     CHECK_EQ(err, OK);
 
     info->mOwnedByComponent = true;
@@ -1540,7 +1540,7 @@
     InitOMXParams(&pcmParams);
     pcmParams.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     CHECK_EQ(err, OK);
@@ -1561,7 +1561,7 @@
         pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
     }
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     CHECK_EQ(err, OK);
@@ -1574,14 +1574,14 @@
         def.nPortIndex = kPortIndexInput;
 
         status_t err =
-            mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
 
         CHECK_EQ(err, OK);
 
         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
         def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
 
-        err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
         CHECK_EQ(err, OK);
     }
 
@@ -1605,14 +1605,14 @@
         def.nPortIndex = kPortIndexInput;
 
         status_t err =
-            mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
 
         CHECK_EQ(err, OK);
 
         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
         def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
 
-        err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
         CHECK_EQ(err, OK);
     }
 
@@ -1637,7 +1637,7 @@
         InitOMXParams(&profile);
         profile.nPortIndex = kPortIndexInput;
 
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
         CHECK_EQ(err, OK);
 
@@ -1645,7 +1645,7 @@
         profile.nSampleRate = sampleRate;
         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
 
-        err = mOMX->set_parameter(
+        err = mOMX->setParameter(
                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
         CHECK_EQ(err, OK);
     }
@@ -1669,7 +1669,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -1718,7 +1718,7 @@
 
     def.nBufferCountActual = def.nBufferCountMin;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -1729,7 +1729,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -1743,7 +1743,7 @@
     def.nBufferSize = compressedSize;
     def.nBufferCountActual = def.nBufferCountMin;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -1834,7 +1834,7 @@
                 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
 
                 status_t err =
-                    mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+                    mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
                 CHECK_EQ(err, OK);
             }
 
@@ -2172,7 +2172,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -2238,7 +2238,7 @@
                 InitOMXParams(&params);
                 params.nPortIndex = portIndex;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
                 CHECK_EQ(err, OK);
 
@@ -2257,7 +2257,7 @@
                 InitOMXParams(&amr);
                 amr.nPortIndex = portIndex;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
                 CHECK_EQ(err, OK);
 
@@ -2289,7 +2289,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -2315,7 +2315,7 @@
                 InitOMXParams(&params);
                 params.nPortIndex = kPortIndexOutput;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
                 CHECK_EQ(err, OK);
 
@@ -2347,7 +2347,7 @@
                 InitOMXParams(&amr);
                 amr.nPortIndex = kPortIndexOutput;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
                 CHECK_EQ(err, OK);
 
@@ -2444,8 +2444,9 @@
             return OK;
         }
 
+        sp<OMXCodecObserver> observer = new OMXCodecObserver;
         IOMX::node_id node;
-        status_t err = omx->allocate_node(componentName, &node);
+        status_t err = omx->allocateNode(componentName, observer, &node);
 
         if (err != OK) {
             continue;
@@ -2463,7 +2464,7 @@
         param.nPortIndex = queryDecoders ? 0 : 1;
 
         for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
-            err = omx->get_parameter(
+            err = omx->getParameter(
                     node, OMX_IndexParamVideoProfileLevelQuerySupported,
                     &param, sizeof(param));
 
@@ -2478,7 +2479,7 @@
             caps->mProfileLevels.push(profileLevel);
         }
 
-        CHECK_EQ(omx->free_node(node), OK);
+        CHECK_EQ(omx->freeNode(node), OK);
     }
 }
 
diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/include/OMX.h
similarity index 61%
rename from media/libstagefright/omx/OMX.h
rename to media/libstagefright/include/OMX.h
index 4c14dd9..a4b62b2 100644
--- a/media/libstagefright/omx/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -19,66 +19,67 @@
 
 #include <media/IOMX.h>
 #include <utils/threads.h>
+#include <utils/KeyedVector.h>
 
 namespace android {
 
-class NodeMeta;
+class OMXNodeInstance;
 
-class OMX : public BnOMX {
+class OMX : public BnOMX,
+            public IBinder::DeathRecipient {
 public:
     OMX();
 
-    virtual status_t list_nodes(List<String8> *list);
+    virtual status_t listNodes(List<String8> *list);
 
-    virtual status_t allocate_node(const char *name, node_id *node);
-    virtual status_t free_node(node_id node);
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer, node_id *node);
 
-    virtual status_t send_command(
+    virtual status_t freeNode(node_id node);
+
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size);
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size);
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size);
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size);
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer);
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer);
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer);
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer);
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer);
+    virtual status_t fillBuffer(node_id node, buffer_id buffer);
 
-    virtual status_t fill_buffer(node_id node, buffer_id buffer);
-
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp);
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index);
@@ -90,44 +91,38 @@
             size_t encodedWidth, size_t encodedHeight,
             size_t displayWidth, size_t displayHeight);
 
-private:
-    static OMX_CALLBACKTYPE kCallbacks;
-
-    Mutex mLock;
-
-    struct CallbackDispatcher;
-    sp<CallbackDispatcher> mDispatcher;
-
-    static OMX_ERRORTYPE OnEvent(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_EVENTTYPE eEvent,
-            OMX_IN OMX_U32 nData1,
-            OMX_IN OMX_U32 nData2,
-            OMX_IN OMX_PTR pEventData);
-
-    static OMX_ERRORTYPE OnEmptyBufferDone(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
-
-    static OMX_ERRORTYPE OnFillBufferDone(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+    virtual void binderDied(const wp<IBinder> &the_late_who);
 
     OMX_ERRORTYPE OnEvent(
-            NodeMeta *meta,
+            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(
-            NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+            node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 
     OMX_ERRORTYPE OnFillBufferDone(
-            NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+            node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    void invalidateNodeID(node_id node);
+
+private:
+    Mutex mLock;
+
+    struct CallbackDispatcher;
+    sp<CallbackDispatcher> mDispatcher;
+
+    int32_t mNodeCounter;
+
+    KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
+    KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
+
+    node_id makeNodeID(OMXNodeInstance *instance);
+    OMXNodeInstance *findInstance(node_id node);
+
+    void invalidateNodeID_l(node_id node);
 
     OMX(const OMX &);
     OMX &operator=(const OMX &);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
new file mode 100644
index 0000000..181742e
--- /dev/null
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009 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 OMX_NODE_INSTANCE_H_
+
+#define OMX_NODE_INSTANCE_H_
+
+#include "OMX.h"
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class IOMXObserver;
+
+struct OMXNodeInstance {
+    OMXNodeInstance(
+            OMX *owner, const sp<IOMXObserver> &observer);
+
+    void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
+
+    OMX *owner();
+    sp<IOMXObserver> observer();
+    OMX::node_id nodeID();
+
+    status_t freeNode();
+
+    status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+    status_t getParameter(OMX_INDEXTYPE index, void *params, size_t size);
+
+    status_t setParameter(
+            OMX_INDEXTYPE index, const void *params, size_t size);
+
+    status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
+    status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
+
+    status_t useBuffer(
+            OMX_U32 portIndex, const sp<IMemory> &params,
+            OMX::buffer_id *buffer);
+
+    status_t allocateBuffer(
+            OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer);
+
+    status_t allocateBufferWithBackup(
+            OMX_U32 portIndex, const sp<IMemory> &params,
+            OMX::buffer_id *buffer);
+
+    status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
+
+    status_t fillBuffer(OMX::buffer_id buffer);
+
+    status_t emptyBuffer(
+            OMX::buffer_id buffer,
+            OMX_U32 rangeOffset, OMX_U32 rangeLength,
+            OMX_U32 flags, OMX_TICKS timestamp);
+
+    status_t getExtensionIndex(
+            const char *parameterName, OMX_INDEXTYPE *index);
+
+    void onMessage(const omx_message &msg);
+    void onObserverDied();
+    void onGetHandleFailed();
+
+    static OMX_CALLBACKTYPE kCallbacks;
+
+private:
+    Mutex mLock;
+
+    OMX *mOwner;
+    OMX::node_id mNodeID;
+    OMX_HANDLETYPE mHandle;
+    sp<IOMXObserver> mObserver;
+
+    ~OMXNodeInstance();
+
+    static OMX_ERRORTYPE OnEvent(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_EVENTTYPE eEvent,
+            OMX_IN OMX_U32 nData1,
+            OMX_IN OMX_U32 nData2,
+            OMX_IN OMX_PTR pEventData);
+
+    static OMX_ERRORTYPE OnEmptyBufferDone(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    static OMX_ERRORTYPE OnFillBufferDone(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    OMXNodeInstance(const OMXNodeInstance &);
+    OMXNodeInstance &operator=(const OMXNodeInstance &);
+};
+
+}  // namespace android
+
+#endif  // OMX_NODE_INSTANCE_H_
+
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 468221e..edbc04e 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_SRC_FILES:=                 \
         ColorConverter.cpp        \
 	OMX.cpp                   \
+        OMXNodeInstance.cpp       \
         QComHardwareRenderer.cpp  \
         SoftwareRenderer.cpp      \
         TIHardwareRenderer.cpp
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 8d100d9..3800a26 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -18,13 +18,12 @@
 #define LOG_TAG "OMX"
 #include <utils/Log.h>
 
-#include <sys/socket.h>
-
-#include "OMX.h"
+#include "../include/OMX.h"
 #include "OMXRenderer.h"
 
 #include "pv_omxcore.h"
 
+#include "../include/OMXNodeInstance.h"
 #include "../include/QComHardwareRenderer.h"
 #include "../include/SoftwareRenderer.h"
 #include "../include/TIHardwareRenderer.h"
@@ -37,47 +36,10 @@
 
 namespace android {
 
-class NodeMeta {
-public:
-    NodeMeta(OMX *owner)
-        : mOwner(owner),
-          mHandle(NULL) {
-    }
-
-    OMX *owner() const {
-        return mOwner;
-    }
-
-    void setHandle(OMX_HANDLETYPE handle) {
-        CHECK_EQ(mHandle, NULL);
-        mHandle = handle;
-    }
-
-    OMX_HANDLETYPE handle() const {
-        return mHandle;
-    }
-
-    void setObserver(const sp<IOMXObserver> &observer) {
-        mObserver = observer;
-    }
-
-    sp<IOMXObserver> observer() {
-        return mObserver;
-    }
-
-private:
-    OMX *mOwner;
-    OMX_HANDLETYPE mHandle;
-    sp<IOMXObserver> mObserver;
-
-    NodeMeta(const NodeMeta &);
-    NodeMeta &operator=(const NodeMeta &);
-};
-
 ////////////////////////////////////////////////////////////////////////////////
 
 struct OMX::CallbackDispatcher : public RefBase {
-    CallbackDispatcher();
+    CallbackDispatcher(OMX *owner);
 
     void post(const omx_message &msg);
 
@@ -86,6 +48,8 @@
 
 private:
     Mutex mLock;
+
+    OMX *mOwner;
     bool mDone;
     Condition mQueueChanged;
     List<omx_message> mQueue;
@@ -101,8 +65,9 @@
     CallbackDispatcher &operator=(const CallbackDispatcher &);
 };
 
-OMX::CallbackDispatcher::CallbackDispatcher()
-    : mDone(false) {
+OMX::CallbackDispatcher::CallbackDispatcher(OMX *owner)
+    : mOwner(owner),
+      mDone(false) {
     pthread_attr_t attr;
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -131,12 +96,12 @@
 }
 
 void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
-    NodeMeta *meta = static_cast<NodeMeta *>(msg.node);
-
-    sp<IOMXObserver> observer = meta->observer();
-    if (observer.get() != NULL) {
-        observer->on_message(msg);
+    OMXNodeInstance *instance = mOwner->findInstance(msg.node);
+    if (instance == NULL) {
+        LOGW("Would have dispatched a message to a node that's already gone.");
+        return;
     }
+    instance->onMessage(msg);
 }
 
 // static
@@ -214,46 +179,30 @@
     BufferMeta &operator=(const BufferMeta &);
 };
 
-// static
-OMX_CALLBACKTYPE OMX::kCallbacks = {
-    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
-};
-
-// static
-OMX_ERRORTYPE OMX::OnEvent(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_EVENTTYPE eEvent,
-        OMX_IN OMX_U32 nData1,
-        OMX_IN OMX_U32 nData2,
-        OMX_IN OMX_PTR pEventData) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnEvent(meta, eEvent, nData1, nData2, pEventData);
-}
-
-// static
-OMX_ERRORTYPE OMX::OnEmptyBufferDone(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnEmptyBufferDone(meta, pBuffer);
-}
-
-// static
-OMX_ERRORTYPE OMX::OnFillBufferDone(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnFillBufferDone(meta, pBuffer);
-}
-
 OMX::OMX()
-    : mDispatcher(new CallbackDispatcher) {
+    : mDispatcher(new CallbackDispatcher(this)),
+      mNodeCounter(0) {
 }
 
-status_t OMX::list_nodes(List<String8> *list) {
+void OMX::binderDied(const wp<IBinder> &the_late_who) {
+    OMXNodeInstance *instance;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
+        CHECK(index >= 0);
+
+        instance = mLiveNodes.editValueAt(index);
+        mLiveNodes.removeItemsAt(index);
+
+        invalidateNodeID_l(instance->nodeID());
+    }
+
+    instance->onObserverDied();
+}
+
+status_t OMX::listNodes(List<String8> *list) {
     OMX_MasterInit();  // XXX Put this somewhere else.
 
     list->clear();
@@ -270,204 +219,132 @@
     return OK;
 }
 
-status_t OMX::allocate_node(const char *name, node_id *node) {
+status_t OMX::allocateNode(
+        const char *name, const sp<IOMXObserver> &observer, node_id *node) {
     Mutex::Autolock autoLock(mLock);
 
     *node = 0;
 
     OMX_MasterInit();  // XXX Put this somewhere else.
 
-    NodeMeta *meta = new NodeMeta(this);
+    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
 
     OMX_HANDLETYPE handle;
     OMX_ERRORTYPE err = OMX_MasterGetHandle(
-            &handle, const_cast<char *>(name), meta, &kCallbacks);
+            &handle, const_cast<char *>(name), instance,
+            &OMXNodeInstance::kCallbacks);
 
     if (err != OMX_ErrorNone) {
         LOGV("FAILED to allocate omx component '%s'", name);
 
-        delete meta;
-        meta = NULL;
+        instance->onGetHandleFailed();
 
         return UNKNOWN_ERROR;
     }
 
-    meta->setHandle(handle);
+    *node = makeNodeID(instance);
 
-    *node = meta;
+    instance->setHandle(*node, handle);
+
+    mLiveNodes.add(observer->asBinder(), instance);
+    observer->asBinder()->linkToDeath(this);
 
     return OK;
 }
 
-status_t OMX::free_node(node_id node) {
-    Mutex::Autolock autoLock(mLock);
+status_t OMX::freeNode(node_id node) {
+    OMXNodeInstance *instance = findInstance(node);
 
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
+    ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
+    CHECK(index >= 0);
+    mLiveNodes.removeItemsAt(index);
+    instance->observer()->asBinder()->unlinkToDeath(this);
 
-    OMX_ERRORTYPE err = OMX_MasterFreeHandle(meta->handle());
-
-    delete meta;
-    meta = NULL;
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return instance->freeNode();
 }
 
-status_t OMX::send_command(
+status_t OMX::sendCommand(
         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_SendCommand(meta->handle(), cmd, param, NULL);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->sendCommand(cmd, param);
 }
 
-status_t OMX::get_parameter(
+status_t OMX::getParameter(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_GetParameter(meta->handle(), index, params);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->getParameter(
+            index, params, size);
 }
 
-status_t OMX::set_parameter(
+status_t OMX::setParameter(
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_SetParameter(meta->handle(), index, const_cast<void *>(params));
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->setParameter(
+            index, params, size);
 }
 
-status_t OMX::get_config(
+status_t OMX::getConfig(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_GetConfig(meta->handle(), index, params);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->getConfig(
+            index, params, size);
 }
 
-status_t OMX::set_config(
+status_t OMX::setConfig(
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_SetConfig(meta->handle(), index, const_cast<void *>(params));
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->setConfig(
+            index, params, size);
 }
 
-status_t OMX::use_buffer(
+status_t OMX::useBuffer(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, params);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_UseBuffer(node_meta->handle(), &header, port_index, buffer_meta,
-                      params->size(), static_cast<OMX_U8 *>(params->pointer()));
-
-    if (err != OMX_ErrorNone) {
-        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
-
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->useBuffer(
+            port_index, params, buffer);
 }
 
-status_t OMX::allocate_buffer(
+status_t OMX::allocateBuffer(
         node_id node, OMX_U32 port_index, size_t size,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, size);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_AllocateBuffer(node_meta->handle(), &header, port_index,
-                           buffer_meta, size);
-
-    if (err != OMX_ErrorNone) {
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->allocateBuffer(
+            port_index, size, buffer);
 }
 
-status_t OMX::allocate_buffer_with_backup(
+status_t OMX::allocateBufferWithBackup(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, params, true);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_AllocateBuffer(
-                node_meta->handle(), &header, port_index, buffer_meta,
-                params->size());
-
-    if (err != OMX_ErrorNone) {
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->allocateBufferWithBackup(
+            port_index, params, buffer);
 }
 
-status_t OMX::free_buffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
+status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
+    return findInstance(node)->freeBuffer(
+            port_index, buffer);
+}
 
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_FreeBuffer(node_meta->handle(), port_index, header);
+status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
+    return findInstance(node)->fillBuffer(buffer);
+}
 
-    delete buffer_meta;
-    buffer_meta = NULL;
+status_t OMX::emptyBuffer(
+        node_id node,
+        buffer_id buffer,
+        OMX_U32 range_offset, OMX_U32 range_length,
+        OMX_U32 flags, OMX_TICKS timestamp) {
+    return findInstance(node)->emptyBuffer(
+            buffer, range_offset, range_length, flags, timestamp);
+}
 
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+status_t OMX::getExtensionIndex(
+        node_id node,
+        const char *parameter_name,
+        OMX_INDEXTYPE *index) {
+    return findInstance(node)->getExtensionIndex(
+            parameter_name, index);
 }
 
 OMX_ERRORTYPE OMX::OnEvent(
-        NodeMeta *meta,
+        node_id node,
         OMX_IN OMX_EVENTTYPE eEvent,
         OMX_IN OMX_U32 nData1,
         OMX_IN OMX_U32 nData2,
@@ -476,7 +353,7 @@
 
     omx_message msg;
     msg.type = omx_message::EVENT;
-    msg.node = meta;
+    msg.node = node;
     msg.u.event_data.event = eEvent;
     msg.u.event_data.data1 = nData1;
     msg.u.event_data.data2 = nData2;
@@ -485,14 +362,14 @@
 
     return OMX_ErrorNone;
 }
-    
+
 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
-        NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
     LOGV("OnEmptyBufferDone buffer=%p", pBuffer);
 
     omx_message msg;
     msg.type = omx_message::EMPTY_BUFFER_DONE;
-    msg.node = meta;
+    msg.node = node;
     msg.u.buffer_data.buffer = pBuffer;
 
     mDispatcher->post(msg);
@@ -501,14 +378,12 @@
 }
 
 OMX_ERRORTYPE OMX::OnFillBufferDone(
-        NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
     LOGV("OnFillBufferDone buffer=%p", pBuffer);
-    BufferMeta *buffer_meta = static_cast<BufferMeta *>(pBuffer->pAppPrivate);
-    buffer_meta->CopyFromOMX(pBuffer);
 
     omx_message msg;
     msg.type = omx_message::FILL_BUFFER_DONE;
-    msg.node = meta;
+    msg.node = node;
     msg.u.extended_buffer_data.buffer = pBuffer;
     msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
@@ -521,64 +396,31 @@
     return OMX_ErrorNone;
 }
 
-status_t OMX::observe_node(
-        node_id node, const sp<IOMXObserver> &observer) {
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
+OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
+    // mLock is already held.
 
-    node_meta->setObserver(observer);
+    node_id node = (node_id)++mNodeCounter;
+    mNodeIDToInstance.add(node, instance);
 
-    return OK;
+    return node;
 }
 
-status_t OMX::fill_buffer(node_id node, buffer_id buffer) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    header->nFilledLen = 0;
-    header->nOffset = 0;
-    header->nFlags = 0;
+OMXNodeInstance *OMX::findInstance(node_id node) {
+    Mutex::Autolock autoLock(mLock);
 
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
+    ssize_t index = mNodeIDToInstance.indexOfKey(node);
 
-    OMX_ERRORTYPE err =
-        OMX_FillThisBuffer(node_meta->handle(), header);
-
-    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+    return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
 }
 
-status_t OMX::empty_buffer(
-        node_id node,
-        buffer_id buffer,
-        OMX_U32 range_offset, OMX_U32 range_length,
-        OMX_U32 flags, OMX_TICKS timestamp) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    header->nFilledLen = range_length;
-    header->nOffset = range_offset;
-    header->nFlags = flags;
-    header->nTimeStamp = timestamp;
-
-    BufferMeta *buffer_meta =
-        static_cast<BufferMeta *>(header->pAppPrivate);
-    buffer_meta->CopyToOMX(header);
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-
-    OMX_ERRORTYPE err =
-        OMX_EmptyThisBuffer(node_meta->handle(), header);
-
-    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+void OMX::invalidateNodeID(node_id node) {
+    Mutex::Autolock autoLock(mLock);
+    invalidateNodeID_l(node);
 }
 
-status_t OMX::get_extension_index(
-        node_id node,
-        const char *parameter_name,
-        OMX_INDEXTYPE *index) {
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-
-    OMX_ERRORTYPE err =
-        OMX_GetExtensionIndex(
-                node_meta->handle(),
-                const_cast<char *>(parameter_name), index);
-
-    return err == OMX_ErrorNone ? OK : UNKNOWN_ERROR;
+void OMX::invalidateNodeID_l(node_id node) {
+    // mLock is held.
+    mNodeIDToInstance.removeItem(node);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
new file mode 100644
index 0000000..d277587
--- /dev/null
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2009 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 "OMXNodeInstance"
+#include <utils/Log.h>
+
+#include "../include/OMXNodeInstance.h"
+
+#include "pv_omxcore.h"
+
+#include <binder/IMemory.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+struct BufferMeta {
+    BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
+        : mMem(mem),
+          mIsBackup(is_backup) {
+    }
+
+    BufferMeta(size_t size)
+        : mSize(size),
+          mIsBackup(false) {
+    }
+
+    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
+        if (!mIsBackup) {
+            return;
+        }
+
+        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
+               header->pBuffer + header->nOffset,
+               header->nFilledLen);
+    }
+
+    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
+        if (!mIsBackup) {
+            return;
+        }
+
+        memcpy(header->pBuffer + header->nOffset,
+               (const OMX_U8 *)mMem->pointer() + header->nOffset,
+               header->nFilledLen);
+    }
+
+private:
+    sp<IMemory> mMem;
+    size_t mSize;
+    bool mIsBackup;
+
+    BufferMeta(const BufferMeta &);
+    BufferMeta &operator=(const BufferMeta &);
+};
+
+// static
+OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
+    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
+};
+
+OMXNodeInstance::OMXNodeInstance(
+        OMX *owner, const sp<IOMXObserver> &observer)
+    : mOwner(owner),
+      mNodeID(NULL),
+      mHandle(NULL),
+      mObserver(observer) {
+}
+
+OMXNodeInstance::~OMXNodeInstance() {
+    CHECK_EQ(mHandle, NULL);
+}
+
+void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
+    CHECK_EQ(mHandle, NULL);
+    mNodeID = node_id;
+    mHandle = handle;
+}
+
+OMX *OMXNodeInstance::owner() {
+    return mOwner;
+}
+
+sp<IOMXObserver> OMXNodeInstance::observer() {
+    return mObserver;
+}
+
+OMX::node_id OMXNodeInstance::nodeID() {
+    return mNodeID;
+}
+
+static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
+    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+}
+
+status_t OMXNodeInstance::freeNode() {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle);
+    mHandle = NULL;
+
+    if (err != OMX_ErrorNone) {
+        LOGE("FreeHandle FAILED with error 0x%08x.", err);
+    }
+
+    mOwner->invalidateNodeID(mNodeID);
+    mNodeID = NULL;
+
+    LOGI("OMXNodeInstance going away.");
+    delete this;
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::sendCommand(
+        OMX_COMMANDTYPE cmd, OMX_S32 param) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getParameter(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setParameter(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SetParameter(
+            mHandle, index, const_cast<void *>(params));
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getConfig(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setConfig(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SetConfig(
+            mHandle, index, const_cast<void *>(params));
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::useBuffer(
+        OMX_U32 portIndex, const sp<IMemory> &params,
+        OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(params);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_UseBuffer(
+            mHandle, &header, portIndex, buffer_meta,
+            params->size(), static_cast<OMX_U8 *>(params->pointer()));
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::allocateBuffer(
+        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(size);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_AllocateBuffer(
+            mHandle, &header, portIndex, buffer_meta, size);
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::allocateBufferWithBackup(
+        OMX_U32 portIndex, const sp<IMemory> &params,
+        OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(params, true);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_AllocateBuffer(
+            mHandle, &header, portIndex, buffer_meta, params->size());
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::freeBuffer(
+        OMX_U32 portIndex, OMX::buffer_id buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
+
+    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
+
+    delete buffer_meta;
+    buffer_meta = NULL;
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    header->nFilledLen = 0;
+    header->nOffset = 0;
+    header->nFlags = 0;
+
+    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::emptyBuffer(
+        OMX::buffer_id buffer,
+        OMX_U32 rangeOffset, OMX_U32 rangeLength,
+        OMX_U32 flags, OMX_TICKS timestamp) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    header->nFilledLen = rangeLength;
+    header->nOffset = rangeOffset;
+    header->nFlags = flags;
+    header->nTimeStamp = timestamp;
+
+    BufferMeta *buffer_meta =
+        static_cast<BufferMeta *>(header->pAppPrivate);
+    buffer_meta->CopyToOMX(header);
+
+    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getExtensionIndex(
+        const char *parameterName, OMX_INDEXTYPE *index) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+            mHandle, const_cast<char *>(parameterName), index);
+
+    return StatusFromOMXError(err);
+}
+
+void OMXNodeInstance::onMessage(const omx_message &msg) {
+    if (msg.type == omx_message::FILL_BUFFER_DONE) {
+        OMX_BUFFERHEADERTYPE *buffer =
+            static_cast<OMX_BUFFERHEADERTYPE *>(
+                    msg.u.extended_buffer_data.buffer);
+
+        BufferMeta *buffer_meta =
+            static_cast<BufferMeta *>(buffer->pAppPrivate);
+
+        buffer_meta->CopyFromOMX(buffer);
+    }
+
+    mObserver->onMessage(msg);
+}
+
+void OMXNodeInstance::onObserverDied() {
+    LOGE("!!! Observer died. Quickly, do something, ... anything...");
+
+    // Try to force shutdown of the node and hope for the best.
+    freeNode();
+}
+
+void OMXNodeInstance::onGetHandleFailed() {
+    delete this;
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEvent(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_EVENTTYPE eEvent,
+        OMX_IN OMX_U32 nData1,
+        OMX_IN OMX_U32 nData2,
+        OMX_IN OMX_PTR pEventData) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnEvent(
+            instance->nodeID(), eEvent, nData1, nData2, pEventData);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
+}
+
+}  // namespace android
+