OMXNodeInstance.cpp revision e2ce6458659c6e1bad420357b61dc10cd8bbe2ab
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 return StatusFromOMXError(err); 238} 239 240status_t OMXNodeInstance::setParameter( 241 OMX_INDEXTYPE index, const void *params, size_t size) { 242 Mutex::Autolock autoLock(mLock); 243 244 OMX_ERRORTYPE err = OMX_SetParameter( 245 mHandle, index, const_cast<void *>(params)); 246 247 return StatusFromOMXError(err); 248} 249 250status_t OMXNodeInstance::getConfig( 251 OMX_INDEXTYPE index, void *params, size_t size) { 252 Mutex::Autolock autoLock(mLock); 253 254 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 255 return StatusFromOMXError(err); 256} 257 258status_t OMXNodeInstance::setConfig( 259 OMX_INDEXTYPE index, const void *params, size_t size) { 260 Mutex::Autolock autoLock(mLock); 261 262 OMX_ERRORTYPE err = OMX_SetConfig( 263 mHandle, index, const_cast<void *>(params)); 264 265 return StatusFromOMXError(err); 266} 267 268status_t OMXNodeInstance::enableGraphicBuffers( 269 OMX_U32 portIndex, OMX_BOOL enable) { 270 Mutex::Autolock autoLock(mLock); 271 272 OMX_INDEXTYPE index; 273 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 274 mHandle, 275 const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"), 276 &index); 277 278 if (err != OMX_ErrorNone) { 279 LOGE("OMX_GetExtensionIndex failed"); 280 281 return StatusFromOMXError(err); 282 } 283 284 OMX_VERSIONTYPE ver; 285 ver.s.nVersionMajor = 1; 286 ver.s.nVersionMinor = 0; 287 ver.s.nRevision = 0; 288 ver.s.nStep = 0; 289 EnableAndroidNativeBuffersParams params = { 290 sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable, 291 }; 292 293 err = OMX_SetParameter(mHandle, index, ¶ms); 294 295 if (err != OMX_ErrorNone) { 296 LOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)", 297 err, err); 298 299 return UNKNOWN_ERROR; 300 } 301 302 return OK; 303} 304 305status_t OMXNodeInstance::getGraphicBufferUsage( 306 OMX_U32 portIndex, OMX_U32* usage) { 307 Mutex::Autolock autoLock(mLock); 308 309 OMX_INDEXTYPE index; 310 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 311 mHandle, 312 const_cast<OMX_STRING>( 313 "OMX.google.android.index.getAndroidNativeBufferUsage"), 314 &index); 315 316 if (err != OMX_ErrorNone) { 317 LOGE("OMX_GetExtensionIndex failed"); 318 319 return StatusFromOMXError(err); 320 } 321 322 OMX_VERSIONTYPE ver; 323 ver.s.nVersionMajor = 1; 324 ver.s.nVersionMinor = 0; 325 ver.s.nRevision = 0; 326 ver.s.nStep = 0; 327 GetAndroidNativeBufferUsageParams params = { 328 sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0, 329 }; 330 331 err = OMX_GetParameter(mHandle, index, ¶ms); 332 333 if (err != OMX_ErrorNone) { 334 LOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)", 335 err, err); 336 return UNKNOWN_ERROR; 337 } 338 339 *usage = params.nUsage; 340 341 return OK; 342} 343 344status_t OMXNodeInstance::storeMetaDataInBuffers( 345 OMX_U32 portIndex, 346 OMX_BOOL enable) { 347 Mutex::Autolock autolock(mLock); 348 349 OMX_INDEXTYPE index; 350 OMX_STRING name = const_cast<OMX_STRING>( 351 "OMX.google.android.index.storeMetaDataInBuffers"); 352 353 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 354 if (err != OMX_ErrorNone) { 355 LOGE("OMX_GetExtensionIndex %s failed", name); 356 return StatusFromOMXError(err); 357 } 358 359 StoreMetaDataInBuffersParams params; 360 memset(¶ms, 0, sizeof(params)); 361 params.nSize = sizeof(params); 362 363 // Version: 1.0.0.0 364 params.nVersion.s.nVersionMajor = 1; 365 366 params.nPortIndex = portIndex; 367 params.bStoreMetaData = enable; 368 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 369 LOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); 370 return UNKNOWN_ERROR; 371 } 372 return err; 373} 374 375status_t OMXNodeInstance::useBuffer( 376 OMX_U32 portIndex, const sp<IMemory> ¶ms, 377 OMX::buffer_id *buffer) { 378 Mutex::Autolock autoLock(mLock); 379 380 BufferMeta *buffer_meta = new BufferMeta(params); 381 382 OMX_BUFFERHEADERTYPE *header; 383 384 OMX_ERRORTYPE err = OMX_UseBuffer( 385 mHandle, &header, portIndex, buffer_meta, 386 params->size(), static_cast<OMX_U8 *>(params->pointer())); 387 388 if (err != OMX_ErrorNone) { 389 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 390 391 delete buffer_meta; 392 buffer_meta = NULL; 393 394 *buffer = 0; 395 396 return UNKNOWN_ERROR; 397 } 398 399 CHECK_EQ(header->pAppPrivate, buffer_meta); 400 401 *buffer = header; 402 403 addActiveBuffer(portIndex, *buffer); 404 405 return OK; 406} 407 408status_t OMXNodeInstance::useGraphicBuffer( 409 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 410 OMX::buffer_id *buffer) { 411 Mutex::Autolock autoLock(mLock); 412 413 OMX_INDEXTYPE index; 414 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 415 mHandle, 416 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"), 417 &index); 418 419 if (err != OMX_ErrorNone) { 420 LOGE("OMX_GetExtensionIndex failed"); 421 422 return StatusFromOMXError(err); 423 } 424 425 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 426 427 OMX_BUFFERHEADERTYPE *header; 428 429 OMX_VERSIONTYPE ver; 430 ver.s.nVersionMajor = 1; 431 ver.s.nVersionMinor = 0; 432 ver.s.nRevision = 0; 433 ver.s.nStep = 0; 434 UseAndroidNativeBufferParams params = { 435 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 436 &header, graphicBuffer, 437 }; 438 439 err = OMX_SetParameter(mHandle, index, ¶ms); 440 441 if (err != OMX_ErrorNone) { 442 LOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, 443 err); 444 445 delete bufferMeta; 446 bufferMeta = NULL; 447 448 *buffer = 0; 449 450 return UNKNOWN_ERROR; 451 } 452 453 CHECK_EQ(header->pAppPrivate, bufferMeta); 454 455 *buffer = header; 456 457 addActiveBuffer(portIndex, *buffer); 458 459 return OK; 460} 461 462status_t OMXNodeInstance::allocateBuffer( 463 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 464 void **buffer_data) { 465 Mutex::Autolock autoLock(mLock); 466 467 BufferMeta *buffer_meta = new BufferMeta(size); 468 469 OMX_BUFFERHEADERTYPE *header; 470 471 OMX_ERRORTYPE err = OMX_AllocateBuffer( 472 mHandle, &header, portIndex, buffer_meta, size); 473 474 if (err != OMX_ErrorNone) { 475 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 476 477 delete buffer_meta; 478 buffer_meta = NULL; 479 480 *buffer = 0; 481 482 return UNKNOWN_ERROR; 483 } 484 485 CHECK_EQ(header->pAppPrivate, buffer_meta); 486 487 *buffer = header; 488 *buffer_data = header->pBuffer; 489 490 addActiveBuffer(portIndex, *buffer); 491 492 return OK; 493} 494 495status_t OMXNodeInstance::allocateBufferWithBackup( 496 OMX_U32 portIndex, const sp<IMemory> ¶ms, 497 OMX::buffer_id *buffer) { 498 Mutex::Autolock autoLock(mLock); 499 500 BufferMeta *buffer_meta = new BufferMeta(params, true); 501 502 OMX_BUFFERHEADERTYPE *header; 503 504 OMX_ERRORTYPE err = OMX_AllocateBuffer( 505 mHandle, &header, portIndex, buffer_meta, params->size()); 506 507 if (err != OMX_ErrorNone) { 508 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 509 510 delete buffer_meta; 511 buffer_meta = NULL; 512 513 *buffer = 0; 514 515 return UNKNOWN_ERROR; 516 } 517 518 CHECK_EQ(header->pAppPrivate, buffer_meta); 519 520 *buffer = header; 521 522 addActiveBuffer(portIndex, *buffer); 523 524 return OK; 525} 526 527status_t OMXNodeInstance::freeBuffer( 528 OMX_U32 portIndex, OMX::buffer_id buffer) { 529 Mutex::Autolock autoLock(mLock); 530 531 removeActiveBuffer(portIndex, buffer); 532 533 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 534 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 535 536 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 537 538 delete buffer_meta; 539 buffer_meta = NULL; 540 541 return StatusFromOMXError(err); 542} 543 544status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 545 Mutex::Autolock autoLock(mLock); 546 547 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 548 header->nFilledLen = 0; 549 header->nOffset = 0; 550 header->nFlags = 0; 551 552 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 553 554 return StatusFromOMXError(err); 555} 556 557status_t OMXNodeInstance::emptyBuffer( 558 OMX::buffer_id buffer, 559 OMX_U32 rangeOffset, OMX_U32 rangeLength, 560 OMX_U32 flags, OMX_TICKS timestamp) { 561 Mutex::Autolock autoLock(mLock); 562 563 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 564 header->nFilledLen = rangeLength; 565 header->nOffset = rangeOffset; 566 header->nFlags = flags; 567 header->nTimeStamp = timestamp; 568 569 BufferMeta *buffer_meta = 570 static_cast<BufferMeta *>(header->pAppPrivate); 571 buffer_meta->CopyToOMX(header); 572 573 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 574 575 return StatusFromOMXError(err); 576} 577 578status_t OMXNodeInstance::getExtensionIndex( 579 const char *parameterName, OMX_INDEXTYPE *index) { 580 Mutex::Autolock autoLock(mLock); 581 582 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 583 mHandle, const_cast<char *>(parameterName), index); 584 585 return StatusFromOMXError(err); 586} 587 588void OMXNodeInstance::onMessage(const omx_message &msg) { 589 if (msg.type == omx_message::FILL_BUFFER_DONE) { 590 OMX_BUFFERHEADERTYPE *buffer = 591 static_cast<OMX_BUFFERHEADERTYPE *>( 592 msg.u.extended_buffer_data.buffer); 593 594 BufferMeta *buffer_meta = 595 static_cast<BufferMeta *>(buffer->pAppPrivate); 596 597 buffer_meta->CopyFromOMX(buffer); 598 } 599 600 mObserver->onMessage(msg); 601} 602 603void OMXNodeInstance::onObserverDied(OMXMaster *master) { 604 LOGE("!!! Observer died. Quickly, do something, ... anything..."); 605 606 // Try to force shutdown of the node and hope for the best. 607 freeNode(master); 608} 609 610void OMXNodeInstance::onGetHandleFailed() { 611 delete this; 612} 613 614// static 615OMX_ERRORTYPE OMXNodeInstance::OnEvent( 616 OMX_IN OMX_HANDLETYPE hComponent, 617 OMX_IN OMX_PTR pAppData, 618 OMX_IN OMX_EVENTTYPE eEvent, 619 OMX_IN OMX_U32 nData1, 620 OMX_IN OMX_U32 nData2, 621 OMX_IN OMX_PTR pEventData) { 622 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 623 if (instance->mDying) { 624 return OMX_ErrorNone; 625 } 626 return instance->owner()->OnEvent( 627 instance->nodeID(), eEvent, nData1, nData2, pEventData); 628} 629 630// static 631OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 632 OMX_IN OMX_HANDLETYPE hComponent, 633 OMX_IN OMX_PTR pAppData, 634 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 635 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 636 if (instance->mDying) { 637 return OMX_ErrorNone; 638 } 639 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 640} 641 642// static 643OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 644 OMX_IN OMX_HANDLETYPE hComponent, 645 OMX_IN OMX_PTR pAppData, 646 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 647 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 648 if (instance->mDying) { 649 return OMX_ErrorNone; 650 } 651 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 652} 653 654void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 655 ActiveBuffer active; 656 active.mPortIndex = portIndex; 657 active.mID = id; 658 mActiveBuffers.push(active); 659} 660 661void OMXNodeInstance::removeActiveBuffer( 662 OMX_U32 portIndex, OMX::buffer_id id) { 663 bool found = false; 664 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 665 if (mActiveBuffers[i].mPortIndex == portIndex 666 && mActiveBuffers[i].mID == id) { 667 found = true; 668 mActiveBuffers.removeItemsAt(i); 669 break; 670 } 671 } 672 673 if (!found) { 674 LOGW("Attempt to remove an active buffer we know nothing about..."); 675 } 676} 677 678void OMXNodeInstance::freeActiveBuffers() { 679 // Make sure to count down here, as freeBuffer will in turn remove 680 // the active buffer from the vector... 681 for (size_t i = mActiveBuffers.size(); i--;) { 682 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 683 } 684} 685 686} // namespace android 687