OMX.cpp revision 20111aa043c5f404472bc63b90bc5aad906b1101
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 <sys/socket.h> 22 23#undef NDEBUG 24#include <assert.h> 25 26#include "OMX.h" 27#include "pv_omxcore.h" 28 29#include <binder/IMemory.h> 30 31#include <OMX_Component.h> 32 33namespace android { 34 35class NodeMeta { 36public: 37 NodeMeta(OMX *owner) 38 : mOwner(owner), 39 mHandle(NULL) { 40 } 41 42 OMX *owner() const { 43 return mOwner; 44 } 45 46 void setHandle(OMX_HANDLETYPE handle) { 47 assert(mHandle == NULL); 48 mHandle = handle; 49 } 50 51 OMX_HANDLETYPE handle() const { 52 return mHandle; 53 } 54 55 void setObserver(const sp<IOMXObserver> &observer) { 56 mObserver = observer; 57 } 58 59 sp<IOMXObserver> observer() { 60 return mObserver; 61 } 62 63private: 64 OMX *mOwner; 65 OMX_HANDLETYPE mHandle; 66 sp<IOMXObserver> mObserver; 67 68 NodeMeta(const NodeMeta &); 69 NodeMeta &operator=(const NodeMeta &); 70}; 71 72class BufferMeta { 73public: 74 BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false) 75 : mOwner(owner), 76 mMem(mem), 77 mIsBackup(is_backup) { 78 } 79 80 BufferMeta(OMX *owner, size_t size) 81 : mOwner(owner), 82 mSize(size), 83 mIsBackup(false) { 84 } 85 86 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 87 if (!mIsBackup) { 88 return; 89 } 90 91 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 92 header->pBuffer + header->nOffset, 93 header->nFilledLen); 94 } 95 96 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 97 if (!mIsBackup) { 98 return; 99 } 100 101 memcpy(header->pBuffer + header->nOffset, 102 (const OMX_U8 *)mMem->pointer() + header->nOffset, 103 header->nFilledLen); 104 } 105 106private: 107 OMX *mOwner; 108 sp<IMemory> mMem; 109 size_t mSize; 110 bool mIsBackup; 111 112 BufferMeta(const BufferMeta &); 113 BufferMeta &operator=(const BufferMeta &); 114}; 115 116// static 117OMX_CALLBACKTYPE OMX::kCallbacks = { 118 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 119}; 120 121// static 122OMX_ERRORTYPE OMX::OnEvent( 123 OMX_IN OMX_HANDLETYPE hComponent, 124 OMX_IN OMX_PTR pAppData, 125 OMX_IN OMX_EVENTTYPE eEvent, 126 OMX_IN OMX_U32 nData1, 127 OMX_IN OMX_U32 nData2, 128 OMX_IN OMX_PTR pEventData) { 129 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 130 return meta->owner()->OnEvent(meta, eEvent, nData1, nData2, pEventData); 131} 132 133// static 134OMX_ERRORTYPE OMX::OnEmptyBufferDone( 135 OMX_IN OMX_HANDLETYPE hComponent, 136 OMX_IN OMX_PTR pAppData, 137 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 138 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 139 return meta->owner()->OnEmptyBufferDone(meta, pBuffer); 140} 141 142// static 143OMX_ERRORTYPE OMX::OnFillBufferDone( 144 OMX_IN OMX_HANDLETYPE hComponent, 145 OMX_IN OMX_PTR pAppData, 146 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 147 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 148 return meta->owner()->OnFillBufferDone(meta, pBuffer); 149} 150 151OMX::OMX() 152#if IOMX_USES_SOCKETS 153 : mSock(-1) 154#endif 155{ 156} 157 158OMX::~OMX() { 159#if IOMX_USES_SOCKETS 160 assert(mSock < 0); 161#endif 162} 163 164#if IOMX_USES_SOCKETS 165status_t OMX::connect(int *sd) { 166 Mutex::Autolock autoLock(mLock); 167 168 if (mSock >= 0) { 169 return UNKNOWN_ERROR; 170 } 171 172 int sockets[2]; 173 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) { 174 return UNKNOWN_ERROR; 175 } 176 177 mSock = sockets[0]; 178 *sd = sockets[1]; 179 180 pthread_attr_t attr; 181 pthread_attr_init(&attr); 182 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 183 184 int err = pthread_create(&mThread, &attr, ThreadWrapper, this); 185 assert(err == 0); 186 187 pthread_attr_destroy(&attr); 188 189 return OK; 190} 191 192// static 193void *OMX::ThreadWrapper(void *me) { 194 ((OMX *)me)->threadEntry(); 195 196 return NULL; 197} 198 199void OMX::threadEntry() { 200 bool done = false; 201 while (!done) { 202 omx_message msg; 203 ssize_t n = recv(mSock, &msg, sizeof(msg), 0); 204 205 if (n <= 0) { 206 break; 207 } 208 209 Mutex::Autolock autoLock(mLock); 210 211 switch (msg.type) { 212 case omx_message::FILL_BUFFER: 213 { 214 OMX_BUFFERHEADERTYPE *header = 215 static_cast<OMX_BUFFERHEADERTYPE *>( 216 msg.u.buffer_data.buffer); 217 218 header->nFilledLen = 0; 219 header->nOffset = 0; 220 header->nFlags = 0; 221 222 NodeMeta *node_meta = static_cast<NodeMeta *>( 223 msg.u.buffer_data.node); 224 225 LOGV("FillThisBuffer buffer=%p", header); 226 227 OMX_ERRORTYPE err = 228 OMX_FillThisBuffer(node_meta->handle(), header); 229 assert(err == OMX_ErrorNone); 230 break; 231 } 232 233 case omx_message::EMPTY_BUFFER: 234 { 235 OMX_BUFFERHEADERTYPE *header = 236 static_cast<OMX_BUFFERHEADERTYPE *>( 237 msg.u.extended_buffer_data.buffer); 238 239 header->nFilledLen = msg.u.extended_buffer_data.range_length; 240 header->nOffset = msg.u.extended_buffer_data.range_offset; 241 header->nFlags = msg.u.extended_buffer_data.flags; 242 header->nTimeStamp = msg.u.extended_buffer_data.timestamp; 243 244 BufferMeta *buffer_meta = 245 static_cast<BufferMeta *>(header->pAppPrivate); 246 buffer_meta->CopyToOMX(header); 247 248 NodeMeta *node_meta = static_cast<NodeMeta *>( 249 msg.u.extended_buffer_data.node); 250 251 LOGV("EmptyThisBuffer buffer=%p", header); 252 253 OMX_ERRORTYPE err = 254 OMX_EmptyThisBuffer(node_meta->handle(), header); 255 assert(err == OMX_ErrorNone); 256 break; 257 } 258 259 case omx_message::SEND_COMMAND: 260 { 261 NodeMeta *node_meta = static_cast<NodeMeta *>( 262 msg.u.send_command_data.node); 263 264 OMX_ERRORTYPE err = 265 OMX_SendCommand( 266 node_meta->handle(), msg.u.send_command_data.cmd, 267 msg.u.send_command_data.param, NULL); 268 assert(err == OMX_ErrorNone); 269 break; 270 } 271 272 case omx_message::DISCONNECT: 273 { 274 omx_message msg; 275 msg.type = omx_message::DISCONNECTED; 276 ssize_t n = send(mSock, &msg, sizeof(msg), 0); 277 assert(n > 0 && static_cast<size_t>(n) == sizeof(msg)); 278 done = true; 279 break; 280 } 281 282 default: 283 LOGE("received unknown omx_message type %d", msg.type); 284 break; 285 } 286 } 287 288 Mutex::Autolock autoLock(mLock); 289 close(mSock); 290 mSock = -1; 291} 292#endif 293 294status_t OMX::list_nodes(List<String8> *list) { 295 OMX_MasterInit(); // XXX Put this somewhere else. 296 297 list->clear(); 298 299 OMX_U32 index = 0; 300 char componentName[256]; 301 while (OMX_MasterComponentNameEnum(componentName, sizeof(componentName), index) 302 == OMX_ErrorNone) { 303 list->push_back(String8(componentName)); 304 305 ++index; 306 } 307 308 return OK; 309} 310 311status_t OMX::allocate_node(const char *name, node_id *node) { 312 Mutex::Autolock autoLock(mLock); 313 314 *node = 0; 315 316 OMX_MasterInit(); // XXX Put this somewhere else. 317 318 NodeMeta *meta = new NodeMeta(this); 319 320 OMX_HANDLETYPE handle; 321 OMX_ERRORTYPE err = OMX_MasterGetHandle( 322 &handle, const_cast<char *>(name), meta, &kCallbacks); 323 324 if (err != OMX_ErrorNone) { 325 LOGE("FAILED to allocate omx component '%s'", name); 326 327 delete meta; 328 meta = NULL; 329 330 return UNKNOWN_ERROR; 331 } 332 333 meta->setHandle(handle); 334 335 *node = meta; 336 337 return OK; 338} 339 340status_t OMX::free_node(node_id node) { 341 Mutex::Autolock autoLock(mLock); 342 343 NodeMeta *meta = static_cast<NodeMeta *>(node); 344 345 OMX_ERRORTYPE err = OMX_MasterFreeHandle(meta->handle()); 346 347 delete meta; 348 meta = NULL; 349 350 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 351} 352 353status_t OMX::send_command( 354 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 355 Mutex::Autolock autoLock(mLock); 356 357#if IOMX_USES_SOCKETS 358 if (mSock < 0) { 359 return UNKNOWN_ERROR; 360 } 361#endif 362 363 NodeMeta *meta = static_cast<NodeMeta *>(node); 364 OMX_ERRORTYPE err = OMX_SendCommand(meta->handle(), cmd, param, NULL); 365 366 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 367} 368 369status_t OMX::get_parameter( 370 node_id node, OMX_INDEXTYPE index, 371 void *params, size_t size) { 372 Mutex::Autolock autoLock(mLock); 373 374 NodeMeta *meta = static_cast<NodeMeta *>(node); 375 OMX_ERRORTYPE err = OMX_GetParameter(meta->handle(), index, params); 376 377 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 378} 379 380status_t OMX::set_parameter( 381 node_id node, OMX_INDEXTYPE index, 382 const void *params, size_t size) { 383 Mutex::Autolock autoLock(mLock); 384 385 NodeMeta *meta = static_cast<NodeMeta *>(node); 386 OMX_ERRORTYPE err = 387 OMX_SetParameter(meta->handle(), index, const_cast<void *>(params)); 388 389 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 390} 391 392status_t OMX::use_buffer( 393 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 394 buffer_id *buffer) { 395 Mutex::Autolock autoLock(mLock); 396 397 BufferMeta *buffer_meta = new BufferMeta(this, params); 398 399 OMX_BUFFERHEADERTYPE *header; 400 401 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 402 OMX_ERRORTYPE err = 403 OMX_UseBuffer(node_meta->handle(), &header, port_index, buffer_meta, 404 params->size(), static_cast<OMX_U8 *>(params->pointer())); 405 406 if (err != OMX_ErrorNone) { 407 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 408 409 delete buffer_meta; 410 buffer_meta = NULL; 411 412 *buffer = 0; 413 return UNKNOWN_ERROR; 414 } 415 416 *buffer = header; 417 418 return OK; 419} 420 421status_t OMX::allocate_buffer( 422 node_id node, OMX_U32 port_index, size_t size, 423 buffer_id *buffer) { 424 Mutex::Autolock autoLock(mLock); 425 426 BufferMeta *buffer_meta = new BufferMeta(this, size); 427 428 OMX_BUFFERHEADERTYPE *header; 429 430 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 431 OMX_ERRORTYPE err = 432 OMX_AllocateBuffer(node_meta->handle(), &header, port_index, 433 buffer_meta, size); 434 435 if (err != OMX_ErrorNone) { 436 delete buffer_meta; 437 buffer_meta = NULL; 438 439 *buffer = 0; 440 return UNKNOWN_ERROR; 441 } 442 443 *buffer = header; 444 445 return OK; 446} 447 448status_t OMX::allocate_buffer_with_backup( 449 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 450 buffer_id *buffer) { 451 Mutex::Autolock autoLock(mLock); 452 453 BufferMeta *buffer_meta = new BufferMeta(this, params, true); 454 455 OMX_BUFFERHEADERTYPE *header; 456 457 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 458 OMX_ERRORTYPE err = 459 OMX_AllocateBuffer( 460 node_meta->handle(), &header, port_index, buffer_meta, 461 params->size()); 462 463 if (err != OMX_ErrorNone) { 464 delete buffer_meta; 465 buffer_meta = NULL; 466 467 *buffer = 0; 468 return UNKNOWN_ERROR; 469 } 470 471 *buffer = header; 472 473 return OK; 474} 475 476status_t OMX::free_buffer(node_id node, OMX_U32 port_index, buffer_id buffer) { 477 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 478 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 479 480 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 481 OMX_ERRORTYPE err = 482 OMX_FreeBuffer(node_meta->handle(), port_index, header); 483 484 delete buffer_meta; 485 buffer_meta = NULL; 486 487 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 488} 489 490OMX_ERRORTYPE OMX::OnEvent( 491 NodeMeta *meta, 492 OMX_IN OMX_EVENTTYPE eEvent, 493 OMX_IN OMX_U32 nData1, 494 OMX_IN OMX_U32 nData2, 495 OMX_IN OMX_PTR pEventData) { 496 LOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2); 497 498 omx_message msg; 499 msg.type = omx_message::EVENT; 500 msg.u.event_data.node = meta; 501 msg.u.event_data.event = eEvent; 502 msg.u.event_data.data1 = nData1; 503 msg.u.event_data.data2 = nData2; 504 505#if !IOMX_USES_SOCKETS 506 sp<IOMXObserver> observer = meta->observer(); 507 if (observer.get() != NULL) { 508 observer->on_message(msg); 509 } 510#else 511 assert(mSock >= 0); 512 513 ssize_t n = send(mSock, &msg, sizeof(msg), 0); 514 assert(n > 0 && static_cast<size_t>(n) == sizeof(msg)); 515#endif 516 517 return OMX_ErrorNone; 518} 519 520OMX_ERRORTYPE OMX::OnEmptyBufferDone( 521 NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { 522 LOGV("OnEmptyBufferDone buffer=%p", pBuffer); 523 524 omx_message msg; 525 msg.type = omx_message::EMPTY_BUFFER_DONE; 526 msg.u.buffer_data.node = meta; 527 msg.u.buffer_data.buffer = pBuffer; 528 529#if !IOMX_USES_SOCKETS 530 sp<IOMXObserver> observer = meta->observer(); 531 if (observer.get() != NULL) { 532 observer->on_message(msg); 533 } 534#else 535 assert(mSock >= 0); 536 ssize_t n = send(mSock, &msg, sizeof(msg), 0); 537 assert(n > 0 && static_cast<size_t>(n) == sizeof(msg)); 538#endif 539 540 return OMX_ErrorNone; 541} 542 543OMX_ERRORTYPE OMX::OnFillBufferDone( 544 NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { 545 LOGV("OnFillBufferDone buffer=%p", pBuffer); 546 BufferMeta *buffer_meta = static_cast<BufferMeta *>(pBuffer->pAppPrivate); 547 buffer_meta->CopyFromOMX(pBuffer); 548 549 omx_message msg; 550 msg.type = omx_message::FILL_BUFFER_DONE; 551 msg.u.extended_buffer_data.node = meta; 552 msg.u.extended_buffer_data.buffer = pBuffer; 553 msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; 554 msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; 555 msg.u.extended_buffer_data.flags = pBuffer->nFlags; 556 msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; 557 msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate; 558 559#if !IOMX_USES_SOCKETS 560 sp<IOMXObserver> observer = meta->observer(); 561 if (observer.get() != NULL) { 562 observer->on_message(msg); 563 } 564#else 565 assert(mSock >= 0); 566 567 ssize_t n = send(mSock, &msg, sizeof(msg), 0); 568 assert(n > 0 && static_cast<size_t>(n) == sizeof(msg)); 569#endif 570 571 return OMX_ErrorNone; 572} 573 574#if !IOMX_USES_SOCKETS 575status_t OMX::observe_node( 576 node_id node, const sp<IOMXObserver> &observer) { 577 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 578 579 node_meta->setObserver(observer); 580 581 return OK; 582} 583 584void OMX::fill_buffer(node_id node, buffer_id buffer) { 585 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 586 header->nFilledLen = 0; 587 header->nOffset = 0; 588 header->nFlags = 0; 589 590 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 591 592 OMX_ERRORTYPE err = 593 OMX_FillThisBuffer(node_meta->handle(), header); 594 assert(err == OMX_ErrorNone); 595} 596 597void OMX::empty_buffer( 598 node_id node, 599 buffer_id buffer, 600 OMX_U32 range_offset, OMX_U32 range_length, 601 OMX_U32 flags, OMX_TICKS timestamp) { 602 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 603 header->nFilledLen = range_length; 604 header->nOffset = range_offset; 605 header->nFlags = flags; 606 header->nTimeStamp = timestamp; 607 608 BufferMeta *buffer_meta = 609 static_cast<BufferMeta *>(header->pAppPrivate); 610 buffer_meta->CopyToOMX(header); 611 612 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 613 614 OMX_ERRORTYPE err = 615 OMX_EmptyThisBuffer(node_meta->handle(), header); 616 assert(err == OMX_ErrorNone); 617} 618#endif 619 620} // namespace android 621 622