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