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