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