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