OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / omx / OMX.cpp
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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "OMX"
19 #include <utils/Log.h>
20
21 #include <dlfcn.h>
22
23 #include <sys/prctl.h>
24 #include <sys/resource.h>
25
26 #include "../include/OMX.h"
27 #include "OMXRenderer.h"
28
29 #include "../include/OMXNodeInstance.h"
30 #include "../include/SoftwareRenderer.h"
31
32 #include <binder/IMemory.h>
33 #include <media/stagefright/MediaDebug.h>
34 #include <media/stagefright/VideoRenderer.h>
35 #include <utils/threads.h>
36
37 #include "OMXMaster.h"
38
39 #include <OMX_Component.h>
40
41 namespace android {
42
43 ////////////////////////////////////////////////////////////////////////////////
44
45 struct OMX::CallbackDispatcher : public RefBase {
46     CallbackDispatcher(OMXNodeInstance *owner);
47
48     void post(const omx_message &msg);
49
50 protected:
51     virtual ~CallbackDispatcher();
52
53 private:
54     Mutex mLock;
55
56     OMXNodeInstance *mOwner;
57     bool mDone;
58     Condition mQueueChanged;
59     List<omx_message> mQueue;
60
61     pthread_t mThread;
62
63     void dispatch(const omx_message &msg);
64
65     static void *ThreadWrapper(void *me);
66     void threadEntry();
67
68     CallbackDispatcher(const CallbackDispatcher &);
69     CallbackDispatcher &operator=(const CallbackDispatcher &);
70 };
71
72 OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
73     : mOwner(owner),
74       mDone(false) {
75     pthread_attr_t attr;
76     pthread_attr_init(&attr);
77     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
78
79     pthread_create(&mThread, &attr, ThreadWrapper, this);
80
81     pthread_attr_destroy(&attr);
82 }
83
84 OMX::CallbackDispatcher::~CallbackDispatcher() {
85     {
86         Mutex::Autolock autoLock(mLock);
87
88         mDone = true;
89         mQueueChanged.signal();
90     }
91
92     // Don't call join on myself
93     CHECK(mThread != pthread_self());
94
95     void *dummy;
96     pthread_join(mThread, &dummy);
97 }
98
99 void OMX::CallbackDispatcher::post(const omx_message &msg) {
100     Mutex::Autolock autoLock(mLock);
101
102     mQueue.push_back(msg);
103     mQueueChanged.signal();
104 }
105
106 void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
107     if (mOwner == NULL) {
108         LOGV("Would have dispatched a message to a node that's already gone.");
109         return;
110     }
111     mOwner->onMessage(msg);
112 }
113
114 // static
115 void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
116     static_cast<CallbackDispatcher *>(me)->threadEntry();
117
118     return NULL;
119 }
120
121 void OMX::CallbackDispatcher::threadEntry() {
122     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
123     prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
124
125     for (;;) {
126         omx_message msg;
127
128         {
129             Mutex::Autolock autoLock(mLock);
130             while (!mDone && mQueue.empty()) {
131                 mQueueChanged.wait(mLock);
132             }
133
134             if (mDone) {
135                 break;
136             }
137
138             msg = *mQueue.begin();
139             mQueue.erase(mQueue.begin());
140         }
141
142         dispatch(msg);
143     }
144 }
145
146 ////////////////////////////////////////////////////////////////////////////////
147
148 OMX::OMX()
149     : mMaster(new OMXMaster),
150       mNodeCounter(0) {
151 }
152
153 OMX::~OMX() {
154     delete mMaster;
155     mMaster = NULL;
156 }
157
158 void OMX::binderDied(const wp<IBinder> &the_late_who) {
159     OMXNodeInstance *instance;
160
161     {
162         Mutex::Autolock autoLock(mLock);
163
164         ssize_t index = mLiveNodes.indexOfKey(the_late_who);
165         CHECK(index >= 0);
166
167         instance = mLiveNodes.editValueAt(index);
168         mLiveNodes.removeItemsAt(index);
169
170         index = mDispatchers.indexOfKey(instance->nodeID());
171         CHECK(index >= 0);
172         mDispatchers.removeItemsAt(index);
173
174         invalidateNodeID_l(instance->nodeID());
175     }
176
177     instance->onObserverDied(mMaster);
178 }
179
180 bool OMX::livesLocally(pid_t pid) {
181     return pid == getpid();
182 }
183
184 status_t OMX::listNodes(List<ComponentInfo> *list) {
185     list->clear();
186
187     OMX_U32 index = 0;
188     char componentName[256];
189     while (mMaster->enumerateComponents(
190                 componentName, sizeof(componentName), index) == OMX_ErrorNone) {
191         list->push_back(ComponentInfo());
192         ComponentInfo &info = *--list->end();
193
194         info.mName = componentName;
195
196         Vector<String8> roles;
197         OMX_ERRORTYPE err =
198             mMaster->getRolesOfComponent(componentName, &roles);
199
200         if (err == OMX_ErrorNone) {
201             for (OMX_U32 i = 0; i < roles.size(); ++i) {
202                 info.mRoles.push_back(roles[i]);
203             }
204         }
205
206         ++index;
207     }
208
209     return OK;
210 }
211
212 status_t OMX::allocateNode(
213         const char *name, const sp<IOMXObserver> &observer, node_id *node) {
214     Mutex::Autolock autoLock(mLock);
215
216     *node = 0;
217
218     OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
219
220     OMX_COMPONENTTYPE *handle;
221     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
222             name, &OMXNodeInstance::kCallbacks,
223             instance, &handle);
224
225     if (err != OMX_ErrorNone) {
226         LOGV("FAILED to allocate omx component '%s'", name);
227
228         instance->onGetHandleFailed();
229
230         return UNKNOWN_ERROR;
231     }
232
233     *node = makeNodeID(instance);
234     mDispatchers.add(*node, new CallbackDispatcher(instance));
235
236     instance->setHandle(*node, handle);
237
238     mLiveNodes.add(observer->asBinder(), instance);
239     observer->asBinder()->linkToDeath(this);
240
241     return OK;
242 }
243
244 status_t OMX::freeNode(node_id node) {
245     OMXNodeInstance *instance = findInstance(node);
246
247     ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
248     CHECK(index >= 0);
249     mLiveNodes.removeItemsAt(index);
250
251     instance->observer()->asBinder()->unlinkToDeath(this);
252
253     status_t err = instance->freeNode(mMaster);
254
255     {
256         Mutex::Autolock autoLock(mLock);
257         index = mDispatchers.indexOfKey(node);
258         CHECK(index >= 0);
259         mDispatchers.removeItemsAt(index);
260     }
261
262     return err;
263 }
264
265 status_t OMX::sendCommand(
266         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
267     return findInstance(node)->sendCommand(cmd, param);
268 }
269
270 status_t OMX::getParameter(
271         node_id node, OMX_INDEXTYPE index,
272         void *params, size_t size) {
273     return findInstance(node)->getParameter(
274             index, params, size);
275 }
276
277 status_t OMX::setParameter(
278         node_id node, OMX_INDEXTYPE index,
279         const void *params, size_t size) {
280     return findInstance(node)->setParameter(
281             index, params, size);
282 }
283
284 status_t OMX::getConfig(
285         node_id node, OMX_INDEXTYPE index,
286         void *params, size_t size) {
287     return findInstance(node)->getConfig(
288             index, params, size);
289 }
290
291 status_t OMX::setConfig(
292         node_id node, OMX_INDEXTYPE index,
293         const void *params, size_t size) {
294     return findInstance(node)->setConfig(
295             index, params, size);
296 }
297
298 status_t OMX::useBuffer(
299         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
300         buffer_id *buffer) {
301     return findInstance(node)->useBuffer(
302             port_index, params, buffer);
303 }
304
305 status_t OMX::allocateBuffer(
306         node_id node, OMX_U32 port_index, size_t size,
307         buffer_id *buffer, void **buffer_data) {
308     return findInstance(node)->allocateBuffer(
309             port_index, size, buffer, buffer_data);
310 }
311
312 status_t OMX::allocateBufferWithBackup(
313         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
314         buffer_id *buffer) {
315     return findInstance(node)->allocateBufferWithBackup(
316             port_index, params, buffer);
317 }
318
319 status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
320     return findInstance(node)->freeBuffer(
321             port_index, buffer);
322 }
323
324 status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
325     return findInstance(node)->fillBuffer(buffer);
326 }
327
328 status_t OMX::emptyBuffer(
329         node_id node,
330         buffer_id buffer,
331         OMX_U32 range_offset, OMX_U32 range_length,
332         OMX_U32 flags, OMX_TICKS timestamp) {
333     return findInstance(node)->emptyBuffer(
334             buffer, range_offset, range_length, flags, timestamp);
335 }
336
337 status_t OMX::getExtensionIndex(
338         node_id node,
339         const char *parameter_name,
340         OMX_INDEXTYPE *index) {
341     return findInstance(node)->getExtensionIndex(
342             parameter_name, index);
343 }
344
345 OMX_ERRORTYPE OMX::OnEvent(
346         node_id node,
347         OMX_IN OMX_EVENTTYPE eEvent,
348         OMX_IN OMX_U32 nData1,
349         OMX_IN OMX_U32 nData2,
350         OMX_IN OMX_PTR pEventData) {
351     LOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2);
352
353     omx_message msg;
354     msg.type = omx_message::EVENT;
355     msg.node = node;
356     msg.u.event_data.event = eEvent;
357     msg.u.event_data.data1 = nData1;
358     msg.u.event_data.data2 = nData2;
359
360     findDispatcher(node)->post(msg);
361
362     return OMX_ErrorNone;
363 }
364
365 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
366         node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
367     LOGV("OnEmptyBufferDone buffer=%p", pBuffer);
368
369     omx_message msg;
370     msg.type = omx_message::EMPTY_BUFFER_DONE;
371     msg.node = node;
372     msg.u.buffer_data.buffer = pBuffer;
373
374     findDispatcher(node)->post(msg);
375
376     return OMX_ErrorNone;
377 }
378
379 OMX_ERRORTYPE OMX::OnFillBufferDone(
380         node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
381     LOGV("OnFillBufferDone buffer=%p", pBuffer);
382
383     omx_message msg;
384     msg.type = omx_message::FILL_BUFFER_DONE;
385     msg.node = node;
386     msg.u.extended_buffer_data.buffer = pBuffer;
387     msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
388     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
389     msg.u.extended_buffer_data.flags = pBuffer->nFlags;
390     msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
391     msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
392     msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
393
394     findDispatcher(node)->post(msg);
395
396     return OMX_ErrorNone;
397 }
398
399 OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
400     // mLock is already held.
401
402     node_id node = (node_id)++mNodeCounter;
403     mNodeIDToInstance.add(node, instance);
404
405     return node;
406 }
407
408 OMXNodeInstance *OMX::findInstance(node_id node) {
409     Mutex::Autolock autoLock(mLock);
410
411     ssize_t index = mNodeIDToInstance.indexOfKey(node);
412
413     return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
414 }
415
416 sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
417     Mutex::Autolock autoLock(mLock);
418
419     ssize_t index = mDispatchers.indexOfKey(node);
420
421     return index < 0 ? NULL : mDispatchers.valueAt(index);
422 }
423
424 void OMX::invalidateNodeID(node_id node) {
425     Mutex::Autolock autoLock(mLock);
426     invalidateNodeID_l(node);
427 }
428
429 void OMX::invalidateNodeID_l(node_id node) {
430     // mLock is held.
431     mNodeIDToInstance.removeItem(node);
432 }
433
434 ////////////////////////////////////////////////////////////////////////////////
435
436 struct SharedVideoRenderer : public VideoRenderer {
437     SharedVideoRenderer(void *libHandle, VideoRenderer *obj)
438         : mLibHandle(libHandle),
439           mObj(obj) {
440     }
441
442     virtual ~SharedVideoRenderer() {
443         delete mObj;
444         mObj = NULL;
445
446         dlclose(mLibHandle);
447         mLibHandle = NULL;
448     }
449
450     virtual void render(
451             const void *data, size_t size, void *platformPrivate) {
452         return mObj->render(data, size, platformPrivate);
453     }
454
455 private:
456     void *mLibHandle;
457     VideoRenderer *mObj;
458
459     SharedVideoRenderer(const SharedVideoRenderer &);
460     SharedVideoRenderer &operator=(const SharedVideoRenderer &);
461 };
462
463 sp<IOMXRenderer> OMX::createRenderer(
464         const sp<ISurface> &surface,
465         const char *componentName,
466         OMX_COLOR_FORMATTYPE colorFormat,
467         size_t encodedWidth, size_t encodedHeight,
468         size_t displayWidth, size_t displayHeight,
469         int32_t rotationDegrees) {
470     Mutex::Autolock autoLock(mLock);
471
472     VideoRenderer *impl = NULL;
473
474     void *libHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
475
476     if (libHandle) {
477         typedef VideoRenderer *(*CreateRendererWithRotationFunc)(
478                 const sp<ISurface> &surface,
479                 const char *componentName,
480                 OMX_COLOR_FORMATTYPE colorFormat,
481                 size_t displayWidth, size_t displayHeight,
482                 size_t decodedWidth, size_t decodedHeight,
483                 int32_t rotationDegrees);
484
485         typedef VideoRenderer *(*CreateRendererFunc)(
486                 const sp<ISurface> &surface,
487                 const char *componentName,
488                 OMX_COLOR_FORMATTYPE colorFormat,
489                 size_t displayWidth, size_t displayHeight,
490                 size_t decodedWidth, size_t decodedHeight);
491
492         CreateRendererWithRotationFunc funcWithRotation =
493             (CreateRendererWithRotationFunc)dlsym(
494                     libHandle,
495                     "_Z26createRendererWithRotationRKN7android2spINS_8"
496                     "ISurfaceEEEPKc20OMX_COLOR_FORMATTYPEjjjji");
497
498         if (funcWithRotation) {
499             impl = (*funcWithRotation)(
500                     surface, componentName, colorFormat,
501                     displayWidth, displayHeight, encodedWidth, encodedHeight,
502                     rotationDegrees);
503         } else {
504             CreateRendererFunc func =
505                 (CreateRendererFunc)dlsym(
506                         libHandle,
507                         "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
508                         "OMX_COLOR_FORMATTYPEjjjj");
509
510             if (func) {
511                 impl = (*func)(surface, componentName, colorFormat,
512                         displayWidth, displayHeight, encodedWidth, encodedHeight);
513             }
514         }
515
516         if (impl) {
517             impl = new SharedVideoRenderer(libHandle, impl);
518             libHandle = NULL;
519         }
520
521         if (libHandle) {
522             dlclose(libHandle);
523             libHandle = NULL;
524         }
525     }
526
527     if (!impl) {
528         LOGW("Using software renderer.");
529         impl = new SoftwareRenderer(
530                 colorFormat,
531                 surface,
532                 displayWidth, displayHeight,
533                 encodedWidth, encodedHeight);
534
535         if (((SoftwareRenderer *)impl)->initCheck() != OK) {
536             delete impl;
537             impl = NULL;
538
539             return NULL;
540         }
541     }
542
543     return new OMXRenderer(impl);
544 }
545
546 OMXRenderer::OMXRenderer(VideoRenderer *impl)
547     : mImpl(impl) {
548 }
549
550 OMXRenderer::~OMXRenderer() {
551     delete mImpl;
552     mImpl = NULL;
553 }
554
555 void OMXRenderer::render(IOMX::buffer_id buffer) {
556     OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
557
558     mImpl->render(
559             header->pBuffer + header->nOffset,
560             header->nFilledLen,
561             header->pPlatformPrivate);
562 }
563
564 }  // namespace android
565