1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <inttypes.h>
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "OMX"
21 #include <utils/Log.h>
22 
23 #include <dlfcn.h>
24 
25 #include "../include/OMX.h"
26 
27 #include "../include/OMXNodeInstance.h"
28 
29 #include <binder/IMemory.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <utils/threads.h>
32 
33 #include "OMXMaster.h"
34 #include "OMXUtils.h"
35 
36 #include <OMX_AsString.h>
37 #include <OMX_Component.h>
38 #include <OMX_VideoExt.h>
39 
40 namespace android {
41 
42 // node ids are created by concatenating the pid with a 16-bit counter
43 static size_t kMaxNodeInstances = (1 << 16);
44 
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 // This provides the underlying Thread used by CallbackDispatcher.
48 // Note that deriving CallbackDispatcher from Thread does not work.
49 
50 struct OMX::CallbackDispatcherThread : public Thread {
CallbackDispatcherThreadandroid::OMX::CallbackDispatcherThread51     CallbackDispatcherThread(CallbackDispatcher *dispatcher)
52         : mDispatcher(dispatcher) {
53     }
54 
55 private:
56     CallbackDispatcher *mDispatcher;
57 
58     bool threadLoop();
59 
60     CallbackDispatcherThread(const CallbackDispatcherThread &);
61     CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
62 };
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 
66 struct OMX::CallbackDispatcher : public RefBase {
67     CallbackDispatcher(OMXNodeInstance *owner);
68 
69     // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
70     // that a new message is available on the queue. Otherwise, the message stays on the queue, but
71     // the listener is not notified of it. It will process this message when a subsequent message
72     // is posted with |realTime| set to true.
73     void post(const omx_message &msg, bool realTime = true);
74 
75     bool loop();
76 
77 protected:
78     virtual ~CallbackDispatcher();
79 
80 private:
81     Mutex mLock;
82 
83     OMXNodeInstance *mOwner;
84     bool mDone;
85     Condition mQueueChanged;
86     std::list<omx_message> mQueue;
87 
88     sp<CallbackDispatcherThread> mThread;
89 
90     void dispatch(std::list<omx_message> &messages);
91 
92     CallbackDispatcher(const CallbackDispatcher &);
93     CallbackDispatcher &operator=(const CallbackDispatcher &);
94 };
95 
CallbackDispatcher(OMXNodeInstance * owner)96 OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
97     : mOwner(owner),
98       mDone(false) {
99     mThread = new CallbackDispatcherThread(this);
100     mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
101 }
102 
~CallbackDispatcher()103 OMX::CallbackDispatcher::~CallbackDispatcher() {
104     {
105         Mutex::Autolock autoLock(mLock);
106 
107         mDone = true;
108         mQueueChanged.signal();
109     }
110 
111     // A join on self can happen if the last ref to CallbackDispatcher
112     // is released within the CallbackDispatcherThread loop
113     status_t status = mThread->join();
114     if (status != WOULD_BLOCK) {
115         // Other than join to self, the only other error return codes are
116         // whatever readyToRun() returns, and we don't override that
117         CHECK_EQ(status, (status_t)NO_ERROR);
118     }
119 }
120 
post(const omx_message & msg,bool realTime)121 void OMX::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
122     Mutex::Autolock autoLock(mLock);
123 
124     mQueue.push_back(msg);
125     if (realTime) {
126         mQueueChanged.signal();
127     }
128 }
129 
dispatch(std::list<omx_message> & messages)130 void OMX::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
131     if (mOwner == NULL) {
132         ALOGV("Would have dispatched a message to a node that's already gone.");
133         return;
134     }
135     mOwner->onMessages(messages);
136 }
137 
loop()138 bool OMX::CallbackDispatcher::loop() {
139     for (;;) {
140         std::list<omx_message> messages;
141 
142         {
143             Mutex::Autolock autoLock(mLock);
144             while (!mDone && mQueue.empty()) {
145                 mQueueChanged.wait(mLock);
146             }
147 
148             if (mDone) {
149                 break;
150             }
151 
152             messages.swap(mQueue);
153         }
154 
155         dispatch(messages);
156     }
157 
158     return false;
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 
threadLoop()163 bool OMX::CallbackDispatcherThread::threadLoop() {
164     return mDispatcher->loop();
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 
OMX()169 OMX::OMX()
170     : mMaster(new OMXMaster),
171       mNodeCounter(0) {
172 }
173 
~OMX()174 OMX::~OMX() {
175     delete mMaster;
176     mMaster = NULL;
177 }
178 
binderDied(const wp<IBinder> & the_late_who)179 void OMX::binderDied(const wp<IBinder> &the_late_who) {
180     OMXNodeInstance *instance;
181 
182     {
183         Mutex::Autolock autoLock(mLock);
184 
185         ssize_t index = mLiveNodes.indexOfKey(the_late_who);
186 
187         if (index < 0) {
188             ALOGE("b/27597103, nonexistent observer on binderDied");
189             android_errorWriteLog(0x534e4554, "27597103");
190             return;
191         }
192 
193         instance = mLiveNodes.editValueAt(index);
194         mLiveNodes.removeItemsAt(index);
195 
196         index = mDispatchers.indexOfKey(instance->nodeID());
197         CHECK(index >= 0);
198         mDispatchers.removeItemsAt(index);
199 
200         invalidateNodeID_l(instance->nodeID());
201     }
202 
203     instance->onObserverDied(mMaster);
204 }
205 
isSecure(node_id node)206 bool OMX::isSecure(node_id node) {
207     OMXNodeInstance *instance = findInstance(node);
208     return (instance == NULL ? false : instance->isSecure());
209 }
210 
livesLocally(node_id,pid_t pid)211 bool OMX::livesLocally(node_id /* node */, pid_t pid) {
212     return pid == getpid();
213 }
214 
listNodes(List<ComponentInfo> * list)215 status_t OMX::listNodes(List<ComponentInfo> *list) {
216     list->clear();
217 
218     OMX_U32 index = 0;
219     char componentName[256];
220     while (mMaster->enumerateComponents(
221                 componentName, sizeof(componentName), index) == OMX_ErrorNone) {
222         list->push_back(ComponentInfo());
223         ComponentInfo &info = *--list->end();
224 
225         info.mName = componentName;
226 
227         Vector<String8> roles;
228         OMX_ERRORTYPE err =
229             mMaster->getRolesOfComponent(componentName, &roles);
230 
231         if (err == OMX_ErrorNone) {
232             for (OMX_U32 i = 0; i < roles.size(); ++i) {
233                 info.mRoles.push_back(roles[i]);
234             }
235         }
236 
237         ++index;
238     }
239 
240     return OK;
241 }
242 
allocateNode(const char * name,const sp<IOMXObserver> & observer,sp<IBinder> * nodeBinder,node_id * node)243 status_t OMX::allocateNode(
244         const char *name, const sp<IOMXObserver> &observer,
245         sp<IBinder> *nodeBinder, node_id *node) {
246     Mutex::Autolock autoLock(mLock);
247 
248     *node = 0;
249     if (nodeBinder != NULL) {
250         *nodeBinder = NULL;
251     }
252 
253     if (mNodeIDToInstance.size() == kMaxNodeInstances) {
254         // all possible node IDs are in use
255         return NO_MEMORY;
256     }
257 
258     OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
259 
260     OMX_COMPONENTTYPE *handle;
261     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
262             name, &OMXNodeInstance::kCallbacks,
263             instance, &handle);
264 
265     if (err != OMX_ErrorNone) {
266         ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
267 
268         instance->onGetHandleFailed();
269 
270         return StatusFromOMXError(err);
271     }
272 
273     *node = makeNodeID_l(instance);
274     mDispatchers.add(*node, new CallbackDispatcher(instance));
275 
276     instance->setHandle(*node, handle);
277 
278     mLiveNodes.add(IInterface::asBinder(observer), instance);
279     IInterface::asBinder(observer)->linkToDeath(this);
280 
281     return OK;
282 }
283 
freeNode(node_id node)284 status_t OMX::freeNode(node_id node) {
285     OMXNodeInstance *instance = findInstance(node);
286 
287     if (instance == NULL) {
288         return OK;
289     }
290 
291     {
292         Mutex::Autolock autoLock(mLock);
293         ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
294         if (index < 0) {
295             // This could conceivably happen if the observer dies at roughly the
296             // same time that a client attempts to free the node explicitly.
297             return OK;
298         }
299         mLiveNodes.removeItemsAt(index);
300     }
301 
302     IInterface::asBinder(instance->observer())->unlinkToDeath(this);
303 
304     status_t err = instance->freeNode(mMaster);
305 
306     {
307         Mutex::Autolock autoLock(mLock);
308         ssize_t index = mDispatchers.indexOfKey(node);
309         CHECK(index >= 0);
310         mDispatchers.removeItemsAt(index);
311     }
312 
313     return err;
314 }
315 
sendCommand(node_id node,OMX_COMMANDTYPE cmd,OMX_S32 param)316 status_t OMX::sendCommand(
317         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
318     OMXNodeInstance *instance = findInstance(node);
319 
320     if (instance == NULL) {
321         return NAME_NOT_FOUND;
322     }
323 
324     return instance->sendCommand(cmd, param);
325 }
326 
getParameter(node_id node,OMX_INDEXTYPE index,void * params,size_t size)327 status_t OMX::getParameter(
328         node_id node, OMX_INDEXTYPE index,
329         void *params, size_t size) {
330     ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size);
331     OMXNodeInstance *instance = findInstance(node);
332 
333     if (instance == NULL) {
334         return NAME_NOT_FOUND;
335     }
336 
337     return instance->getParameter(
338             index, params, size);
339 }
340 
setParameter(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)341 status_t OMX::setParameter(
342         node_id node, OMX_INDEXTYPE index,
343         const void *params, size_t size) {
344     ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size);
345     OMXNodeInstance *instance = findInstance(node);
346 
347     if (instance == NULL) {
348         return NAME_NOT_FOUND;
349     }
350 
351     return instance->setParameter(
352             index, params, size);
353 }
354 
getConfig(node_id node,OMX_INDEXTYPE index,void * params,size_t size)355 status_t OMX::getConfig(
356         node_id node, OMX_INDEXTYPE index,
357         void *params, size_t size) {
358     OMXNodeInstance *instance = findInstance(node);
359 
360     if (instance == NULL) {
361         return NAME_NOT_FOUND;
362     }
363 
364     return instance->getConfig(
365             index, params, size);
366 }
367 
setConfig(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)368 status_t OMX::setConfig(
369         node_id node, OMX_INDEXTYPE index,
370         const void *params, size_t size) {
371     OMXNodeInstance *instance = findInstance(node);
372 
373     if (instance == NULL) {
374         return NAME_NOT_FOUND;
375     }
376 
377     return instance->setConfig(
378             index, params, size);
379 }
380 
getState(node_id node,OMX_STATETYPE * state)381 status_t OMX::getState(
382         node_id node, OMX_STATETYPE* state) {
383     OMXNodeInstance *instance = findInstance(node);
384 
385     if (instance == NULL) {
386         return NAME_NOT_FOUND;
387     }
388 
389     return instance->getState(
390             state);
391 }
392 
enableNativeBuffers(node_id node,OMX_U32 port_index,OMX_BOOL graphic,OMX_BOOL enable)393 status_t OMX::enableNativeBuffers(
394         node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
395     OMXNodeInstance *instance = findInstance(node);
396 
397     if (instance == NULL) {
398         return NAME_NOT_FOUND;
399     }
400 
401     return instance->enableNativeBuffers(port_index, graphic, enable);
402 }
403 
getGraphicBufferUsage(node_id node,OMX_U32 port_index,OMX_U32 * usage)404 status_t OMX::getGraphicBufferUsage(
405         node_id node, OMX_U32 port_index, OMX_U32* usage) {
406     OMXNodeInstance *instance = findInstance(node);
407 
408     if (instance == NULL) {
409         return NAME_NOT_FOUND;
410     }
411 
412     return instance->getGraphicBufferUsage(port_index, usage);
413 }
414 
storeMetaDataInBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable,MetadataBufferType * type)415 status_t OMX::storeMetaDataInBuffers(
416         node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
417     OMXNodeInstance *instance = findInstance(node);
418 
419     if (instance == NULL) {
420         return NAME_NOT_FOUND;
421     }
422 
423     return instance->storeMetaDataInBuffers(port_index, enable, type);
424 }
425 
prepareForAdaptivePlayback(node_id node,OMX_U32 portIndex,OMX_BOOL enable,OMX_U32 maxFrameWidth,OMX_U32 maxFrameHeight)426 status_t OMX::prepareForAdaptivePlayback(
427         node_id node, OMX_U32 portIndex, OMX_BOOL enable,
428         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
429     OMXNodeInstance *instance = findInstance(node);
430 
431     if (instance == NULL) {
432         return NAME_NOT_FOUND;
433     }
434 
435     return instance->prepareForAdaptivePlayback(
436             portIndex, enable, maxFrameWidth, maxFrameHeight);
437 }
438 
configureVideoTunnelMode(node_id node,OMX_U32 portIndex,OMX_BOOL tunneled,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)439 status_t OMX::configureVideoTunnelMode(
440         node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
441         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
442     OMXNodeInstance *instance = findInstance(node);
443 
444     if (instance == NULL) {
445         return NAME_NOT_FOUND;
446     }
447 
448     return instance->configureVideoTunnelMode(
449             portIndex, tunneled, audioHwSync, sidebandHandle);
450 }
451 
useBuffer(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)452 status_t OMX::useBuffer(
453         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
454         buffer_id *buffer, OMX_U32 allottedSize) {
455     OMXNodeInstance *instance = findInstance(node);
456 
457     if (instance == NULL) {
458         return NAME_NOT_FOUND;
459     }
460 
461     return instance->useBuffer(
462             port_index, params, buffer, allottedSize);
463 }
464 
useGraphicBuffer(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id * buffer)465 status_t OMX::useGraphicBuffer(
466         node_id node, OMX_U32 port_index,
467         const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
468     OMXNodeInstance *instance = findInstance(node);
469 
470     if (instance == NULL) {
471         return NAME_NOT_FOUND;
472     }
473 
474     return instance->useGraphicBuffer(
475             port_index, graphicBuffer, buffer);
476 }
477 
updateGraphicBufferInMeta(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id buffer)478 status_t OMX::updateGraphicBufferInMeta(
479         node_id node, OMX_U32 port_index,
480         const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
481     OMXNodeInstance *instance = findInstance(node);
482 
483     if (instance == NULL) {
484         return NAME_NOT_FOUND;
485     }
486 
487     return instance->updateGraphicBufferInMeta(
488             port_index, graphicBuffer, buffer);
489 }
490 
updateNativeHandleInMeta(node_id node,OMX_U32 port_index,const sp<NativeHandle> & nativeHandle,buffer_id buffer)491 status_t OMX::updateNativeHandleInMeta(
492         node_id node, OMX_U32 port_index,
493         const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
494     OMXNodeInstance *instance = findInstance(node);
495 
496     if (instance == NULL) {
497         return NAME_NOT_FOUND;
498     }
499 
500     return instance->updateNativeHandleInMeta(
501             port_index, nativeHandle, buffer);
502 }
503 
createInputSurface(node_id node,OMX_U32 port_index,android_dataspace dataSpace,sp<IGraphicBufferProducer> * bufferProducer,MetadataBufferType * type)504 status_t OMX::createInputSurface(
505         node_id node, OMX_U32 port_index, android_dataspace dataSpace,
506         sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
507     OMXNodeInstance *instance = findInstance(node);
508 
509     if (instance == NULL) {
510         return NAME_NOT_FOUND;
511     }
512 
513     return instance->createInputSurface(
514             port_index, dataSpace, bufferProducer, type);
515 }
516 
createPersistentInputSurface(sp<IGraphicBufferProducer> * bufferProducer,sp<IGraphicBufferConsumer> * bufferConsumer)517 status_t OMX::createPersistentInputSurface(
518         sp<IGraphicBufferProducer> *bufferProducer,
519         sp<IGraphicBufferConsumer> *bufferConsumer) {
520     return OMXNodeInstance::createPersistentInputSurface(
521             bufferProducer, bufferConsumer);
522 }
523 
setInputSurface(node_id node,OMX_U32 port_index,const sp<IGraphicBufferConsumer> & bufferConsumer,MetadataBufferType * type)524 status_t OMX::setInputSurface(
525         node_id node, OMX_U32 port_index,
526         const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
527     OMXNodeInstance *instance = findInstance(node);
528 
529     if (instance == NULL) {
530         return NAME_NOT_FOUND;
531     }
532 
533     return instance->setInputSurface(port_index, bufferConsumer, type);
534 }
535 
536 
signalEndOfInputStream(node_id node)537 status_t OMX::signalEndOfInputStream(node_id node) {
538     OMXNodeInstance *instance = findInstance(node);
539 
540     if (instance == NULL) {
541         return NAME_NOT_FOUND;
542     }
543 
544     return instance->signalEndOfInputStream();
545 }
546 
allocateSecureBuffer(node_id node,OMX_U32 port_index,size_t size,buffer_id * buffer,void ** buffer_data,sp<NativeHandle> * native_handle)547 status_t OMX::allocateSecureBuffer(
548         node_id node, OMX_U32 port_index, size_t size,
549         buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
550     OMXNodeInstance *instance = findInstance(node);
551 
552     if (instance == NULL) {
553         return NAME_NOT_FOUND;
554     }
555 
556     return instance->allocateSecureBuffer(
557             port_index, size, buffer, buffer_data, native_handle);
558 }
559 
allocateBufferWithBackup(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)560 status_t OMX::allocateBufferWithBackup(
561         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
562         buffer_id *buffer, OMX_U32 allottedSize) {
563     OMXNodeInstance *instance = findInstance(node);
564 
565     if (instance == NULL) {
566         return NAME_NOT_FOUND;
567     }
568 
569     return instance->allocateBufferWithBackup(
570             port_index, params, buffer, allottedSize);
571 }
572 
freeBuffer(node_id node,OMX_U32 port_index,buffer_id buffer)573 status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
574     OMXNodeInstance *instance = findInstance(node);
575 
576     if (instance == NULL) {
577         return NAME_NOT_FOUND;
578     }
579 
580     return instance->freeBuffer(
581             port_index, buffer);
582 }
583 
fillBuffer(node_id node,buffer_id buffer,int fenceFd)584 status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
585     OMXNodeInstance *instance = findInstance(node);
586 
587     if (instance == NULL) {
588         return NAME_NOT_FOUND;
589     }
590 
591     return instance->fillBuffer(buffer, fenceFd);
592 }
593 
emptyBuffer(node_id node,buffer_id buffer,OMX_U32 range_offset,OMX_U32 range_length,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)594 status_t OMX::emptyBuffer(
595         node_id node,
596         buffer_id buffer,
597         OMX_U32 range_offset, OMX_U32 range_length,
598         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
599     OMXNodeInstance *instance = findInstance(node);
600 
601     if (instance == NULL) {
602         return NAME_NOT_FOUND;
603     }
604 
605     return instance->emptyBuffer(
606             buffer, range_offset, range_length, flags, timestamp, fenceFd);
607 }
608 
getExtensionIndex(node_id node,const char * parameter_name,OMX_INDEXTYPE * index)609 status_t OMX::getExtensionIndex(
610         node_id node,
611         const char *parameter_name,
612         OMX_INDEXTYPE *index) {
613     OMXNodeInstance *instance = findInstance(node);
614 
615     if (instance == NULL) {
616         return NAME_NOT_FOUND;
617     }
618 
619     return instance->getExtensionIndex(
620             parameter_name, index);
621 }
622 
setInternalOption(node_id node,OMX_U32 port_index,InternalOptionType type,const void * data,size_t size)623 status_t OMX::setInternalOption(
624         node_id node,
625         OMX_U32 port_index,
626         InternalOptionType type,
627         const void *data,
628         size_t size) {
629     OMXNodeInstance *instance = findInstance(node);
630 
631     if (instance == NULL) {
632         return NAME_NOT_FOUND;
633     }
634 
635     return instance->setInternalOption(port_index, type, data, size);
636 }
637 
OnEvent(node_id node,OMX_IN OMX_EVENTTYPE eEvent,OMX_IN OMX_U32 nData1,OMX_IN OMX_U32 nData2,OMX_IN OMX_PTR pEventData)638 OMX_ERRORTYPE OMX::OnEvent(
639         node_id node,
640         OMX_IN OMX_EVENTTYPE eEvent,
641         OMX_IN OMX_U32 nData1,
642         OMX_IN OMX_U32 nData2,
643         OMX_IN OMX_PTR pEventData) {
644     ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
645     OMXNodeInstance *instance = findInstance(node);
646 
647     if (instance == NULL) {
648         return OMX_ErrorComponentNotFound;
649     }
650 
651     // Forward to OMXNodeInstance.
652     instance->onEvent(eEvent, nData1, nData2);
653 
654     sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
655 
656     // output rendered events are not processed as regular events until they hit the observer
657     if (eEvent == OMX_EventOutputRendered) {
658         if (pEventData == NULL) {
659             return OMX_ErrorBadParameter;
660         }
661 
662         // process data from array
663         OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
664         for (size_t i = 0; i < nData1; ++i) {
665             omx_message msg;
666             msg.type = omx_message::FRAME_RENDERED;
667             msg.node = node;
668             msg.fenceFd = -1;
669             msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
670             msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
671 
672             dispatcher->post(msg, false /* realTime */);
673         }
674         return OMX_ErrorNone;
675     }
676 
677     omx_message msg;
678     msg.type = omx_message::EVENT;
679     msg.node = node;
680     msg.fenceFd = -1;
681     msg.u.event_data.event = eEvent;
682     msg.u.event_data.data1 = nData1;
683     msg.u.event_data.data2 = nData2;
684 
685     dispatcher->post(msg, true /* realTime */);
686 
687     return OMX_ErrorNone;
688 }
689 
OnEmptyBufferDone(node_id node,buffer_id buffer,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer,int fenceFd)690 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
691         node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
692     ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
693 
694     omx_message msg;
695     msg.type = omx_message::EMPTY_BUFFER_DONE;
696     msg.node = node;
697     msg.fenceFd = fenceFd;
698     msg.u.buffer_data.buffer = buffer;
699 
700     findDispatcher(node)->post(msg);
701 
702     return OMX_ErrorNone;
703 }
704 
OnFillBufferDone(node_id node,buffer_id buffer,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer,int fenceFd)705 OMX_ERRORTYPE OMX::OnFillBufferDone(
706         node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
707     ALOGV("OnFillBufferDone buffer=%p", pBuffer);
708 
709     omx_message msg;
710     msg.type = omx_message::FILL_BUFFER_DONE;
711     msg.node = node;
712     msg.fenceFd = fenceFd;
713     msg.u.extended_buffer_data.buffer = buffer;
714     msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
715     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
716     msg.u.extended_buffer_data.flags = pBuffer->nFlags;
717     msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
718 
719     findDispatcher(node)->post(msg);
720 
721     return OMX_ErrorNone;
722 }
723 
makeNodeID_l(OMXNodeInstance * instance)724 OMX::node_id OMX::makeNodeID_l(OMXNodeInstance *instance) {
725     // mLock is already held.
726 
727     node_id prefix = node_id(getpid() << 16);
728     node_id node = 0;
729     do  {
730         if (++mNodeCounter >= kMaxNodeInstances) {
731             mNodeCounter = 0; // OK to use because we're combining with the pid
732         }
733         node = node_id(prefix | mNodeCounter);
734     } while (mNodeIDToInstance.indexOfKey(node) >= 0);
735     mNodeIDToInstance.add(node, instance);
736 
737     return node;
738 }
739 
findInstance(node_id node)740 OMXNodeInstance *OMX::findInstance(node_id node) {
741     Mutex::Autolock autoLock(mLock);
742 
743     ssize_t index = mNodeIDToInstance.indexOfKey(node);
744 
745     return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
746 }
747 
findDispatcher(node_id node)748 sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
749     Mutex::Autolock autoLock(mLock);
750 
751     ssize_t index = mDispatchers.indexOfKey(node);
752 
753     return index < 0 ? NULL : mDispatchers.valueAt(index);
754 }
755 
invalidateNodeID(node_id node)756 void OMX::invalidateNodeID(node_id node) {
757     Mutex::Autolock autoLock(mLock);
758     invalidateNodeID_l(node);
759 }
760 
invalidateNodeID_l(node_id node)761 void OMX::invalidateNodeID_l(node_id node) {
762     // mLock is held.
763     mNodeIDToInstance.removeItem(node);
764 }
765 
766 }  // namespace android
767