2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
23 #include <sys/prctl.h>
24 #include <sys/resource.h>
26 #include "../include/OMX.h"
27 #include "OMXRenderer.h"
29 #include "../include/OMXNodeInstance.h"
30 #include "../include/SoftwareRenderer.h"
32 #include <binder/IMemory.h>
33 #include <media/stagefright/MediaDebug.h>
34 #include <media/stagefright/VideoRenderer.h>
35 #include <utils/threads.h>
37 #include "OMXMaster.h"
39 #include <OMX_Component.h>
43 ////////////////////////////////////////////////////////////////////////////////
45 struct OMX::CallbackDispatcher : public RefBase {
46 CallbackDispatcher(OMXNodeInstance *owner);
48 void post(const omx_message &msg);
51 virtual ~CallbackDispatcher();
56 OMXNodeInstance *mOwner;
58 Condition mQueueChanged;
59 List<omx_message> mQueue;
63 void dispatch(const omx_message &msg);
65 static void *ThreadWrapper(void *me);
68 CallbackDispatcher(const CallbackDispatcher &);
69 CallbackDispatcher &operator=(const CallbackDispatcher &);
72 OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
76 pthread_attr_init(&attr);
77 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
79 pthread_create(&mThread, &attr, ThreadWrapper, this);
81 pthread_attr_destroy(&attr);
84 OMX::CallbackDispatcher::~CallbackDispatcher() {
86 Mutex::Autolock autoLock(mLock);
89 mQueueChanged.signal();
92 // Don't call join on myself
93 CHECK(mThread != pthread_self());
96 pthread_join(mThread, &dummy);
99 void OMX::CallbackDispatcher::post(const omx_message &msg) {
100 Mutex::Autolock autoLock(mLock);
102 mQueue.push_back(msg);
103 mQueueChanged.signal();
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.");
111 mOwner->onMessage(msg);
115 void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
116 static_cast<CallbackDispatcher *>(me)->threadEntry();
121 void OMX::CallbackDispatcher::threadEntry() {
122 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
123 prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
129 Mutex::Autolock autoLock(mLock);
130 while (!mDone && mQueue.empty()) {
131 mQueueChanged.wait(mLock);
138 msg = *mQueue.begin();
139 mQueue.erase(mQueue.begin());
146 ////////////////////////////////////////////////////////////////////////////////
149 : mMaster(new OMXMaster),
158 void OMX::binderDied(const wp<IBinder> &the_late_who) {
159 OMXNodeInstance *instance;
162 Mutex::Autolock autoLock(mLock);
164 ssize_t index = mLiveNodes.indexOfKey(the_late_who);
167 instance = mLiveNodes.editValueAt(index);
168 mLiveNodes.removeItemsAt(index);
170 index = mDispatchers.indexOfKey(instance->nodeID());
172 mDispatchers.removeItemsAt(index);
174 invalidateNodeID_l(instance->nodeID());
177 instance->onObserverDied(mMaster);
180 bool OMX::livesLocally(pid_t pid) {
181 return pid == getpid();
184 status_t OMX::listNodes(List<ComponentInfo> *list) {
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();
194 info.mName = componentName;
196 Vector<String8> roles;
198 mMaster->getRolesOfComponent(componentName, &roles);
200 if (err == OMX_ErrorNone) {
201 for (OMX_U32 i = 0; i < roles.size(); ++i) {
202 info.mRoles.push_back(roles[i]);
212 status_t OMX::allocateNode(
213 const char *name, const sp<IOMXObserver> &observer, node_id *node) {
214 Mutex::Autolock autoLock(mLock);
218 OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
220 OMX_COMPONENTTYPE *handle;
221 OMX_ERRORTYPE err = mMaster->makeComponentInstance(
222 name, &OMXNodeInstance::kCallbacks,
225 if (err != OMX_ErrorNone) {
226 LOGV("FAILED to allocate omx component '%s'", name);
228 instance->onGetHandleFailed();
230 return UNKNOWN_ERROR;
233 *node = makeNodeID(instance);
234 mDispatchers.add(*node, new CallbackDispatcher(instance));
236 instance->setHandle(*node, handle);
238 mLiveNodes.add(observer->asBinder(), instance);
239 observer->asBinder()->linkToDeath(this);
244 status_t OMX::freeNode(node_id node) {
245 OMXNodeInstance *instance = findInstance(node);
247 ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
249 mLiveNodes.removeItemsAt(index);
251 instance->observer()->asBinder()->unlinkToDeath(this);
253 status_t err = instance->freeNode(mMaster);
256 Mutex::Autolock autoLock(mLock);
257 index = mDispatchers.indexOfKey(node);
259 mDispatchers.removeItemsAt(index);
265 status_t OMX::sendCommand(
266 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
267 return findInstance(node)->sendCommand(cmd, param);
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);
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);
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);
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);
298 status_t OMX::useBuffer(
299 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
301 return findInstance(node)->useBuffer(
302 port_index, params, buffer);
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);
312 status_t OMX::allocateBufferWithBackup(
313 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
315 return findInstance(node)->allocateBufferWithBackup(
316 port_index, params, buffer);
319 status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
320 return findInstance(node)->freeBuffer(
324 status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
325 return findInstance(node)->fillBuffer(buffer);
328 status_t OMX::emptyBuffer(
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);
337 status_t OMX::getExtensionIndex(
339 const char *parameter_name,
340 OMX_INDEXTYPE *index) {
341 return findInstance(node)->getExtensionIndex(
342 parameter_name, index);
345 OMX_ERRORTYPE OMX::OnEvent(
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);
354 msg.type = omx_message::EVENT;
356 msg.u.event_data.event = eEvent;
357 msg.u.event_data.data1 = nData1;
358 msg.u.event_data.data2 = nData2;
360 findDispatcher(node)->post(msg);
362 return OMX_ErrorNone;
365 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
366 node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
367 LOGV("OnEmptyBufferDone buffer=%p", pBuffer);
370 msg.type = omx_message::EMPTY_BUFFER_DONE;
372 msg.u.buffer_data.buffer = pBuffer;
374 findDispatcher(node)->post(msg);
376 return OMX_ErrorNone;
379 OMX_ERRORTYPE OMX::OnFillBufferDone(
380 node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
381 LOGV("OnFillBufferDone buffer=%p", pBuffer);
384 msg.type = omx_message::FILL_BUFFER_DONE;
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;
394 findDispatcher(node)->post(msg);
396 return OMX_ErrorNone;
399 OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
400 // mLock is already held.
402 node_id node = (node_id)++mNodeCounter;
403 mNodeIDToInstance.add(node, instance);
408 OMXNodeInstance *OMX::findInstance(node_id node) {
409 Mutex::Autolock autoLock(mLock);
411 ssize_t index = mNodeIDToInstance.indexOfKey(node);
413 return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
416 sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
417 Mutex::Autolock autoLock(mLock);
419 ssize_t index = mDispatchers.indexOfKey(node);
421 return index < 0 ? NULL : mDispatchers.valueAt(index);
424 void OMX::invalidateNodeID(node_id node) {
425 Mutex::Autolock autoLock(mLock);
426 invalidateNodeID_l(node);
429 void OMX::invalidateNodeID_l(node_id node) {
431 mNodeIDToInstance.removeItem(node);
434 ////////////////////////////////////////////////////////////////////////////////
436 struct SharedVideoRenderer : public VideoRenderer {
437 SharedVideoRenderer(void *libHandle, VideoRenderer *obj)
438 : mLibHandle(libHandle),
442 virtual ~SharedVideoRenderer() {
451 const void *data, size_t size, void *platformPrivate) {
452 return mObj->render(data, size, platformPrivate);
459 SharedVideoRenderer(const SharedVideoRenderer &);
460 SharedVideoRenderer &operator=(const SharedVideoRenderer &);
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);
472 VideoRenderer *impl = NULL;
474 void *libHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
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);
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);
492 CreateRendererWithRotationFunc funcWithRotation =
493 (CreateRendererWithRotationFunc)dlsym(
495 "_Z26createRendererWithRotationRKN7android2spINS_8"
496 "ISurfaceEEEPKc20OMX_COLOR_FORMATTYPEjjjji");
498 if (funcWithRotation) {
499 impl = (*funcWithRotation)(
500 surface, componentName, colorFormat,
501 displayWidth, displayHeight, encodedWidth, encodedHeight,
504 CreateRendererFunc func =
505 (CreateRendererFunc)dlsym(
507 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
508 "OMX_COLOR_FORMATTYPEjjjj");
511 impl = (*func)(surface, componentName, colorFormat,
512 displayWidth, displayHeight, encodedWidth, encodedHeight);
517 impl = new SharedVideoRenderer(libHandle, impl);
528 LOGW("Using software renderer.");
529 impl = new SoftwareRenderer(
532 displayWidth, displayHeight,
533 encodedWidth, encodedHeight);
535 if (((SoftwareRenderer *)impl)->initCheck() != OK) {
543 return new OMXRenderer(impl);
546 OMXRenderer::OMXRenderer(VideoRenderer *impl)
550 OMXRenderer::~OMXRenderer() {
555 void OMXRenderer::render(IOMX::buffer_id buffer) {
556 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
559 header->pBuffer + header->nOffset,
561 header->pPlatformPrivate);
564 } // namespace android