OMXNodeInstance.cpp revision 30358faf33fb9b638257b017fadb4c5f7352d903
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 73 void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { 74 mGraphicBuffer = graphicBuffer; 75 } 76 77private: 78 sp<GraphicBuffer> mGraphicBuffer; 79 sp<IMemory> mMem; 80 size_t mSize; 81 bool mIsBackup; 82 83 BufferMeta(const BufferMeta &); 84 BufferMeta &operator=(const BufferMeta &); 85}; 86 87// static 88OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 89 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 90}; 91 92OMXNodeInstance::OMXNodeInstance( 93 OMX *owner, const sp<IOMXObserver> &observer) 94 : mOwner(owner), 95 mNodeID(0), 96 mHandle(NULL), 97 mObserver(observer), 98 mDying(false) 99#ifdef __LP64__ 100 , mBufferIDCount(0) 101#endif 102{ 103} 104 105OMXNodeInstance::~OMXNodeInstance() { 106 CHECK(mHandle == NULL); 107} 108 109void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 110 CHECK(mHandle == NULL); 111 mNodeID = node_id; 112 mHandle = handle; 113} 114 115sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() { 116 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 117 return mGraphicBufferSource; 118} 119 120void OMXNodeInstance::setGraphicBufferSource( 121 const sp<GraphicBufferSource>& bufferSource) { 122 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 123 mGraphicBufferSource = bufferSource; 124} 125 126OMX *OMXNodeInstance::owner() { 127 return mOwner; 128} 129 130sp<IOMXObserver> OMXNodeInstance::observer() { 131 return mObserver; 132} 133 134OMX::node_id OMXNodeInstance::nodeID() { 135 return mNodeID; 136} 137 138static status_t StatusFromOMXError(OMX_ERRORTYPE err) { 139 switch (err) { 140 case OMX_ErrorNone: 141 return OK; 142 case OMX_ErrorUnsupportedSetting: 143 return ERROR_UNSUPPORTED; 144 default: 145 return UNKNOWN_ERROR; 146 } 147} 148 149status_t OMXNodeInstance::freeNode(OMXMaster *master) { 150 static int32_t kMaxNumIterations = 10; 151 152 // exit if we have already freed the node 153 if (mHandle == NULL) { 154 return OK; 155 } 156 157 // Transition the node from its current state all the way down 158 // to "Loaded". 159 // This ensures that all active buffers are properly freed even 160 // for components that don't do this themselves on a call to 161 // "FreeHandle". 162 163 // The code below may trigger some more events to be dispatched 164 // by the OMX component - we want to ignore them as our client 165 // does not expect them. 166 mDying = true; 167 168 OMX_STATETYPE state; 169 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 170 switch (state) { 171 case OMX_StateExecuting: 172 { 173 ALOGV("forcing Executing->Idle"); 174 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 175 OMX_ERRORTYPE err; 176 int32_t iteration = 0; 177 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 178 && state != OMX_StateIdle 179 && state != OMX_StateInvalid) { 180 if (++iteration > kMaxNumIterations) { 181 ALOGE("component failed to enter Idle state, aborting."); 182 state = OMX_StateInvalid; 183 break; 184 } 185 186 usleep(100000); 187 } 188 CHECK_EQ(err, OMX_ErrorNone); 189 190 if (state == OMX_StateInvalid) { 191 break; 192 } 193 194 // fall through 195 } 196 197 case OMX_StateIdle: 198 { 199 ALOGV("forcing Idle->Loaded"); 200 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 201 202 freeActiveBuffers(); 203 204 OMX_ERRORTYPE err; 205 int32_t iteration = 0; 206 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 207 && state != OMX_StateLoaded 208 && state != OMX_StateInvalid) { 209 if (++iteration > kMaxNumIterations) { 210 ALOGE("component failed to enter Loaded state, aborting."); 211 state = OMX_StateInvalid; 212 break; 213 } 214 215 ALOGV("waiting for Loaded state..."); 216 usleep(100000); 217 } 218 CHECK_EQ(err, OMX_ErrorNone); 219 220 // fall through 221 } 222 223 case OMX_StateLoaded: 224 case OMX_StateInvalid: 225 break; 226 227 default: 228 CHECK(!"should not be here, unknown state."); 229 break; 230 } 231 232 ALOGV("calling destroyComponentInstance"); 233 OMX_ERRORTYPE err = master->destroyComponentInstance( 234 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 235 ALOGV("destroyComponentInstance returned err %d", err); 236 237 mHandle = NULL; 238 239 if (err != OMX_ErrorNone) { 240 ALOGE("FreeHandle FAILED with error 0x%08x.", err); 241 } 242 243 mOwner->invalidateNodeID(mNodeID); 244 mNodeID = 0; 245 246 ALOGV("OMXNodeInstance going away."); 247 delete this; 248 249 return StatusFromOMXError(err); 250} 251 252status_t OMXNodeInstance::sendCommand( 253 OMX_COMMANDTYPE cmd, OMX_S32 param) { 254 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 255 if (bufferSource != NULL && cmd == OMX_CommandStateSet) { 256 if (param == OMX_StateIdle) { 257 // Initiating transition from Executing -> Idle 258 // ACodec is waiting for all buffers to be returned, do NOT 259 // submit any more buffers to the codec. 260 bufferSource->omxIdle(); 261 } else if (param == OMX_StateLoaded) { 262 // Initiating transition from Idle/Executing -> Loaded 263 // Buffers are about to be freed. 264 bufferSource->omxLoaded(); 265 setGraphicBufferSource(NULL); 266 } 267 268 // fall through 269 } 270 271 Mutex::Autolock autoLock(mLock); 272 273 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 274 return StatusFromOMXError(err); 275} 276 277status_t OMXNodeInstance::getParameter( 278 OMX_INDEXTYPE index, void *params, size_t /* size */) { 279 Mutex::Autolock autoLock(mLock); 280 281 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 282 ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err); 283 return StatusFromOMXError(err); 284} 285 286status_t OMXNodeInstance::setParameter( 287 OMX_INDEXTYPE index, const void *params, size_t /* size */) { 288 Mutex::Autolock autoLock(mLock); 289 290 OMX_ERRORTYPE err = OMX_SetParameter( 291 mHandle, index, const_cast<void *>(params)); 292 ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err); 293 return StatusFromOMXError(err); 294} 295 296status_t OMXNodeInstance::getConfig( 297 OMX_INDEXTYPE index, void *params, size_t /* size */) { 298 Mutex::Autolock autoLock(mLock); 299 300 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 301 return StatusFromOMXError(err); 302} 303 304status_t OMXNodeInstance::setConfig( 305 OMX_INDEXTYPE index, const void *params, size_t /* size */) { 306 Mutex::Autolock autoLock(mLock); 307 308 OMX_ERRORTYPE err = OMX_SetConfig( 309 mHandle, index, const_cast<void *>(params)); 310 311 return StatusFromOMXError(err); 312} 313 314status_t OMXNodeInstance::getState(OMX_STATETYPE* state) { 315 Mutex::Autolock autoLock(mLock); 316 317 OMX_ERRORTYPE err = OMX_GetState(mHandle, state); 318 319 return StatusFromOMXError(err); 320} 321 322status_t OMXNodeInstance::enableGraphicBuffers( 323 OMX_U32 portIndex, OMX_BOOL enable) { 324 Mutex::Autolock autoLock(mLock); 325 OMX_STRING name = const_cast<OMX_STRING>( 326 "OMX.google.android.index.enableAndroidNativeBuffers"); 327 328 OMX_INDEXTYPE index; 329 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 330 331 if (err != OMX_ErrorNone) { 332 if (enable) { 333 ALOGE("OMX_GetExtensionIndex %s failed", name); 334 } 335 336 return StatusFromOMXError(err); 337 } 338 339 OMX_VERSIONTYPE ver; 340 ver.s.nVersionMajor = 1; 341 ver.s.nVersionMinor = 0; 342 ver.s.nRevision = 0; 343 ver.s.nStep = 0; 344 EnableAndroidNativeBuffersParams params = { 345 sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable, 346 }; 347 348 err = OMX_SetParameter(mHandle, index, ¶ms); 349 350 if (err != OMX_ErrorNone) { 351 ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)", 352 err, err); 353 354 return UNKNOWN_ERROR; 355 } 356 357 return OK; 358} 359 360status_t OMXNodeInstance::getGraphicBufferUsage( 361 OMX_U32 portIndex, OMX_U32* usage) { 362 Mutex::Autolock autoLock(mLock); 363 364 OMX_INDEXTYPE index; 365 OMX_STRING name = const_cast<OMX_STRING>( 366 "OMX.google.android.index.getAndroidNativeBufferUsage"); 367 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 368 369 if (err != OMX_ErrorNone) { 370 ALOGE("OMX_GetExtensionIndex %s failed", name); 371 372 return StatusFromOMXError(err); 373 } 374 375 OMX_VERSIONTYPE ver; 376 ver.s.nVersionMajor = 1; 377 ver.s.nVersionMinor = 0; 378 ver.s.nRevision = 0; 379 ver.s.nStep = 0; 380 GetAndroidNativeBufferUsageParams params = { 381 sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0, 382 }; 383 384 err = OMX_GetParameter(mHandle, index, ¶ms); 385 386 if (err != OMX_ErrorNone) { 387 ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)", 388 err, err); 389 return UNKNOWN_ERROR; 390 } 391 392 *usage = params.nUsage; 393 394 return OK; 395} 396 397status_t OMXNodeInstance::storeMetaDataInBuffers( 398 OMX_U32 portIndex, 399 OMX_BOOL enable) { 400 Mutex::Autolock autolock(mLock); 401 return storeMetaDataInBuffers_l( 402 portIndex, enable, 403 OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */); 404} 405 406status_t OMXNodeInstance::storeMetaDataInBuffers_l( 407 OMX_U32 portIndex, 408 OMX_BOOL enable, 409 OMX_BOOL useGraphicBuffer, 410 OMX_BOOL *usingGraphicBufferInMetadata) { 411 OMX_INDEXTYPE index; 412 OMX_STRING name = const_cast<OMX_STRING>( 413 "OMX.google.android.index.storeMetaDataInBuffers"); 414 415 OMX_STRING graphicBufferName = const_cast<OMX_STRING>( 416 "OMX.google.android.index.storeGraphicBufferInMetaData"); 417 if (usingGraphicBufferInMetadata == NULL) { 418 usingGraphicBufferInMetadata = &useGraphicBuffer; 419 } 420 421 OMX_ERRORTYPE err = 422 (useGraphicBuffer && portIndex == kPortIndexInput) 423 ? OMX_GetExtensionIndex(mHandle, graphicBufferName, &index) 424 : OMX_ErrorBadParameter; 425 if (err == OMX_ErrorNone) { 426 *usingGraphicBufferInMetadata = OMX_TRUE; 427 } else { 428 *usingGraphicBufferInMetadata = OMX_FALSE; 429 err = OMX_GetExtensionIndex(mHandle, name, &index); 430 } 431 432 if (err != OMX_ErrorNone) { 433 ALOGE("OMX_GetExtensionIndex %s failed", name); 434 return StatusFromOMXError(err); 435 } 436 437 StoreMetaDataInBuffersParams params; 438 memset(¶ms, 0, sizeof(params)); 439 params.nSize = sizeof(params); 440 441 // Version: 1.0.0.0 442 params.nVersion.s.nVersionMajor = 1; 443 444 params.nPortIndex = portIndex; 445 params.bStoreMetaData = enable; 446 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 447 ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); 448 *usingGraphicBufferInMetadata = OMX_FALSE; 449 return UNKNOWN_ERROR; 450 } 451 return err; 452} 453 454status_t OMXNodeInstance::prepareForAdaptivePlayback( 455 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, 456 OMX_U32 maxFrameHeight) { 457 Mutex::Autolock autolock(mLock); 458 459 OMX_INDEXTYPE index; 460 OMX_STRING name = const_cast<OMX_STRING>( 461 "OMX.google.android.index.prepareForAdaptivePlayback"); 462 463 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 464 if (err != OMX_ErrorNone) { 465 ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name); 466 return StatusFromOMXError(err); 467 } 468 469 PrepareForAdaptivePlaybackParams params; 470 params.nSize = sizeof(params); 471 params.nVersion.s.nVersionMajor = 1; 472 params.nVersion.s.nVersionMinor = 0; 473 params.nVersion.s.nRevision = 0; 474 params.nVersion.s.nStep = 0; 475 476 params.nPortIndex = portIndex; 477 params.bEnable = enable; 478 params.nMaxFrameWidth = maxFrameWidth; 479 params.nMaxFrameHeight = maxFrameHeight; 480 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 481 ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback " 482 "with error %d (0x%08x)", err, err); 483 return UNKNOWN_ERROR; 484 } 485 return err; 486} 487 488status_t OMXNodeInstance::configureVideoTunnelMode( 489 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, 490 native_handle_t **sidebandHandle) { 491 Mutex::Autolock autolock(mLock); 492 493 OMX_INDEXTYPE index; 494 OMX_STRING name = const_cast<OMX_STRING>( 495 "OMX.google.android.index.configureVideoTunnelMode"); 496 497 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 498 if (err != OMX_ErrorNone) { 499 ALOGE("configureVideoTunnelMode extension is missing!"); 500 return StatusFromOMXError(err); 501 } 502 503 ConfigureVideoTunnelModeParams tunnelParams; 504 tunnelParams.nSize = sizeof(tunnelParams); 505 tunnelParams.nVersion.s.nVersionMajor = 1; 506 tunnelParams.nVersion.s.nVersionMinor = 0; 507 tunnelParams.nVersion.s.nRevision = 0; 508 tunnelParams.nVersion.s.nStep = 0; 509 510 tunnelParams.nPortIndex = portIndex; 511 tunnelParams.bTunneled = tunneled; 512 tunnelParams.nAudioHwSync = audioHwSync; 513 err = OMX_SetParameter(mHandle, index, &tunnelParams); 514 if (err != OMX_ErrorNone) { 515 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 516 return UNKNOWN_ERROR; 517 } 518 519 err = OMX_GetParameter(mHandle, index, &tunnelParams); 520 if (err != OMX_ErrorNone) { 521 ALOGE("GetVideoTunnelWindow failed! (err %d).", err); 522 return UNKNOWN_ERROR; 523 } 524 if (sidebandHandle) { 525 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; 526 } 527 528 return err; 529} 530 531status_t OMXNodeInstance::useBuffer( 532 OMX_U32 portIndex, const sp<IMemory> ¶ms, 533 OMX::buffer_id *buffer) { 534 Mutex::Autolock autoLock(mLock); 535 536 BufferMeta *buffer_meta = new BufferMeta(params); 537 538 OMX_BUFFERHEADERTYPE *header; 539 540 OMX_ERRORTYPE err = OMX_UseBuffer( 541 mHandle, &header, portIndex, buffer_meta, 542 params->size(), static_cast<OMX_U8 *>(params->pointer())); 543 544 if (err != OMX_ErrorNone) { 545 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 546 547 delete buffer_meta; 548 buffer_meta = NULL; 549 550 *buffer = 0; 551 552 return UNKNOWN_ERROR; 553 } 554 555 CHECK_EQ(header->pAppPrivate, buffer_meta); 556 557 *buffer = makeBufferID(header); 558 559 addActiveBuffer(portIndex, *buffer); 560 561 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 562 if (bufferSource != NULL && portIndex == kPortIndexInput) { 563 bufferSource->addCodecBuffer(header); 564 } 565 566 return OK; 567} 568 569status_t OMXNodeInstance::useGraphicBuffer2_l( 570 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 571 OMX::buffer_id *buffer) { 572 573 // port definition 574 OMX_PARAM_PORTDEFINITIONTYPE def; 575 def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 576 def.nVersion.s.nVersionMajor = 1; 577 def.nVersion.s.nVersionMinor = 0; 578 def.nVersion.s.nRevision = 0; 579 def.nVersion.s.nStep = 0; 580 def.nPortIndex = portIndex; 581 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 582 if (err != OMX_ErrorNone) 583 { 584 ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__); 585 return err; 586 } 587 588 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 589 590 OMX_BUFFERHEADERTYPE *header = NULL; 591 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 592 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 593 594 err = OMX_UseBuffer( 595 mHandle, 596 &header, 597 portIndex, 598 bufferMeta, 599 def.nBufferSize, 600 bufferHandle); 601 602 if (err != OMX_ErrorNone) { 603 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 604 delete bufferMeta; 605 bufferMeta = NULL; 606 *buffer = 0; 607 return UNKNOWN_ERROR; 608 } 609 610 CHECK_EQ(header->pBuffer, bufferHandle); 611 CHECK_EQ(header->pAppPrivate, bufferMeta); 612 613 *buffer = makeBufferID(header); 614 615 addActiveBuffer(portIndex, *buffer); 616 617 return OK; 618} 619 620// XXX: This function is here for backwards compatibility. Once the OMX 621// implementations have been updated this can be removed and useGraphicBuffer2 622// can be renamed to useGraphicBuffer. 623status_t OMXNodeInstance::useGraphicBuffer( 624 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 625 OMX::buffer_id *buffer) { 626 Mutex::Autolock autoLock(mLock); 627 628 // See if the newer version of the extension is present. 629 OMX_INDEXTYPE index; 630 if (OMX_GetExtensionIndex( 631 mHandle, 632 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 633 &index) == OMX_ErrorNone) { 634 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 635 } 636 637 OMX_STRING name = const_cast<OMX_STRING>( 638 "OMX.google.android.index.useAndroidNativeBuffer"); 639 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 640 641 if (err != OMX_ErrorNone) { 642 ALOGE("OMX_GetExtensionIndex %s failed", name); 643 644 return StatusFromOMXError(err); 645 } 646 647 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 648 649 OMX_BUFFERHEADERTYPE *header; 650 651 OMX_VERSIONTYPE ver; 652 ver.s.nVersionMajor = 1; 653 ver.s.nVersionMinor = 0; 654 ver.s.nRevision = 0; 655 ver.s.nStep = 0; 656 UseAndroidNativeBufferParams params = { 657 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 658 &header, graphicBuffer, 659 }; 660 661 err = OMX_SetParameter(mHandle, index, ¶ms); 662 663 if (err != OMX_ErrorNone) { 664 ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, 665 err); 666 667 delete bufferMeta; 668 bufferMeta = NULL; 669 670 *buffer = 0; 671 672 return UNKNOWN_ERROR; 673 } 674 675 CHECK_EQ(header->pAppPrivate, bufferMeta); 676 677 *buffer = makeBufferID(header); 678 679 addActiveBuffer(portIndex, *buffer); 680 681 return OK; 682} 683 684status_t OMXNodeInstance::updateGraphicBufferInMeta( 685 OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer, 686 OMX::buffer_id buffer) { 687 Mutex::Autolock autoLock(mLock); 688 689 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 690 VideoDecoderOutputMetaData *metadata = 691 (VideoDecoderOutputMetaData *)(header->pBuffer); 692 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 693 bufferMeta->setGraphicBuffer(graphicBuffer); 694 metadata->eType = kMetadataBufferTypeGrallocSource; 695 metadata->pHandle = graphicBuffer->handle; 696 697 return OK; 698} 699 700status_t OMXNodeInstance::createInputSurface( 701 OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) { 702 Mutex::Autolock autolock(mLock); 703 status_t err; 704 705 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); 706 if (surfaceCheck != NULL) { 707 return ALREADY_EXISTS; 708 } 709 710 // Input buffers will hold meta-data (gralloc references). 711 OMX_BOOL usingGraphicBuffer = OMX_FALSE; 712 err = storeMetaDataInBuffers_l( 713 portIndex, OMX_TRUE, 714 OMX_TRUE /* useGraphicBuffer */, &usingGraphicBuffer); 715 if (err != OK) { 716 return err; 717 } 718 719 // Retrieve the width and height of the graphic buffer, set when the 720 // codec was configured. 721 OMX_PARAM_PORTDEFINITIONTYPE def; 722 def.nSize = sizeof(def); 723 def.nVersion.s.nVersionMajor = 1; 724 def.nVersion.s.nVersionMinor = 0; 725 def.nVersion.s.nRevision = 0; 726 def.nVersion.s.nStep = 0; 727 def.nPortIndex = portIndex; 728 OMX_ERRORTYPE oerr = OMX_GetParameter( 729 mHandle, OMX_IndexParamPortDefinition, &def); 730 CHECK(oerr == OMX_ErrorNone); 731 732 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 733 ALOGE("createInputSurface requires COLOR_FormatSurface " 734 "(AndroidOpaque) color format"); 735 return INVALID_OPERATION; 736 } 737 738 GraphicBufferSource* bufferSource = new GraphicBufferSource( 739 this, def.format.video.nFrameWidth, def.format.video.nFrameHeight, 740 def.nBufferCountActual, usingGraphicBuffer); 741 if ((err = bufferSource->initCheck()) != OK) { 742 delete bufferSource; 743 return err; 744 } 745 setGraphicBufferSource(bufferSource); 746 747 *bufferProducer = bufferSource->getIGraphicBufferProducer(); 748 return OK; 749} 750 751status_t OMXNodeInstance::signalEndOfInputStream() { 752 // For non-Surface input, the MediaCodec should convert the call to a 753 // pair of requests (dequeue input buffer, queue input buffer with EOS 754 // flag set). Seems easier than doing the equivalent from here. 755 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 756 if (bufferSource == NULL) { 757 ALOGW("signalEndOfInputStream can only be used with Surface input"); 758 return INVALID_OPERATION; 759 }; 760 return bufferSource->signalEndOfInputStream(); 761} 762 763status_t OMXNodeInstance::allocateBuffer( 764 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 765 void **buffer_data) { 766 Mutex::Autolock autoLock(mLock); 767 768 BufferMeta *buffer_meta = new BufferMeta(size); 769 770 OMX_BUFFERHEADERTYPE *header; 771 772 OMX_ERRORTYPE err = OMX_AllocateBuffer( 773 mHandle, &header, portIndex, buffer_meta, size); 774 775 if (err != OMX_ErrorNone) { 776 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 777 778 delete buffer_meta; 779 buffer_meta = NULL; 780 781 *buffer = 0; 782 783 return UNKNOWN_ERROR; 784 } 785 786 CHECK_EQ(header->pAppPrivate, buffer_meta); 787 788 *buffer = makeBufferID(header); 789 *buffer_data = header->pBuffer; 790 791 addActiveBuffer(portIndex, *buffer); 792 793 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 794 if (bufferSource != NULL && portIndex == kPortIndexInput) { 795 bufferSource->addCodecBuffer(header); 796 } 797 798 return OK; 799} 800 801status_t OMXNodeInstance::allocateBufferWithBackup( 802 OMX_U32 portIndex, const sp<IMemory> ¶ms, 803 OMX::buffer_id *buffer) { 804 Mutex::Autolock autoLock(mLock); 805 806 BufferMeta *buffer_meta = new BufferMeta(params, true); 807 808 OMX_BUFFERHEADERTYPE *header; 809 810 OMX_ERRORTYPE err = OMX_AllocateBuffer( 811 mHandle, &header, portIndex, buffer_meta, params->size()); 812 813 if (err != OMX_ErrorNone) { 814 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 815 816 delete buffer_meta; 817 buffer_meta = NULL; 818 819 *buffer = 0; 820 821 return UNKNOWN_ERROR; 822 } 823 824 CHECK_EQ(header->pAppPrivate, buffer_meta); 825 826 *buffer = makeBufferID(header); 827 828 addActiveBuffer(portIndex, *buffer); 829 830 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 831 if (bufferSource != NULL && portIndex == kPortIndexInput) { 832 bufferSource->addCodecBuffer(header); 833 } 834 835 return OK; 836} 837 838status_t OMXNodeInstance::freeBuffer( 839 OMX_U32 portIndex, OMX::buffer_id buffer) { 840 Mutex::Autolock autoLock(mLock); 841 842 removeActiveBuffer(portIndex, buffer); 843 844 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 845 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 846 847 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 848 849 delete buffer_meta; 850 buffer_meta = NULL; 851 invalidateBufferID(buffer); 852 853 return StatusFromOMXError(err); 854} 855 856status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 857 Mutex::Autolock autoLock(mLock); 858 859 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 860 header->nFilledLen = 0; 861 header->nOffset = 0; 862 header->nFlags = 0; 863 864 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 865 866 return StatusFromOMXError(err); 867} 868 869status_t OMXNodeInstance::emptyBuffer( 870 OMX::buffer_id buffer, 871 OMX_U32 rangeOffset, OMX_U32 rangeLength, 872 OMX_U32 flags, OMX_TICKS timestamp) { 873 Mutex::Autolock autoLock(mLock); 874 875 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 876 header->nFilledLen = rangeLength; 877 header->nOffset = rangeOffset; 878 header->nFlags = flags; 879 header->nTimeStamp = timestamp; 880 881 BufferMeta *buffer_meta = 882 static_cast<BufferMeta *>(header->pAppPrivate); 883 buffer_meta->CopyToOMX(header); 884 885 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 886 887 return StatusFromOMXError(err); 888} 889 890// like emptyBuffer, but the data is already in header->pBuffer 891status_t OMXNodeInstance::emptyDirectBuffer( 892 OMX_BUFFERHEADERTYPE *header, 893 OMX_U32 rangeOffset, OMX_U32 rangeLength, 894 OMX_U32 flags, OMX_TICKS timestamp) { 895 Mutex::Autolock autoLock(mLock); 896 897 header->nFilledLen = rangeLength; 898 header->nOffset = rangeOffset; 899 header->nFlags = flags; 900 header->nTimeStamp = timestamp; 901 902 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 903 if (err != OMX_ErrorNone) { 904 ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err); 905 } 906 907 return StatusFromOMXError(err); 908} 909 910status_t OMXNodeInstance::getExtensionIndex( 911 const char *parameterName, OMX_INDEXTYPE *index) { 912 Mutex::Autolock autoLock(mLock); 913 914 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 915 mHandle, const_cast<char *>(parameterName), index); 916 917 return StatusFromOMXError(err); 918} 919 920status_t OMXNodeInstance::setInternalOption( 921 OMX_U32 portIndex, 922 IOMX::InternalOptionType type, 923 const void *data, 924 size_t size) { 925 switch (type) { 926 case IOMX::INTERNAL_OPTION_SUSPEND: 927 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 928 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: 929 case IOMX::INTERNAL_OPTION_START_TIME: 930 case IOMX::INTERNAL_OPTION_TIME_LAPSE: 931 { 932 const sp<GraphicBufferSource> &bufferSource = 933 getGraphicBufferSource(); 934 935 if (bufferSource == NULL || portIndex != kPortIndexInput) { 936 return ERROR_UNSUPPORTED; 937 } 938 939 if (type == IOMX::INTERNAL_OPTION_SUSPEND) { 940 if (size != sizeof(bool)) { 941 return INVALID_OPERATION; 942 } 943 944 bool suspend = *(bool *)data; 945 bufferSource->suspend(suspend); 946 } else if (type == 947 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){ 948 if (size != sizeof(int64_t)) { 949 return INVALID_OPERATION; 950 } 951 952 int64_t delayUs = *(int64_t *)data; 953 954 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs); 955 } else if (type == 956 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){ 957 if (size != sizeof(int64_t)) { 958 return INVALID_OPERATION; 959 } 960 961 int64_t maxGapUs = *(int64_t *)data; 962 963 return bufferSource->setMaxTimestampGapUs(maxGapUs); 964 } else if (type == IOMX::INTERNAL_OPTION_START_TIME) { 965 if (size != sizeof(int64_t)) { 966 return INVALID_OPERATION; 967 } 968 969 int64_t skipFramesBeforeUs = *(int64_t *)data; 970 971 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs); 972 } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE 973 if (size != sizeof(int64_t) * 2) { 974 return INVALID_OPERATION; 975 } 976 977 bufferSource->setTimeLapseUs((int64_t *)data); 978 } 979 980 return OK; 981 } 982 983 default: 984 return ERROR_UNSUPPORTED; 985 } 986} 987 988void OMXNodeInstance::onMessage(const omx_message &msg) { 989 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 990 991 if (msg.type == omx_message::FILL_BUFFER_DONE) { 992 OMX_BUFFERHEADERTYPE *buffer = 993 findBufferHeader(msg.u.extended_buffer_data.buffer); 994 995 BufferMeta *buffer_meta = 996 static_cast<BufferMeta *>(buffer->pAppPrivate); 997 998 buffer_meta->CopyFromOMX(buffer); 999 1000 if (bufferSource != NULL) { 1001 // fix up the buffer info (especially timestamp) if needed 1002 bufferSource->codecBufferFilled(buffer); 1003 1004 omx_message newMsg = msg; 1005 newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp; 1006 mObserver->onMessage(newMsg); 1007 return; 1008 } 1009 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 1010 if (bufferSource != NULL) { 1011 // This is one of the buffers used exclusively by 1012 // GraphicBufferSource. 1013 // Don't dispatch a message back to ACodec, since it doesn't 1014 // know that anyone asked to have the buffer emptied and will 1015 // be very confused. 1016 1017 OMX_BUFFERHEADERTYPE *buffer = 1018 findBufferHeader(msg.u.buffer_data.buffer); 1019 1020 bufferSource->codecBufferEmptied(buffer); 1021 return; 1022 } 1023 } 1024 1025 mObserver->onMessage(msg); 1026} 1027 1028void OMXNodeInstance::onObserverDied(OMXMaster *master) { 1029 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 1030 1031 // Try to force shutdown of the node and hope for the best. 1032 freeNode(master); 1033} 1034 1035void OMXNodeInstance::onGetHandleFailed() { 1036 delete this; 1037} 1038 1039// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 1040// Don't try to acquire mLock here -- in rare circumstances this will hang. 1041void OMXNodeInstance::onEvent( 1042 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 1043 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1044 1045 if (bufferSource != NULL 1046 && event == OMX_EventCmdComplete 1047 && arg1 == OMX_CommandStateSet 1048 && arg2 == OMX_StateExecuting) { 1049 bufferSource->omxExecuting(); 1050 } 1051} 1052 1053// static 1054OMX_ERRORTYPE OMXNodeInstance::OnEvent( 1055 OMX_IN OMX_HANDLETYPE /* hComponent */, 1056 OMX_IN OMX_PTR pAppData, 1057 OMX_IN OMX_EVENTTYPE eEvent, 1058 OMX_IN OMX_U32 nData1, 1059 OMX_IN OMX_U32 nData2, 1060 OMX_IN OMX_PTR pEventData) { 1061 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1062 if (instance->mDying) { 1063 return OMX_ErrorNone; 1064 } 1065 return instance->owner()->OnEvent( 1066 instance->nodeID(), eEvent, nData1, nData2, pEventData); 1067} 1068 1069// static 1070OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 1071 OMX_IN OMX_HANDLETYPE /* hComponent */, 1072 OMX_IN OMX_PTR pAppData, 1073 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1074 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1075 if (instance->mDying) { 1076 return OMX_ErrorNone; 1077 } 1078 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), 1079 instance->findBufferID(pBuffer), pBuffer); 1080} 1081 1082// static 1083OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 1084 OMX_IN OMX_HANDLETYPE /* hComponent */, 1085 OMX_IN OMX_PTR pAppData, 1086 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1087 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1088 if (instance->mDying) { 1089 return OMX_ErrorNone; 1090 } 1091 return instance->owner()->OnFillBufferDone(instance->nodeID(), 1092 instance->findBufferID(pBuffer), pBuffer); 1093} 1094 1095void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 1096 ActiveBuffer active; 1097 active.mPortIndex = portIndex; 1098 active.mID = id; 1099 mActiveBuffers.push(active); 1100} 1101 1102void OMXNodeInstance::removeActiveBuffer( 1103 OMX_U32 portIndex, OMX::buffer_id id) { 1104 bool found = false; 1105 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 1106 if (mActiveBuffers[i].mPortIndex == portIndex 1107 && mActiveBuffers[i].mID == id) { 1108 found = true; 1109 mActiveBuffers.removeItemsAt(i); 1110 break; 1111 } 1112 } 1113 1114 if (!found) { 1115 ALOGW("Attempt to remove an active buffer we know nothing about..."); 1116 } 1117} 1118 1119void OMXNodeInstance::freeActiveBuffers() { 1120 // Make sure to count down here, as freeBuffer will in turn remove 1121 // the active buffer from the vector... 1122 for (size_t i = mActiveBuffers.size(); i--;) { 1123 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 1124 } 1125} 1126 1127#ifdef __LP64__ 1128 1129OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1130 if (bufferHeader == NULL) { 1131 return 0; 1132 } 1133 Mutex::Autolock autoLock(mBufferIDLock); 1134 OMX::buffer_id buffer; 1135 do { // handle the very unlikely case of ID overflow 1136 if (++mBufferIDCount == 0) { 1137 ++mBufferIDCount; 1138 } 1139 buffer = (OMX::buffer_id)mBufferIDCount; 1140 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); 1141 mBufferIDToBufferHeader.add(buffer, bufferHeader); 1142 mBufferHeaderToBufferID.add(bufferHeader, buffer); 1143 return buffer; 1144} 1145 1146OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { 1147 if (buffer == 0) { 1148 return NULL; 1149 } 1150 Mutex::Autolock autoLock(mBufferIDLock); 1151 return mBufferIDToBufferHeader.valueFor(buffer); 1152} 1153 1154OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1155 if (bufferHeader == NULL) { 1156 return 0; 1157 } 1158 Mutex::Autolock autoLock(mBufferIDLock); 1159 return mBufferHeaderToBufferID.valueFor(bufferHeader); 1160} 1161 1162void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) { 1163 if (buffer == 0) { 1164 return; 1165 } 1166 Mutex::Autolock autoLock(mBufferIDLock); 1167 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer)); 1168 mBufferIDToBufferHeader.removeItem(buffer); 1169} 1170 1171#else 1172 1173OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1174 return (OMX::buffer_id)bufferHeader; 1175} 1176 1177OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { 1178 return (OMX_BUFFERHEADERTYPE *)buffer; 1179} 1180 1181OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1182 return (OMX::buffer_id)bufferHeader; 1183} 1184 1185void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) { 1186} 1187 1188#endif 1189 1190} // namespace android 1191