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> ¶ms,
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> ¶ms,
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