OMXNodeInstance.cpp revision 5a446aafff3020d607ad6fb14cc7ae76dd8f7947
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(portIndex, enable); 397} 398 399status_t OMXNodeInstance::storeMetaDataInBuffers_l( 400 OMX_U32 portIndex, 401 OMX_BOOL enable) { 402 OMX_INDEXTYPE index; 403 OMX_STRING name = const_cast<OMX_STRING>( 404 "OMX.google.android.index.storeMetaDataInBuffers"); 405 406 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 407 if (err != OMX_ErrorNone) { 408 ALOGE("OMX_GetExtensionIndex %s failed", name); 409 410 return StatusFromOMXError(err); 411 } 412 413 StoreMetaDataInBuffersParams params; 414 memset(¶ms, 0, sizeof(params)); 415 params.nSize = sizeof(params); 416 417 // Version: 1.0.0.0 418 params.nVersion.s.nVersionMajor = 1; 419 420 params.nPortIndex = portIndex; 421 params.bStoreMetaData = enable; 422 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 423 ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); 424 return UNKNOWN_ERROR; 425 } 426 return err; 427} 428 429status_t OMXNodeInstance::prepareForAdaptivePlayback( 430 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, 431 OMX_U32 maxFrameHeight) { 432 Mutex::Autolock autolock(mLock); 433 434 OMX_INDEXTYPE index; 435 OMX_STRING name = const_cast<OMX_STRING>( 436 "OMX.google.android.index.prepareForAdaptivePlayback"); 437 438 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 439 if (err != OMX_ErrorNone) { 440 ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name); 441 return StatusFromOMXError(err); 442 } 443 444 PrepareForAdaptivePlaybackParams params; 445 params.nSize = sizeof(params); 446 params.nVersion.s.nVersionMajor = 1; 447 params.nVersion.s.nVersionMinor = 0; 448 params.nVersion.s.nRevision = 0; 449 params.nVersion.s.nStep = 0; 450 451 params.nPortIndex = portIndex; 452 params.bEnable = enable; 453 params.nMaxFrameWidth = maxFrameWidth; 454 params.nMaxFrameHeight = maxFrameHeight; 455 if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { 456 ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback " 457 "with error %d (0x%08x)", err, err); 458 return UNKNOWN_ERROR; 459 } 460 return err; 461} 462 463status_t OMXNodeInstance::configureVideoTunnelMode( 464 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, 465 native_handle_t **sidebandHandle) { 466 Mutex::Autolock autolock(mLock); 467 468 OMX_INDEXTYPE index; 469 OMX_STRING name = const_cast<OMX_STRING>( 470 "OMX.google.android.index.configureVideoTunnelMode"); 471 472 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 473 if (err != OMX_ErrorNone) { 474 ALOGE("configureVideoTunnelMode extension is missing!"); 475 return StatusFromOMXError(err); 476 } 477 478 ConfigureVideoTunnelModeParams tunnelParams; 479 tunnelParams.nSize = sizeof(tunnelParams); 480 tunnelParams.nVersion.s.nVersionMajor = 1; 481 tunnelParams.nVersion.s.nVersionMinor = 0; 482 tunnelParams.nVersion.s.nRevision = 0; 483 tunnelParams.nVersion.s.nStep = 0; 484 485 tunnelParams.nPortIndex = portIndex; 486 tunnelParams.bTunneled = tunneled; 487 tunnelParams.nAudioHwSync = audioHwSync; 488 err = OMX_SetParameter(mHandle, index, &tunnelParams); 489 if (err != OMX_ErrorNone) { 490 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 491 return UNKNOWN_ERROR; 492 } 493 494 err = OMX_GetParameter(mHandle, index, &tunnelParams); 495 if (err != OMX_ErrorNone) { 496 ALOGE("GetVideoTunnelWindow failed! (err %d).", err); 497 return UNKNOWN_ERROR; 498 } 499 if (sidebandHandle) { 500 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; 501 } 502 503 return err; 504} 505 506status_t OMXNodeInstance::useBuffer( 507 OMX_U32 portIndex, const sp<IMemory> ¶ms, 508 OMX::buffer_id *buffer) { 509 Mutex::Autolock autoLock(mLock); 510 511 BufferMeta *buffer_meta = new BufferMeta(params); 512 513 OMX_BUFFERHEADERTYPE *header; 514 515 OMX_ERRORTYPE err = OMX_UseBuffer( 516 mHandle, &header, portIndex, buffer_meta, 517 params->size(), static_cast<OMX_U8 *>(params->pointer())); 518 519 if (err != OMX_ErrorNone) { 520 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 521 522 delete buffer_meta; 523 buffer_meta = NULL; 524 525 *buffer = 0; 526 527 return UNKNOWN_ERROR; 528 } 529 530 CHECK_EQ(header->pAppPrivate, buffer_meta); 531 532 *buffer = makeBufferID(header); 533 534 addActiveBuffer(portIndex, *buffer); 535 536 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 537 if (bufferSource != NULL && portIndex == kPortIndexInput) { 538 bufferSource->addCodecBuffer(header); 539 } 540 541 return OK; 542} 543 544status_t OMXNodeInstance::useGraphicBuffer2_l( 545 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 546 OMX::buffer_id *buffer) { 547 548 // port definition 549 OMX_PARAM_PORTDEFINITIONTYPE def; 550 def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 551 def.nVersion.s.nVersionMajor = 1; 552 def.nVersion.s.nVersionMinor = 0; 553 def.nVersion.s.nRevision = 0; 554 def.nVersion.s.nStep = 0; 555 def.nPortIndex = portIndex; 556 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 557 if (err != OMX_ErrorNone) 558 { 559 ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__); 560 return err; 561 } 562 563 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 564 565 OMX_BUFFERHEADERTYPE *header = NULL; 566 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 567 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 568 569 err = OMX_UseBuffer( 570 mHandle, 571 &header, 572 portIndex, 573 bufferMeta, 574 def.nBufferSize, 575 bufferHandle); 576 577 if (err != OMX_ErrorNone) { 578 ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 579 delete bufferMeta; 580 bufferMeta = NULL; 581 *buffer = 0; 582 return UNKNOWN_ERROR; 583 } 584 585 CHECK_EQ(header->pBuffer, bufferHandle); 586 CHECK_EQ(header->pAppPrivate, bufferMeta); 587 588 *buffer = makeBufferID(header); 589 590 addActiveBuffer(portIndex, *buffer); 591 592 return OK; 593} 594 595// XXX: This function is here for backwards compatibility. Once the OMX 596// implementations have been updated this can be removed and useGraphicBuffer2 597// can be renamed to useGraphicBuffer. 598status_t OMXNodeInstance::useGraphicBuffer( 599 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 600 OMX::buffer_id *buffer) { 601 Mutex::Autolock autoLock(mLock); 602 603 // See if the newer version of the extension is present. 604 OMX_INDEXTYPE index; 605 if (OMX_GetExtensionIndex( 606 mHandle, 607 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 608 &index) == OMX_ErrorNone) { 609 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 610 } 611 612 OMX_STRING name = const_cast<OMX_STRING>( 613 "OMX.google.android.index.useAndroidNativeBuffer"); 614 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 615 616 if (err != OMX_ErrorNone) { 617 ALOGE("OMX_GetExtensionIndex %s failed", name); 618 619 return StatusFromOMXError(err); 620 } 621 622 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 623 624 OMX_BUFFERHEADERTYPE *header; 625 626 OMX_VERSIONTYPE ver; 627 ver.s.nVersionMajor = 1; 628 ver.s.nVersionMinor = 0; 629 ver.s.nRevision = 0; 630 ver.s.nStep = 0; 631 UseAndroidNativeBufferParams params = { 632 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 633 &header, graphicBuffer, 634 }; 635 636 err = OMX_SetParameter(mHandle, index, ¶ms); 637 638 if (err != OMX_ErrorNone) { 639 ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, 640 err); 641 642 delete bufferMeta; 643 bufferMeta = NULL; 644 645 *buffer = 0; 646 647 return UNKNOWN_ERROR; 648 } 649 650 CHECK_EQ(header->pAppPrivate, bufferMeta); 651 652 *buffer = makeBufferID(header); 653 654 addActiveBuffer(portIndex, *buffer); 655 656 return OK; 657} 658 659status_t OMXNodeInstance::updateGraphicBufferInMeta( 660 OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer, 661 OMX::buffer_id buffer) { 662 Mutex::Autolock autoLock(mLock); 663 664 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 665 VideoDecoderOutputMetaData *metadata = 666 (VideoDecoderOutputMetaData *)(header->pBuffer); 667 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 668 bufferMeta->setGraphicBuffer(graphicBuffer); 669 metadata->eType = kMetadataBufferTypeGrallocSource; 670 metadata->pHandle = graphicBuffer->handle; 671 672 return OK; 673} 674 675status_t OMXNodeInstance::createInputSurface( 676 OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) { 677 Mutex::Autolock autolock(mLock); 678 status_t err; 679 680 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); 681 if (surfaceCheck != NULL) { 682 return ALREADY_EXISTS; 683 } 684 685 // Input buffers will hold meta-data (gralloc references). 686 err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE); 687 if (err != OK) { 688 return err; 689 } 690 691 // Retrieve the width and height of the graphic buffer, set when the 692 // codec was configured. 693 OMX_PARAM_PORTDEFINITIONTYPE def; 694 def.nSize = sizeof(def); 695 def.nVersion.s.nVersionMajor = 1; 696 def.nVersion.s.nVersionMinor = 0; 697 def.nVersion.s.nRevision = 0; 698 def.nVersion.s.nStep = 0; 699 def.nPortIndex = portIndex; 700 OMX_ERRORTYPE oerr = OMX_GetParameter( 701 mHandle, OMX_IndexParamPortDefinition, &def); 702 CHECK(oerr == OMX_ErrorNone); 703 704 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 705 ALOGE("createInputSurface requires COLOR_FormatSurface " 706 "(AndroidOpaque) color format"); 707 return INVALID_OPERATION; 708 } 709 710 GraphicBufferSource* bufferSource = new GraphicBufferSource( 711 this, def.format.video.nFrameWidth, def.format.video.nFrameHeight, 712 def.nBufferCountActual); 713 if ((err = bufferSource->initCheck()) != OK) { 714 delete bufferSource; 715 return err; 716 } 717 setGraphicBufferSource(bufferSource); 718 719 *bufferProducer = bufferSource->getIGraphicBufferProducer(); 720 return OK; 721} 722 723status_t OMXNodeInstance::signalEndOfInputStream() { 724 // For non-Surface input, the MediaCodec should convert the call to a 725 // pair of requests (dequeue input buffer, queue input buffer with EOS 726 // flag set). Seems easier than doing the equivalent from here. 727 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 728 if (bufferSource == NULL) { 729 ALOGW("signalEndOfInputStream can only be used with Surface input"); 730 return INVALID_OPERATION; 731 }; 732 return bufferSource->signalEndOfInputStream(); 733} 734 735status_t OMXNodeInstance::allocateBuffer( 736 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 737 void **buffer_data) { 738 Mutex::Autolock autoLock(mLock); 739 740 BufferMeta *buffer_meta = new BufferMeta(size); 741 742 OMX_BUFFERHEADERTYPE *header; 743 744 OMX_ERRORTYPE err = OMX_AllocateBuffer( 745 mHandle, &header, portIndex, buffer_meta, size); 746 747 if (err != OMX_ErrorNone) { 748 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 749 750 delete buffer_meta; 751 buffer_meta = NULL; 752 753 *buffer = 0; 754 755 return UNKNOWN_ERROR; 756 } 757 758 CHECK_EQ(header->pAppPrivate, buffer_meta); 759 760 *buffer = makeBufferID(header); 761 *buffer_data = header->pBuffer; 762 763 addActiveBuffer(portIndex, *buffer); 764 765 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 766 if (bufferSource != NULL && portIndex == kPortIndexInput) { 767 bufferSource->addCodecBuffer(header); 768 } 769 770 return OK; 771} 772 773status_t OMXNodeInstance::allocateBufferWithBackup( 774 OMX_U32 portIndex, const sp<IMemory> ¶ms, 775 OMX::buffer_id *buffer) { 776 Mutex::Autolock autoLock(mLock); 777 778 BufferMeta *buffer_meta = new BufferMeta(params, true); 779 780 OMX_BUFFERHEADERTYPE *header; 781 782 OMX_ERRORTYPE err = OMX_AllocateBuffer( 783 mHandle, &header, portIndex, buffer_meta, params->size()); 784 785 if (err != OMX_ErrorNone) { 786 ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 787 788 delete buffer_meta; 789 buffer_meta = NULL; 790 791 *buffer = 0; 792 793 return UNKNOWN_ERROR; 794 } 795 796 CHECK_EQ(header->pAppPrivate, buffer_meta); 797 798 *buffer = makeBufferID(header); 799 800 addActiveBuffer(portIndex, *buffer); 801 802 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 803 if (bufferSource != NULL && portIndex == kPortIndexInput) { 804 bufferSource->addCodecBuffer(header); 805 } 806 807 return OK; 808} 809 810status_t OMXNodeInstance::freeBuffer( 811 OMX_U32 portIndex, OMX::buffer_id buffer) { 812 Mutex::Autolock autoLock(mLock); 813 814 removeActiveBuffer(portIndex, buffer); 815 816 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 817 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 818 819 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 820 821 delete buffer_meta; 822 buffer_meta = NULL; 823 invalidateBufferID(buffer); 824 825 return StatusFromOMXError(err); 826} 827 828status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 829 Mutex::Autolock autoLock(mLock); 830 831 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 832 header->nFilledLen = 0; 833 header->nOffset = 0; 834 header->nFlags = 0; 835 836 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 837 838 return StatusFromOMXError(err); 839} 840 841status_t OMXNodeInstance::emptyBuffer( 842 OMX::buffer_id buffer, 843 OMX_U32 rangeOffset, OMX_U32 rangeLength, 844 OMX_U32 flags, OMX_TICKS timestamp) { 845 Mutex::Autolock autoLock(mLock); 846 847 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 848 header->nFilledLen = rangeLength; 849 header->nOffset = rangeOffset; 850 header->nFlags = flags; 851 header->nTimeStamp = timestamp; 852 853 BufferMeta *buffer_meta = 854 static_cast<BufferMeta *>(header->pAppPrivate); 855 buffer_meta->CopyToOMX(header); 856 857 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 858 859 return StatusFromOMXError(err); 860} 861 862// like emptyBuffer, but the data is already in header->pBuffer 863status_t OMXNodeInstance::emptyDirectBuffer( 864 OMX_BUFFERHEADERTYPE *header, 865 OMX_U32 rangeOffset, OMX_U32 rangeLength, 866 OMX_U32 flags, OMX_TICKS timestamp) { 867 Mutex::Autolock autoLock(mLock); 868 869 header->nFilledLen = rangeLength; 870 header->nOffset = rangeOffset; 871 header->nFlags = flags; 872 header->nTimeStamp = timestamp; 873 874 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 875 if (err != OMX_ErrorNone) { 876 ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err); 877 } 878 879 return StatusFromOMXError(err); 880} 881 882status_t OMXNodeInstance::getExtensionIndex( 883 const char *parameterName, OMX_INDEXTYPE *index) { 884 Mutex::Autolock autoLock(mLock); 885 886 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 887 mHandle, const_cast<char *>(parameterName), index); 888 889 return StatusFromOMXError(err); 890} 891 892status_t OMXNodeInstance::setInternalOption( 893 OMX_U32 portIndex, 894 IOMX::InternalOptionType type, 895 const void *data, 896 size_t size) { 897 switch (type) { 898 case IOMX::INTERNAL_OPTION_SUSPEND: 899 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 900 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: 901 case IOMX::INTERNAL_OPTION_START_TIME: 902 case IOMX::INTERNAL_OPTION_TIME_LAPSE: 903 { 904 const sp<GraphicBufferSource> &bufferSource = 905 getGraphicBufferSource(); 906 907 if (bufferSource == NULL || portIndex != kPortIndexInput) { 908 return ERROR_UNSUPPORTED; 909 } 910 911 if (type == IOMX::INTERNAL_OPTION_SUSPEND) { 912 if (size != sizeof(bool)) { 913 return INVALID_OPERATION; 914 } 915 916 bool suspend = *(bool *)data; 917 bufferSource->suspend(suspend); 918 } else if (type == 919 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){ 920 if (size != sizeof(int64_t)) { 921 return INVALID_OPERATION; 922 } 923 924 int64_t delayUs = *(int64_t *)data; 925 926 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs); 927 } else if (type == 928 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){ 929 if (size != sizeof(int64_t)) { 930 return INVALID_OPERATION; 931 } 932 933 int64_t maxGapUs = *(int64_t *)data; 934 935 return bufferSource->setMaxTimestampGapUs(maxGapUs); 936 } else if (type == IOMX::INTERNAL_OPTION_START_TIME) { 937 if (size != sizeof(int64_t)) { 938 return INVALID_OPERATION; 939 } 940 941 int64_t skipFramesBeforeUs = *(int64_t *)data; 942 943 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs); 944 } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE 945 if (size != sizeof(int64_t) * 2) { 946 return INVALID_OPERATION; 947 } 948 949 bufferSource->setTimeLapseUs((int64_t *)data); 950 } 951 952 return OK; 953 } 954 955 default: 956 return ERROR_UNSUPPORTED; 957 } 958} 959 960void OMXNodeInstance::onMessage(const omx_message &msg) { 961 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 962 963 if (msg.type == omx_message::FILL_BUFFER_DONE) { 964 OMX_BUFFERHEADERTYPE *buffer = 965 findBufferHeader(msg.u.extended_buffer_data.buffer); 966 967 BufferMeta *buffer_meta = 968 static_cast<BufferMeta *>(buffer->pAppPrivate); 969 970 buffer_meta->CopyFromOMX(buffer); 971 972 if (bufferSource != NULL) { 973 // fix up the buffer info (especially timestamp) if needed 974 bufferSource->codecBufferFilled(buffer); 975 976 omx_message newMsg = msg; 977 newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp; 978 mObserver->onMessage(newMsg); 979 return; 980 } 981 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 982 if (bufferSource != NULL) { 983 // This is one of the buffers used exclusively by 984 // GraphicBufferSource. 985 // Don't dispatch a message back to ACodec, since it doesn't 986 // know that anyone asked to have the buffer emptied and will 987 // be very confused. 988 989 OMX_BUFFERHEADERTYPE *buffer = 990 findBufferHeader(msg.u.buffer_data.buffer); 991 992 bufferSource->codecBufferEmptied(buffer); 993 return; 994 } 995 } 996 997 mObserver->onMessage(msg); 998} 999 1000void OMXNodeInstance::onObserverDied(OMXMaster *master) { 1001 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 1002 1003 // Try to force shutdown of the node and hope for the best. 1004 freeNode(master); 1005} 1006 1007void OMXNodeInstance::onGetHandleFailed() { 1008 delete this; 1009} 1010 1011// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 1012// Don't try to acquire mLock here -- in rare circumstances this will hang. 1013void OMXNodeInstance::onEvent( 1014 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 1015 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1016 1017 if (bufferSource != NULL 1018 && event == OMX_EventCmdComplete 1019 && arg1 == OMX_CommandStateSet 1020 && arg2 == OMX_StateExecuting) { 1021 bufferSource->omxExecuting(); 1022 } 1023} 1024 1025// static 1026OMX_ERRORTYPE OMXNodeInstance::OnEvent( 1027 OMX_IN OMX_HANDLETYPE /* hComponent */, 1028 OMX_IN OMX_PTR pAppData, 1029 OMX_IN OMX_EVENTTYPE eEvent, 1030 OMX_IN OMX_U32 nData1, 1031 OMX_IN OMX_U32 nData2, 1032 OMX_IN OMX_PTR pEventData) { 1033 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1034 if (instance->mDying) { 1035 return OMX_ErrorNone; 1036 } 1037 return instance->owner()->OnEvent( 1038 instance->nodeID(), eEvent, nData1, nData2, pEventData); 1039} 1040 1041// static 1042OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 1043 OMX_IN OMX_HANDLETYPE /* hComponent */, 1044 OMX_IN OMX_PTR pAppData, 1045 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1046 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1047 if (instance->mDying) { 1048 return OMX_ErrorNone; 1049 } 1050 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), 1051 instance->findBufferID(pBuffer), pBuffer); 1052} 1053 1054// static 1055OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 1056 OMX_IN OMX_HANDLETYPE /* hComponent */, 1057 OMX_IN OMX_PTR pAppData, 1058 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1059 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1060 if (instance->mDying) { 1061 return OMX_ErrorNone; 1062 } 1063 return instance->owner()->OnFillBufferDone(instance->nodeID(), 1064 instance->findBufferID(pBuffer), pBuffer); 1065} 1066 1067void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 1068 ActiveBuffer active; 1069 active.mPortIndex = portIndex; 1070 active.mID = id; 1071 mActiveBuffers.push(active); 1072} 1073 1074void OMXNodeInstance::removeActiveBuffer( 1075 OMX_U32 portIndex, OMX::buffer_id id) { 1076 bool found = false; 1077 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 1078 if (mActiveBuffers[i].mPortIndex == portIndex 1079 && mActiveBuffers[i].mID == id) { 1080 found = true; 1081 mActiveBuffers.removeItemsAt(i); 1082 break; 1083 } 1084 } 1085 1086 if (!found) { 1087 ALOGW("Attempt to remove an active buffer we know nothing about..."); 1088 } 1089} 1090 1091void OMXNodeInstance::freeActiveBuffers() { 1092 // Make sure to count down here, as freeBuffer will in turn remove 1093 // the active buffer from the vector... 1094 for (size_t i = mActiveBuffers.size(); i--;) { 1095 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 1096 } 1097} 1098 1099#ifdef __LP64__ 1100 1101OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1102 if (bufferHeader == NULL) { 1103 return 0; 1104 } 1105 Mutex::Autolock autoLock(mBufferIDLock); 1106 OMX::buffer_id buffer; 1107 do { // handle the very unlikely case of ID overflow 1108 if (++mBufferIDCount == 0) { 1109 ++mBufferIDCount; 1110 } 1111 buffer = (OMX::buffer_id)mBufferIDCount; 1112 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); 1113 mBufferIDToBufferHeader.add(buffer, bufferHeader); 1114 mBufferHeaderToBufferID.add(bufferHeader, buffer); 1115 return buffer; 1116} 1117 1118OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { 1119 if (buffer == 0) { 1120 return NULL; 1121 } 1122 Mutex::Autolock autoLock(mBufferIDLock); 1123 return mBufferIDToBufferHeader.valueFor(buffer); 1124} 1125 1126OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1127 if (bufferHeader == NULL) { 1128 return 0; 1129 } 1130 Mutex::Autolock autoLock(mBufferIDLock); 1131 return mBufferHeaderToBufferID.valueFor(bufferHeader); 1132} 1133 1134void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) { 1135 if (buffer == 0) { 1136 return; 1137 } 1138 Mutex::Autolock autoLock(mBufferIDLock); 1139 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer)); 1140 mBufferIDToBufferHeader.removeItem(buffer); 1141} 1142 1143#else 1144 1145OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1146 return (OMX::buffer_id)bufferHeader; 1147} 1148 1149OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { 1150 return (OMX_BUFFERHEADERTYPE *)buffer; 1151} 1152 1153OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1154 return (OMX::buffer_id)bufferHeader; 1155} 1156 1157void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) { 1158} 1159 1160#endif 1161 1162} // namespace android 1163