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