OMXNodeInstance.cpp revision 92cb8f928dc9e237c356c942d10b5c0c1e04b2ae
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#include "GraphicBufferSource.h" 24 25#include <OMX_Component.h> 26 27#include <binder/IMemory.h> 28#include <gui/BufferQueue.h> 29#include <HardwareAPI.h> 30#include <media/stagefright/foundation/ADebug.h> 31#include <media/stagefright/MediaErrors.h> 32 33static const OMX_U32 kPortIndexInput = 0; 34 35namespace android { 36 37struct BufferMeta { 38 BufferMeta(const sp<IMemory> &mem, bool is_backup = false) 39 : mMem(mem), 40 mIsBackup(is_backup) { 41 } 42 43 BufferMeta(size_t size) 44 : mSize(size), 45 mIsBackup(false) { 46 } 47 48 BufferMeta(const sp<GraphicBuffer> &graphicBuffer) 49 : mGraphicBuffer(graphicBuffer), 50 mIsBackup(false) { 51 } 52 53 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 54 if (!mIsBackup) { 55 return; 56 } 57 58 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 59 header->pBuffer + header->nOffset, 60 header->nFilledLen); 61 } 62 63 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 64 if (!mIsBackup) { 65 return; 66 } 67 68 memcpy(header->pBuffer + header->nOffset, 69 (const OMX_U8 *)mMem->pointer() + header->nOffset, 70 header->nFilledLen); 71 } 72 73private: 74 sp<GraphicBuffer> mGraphicBuffer; 75 sp<IMemory> mMem; 76 size_t mSize; 77 bool mIsBackup; 78 79 BufferMeta(const BufferMeta &); 80 BufferMeta &operator=(const BufferMeta &); 81}; 82 83// static 84OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 85 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 86}; 87 88OMXNodeInstance::OMXNodeInstance( 89 OMX *owner, const sp<IOMXObserver> &observer) 90 : mOwner(owner), 91 mNodeID(NULL), 92 mHandle(NULL), 93 mObserver(observer), 94 mDying(false) { 95} 96 97OMXNodeInstance::~OMXNodeInstance() { 98 CHECK(mHandle == NULL); 99} 100 101void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 102 CHECK(mHandle == NULL); 103 mNodeID = node_id; 104 mHandle = handle; 105} 106 107sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() { 108 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 109 return mGraphicBufferSource; 110} 111 112void OMXNodeInstance::setGraphicBufferSource( 113 const sp<GraphicBufferSource>& bufferSource) { 114 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 115 mGraphicBufferSource = bufferSource; 116} 117 118OMX *OMXNodeInstance::owner() { 119 return mOwner; 120} 121 122sp<IOMXObserver> OMXNodeInstance::observer() { 123 return mObserver; 124} 125 126OMX::node_id OMXNodeInstance::nodeID() { 127 return mNodeID; 128} 129 130static status_t StatusFromOMXError(OMX_ERRORTYPE err) { 131 switch (err) { 132 case OMX_ErrorNone: 133 return OK; 134 case OMX_ErrorUnsupportedSetting: 135 return ERROR_UNSUPPORTED; 136 default: 137 return UNKNOWN_ERROR; 138 } 139} 140 141status_t OMXNodeInstance::freeNode(OMXMaster *master) { 142 static int32_t kMaxNumIterations = 10; 143 144 // Transition the node from its current state all the way down 145 // to "Loaded". 146 // This ensures that all active buffers are properly freed even 147 // for components that don't do this themselves on a call to 148 // "FreeHandle". 149 150 // The code below may trigger some more events to be dispatched 151 // by the OMX component - we want to ignore them as our client 152 // does not expect them. 153 mDying = true; 154 155 OMX_STATETYPE state; 156 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 157 switch (state) { 158 case OMX_StateExecuting: 159 { 160 ALOGV("forcing Executing->Idle"); 161 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 162 OMX_ERRORTYPE err; 163 int32_t iteration = 0; 164 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 165 && state != OMX_StateIdle 166 && state != OMX_StateInvalid) { 167 if (++iteration > kMaxNumIterations) { 168 ALOGE("component failed to enter Idle state, aborting."); 169 state = OMX_StateInvalid; 170 break; 171 } 172 173 usleep(100000); 174 } 175 CHECK_EQ(err, OMX_ErrorNone); 176 177 if (state == OMX_StateInvalid) { 178 break; 179 } 180 181 // fall through 182 } 183 184 case OMX_StateIdle: 185 { 186 ALOGV("forcing Idle->Loaded"); 187 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 188 189 freeActiveBuffers(); 190 191 OMX_ERRORTYPE err; 192 int32_t iteration = 0; 193 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 194 && state != OMX_StateLoaded 195 && state != OMX_StateInvalid) { 196 if (++iteration > kMaxNumIterations) { 197 ALOGE("component failed to enter Loaded state, aborting."); 198 state = OMX_StateInvalid; 199 break; 200 } 201 202 ALOGV("waiting for Loaded state..."); 203 usleep(100000); 204 } 205 CHECK_EQ(err, OMX_ErrorNone); 206 207 // fall through 208 } 209 210 case OMX_StateLoaded: 211 case OMX_StateInvalid: 212 break; 213 214 default: 215 CHECK(!"should not be here, unknown state."); 216 break; 217 } 218 219 ALOGV("calling destroyComponentInstance"); 220 OMX_ERRORTYPE err = master->destroyComponentInstance( 221 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 222 ALOGV("destroyComponentInstance returned err %d", err); 223 224 mHandle = NULL; 225 226 if (err != OMX_ErrorNone) { 227 ALOGE("FreeHandle FAILED with error 0x%08x.", err); 228 } 229 230 mOwner->invalidateNodeID(mNodeID); 231 mNodeID = NULL; 232 233 ALOGV("OMXNodeInstance going away."); 234 delete this; 235 236 return StatusFromOMXError(err); 237} 238 239status_t OMXNodeInstance::sendCommand( 240 OMX_COMMANDTYPE cmd, OMX_S32 param) { 241 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 242 if (bufferSource != NULL 243 && cmd == OMX_CommandStateSet 244 && param == OMX_StateLoaded) { 245 // Initiating transition from Executing -> Loaded 246 // Buffers are about to be freed. 247 bufferSource->omxLoaded(); 248 setGraphicBufferSource(NULL); 249 250 // fall through 251 } 252 253 Mutex::Autolock autoLock(mLock); 254 255 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 256 return StatusFromOMXError(err); 257} 258 259status_t OMXNodeInstance::getParameter( 260 OMX_INDEXTYPE index, void *params, size_t size) { 261 Mutex::Autolock autoLock(mLock); 262 263 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 264 265 return StatusFromOMXError(err); 266} 267 268status_t OMXNodeInstance::setParameter( 269 OMX_INDEXTYPE index, const void *params, size_t size) { 270 Mutex::Autolock autoLock(mLock); 271 272 OMX_ERRORTYPE err = OMX_SetParameter( 273 mHandle, index, const_cast<void *>(params)); 274 275 return StatusFromOMXError(err); 276} 277 278status_t OMXNodeInstance::getConfig( 279 OMX_INDEXTYPE index, void *params, size_t size) { 280 Mutex::Autolock autoLock(mLock); 281 282 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 283 return StatusFromOMXError(err); 284} 285 286status_t OMXNodeInstance::setConfig( 287 OMX_INDEXTYPE index, const void *params, size_t size) { 288 Mutex::Autolock autoLock(mLock); 289 290 OMX_ERRORTYPE err = OMX_SetConfig( 291 mHandle, index, const_cast<void *>(params)); 292 293 return StatusFromOMXError(err); 294} 295 296status_t OMXNodeInstance::getState(OMX_STATETYPE* state) { 297 Mutex::Autolock autoLock(mLock); 298 299 OMX_ERRORTYPE err = OMX_GetState(mHandle, state); 300 301 return StatusFromOMXError(err); 302} 303 304status_t OMXNodeInstance::enableGraphicBuffers( 305 OMX_U32 portIndex, OMX_BOOL enable) { 306 Mutex::Autolock autoLock(mLock); 307 OMX_STRING name = const_cast<OMX_STRING>( 308 "OMX.google.android.index.enableAndroidNativeBuffers"); 309 310 OMX_INDEXTYPE index; 311 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 312 313 if (err != OMX_ErrorNone) { 314 if (enable) { 315 ALOGE("OMX_GetExtensionIndex %s failed", name); 316 } 317 318 return StatusFromOMXError(err); 319 } 320 321 OMX_VERSIONTYPE ver; 322 ver.s.nVersionMajor = 1; 323 ver.s.nVersionMinor = 0; 324 ver.s.nRevision = 0; 325 ver.s.nStep = 0; 326 EnableAndroidNativeBuffersParams params = { 327 sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable, 328 }; 329 330 err = OMX_SetParameter(mHandle, index, ¶ms); 331 332 if (err != OMX_ErrorNone) { 333 ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)", 334 err, err); 335 336 return UNKNOWN_ERROR; 337 } 338 339 return OK; 340} 341 342status_t OMXNodeInstance::getGraphicBufferUsage( 343 OMX_U32 portIndex, OMX_U32* usage) { 344 Mutex::Autolock autoLock(mLock); 345 346 OMX_INDEXTYPE index; 347 OMX_STRING name = const_cast<OMX_STRING>( 348 "OMX.google.android.index.getAndroidNativeBufferUsage"); 349 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 350 351 if (err != OMX_ErrorNone) { 352 ALOGE("OMX_GetExtensionIndex %s failed", name); 353 354 return StatusFromOMXError(err); 355 } 356 357 OMX_VERSIONTYPE ver; 358 ver.s.nVersionMajor = 1; 359 ver.s.nVersionMinor = 0; 360 ver.s.nRevision = 0; 361 ver.s.nStep = 0; 362 GetAndroidNativeBufferUsageParams params = { 363 sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0, 364 }; 365 366 err = OMX_GetParameter(mHandle, index, ¶ms); 367 368 if (err != OMX_ErrorNone) { 369 ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)", 370 err, err); 371 return UNKNOWN_ERROR; 372 } 373 374 *usage = params.nUsage; 375 376 return OK; 377} 378 379status_t OMXNodeInstance::storeMetaDataInBuffers( 380 OMX_U32 portIndex, 381 OMX_BOOL enable) { 382 Mutex::Autolock autolock(mLock); 383 return storeMetaDataInBuffers_l(portIndex, enable); 384} 385 386status_t OMXNodeInstance::storeMetaDataInBuffers_l( 387 OMX_U32 portIndex, 388 OMX_BOOL enable) { 389 OMX_INDEXTYPE index; 390 OMX_STRING name = const_cast<OMX_STRING>( 391 "OMX.google.android.index.storeMetaDataInBuffers"); 392 393 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 394 if (err != OMX_ErrorNone) { 395 ALOGE("OMX_GetExtensionIndex %s failed", name); 396 397 return StatusFromOMXError(err); 398 } 399 400 StoreMetaDataInBuffersParams params; 401 memset(¶ms, 0, sizeof(params)); 402 params.nSize = sizeof(params); 403 404 // Version: 1.0.0.0 405 params.nVersion.s.nVersionMajor = 1; 406 407 params.nPortIndex = portIndex; 408 params.bStoreMetaData = enable; 409 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 410 ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); 411 return UNKNOWN_ERROR; 412 } 413 return err; 414} 415 416status_t OMXNodeInstance::useBuffer( 417 OMX_U32 portIndex, const sp<IMemory> ¶ms, 418 OMX::buffer_id *buffer) { 419 Mutex::Autolock autoLock(mLock); 420 421 BufferMeta *buffer_meta = new BufferMeta(params); 422 423 OMX_BUFFERHEADERTYPE *header; 424 425 OMX_ERRORTYPE err = OMX_UseBuffer( 426 mHandle, &header, portIndex, buffer_meta, 427 params->size(), static_cast<OMX_U8 *>(params->pointer())); 428 429 if (err != OMX_ErrorNone) { 430 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 431 432 delete buffer_meta; 433 buffer_meta = NULL; 434 435 *buffer = 0; 436 437 return UNKNOWN_ERROR; 438 } 439 440 CHECK_EQ(header->pAppPrivate, buffer_meta); 441 442 *buffer = header; 443 444 addActiveBuffer(portIndex, *buffer); 445 446 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 447 if (bufferSource != NULL && portIndex == kPortIndexInput) { 448 bufferSource->addCodecBuffer(header); 449 } 450 451 return OK; 452} 453 454status_t OMXNodeInstance::useGraphicBuffer2_l( 455 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 456 OMX::buffer_id *buffer) { 457 458 // port definition 459 OMX_PARAM_PORTDEFINITIONTYPE def; 460 def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 461 def.nVersion.s.nVersionMajor = 1; 462 def.nVersion.s.nVersionMinor = 0; 463 def.nVersion.s.nRevision = 0; 464 def.nVersion.s.nStep = 0; 465 def.nPortIndex = portIndex; 466 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 467 if (err != OMX_ErrorNone) 468 { 469 ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__); 470 return err; 471 } 472 473 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 474 475 OMX_BUFFERHEADERTYPE *header = NULL; 476 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 477 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 478 479 err = OMX_UseBuffer( 480 mHandle, 481 &header, 482 portIndex, 483 bufferMeta, 484 def.nBufferSize, 485 bufferHandle); 486 487 if (err != OMX_ErrorNone) { 488 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 489 delete bufferMeta; 490 bufferMeta = NULL; 491 *buffer = 0; 492 return UNKNOWN_ERROR; 493 } 494 495 CHECK_EQ(header->pBuffer, bufferHandle); 496 CHECK_EQ(header->pAppPrivate, bufferMeta); 497 498 *buffer = header; 499 500 addActiveBuffer(portIndex, *buffer); 501 502 return OK; 503} 504 505// XXX: This function is here for backwards compatibility. Once the OMX 506// implementations have been updated this can be removed and useGraphicBuffer2 507// can be renamed to useGraphicBuffer. 508status_t OMXNodeInstance::useGraphicBuffer( 509 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 510 OMX::buffer_id *buffer) { 511 Mutex::Autolock autoLock(mLock); 512 513 // See if the newer version of the extension is present. 514 OMX_INDEXTYPE index; 515 if (OMX_GetExtensionIndex( 516 mHandle, 517 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 518 &index) == OMX_ErrorNone) { 519 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 520 } 521 522 OMX_STRING name = const_cast<OMX_STRING>( 523 "OMX.google.android.index.useAndroidNativeBuffer"); 524 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 525 526 if (err != OMX_ErrorNone) { 527 ALOGE("OMX_GetExtensionIndex %s failed", name); 528 529 return StatusFromOMXError(err); 530 } 531 532 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 533 534 OMX_BUFFERHEADERTYPE *header; 535 536 OMX_VERSIONTYPE ver; 537 ver.s.nVersionMajor = 1; 538 ver.s.nVersionMinor = 0; 539 ver.s.nRevision = 0; 540 ver.s.nStep = 0; 541 UseAndroidNativeBufferParams params = { 542 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 543 &header, graphicBuffer, 544 }; 545 546 err = OMX_SetParameter(mHandle, index, ¶ms); 547 548 if (err != OMX_ErrorNone) { 549 ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, 550 err); 551 552 delete bufferMeta; 553 bufferMeta = NULL; 554 555 *buffer = 0; 556 557 return UNKNOWN_ERROR; 558 } 559 560 CHECK_EQ(header->pAppPrivate, bufferMeta); 561 562 *buffer = header; 563 564 addActiveBuffer(portIndex, *buffer); 565 566 return OK; 567} 568 569status_t OMXNodeInstance::createInputSurface( 570 OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) { 571 Mutex::Autolock autolock(mLock); 572 status_t err; 573 574 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); 575 if (surfaceCheck != NULL) { 576 return ALREADY_EXISTS; 577 } 578 579 // Input buffers will hold meta-data (gralloc references). 580 err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE); 581 if (err != OK) { 582 return err; 583 } 584 585 // Retrieve the width and height of the graphic buffer, set when the 586 // codec was configured. 587 OMX_PARAM_PORTDEFINITIONTYPE def; 588 def.nSize = sizeof(def); 589 def.nVersion.s.nVersionMajor = 1; 590 def.nVersion.s.nVersionMinor = 0; 591 def.nVersion.s.nRevision = 0; 592 def.nVersion.s.nStep = 0; 593 def.nPortIndex = portIndex; 594 OMX_ERRORTYPE oerr = OMX_GetParameter( 595 mHandle, OMX_IndexParamPortDefinition, &def); 596 CHECK(oerr == OMX_ErrorNone); 597 598 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 599 ALOGE("createInputSurface requires COLOR_FormatSurface " 600 "(AndroidOpaque) color format"); 601 return INVALID_OPERATION; 602 } 603 604 GraphicBufferSource* bufferSource = new GraphicBufferSource( 605 this, def.format.video.nFrameWidth, def.format.video.nFrameHeight, 606 def.nBufferCountActual); 607 if ((err = bufferSource->initCheck()) != OK) { 608 delete bufferSource; 609 return err; 610 } 611 setGraphicBufferSource(bufferSource); 612 613 *bufferProducer = bufferSource->getIGraphicBufferProducer(); 614 return OK; 615} 616 617status_t OMXNodeInstance::signalEndOfInputStream() { 618 // For non-Surface input, the MediaCodec should convert the call to a 619 // pair of requests (dequeue input buffer, queue input buffer with EOS 620 // flag set). Seems easier than doing the equivalent from here. 621 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 622 if (bufferSource == NULL) { 623 ALOGW("signalEndOfInputStream can only be used with Surface input"); 624 return INVALID_OPERATION; 625 }; 626 return bufferSource->signalEndOfInputStream(); 627} 628 629status_t OMXNodeInstance::allocateBuffer( 630 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 631 void **buffer_data) { 632 Mutex::Autolock autoLock(mLock); 633 634 BufferMeta *buffer_meta = new BufferMeta(size); 635 636 OMX_BUFFERHEADERTYPE *header; 637 638 OMX_ERRORTYPE err = OMX_AllocateBuffer( 639 mHandle, &header, portIndex, buffer_meta, size); 640 641 if (err != OMX_ErrorNone) { 642 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 643 644 delete buffer_meta; 645 buffer_meta = NULL; 646 647 *buffer = 0; 648 649 return UNKNOWN_ERROR; 650 } 651 652 CHECK_EQ(header->pAppPrivate, buffer_meta); 653 654 *buffer = header; 655 *buffer_data = header->pBuffer; 656 657 addActiveBuffer(portIndex, *buffer); 658 659 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 660 if (bufferSource != NULL && portIndex == kPortIndexInput) { 661 bufferSource->addCodecBuffer(header); 662 } 663 664 return OK; 665} 666 667status_t OMXNodeInstance::allocateBufferWithBackup( 668 OMX_U32 portIndex, const sp<IMemory> ¶ms, 669 OMX::buffer_id *buffer) { 670 Mutex::Autolock autoLock(mLock); 671 672 BufferMeta *buffer_meta = new BufferMeta(params, true); 673 674 OMX_BUFFERHEADERTYPE *header; 675 676 OMX_ERRORTYPE err = OMX_AllocateBuffer( 677 mHandle, &header, portIndex, buffer_meta, params->size()); 678 679 if (err != OMX_ErrorNone) { 680 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 681 682 delete buffer_meta; 683 buffer_meta = NULL; 684 685 *buffer = 0; 686 687 return UNKNOWN_ERROR; 688 } 689 690 CHECK_EQ(header->pAppPrivate, buffer_meta); 691 692 *buffer = header; 693 694 addActiveBuffer(portIndex, *buffer); 695 696 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 697 if (bufferSource != NULL && portIndex == kPortIndexInput) { 698 bufferSource->addCodecBuffer(header); 699 } 700 701 return OK; 702} 703 704status_t OMXNodeInstance::freeBuffer( 705 OMX_U32 portIndex, OMX::buffer_id buffer) { 706 Mutex::Autolock autoLock(mLock); 707 708 removeActiveBuffer(portIndex, buffer); 709 710 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 711 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 712 713 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 714 715 delete buffer_meta; 716 buffer_meta = NULL; 717 718 return StatusFromOMXError(err); 719} 720 721status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 722 Mutex::Autolock autoLock(mLock); 723 724 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 725 header->nFilledLen = 0; 726 header->nOffset = 0; 727 header->nFlags = 0; 728 729 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 730 731 return StatusFromOMXError(err); 732} 733 734status_t OMXNodeInstance::emptyBuffer( 735 OMX::buffer_id buffer, 736 OMX_U32 rangeOffset, OMX_U32 rangeLength, 737 OMX_U32 flags, OMX_TICKS timestamp) { 738 Mutex::Autolock autoLock(mLock); 739 740 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 741 header->nFilledLen = rangeLength; 742 header->nOffset = rangeOffset; 743 header->nFlags = flags; 744 header->nTimeStamp = timestamp; 745 746 BufferMeta *buffer_meta = 747 static_cast<BufferMeta *>(header->pAppPrivate); 748 buffer_meta->CopyToOMX(header); 749 750 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 751 752 return StatusFromOMXError(err); 753} 754 755// like emptyBuffer, but the data is already in header->pBuffer 756status_t OMXNodeInstance::emptyDirectBuffer( 757 OMX_BUFFERHEADERTYPE *header, 758 OMX_U32 rangeOffset, OMX_U32 rangeLength, 759 OMX_U32 flags, OMX_TICKS timestamp) { 760 Mutex::Autolock autoLock(mLock); 761 762 header->nFilledLen = rangeLength; 763 header->nOffset = rangeOffset; 764 header->nFlags = flags; 765 header->nTimeStamp = timestamp; 766 767 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 768 if (err != OMX_ErrorNone) { 769 ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err); 770 } 771 772 return StatusFromOMXError(err); 773} 774 775status_t OMXNodeInstance::getExtensionIndex( 776 const char *parameterName, OMX_INDEXTYPE *index) { 777 Mutex::Autolock autoLock(mLock); 778 779 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 780 mHandle, const_cast<char *>(parameterName), index); 781 782 return StatusFromOMXError(err); 783} 784 785status_t OMXNodeInstance::setInternalOption( 786 OMX_U32 portIndex, 787 IOMX::InternalOptionType type, 788 const void *data, 789 size_t size) { 790 switch (type) { 791 case IOMX::INTERNAL_OPTION_SUSPEND: 792 { 793 const sp<GraphicBufferSource> &bufferSource = 794 getGraphicBufferSource(); 795 796 if (bufferSource == NULL || portIndex != kPortIndexInput) { 797 return ERROR_UNSUPPORTED; 798 } 799 800 if (size != sizeof(bool)) { 801 return INVALID_OPERATION; 802 } 803 804 bool suspend = *(bool *)data; 805 bufferSource->suspend(suspend); 806 807 return OK; 808 } 809 810 default: 811 return ERROR_UNSUPPORTED; 812 } 813} 814 815void OMXNodeInstance::onMessage(const omx_message &msg) { 816 if (msg.type == omx_message::FILL_BUFFER_DONE) { 817 OMX_BUFFERHEADERTYPE *buffer = 818 static_cast<OMX_BUFFERHEADERTYPE *>( 819 msg.u.extended_buffer_data.buffer); 820 821 BufferMeta *buffer_meta = 822 static_cast<BufferMeta *>(buffer->pAppPrivate); 823 824 buffer_meta->CopyFromOMX(buffer); 825 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 826 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 827 828 if (bufferSource != NULL) { 829 // This is one of the buffers used exclusively by 830 // GraphicBufferSource. 831 // Don't dispatch a message back to ACodec, since it doesn't 832 // know that anyone asked to have the buffer emptied and will 833 // be very confused. 834 835 OMX_BUFFERHEADERTYPE *buffer = 836 static_cast<OMX_BUFFERHEADERTYPE *>( 837 msg.u.buffer_data.buffer); 838 839 bufferSource->codecBufferEmptied(buffer); 840 return; 841 } 842 } 843 844 mObserver->onMessage(msg); 845} 846 847void OMXNodeInstance::onObserverDied(OMXMaster *master) { 848 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 849 850 // Try to force shutdown of the node and hope for the best. 851 freeNode(master); 852} 853 854void OMXNodeInstance::onGetHandleFailed() { 855 delete this; 856} 857 858// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 859// Don't try to acquire mLock here -- in rare circumstances this will hang. 860void OMXNodeInstance::onEvent( 861 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 862 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 863 864 if (bufferSource != NULL 865 && event == OMX_EventCmdComplete 866 && arg1 == OMX_CommandStateSet 867 && arg2 == OMX_StateExecuting) { 868 bufferSource->omxExecuting(); 869 } 870} 871 872// static 873OMX_ERRORTYPE OMXNodeInstance::OnEvent( 874 OMX_IN OMX_HANDLETYPE hComponent, 875 OMX_IN OMX_PTR pAppData, 876 OMX_IN OMX_EVENTTYPE eEvent, 877 OMX_IN OMX_U32 nData1, 878 OMX_IN OMX_U32 nData2, 879 OMX_IN OMX_PTR pEventData) { 880 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 881 if (instance->mDying) { 882 return OMX_ErrorNone; 883 } 884 return instance->owner()->OnEvent( 885 instance->nodeID(), eEvent, nData1, nData2, pEventData); 886} 887 888// static 889OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 890 OMX_IN OMX_HANDLETYPE hComponent, 891 OMX_IN OMX_PTR pAppData, 892 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 893 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 894 if (instance->mDying) { 895 return OMX_ErrorNone; 896 } 897 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 898} 899 900// static 901OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 902 OMX_IN OMX_HANDLETYPE hComponent, 903 OMX_IN OMX_PTR pAppData, 904 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 905 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 906 if (instance->mDying) { 907 return OMX_ErrorNone; 908 } 909 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 910} 911 912void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 913 ActiveBuffer active; 914 active.mPortIndex = portIndex; 915 active.mID = id; 916 mActiveBuffers.push(active); 917} 918 919void OMXNodeInstance::removeActiveBuffer( 920 OMX_U32 portIndex, OMX::buffer_id id) { 921 bool found = false; 922 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 923 if (mActiveBuffers[i].mPortIndex == portIndex 924 && mActiveBuffers[i].mID == id) { 925 found = true; 926 mActiveBuffers.removeItemsAt(i); 927 break; 928 } 929 } 930 931 if (!found) { 932 ALOGW("Attempt to remove an active buffer we know nothing about..."); 933 } 934} 935 936void OMXNodeInstance::freeActiveBuffers() { 937 // Make sure to count down here, as freeBuffer will in turn remove 938 // the active buffer from the vector... 939 for (size_t i = mActiveBuffers.size(); i--;) { 940 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 941 } 942} 943 944} // namespace android 945