OMX.cpp revision e3ec3cec3a2e27033249ff82964d2cbd441d9873
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1790ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian//#define LOG_NDEBUG 0
1890ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#define LOG_TAG "OMX"
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <dlfcn.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "../include/OMX.h"
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "OMXRenderer.h"
259cce325fae8adcf7560a28eef394489f09bad74dMathias Agopian
26c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include "../include/OMXNodeInstance.h"
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "../include/SoftwareRenderer.h"
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <binder/IMemory.h>
3090ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <media/stagefright/MediaDebug.h>
3190ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <media/stagefright/VideoRenderer.h>
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
339cce325fae8adcf7560a28eef394489f09bad74dMathias Agopian#include "OMXMaster.h"
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <OMX_Component.h>
36439cf8576d3b846c0aa0944d84372259bf075d51Mathias Agopian
378b33f032327f8de0dcc0e6d0d43ed80f834b51f6Mathias Agopiannamespace android {
38c666cae2d5995097ec49a87e375e2afdd92802b7Mathias Agopian
39d0566bc26fcf6ca396118701fa11900b627f2c09Mathias Agopian////////////////////////////////////////////////////////////////////////////////
40d0566bc26fcf6ca396118701fa11900b627f2c09Mathias Agopian
41a67932fe6864ac346e7f78b86df11cf6c5344137Mathias Agopianstruct OMX::CallbackDispatcher : public RefBase {
423165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    CallbackDispatcher(OMX *owner);
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void post(const omx_message &msg);
45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
463165cc21cfea781988407b19bd83292b19f05f55Mathias Agopianprotected:
4728378392fd5aa3e0a392c9eb64634055678c3987Jamie Gennis    virtual ~CallbackDispatcher();
483165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian
492d5e230292c27d59f4c096bc742a0a19abf811c1Jamie Gennisprivate:
5028378392fd5aa3e0a392c9eb64634055678c3987Jamie Gennis    Mutex mLock;
5128378392fd5aa3e0a392c9eb64634055678c3987Jamie Gennis
52e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    OMX *mOwner;
53e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    bool mDone;
54e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    Condition mQueueChanged;
55e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    List<omx_message> mQueue;
56e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pthread_t mThread;
58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void dispatch(const omx_message &msg);
607e27f05739c8a2655cf0f7faea35614ce0a50278Mathias Agopian
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    static void *ThreadWrapper(void *me);
629a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    void threadEntry();
639a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
649a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    CallbackDispatcher(const CallbackDispatcher &);
659a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    CallbackDispatcher &operator=(const CallbackDispatcher &);
66e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian};
67e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
68e57f292595bec48f65c8088b00ff6beea01217e9Mathias AgopianOMX::CallbackDispatcher::CallbackDispatcher(OMX *owner)
699d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown    : mOwner(owner),
70e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian      mDone(false) {
71e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    pthread_attr_t attr;
72dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis    pthread_attr_init(&attr);
73dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
74e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
75e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    pthread_create(&mThread, &attr, ThreadWrapper, this);
76e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
77e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    pthread_attr_destroy(&attr);
78e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian}
79e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
809cce325fae8adcf7560a28eef394489f09bad74dMathias AgopianOMX::CallbackDispatcher::~CallbackDispatcher() {
813165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    {
823165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian        Mutex::Autolock autoLock(mLock);
83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mDone = true;
859cce325fae8adcf7560a28eef394489f09bad74dMathias Agopian        mQueueChanged.signal();
86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void *dummy;
89e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    pthread_join(mThread, &dummy);
90e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian}
91e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian
92e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopianvoid OMX::CallbackDispatcher::post(const omx_message &msg) {
93e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian    Mutex::Autolock autoLock(mLock);
941b0b30d04304392748a8a4ab5a69e52a19f51b3aMathias Agopian    mQueue.push_back(msg);
951b0b30d04304392748a8a4ab5a69e52a19f51b3aMathias Agopian    mQueueChanged.signal();
961b0b30d04304392748a8a4ab5a69e52a19f51b3aMathias Agopian}
979d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown
9874c40c0a273dbfd7d10617c4cc1b0c066bfc812eMathias Agopianvoid OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
999d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown    OMXNodeInstance *instance = mOwner->findInstance(msg.node);
1009d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown    if (instance == NULL) {
1011b0b30d04304392748a8a4ab5a69e52a19f51b3aMathias Agopian        LOGV("Would have dispatched a message to a node that's already gone.");
1028e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross        return;
1038e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross    }
104c01a79d77b829e7de86ef137694e8ad708470ca1Andy McFadden    instance->onMessage(msg);
1058e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross}
1068e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross
107c01a79d77b829e7de86ef137694e8ad708470ca1Andy McFadden// static
1083094df359d1e6e2ae8ca4e935cc093f563804c96Mathias Agopianvoid *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
1099d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown    static_cast<CallbackDispatcher *>(me)->threadEntry();
1109d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown
1119d4e3d2f42e93e2d12bacabe97d307d30c3c20ddJeff Brown    return NULL;
112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid OMX::CallbackDispatcher::threadEntry() {
115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    for (;;) {
1163165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian        omx_message msg;
117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        {
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            Mutex::Autolock autoLock(mLock);
120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            while (!mDone && mQueue.empty()) {
121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                mQueueChanged.wait(mLock);
122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
1239a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
124e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian            if (mDone) {
125e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian                break;
126e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian            }
127698c0873cf2e07bdc7fd1e72169aee2a19fa40d7Mathias Agopian
128134f0422866e8985188ed10dfbdcb8e6c34b87f7Jamie Gennis            msg = *mQueue.begin();
129e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian            mQueue.erase(mQueue.begin());
1308e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross        }
1318e533069e5721e55cb9768e140e16546c3a4a8b6Colin Cross
132e57f292595bec48f65c8088b00ff6beea01217e9Mathias Agopian        dispatch(msg);
1333094df359d1e6e2ae8ca4e935cc093f563804c96Mathias Agopian    }
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1363165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian////////////////////////////////////////////////////////////////////////////////
1373165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian
138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectclass BufferMeta {
139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpublic:
140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false)
141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        : mOwner(owner),
142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project          mMem(mem),
143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project          mIsBackup(is_backup) {
14490ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian    }
145
146    BufferMeta(OMX *owner, size_t size)
147        : mOwner(owner),
148          mSize(size),
149          mIsBackup(false) {
150    }
151
152    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
153        if (!mIsBackup) {
154            return;
155        }
156
157        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
158               header->pBuffer + header->nOffset,
159               header->nFilledLen);
160    }
161
162    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
163        if (!mIsBackup) {
164            return;
165        }
166
167        memcpy(header->pBuffer + header->nOffset,
168               (const OMX_U8 *)mMem->pointer() + header->nOffset,
169               header->nFilledLen);
170    }
171
172private:
173    OMX *mOwner;
174    sp<IMemory> mMem;
175    size_t mSize;
176    bool mIsBackup;
177
178    BufferMeta(const BufferMeta &);
179    BufferMeta &operator=(const BufferMeta &);
180};
181
182OMX::OMX()
183    : mMaster(new OMXMaster),
184      mDispatcher(new CallbackDispatcher(this)),
185      mNodeCounter(0) {
186}
187
188OMX::~OMX() {
189    delete mMaster;
190    mMaster = NULL;
191}
192
193void OMX::binderDied(const wp<IBinder> &the_late_who) {
194    OMXNodeInstance *instance;
195
196    {
197        Mutex::Autolock autoLock(mLock);
198
199        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
200        CHECK(index >= 0);
201
202        instance = mLiveNodes.editValueAt(index);
203        mLiveNodes.removeItemsAt(index);
204
205        invalidateNodeID_l(instance->nodeID());
206    }
207
208    instance->onObserverDied();
209}
210
211status_t OMX::listNodes(List<String8> *list) {
212    list->clear();
213
214    OMX_U32 index = 0;
215    char componentName[256];
216    while (mMaster->enumerateComponents(
217                componentName, sizeof(componentName), index) == OMX_ErrorNone) {
218        list->push_back(String8(componentName));
219
220        ++index;
221    }
222
223    return OK;
224}
225
226status_t OMX::allocateNode(
227        const char *name, const sp<IOMXObserver> &observer, node_id *node) {
228    Mutex::Autolock autoLock(mLock);
229
230    *node = 0;
231
232    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
233
234    OMX_COMPONENTTYPE *handle;
235    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
236            name, &OMXNodeInstance::kCallbacks,
237            instance, &handle);
238
239    if (err != OMX_ErrorNone) {
240        LOGV("FAILED to allocate omx component '%s'", name);
241
242        instance->onGetHandleFailed();
243
244        return UNKNOWN_ERROR;
245    }
246
247    *node = makeNodeID(instance);
248
249    instance->setHandle(*node, handle);
250
251    mLiveNodes.add(observer->asBinder(), instance);
252    observer->asBinder()->linkToDeath(this);
253
254    return OK;
255}
256
257status_t OMX::freeNode(node_id node) {
258    OMXNodeInstance *instance = findInstance(node);
259
260    ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
261    CHECK(index >= 0);
262    mLiveNodes.removeItemsAt(index);
263    instance->observer()->asBinder()->unlinkToDeath(this);
264
265    return instance->freeNode();
266}
267
268status_t OMX::sendCommand(
269        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
270    return findInstance(node)->sendCommand(cmd, param);
271}
272
273status_t OMX::getParameter(
274        node_id node, OMX_INDEXTYPE index,
275        void *params, size_t size) {
276    return findInstance(node)->getParameter(
277            index, params, size);
278}
279
280status_t OMX::setParameter(
281        node_id node, OMX_INDEXTYPE index,
282        const void *params, size_t size) {
283    return findInstance(node)->setParameter(
284            index, params, size);
285}
286
287status_t OMX::getConfig(
288        node_id node, OMX_INDEXTYPE index,
289        void *params, size_t size) {
290    return findInstance(node)->getConfig(
291            index, params, size);
292}
293
294status_t OMX::setConfig(
295        node_id node, OMX_INDEXTYPE index,
296        const void *params, size_t size) {
297    return findInstance(node)->setConfig(
298            index, params, size);
299}
300
301status_t OMX::useBuffer(
302        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
303        buffer_id *buffer) {
304    return findInstance(node)->useBuffer(
305            port_index, params, buffer);
306}
307
308status_t OMX::allocateBuffer(
309        node_id node, OMX_U32 port_index, size_t size,
310        buffer_id *buffer) {
311    return findInstance(node)->allocateBuffer(
312            port_index, size, buffer);
313}
314
315status_t OMX::allocateBufferWithBackup(
316        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
317        buffer_id *buffer) {
318    return findInstance(node)->allocateBufferWithBackup(
319            port_index, params, buffer);
320}
321
322status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
323    return findInstance(node)->freeBuffer(
324            port_index, buffer);
325}
326
327status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
328    return findInstance(node)->fillBuffer(buffer);
329}
330
331status_t OMX::emptyBuffer(
332        node_id node,
333        buffer_id buffer,
334        OMX_U32 range_offset, OMX_U32 range_length,
335        OMX_U32 flags, OMX_TICKS timestamp) {
336    return findInstance(node)->emptyBuffer(
337            buffer, range_offset, range_length, flags, timestamp);
338}
339
340status_t OMX::getExtensionIndex(
341        node_id node,
342        const char *parameter_name,
343        OMX_INDEXTYPE *index) {
344    return findInstance(node)->getExtensionIndex(
345            parameter_name, index);
346}
347
348OMX_ERRORTYPE OMX::OnEvent(
349        node_id node,
350        OMX_IN OMX_EVENTTYPE eEvent,
351        OMX_IN OMX_U32 nData1,
352        OMX_IN OMX_U32 nData2,
353        OMX_IN OMX_PTR pEventData) {
354    LOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2);
355
356    omx_message msg;
357    msg.type = omx_message::EVENT;
358    msg.node = node;
359    msg.u.event_data.event = eEvent;
360    msg.u.event_data.data1 = nData1;
361    msg.u.event_data.data2 = nData2;
362
363    mDispatcher->post(msg);
364
365    return OMX_ErrorNone;
366}
367
368OMX_ERRORTYPE OMX::OnEmptyBufferDone(
369        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
370    LOGV("OnEmptyBufferDone buffer=%p", pBuffer);
371
372    omx_message msg;
373    msg.type = omx_message::EMPTY_BUFFER_DONE;
374    msg.node = node;
375    msg.u.buffer_data.buffer = pBuffer;
376
377    mDispatcher->post(msg);
378
379    return OMX_ErrorNone;
380}
381
382OMX_ERRORTYPE OMX::OnFillBufferDone(
383        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
384    LOGV("OnFillBufferDone buffer=%p", pBuffer);
385
386    omx_message msg;
387    msg.type = omx_message::FILL_BUFFER_DONE;
388    msg.node = node;
389    msg.u.extended_buffer_data.buffer = pBuffer;
390    msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
391    msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
392    msg.u.extended_buffer_data.flags = pBuffer->nFlags;
393    msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
394    msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
395
396    mDispatcher->post(msg);
397
398    return OMX_ErrorNone;
399}
400
401OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
402    // mLock is already held.
403
404    node_id node = (node_id)++mNodeCounter;
405    mNodeIDToInstance.add(node, instance);
406
407    return node;
408}
409
410OMXNodeInstance *OMX::findInstance(node_id node) {
411    Mutex::Autolock autoLock(mLock);
412
413    ssize_t index = mNodeIDToInstance.indexOfKey(node);
414
415    return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
416}
417
418void OMX::invalidateNodeID(node_id node) {
419    Mutex::Autolock autoLock(mLock);
420    invalidateNodeID_l(node);
421}
422
423void OMX::invalidateNodeID_l(node_id node) {
424    // mLock is held.
425    mNodeIDToInstance.removeItem(node);
426}
427
428////////////////////////////////////////////////////////////////////////////////
429
430sp<IOMXRenderer> OMX::createRenderer(
431        const sp<ISurface> &surface,
432        const char *componentName,
433        OMX_COLOR_FORMATTYPE colorFormat,
434        size_t encodedWidth, size_t encodedHeight,
435        size_t displayWidth, size_t displayHeight) {
436    Mutex::Autolock autoLock(mLock);
437
438    VideoRenderer *impl = NULL;
439
440    static void *libHandle = NULL;
441
442    if (!libHandle) {
443        libHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
444    }
445
446    if (libHandle) {
447        typedef VideoRenderer *(*CreateRendererFunc)(
448                const sp<ISurface> &surface,
449                const char *componentName,
450                OMX_COLOR_FORMATTYPE colorFormat,
451                size_t displayWidth, size_t displayHeight,
452                size_t decodedWidth, size_t decodedHeight);
453
454        CreateRendererFunc func =
455            (CreateRendererFunc)dlsym(
456                    libHandle,
457                    "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
458                    "OMX_COLOR_FORMATTYPEjjjj");
459
460        if (func) {
461            impl = (*func)(surface, componentName, colorFormat,
462                    displayWidth, displayHeight, encodedWidth, encodedHeight);
463        }
464    }
465
466    if (!impl) {
467        LOGW("Using software renderer.");
468        impl = new SoftwareRenderer(
469                colorFormat,
470                surface,
471                displayWidth, displayHeight,
472                encodedWidth, encodedHeight);
473    }
474
475    return new OMXRenderer(impl);
476}
477
478OMXRenderer::OMXRenderer(VideoRenderer *impl)
479    : mImpl(impl) {
480}
481
482OMXRenderer::~OMXRenderer() {
483    delete mImpl;
484    mImpl = NULL;
485}
486
487void OMXRenderer::render(IOMX::buffer_id buffer) {
488    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
489
490    mImpl->render(
491            header->pBuffer + header->nOffset,
492            header->nFilledLen,
493            header->pPlatformPrivate);
494}
495
496}  // namespace android
497
498