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