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