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