OMXNodeInstance.cpp revision bbba88cb1bdc34705d1477208990a06904c022e7
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 "OMXNodeInstance" 19#include <utils/Log.h> 20 21#include "../include/OMXNodeInstance.h" 22#include "OMXMaster.h" 23 24#include <OMX_Component.h> 25 26#include <binder/IMemory.h> 27#include <media/stagefright/HardwareAPI.h> 28#include <media/stagefright/MediaDebug.h> 29#include <media/stagefright/MediaErrors.h> 30 31namespace android { 32 33struct BufferMeta { 34 BufferMeta(const sp<IMemory> &mem, bool is_backup = false) 35 : mMem(mem), 36 mIsBackup(is_backup) { 37 } 38 39 BufferMeta(size_t size) 40 : mSize(size), 41 mIsBackup(false) { 42 } 43 44 BufferMeta(const sp<GraphicBuffer> &graphicBuffer) 45 : mGraphicBuffer(graphicBuffer), 46 mIsBackup(false) { 47 } 48 49 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 50 if (!mIsBackup) { 51 return; 52 } 53 54 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 55 header->pBuffer + header->nOffset, 56 header->nFilledLen); 57 } 58 59 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 60 if (!mIsBackup) { 61 return; 62 } 63 64 memcpy(header->pBuffer + header->nOffset, 65 (const OMX_U8 *)mMem->pointer() + header->nOffset, 66 header->nFilledLen); 67 } 68 69private: 70 sp<GraphicBuffer> mGraphicBuffer; 71 sp<IMemory> mMem; 72 size_t mSize; 73 bool mIsBackup; 74 75 BufferMeta(const BufferMeta &); 76 BufferMeta &operator=(const BufferMeta &); 77}; 78 79// static 80OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 81 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 82}; 83 84OMXNodeInstance::OMXNodeInstance( 85 OMX *owner, const sp<IOMXObserver> &observer) 86 : mOwner(owner), 87 mNodeID(NULL), 88 mHandle(NULL), 89 mObserver(observer), 90 mDying(false) { 91} 92 93OMXNodeInstance::~OMXNodeInstance() { 94 CHECK_EQ(mHandle, NULL); 95} 96 97void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 98 CHECK_EQ(mHandle, NULL); 99 mNodeID = node_id; 100 mHandle = handle; 101} 102 103OMX *OMXNodeInstance::owner() { 104 return mOwner; 105} 106 107sp<IOMXObserver> OMXNodeInstance::observer() { 108 return mObserver; 109} 110 111OMX::node_id OMXNodeInstance::nodeID() { 112 return mNodeID; 113} 114 115static status_t StatusFromOMXError(OMX_ERRORTYPE err) { 116 switch (err) { 117 case OMX_ErrorNone: 118 return OK; 119 case OMX_ErrorUnsupportedSetting: 120 return ERROR_UNSUPPORTED; 121 default: 122 return UNKNOWN_ERROR; 123 } 124} 125 126status_t OMXNodeInstance::freeNode(OMXMaster *master) { 127 static int32_t kMaxNumIterations = 10; 128 129 // Transition the node from its current state all the way down 130 // to "Loaded". 131 // This ensures that all active buffers are properly freed even 132 // for components that don't do this themselves on a call to 133 // "FreeHandle". 134 135 // The code below may trigger some more events to be dispatched 136 // by the OMX component - we want to ignore them as our client 137 // does not expect them. 138 mDying = true; 139 140 OMX_STATETYPE state; 141 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 142 switch (state) { 143 case OMX_StateExecuting: 144 { 145 LOGV("forcing Executing->Idle"); 146 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 147 OMX_ERRORTYPE err; 148 int32_t iteration = 0; 149 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 150 && state != OMX_StateIdle 151 && state != OMX_StateInvalid) { 152 if (++iteration > kMaxNumIterations) { 153 LOGE("component failed to enter Idle state, aborting."); 154 state = OMX_StateInvalid; 155 break; 156 } 157 158 usleep(100000); 159 } 160 CHECK_EQ(err, OMX_ErrorNone); 161 162 if (state == OMX_StateInvalid) { 163 break; 164 } 165 166 // fall through 167 } 168 169 case OMX_StateIdle: 170 { 171 LOGV("forcing Idle->Loaded"); 172 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 173 174 freeActiveBuffers(); 175 176 OMX_ERRORTYPE err; 177 int32_t iteration = 0; 178 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 179 && state != OMX_StateLoaded 180 && state != OMX_StateInvalid) { 181 if (++iteration > kMaxNumIterations) { 182 LOGE("component failed to enter Loaded state, aborting."); 183 state = OMX_StateInvalid; 184 break; 185 } 186 187 LOGV("waiting for Loaded state..."); 188 usleep(100000); 189 } 190 CHECK_EQ(err, OMX_ErrorNone); 191 192 // fall through 193 } 194 195 case OMX_StateLoaded: 196 case OMX_StateInvalid: 197 break; 198 199 default: 200 CHECK(!"should not be here, unknown state."); 201 break; 202 } 203 204 LOGV("calling destroyComponentInstance"); 205 OMX_ERRORTYPE err = master->destroyComponentInstance( 206 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 207 LOGV("destroyComponentInstance returned err %d", err); 208 209 mHandle = NULL; 210 211 if (err != OMX_ErrorNone) { 212 LOGE("FreeHandle FAILED with error 0x%08x.", err); 213 } 214 215 mOwner->invalidateNodeID(mNodeID); 216 mNodeID = NULL; 217 218 LOGV("OMXNodeInstance going away."); 219 delete this; 220 221 return StatusFromOMXError(err); 222} 223 224status_t OMXNodeInstance::sendCommand( 225 OMX_COMMANDTYPE cmd, OMX_S32 param) { 226 Mutex::Autolock autoLock(mLock); 227 228 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 229 return StatusFromOMXError(err); 230} 231 232status_t OMXNodeInstance::getParameter( 233 OMX_INDEXTYPE index, void *params, size_t size) { 234 Mutex::Autolock autoLock(mLock); 235 236 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 237 238 return StatusFromOMXError(err); 239} 240 241status_t OMXNodeInstance::setParameter( 242 OMX_INDEXTYPE index, const void *params, size_t size) { 243 Mutex::Autolock autoLock(mLock); 244 245 OMX_ERRORTYPE err = OMX_SetParameter( 246 mHandle, index, const_cast<void *>(params)); 247 248 return StatusFromOMXError(err); 249} 250 251status_t OMXNodeInstance::getConfig( 252 OMX_INDEXTYPE index, void *params, size_t size) { 253 Mutex::Autolock autoLock(mLock); 254 255 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 256 return StatusFromOMXError(err); 257} 258 259status_t OMXNodeInstance::setConfig( 260 OMX_INDEXTYPE index, const void *params, size_t size) { 261 Mutex::Autolock autoLock(mLock); 262 263 OMX_ERRORTYPE err = OMX_SetConfig( 264 mHandle, index, const_cast<void *>(params)); 265 266 return StatusFromOMXError(err); 267} 268 269status_t OMXNodeInstance::enableGraphicBuffers( 270 OMX_U32 portIndex, OMX_BOOL enable) { 271 Mutex::Autolock autoLock(mLock); 272 273 OMX_INDEXTYPE index; 274 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 275 mHandle, 276 const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"), 277 &index); 278 279 if (err != OMX_ErrorNone) { 280 LOGE("OMX_GetExtensionIndex failed"); 281 282 return StatusFromOMXError(err); 283 } 284 285 OMX_VERSIONTYPE ver; 286 ver.s.nVersionMajor = 1; 287 ver.s.nVersionMinor = 0; 288 ver.s.nRevision = 0; 289 ver.s.nStep = 0; 290 EnableAndroidNativeBuffersParams params = { 291 sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable, 292 }; 293 294 err = OMX_SetParameter(mHandle, index, ¶ms); 295 296 if (err != OMX_ErrorNone) { 297 LOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)", 298 err, err); 299 300 return UNKNOWN_ERROR; 301 } 302 303 return OK; 304} 305 306status_t OMXNodeInstance::getGraphicBufferUsage( 307 OMX_U32 portIndex, OMX_U32* usage) { 308 Mutex::Autolock autoLock(mLock); 309 310 OMX_INDEXTYPE index; 311 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 312 mHandle, 313 const_cast<OMX_STRING>( 314 "OMX.google.android.index.getAndroidNativeBufferUsage"), 315 &index); 316 317 if (err != OMX_ErrorNone) { 318 LOGE("OMX_GetExtensionIndex failed"); 319 320 return StatusFromOMXError(err); 321 } 322 323 OMX_VERSIONTYPE ver; 324 ver.s.nVersionMajor = 1; 325 ver.s.nVersionMinor = 0; 326 ver.s.nRevision = 0; 327 ver.s.nStep = 0; 328 GetAndroidNativeBufferUsageParams params = { 329 sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0, 330 }; 331 332 err = OMX_GetParameter(mHandle, index, ¶ms); 333 334 if (err != OMX_ErrorNone) { 335 LOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)", 336 err, err); 337 return UNKNOWN_ERROR; 338 } 339 340 *usage = params.nUsage; 341 342 return OK; 343} 344 345status_t OMXNodeInstance::storeMetaDataInBuffers( 346 OMX_U32 portIndex, 347 OMX_BOOL enable) { 348 Mutex::Autolock autolock(mLock); 349 350 OMX_INDEXTYPE index; 351 OMX_STRING name = const_cast<OMX_STRING>( 352 "OMX.google.android.index.storeMetaDataInBuffers"); 353 354 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 355 if (err != OMX_ErrorNone) { 356 LOGE("OMX_GetExtensionIndex %s failed", name); 357 return StatusFromOMXError(err); 358 } 359 360 StoreMetaDataInBuffersParams params; 361 memset(¶ms, 0, sizeof(params)); 362 params.nSize = sizeof(params); 363 364 // Version: 1.0.0.0 365 params.nVersion.s.nVersionMajor = 1; 366 367 params.nPortIndex = portIndex; 368 params.bStoreMetaData = enable; 369 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 370 LOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); 371 return UNKNOWN_ERROR; 372 } 373 return err; 374} 375 376status_t OMXNodeInstance::useBuffer( 377 OMX_U32 portIndex, const sp<IMemory> ¶ms, 378 OMX::buffer_id *buffer) { 379 Mutex::Autolock autoLock(mLock); 380 381 BufferMeta *buffer_meta = new BufferMeta(params); 382 383 OMX_BUFFERHEADERTYPE *header; 384 385 OMX_ERRORTYPE err = OMX_UseBuffer( 386 mHandle, &header, portIndex, buffer_meta, 387 params->size(), static_cast<OMX_U8 *>(params->pointer())); 388 389 if (err != OMX_ErrorNone) { 390 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 391 392 delete buffer_meta; 393 buffer_meta = NULL; 394 395 *buffer = 0; 396 397 return UNKNOWN_ERROR; 398 } 399 400 CHECK_EQ(header->pAppPrivate, buffer_meta); 401 402 *buffer = header; 403 404 addActiveBuffer(portIndex, *buffer); 405 406 return OK; 407} 408 409status_t OMXNodeInstance::useGraphicBuffer( 410 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 411 OMX::buffer_id *buffer) { 412 Mutex::Autolock autoLock(mLock); 413 414 OMX_INDEXTYPE index; 415 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 416 mHandle, 417 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"), 418 &index); 419 420 if (err != OMX_ErrorNone) { 421 LOGE("OMX_GetExtensionIndex failed"); 422 423 return StatusFromOMXError(err); 424 } 425 426 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 427 428 OMX_BUFFERHEADERTYPE *header; 429 430 OMX_VERSIONTYPE ver; 431 ver.s.nVersionMajor = 1; 432 ver.s.nVersionMinor = 0; 433 ver.s.nRevision = 0; 434 ver.s.nStep = 0; 435 UseAndroidNativeBufferParams params = { 436 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 437 &header, graphicBuffer, 438 }; 439 440 err = OMX_SetParameter(mHandle, index, ¶ms); 441 442 if (err != OMX_ErrorNone) { 443 LOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, 444 err); 445 446 delete bufferMeta; 447 bufferMeta = NULL; 448 449 *buffer = 0; 450 451 return UNKNOWN_ERROR; 452 } 453 454 CHECK_EQ(header->pAppPrivate, bufferMeta); 455 456 *buffer = header; 457 458 addActiveBuffer(portIndex, *buffer); 459 460 return OK; 461} 462 463status_t OMXNodeInstance::allocateBuffer( 464 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 465 void **buffer_data) { 466 Mutex::Autolock autoLock(mLock); 467 468 BufferMeta *buffer_meta = new BufferMeta(size); 469 470 OMX_BUFFERHEADERTYPE *header; 471 472 OMX_ERRORTYPE err = OMX_AllocateBuffer( 473 mHandle, &header, portIndex, buffer_meta, size); 474 475 if (err != OMX_ErrorNone) { 476 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 477 478 delete buffer_meta; 479 buffer_meta = NULL; 480 481 *buffer = 0; 482 483 return UNKNOWN_ERROR; 484 } 485 486 CHECK_EQ(header->pAppPrivate, buffer_meta); 487 488 *buffer = header; 489 *buffer_data = header->pBuffer; 490 491 addActiveBuffer(portIndex, *buffer); 492 493 return OK; 494} 495 496status_t OMXNodeInstance::allocateBufferWithBackup( 497 OMX_U32 portIndex, const sp<IMemory> ¶ms, 498 OMX::buffer_id *buffer) { 499 Mutex::Autolock autoLock(mLock); 500 501 BufferMeta *buffer_meta = new BufferMeta(params, true); 502 503 OMX_BUFFERHEADERTYPE *header; 504 505 OMX_ERRORTYPE err = OMX_AllocateBuffer( 506 mHandle, &header, portIndex, buffer_meta, params->size()); 507 508 if (err != OMX_ErrorNone) { 509 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 510 511 delete buffer_meta; 512 buffer_meta = NULL; 513 514 *buffer = 0; 515 516 return UNKNOWN_ERROR; 517 } 518 519 CHECK_EQ(header->pAppPrivate, buffer_meta); 520 521 *buffer = header; 522 523 addActiveBuffer(portIndex, *buffer); 524 525 return OK; 526} 527 528status_t OMXNodeInstance::freeBuffer( 529 OMX_U32 portIndex, OMX::buffer_id buffer) { 530 Mutex::Autolock autoLock(mLock); 531 532 removeActiveBuffer(portIndex, buffer); 533 534 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 535 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 536 537 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 538 539 delete buffer_meta; 540 buffer_meta = NULL; 541 542 return StatusFromOMXError(err); 543} 544 545status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 546 Mutex::Autolock autoLock(mLock); 547 548 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 549 header->nFilledLen = 0; 550 header->nOffset = 0; 551 header->nFlags = 0; 552 553 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 554 555 return StatusFromOMXError(err); 556} 557 558status_t OMXNodeInstance::emptyBuffer( 559 OMX::buffer_id buffer, 560 OMX_U32 rangeOffset, OMX_U32 rangeLength, 561 OMX_U32 flags, OMX_TICKS timestamp) { 562 Mutex::Autolock autoLock(mLock); 563 564 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 565 header->nFilledLen = rangeLength; 566 header->nOffset = rangeOffset; 567 header->nFlags = flags; 568 header->nTimeStamp = timestamp; 569 570 BufferMeta *buffer_meta = 571 static_cast<BufferMeta *>(header->pAppPrivate); 572 buffer_meta->CopyToOMX(header); 573 574 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 575 576 return StatusFromOMXError(err); 577} 578 579status_t OMXNodeInstance::getExtensionIndex( 580 const char *parameterName, OMX_INDEXTYPE *index) { 581 Mutex::Autolock autoLock(mLock); 582 583 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 584 mHandle, const_cast<char *>(parameterName), index); 585 586 return StatusFromOMXError(err); 587} 588 589void OMXNodeInstance::onMessage(const omx_message &msg) { 590 if (msg.type == omx_message::FILL_BUFFER_DONE) { 591 OMX_BUFFERHEADERTYPE *buffer = 592 static_cast<OMX_BUFFERHEADERTYPE *>( 593 msg.u.extended_buffer_data.buffer); 594 595 BufferMeta *buffer_meta = 596 static_cast<BufferMeta *>(buffer->pAppPrivate); 597 598 buffer_meta->CopyFromOMX(buffer); 599 } 600 601 mObserver->onMessage(msg); 602} 603 604void OMXNodeInstance::onObserverDied(OMXMaster *master) { 605 LOGE("!!! Observer died. Quickly, do something, ... anything..."); 606 607 // Try to force shutdown of the node and hope for the best. 608 freeNode(master); 609} 610 611void OMXNodeInstance::onGetHandleFailed() { 612 delete this; 613} 614 615// static 616OMX_ERRORTYPE OMXNodeInstance::OnEvent( 617 OMX_IN OMX_HANDLETYPE hComponent, 618 OMX_IN OMX_PTR pAppData, 619 OMX_IN OMX_EVENTTYPE eEvent, 620 OMX_IN OMX_U32 nData1, 621 OMX_IN OMX_U32 nData2, 622 OMX_IN OMX_PTR pEventData) { 623 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 624 if (instance->mDying) { 625 return OMX_ErrorNone; 626 } 627 return instance->owner()->OnEvent( 628 instance->nodeID(), eEvent, nData1, nData2, pEventData); 629} 630 631// static 632OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 633 OMX_IN OMX_HANDLETYPE hComponent, 634 OMX_IN OMX_PTR pAppData, 635 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 636 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 637 if (instance->mDying) { 638 return OMX_ErrorNone; 639 } 640 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 641} 642 643// static 644OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 645 OMX_IN OMX_HANDLETYPE hComponent, 646 OMX_IN OMX_PTR pAppData, 647 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 648 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 649 if (instance->mDying) { 650 return OMX_ErrorNone; 651 } 652 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 653} 654 655void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 656 ActiveBuffer active; 657 active.mPortIndex = portIndex; 658 active.mID = id; 659 mActiveBuffers.push(active); 660} 661 662void OMXNodeInstance::removeActiveBuffer( 663 OMX_U32 portIndex, OMX::buffer_id id) { 664 bool found = false; 665 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 666 if (mActiveBuffers[i].mPortIndex == portIndex 667 && mActiveBuffers[i].mID == id) { 668 found = true; 669 mActiveBuffers.removeItemsAt(i); 670 break; 671 } 672 } 673 674 if (!found) { 675 LOGW("Attempt to remove an active buffer we know nothing about..."); 676 } 677} 678 679void OMXNodeInstance::freeActiveBuffers() { 680 // Make sure to count down here, as freeBuffer will in turn remove 681 // the active buffer from the vector... 682 for (size_t i = mActiveBuffers.size(); i--;) { 683 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 684 } 685} 686 687} // namespace android 688