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
40namespace android {
41
42// node ids are created by concatenating the pid with a 16-bit counter
43static 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
50struct OMX::CallbackDispatcherThread : public Thread {
51    CallbackDispatcherThread(CallbackDispatcher *dispatcher)
52        : mDispatcher(dispatcher) {
53    }
54
55private:
56    CallbackDispatcher *mDispatcher;
57
58    bool threadLoop();
59
60    CallbackDispatcherThread(const CallbackDispatcherThread &);
61    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
62};
63
64////////////////////////////////////////////////////////////////////////////////
65
66struct 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
77protected:
78    virtual ~CallbackDispatcher();
79
80private:
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
96OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
97    : mOwner(owner),
98      mDone(false) {
99    mThread = new CallbackDispatcherThread(this);
100    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
101}
102
103OMX::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
121void 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
130void 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
138bool 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
163bool OMX::CallbackDispatcherThread::threadLoop() {
164    return mDispatcher->loop();
165}
166
167////////////////////////////////////////////////////////////////////////////////
168
169OMX::OMX()
170    : mMaster(new OMXMaster),
171      mNodeCounter(0) {
172}
173
174OMX::~OMX() {
175    delete mMaster;
176    mMaster = NULL;
177}
178
179void 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
206bool OMX::isSecure(node_id node) {
207    OMXNodeInstance *instance = findInstance(node);
208    return (instance == NULL ? false : instance->isSecure());
209}
210
211bool OMX::livesLocally(node_id /* node */, pid_t pid) {
212    return pid == getpid();
213}
214
215status_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
243status_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
284status_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
316status_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
327status_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
341status_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
355status_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
368status_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
381status_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
393status_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
404status_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
415status_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
426status_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
439status_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
452status_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
465status_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
478status_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
491status_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
504status_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
517status_t OMX::createPersistentInputSurface(
518        sp<IGraphicBufferProducer> *bufferProducer,
519        sp<IGraphicBufferConsumer> *bufferConsumer) {
520    return OMXNodeInstance::createPersistentInputSurface(
521            bufferProducer, bufferConsumer);
522}
523
524status_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
537status_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
547status_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
560status_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
573status_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
584status_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
594status_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
609status_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
623status_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
638OMX_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
690OMX_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
705OMX_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
724OMX::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
740OMXNodeInstance *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
748sp<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
756void OMX::invalidateNodeID(node_id node) {
757    Mutex::Autolock autoLock(mLock);
758    invalidateNodeID_l(node);
759}
760
761void OMX::invalidateNodeID_l(node_id node) {
762    // mLock is held.
763    mNodeIDToInstance.removeItem(node);
764}
765
766}  // namespace android
767