OMXNodeInstance.cpp revision d3ed3883c2d7bf3fb871be512055ed72cea964da
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 <inttypes.h> 22 23#include "../include/OMXNodeInstance.h" 24#include "OMXMaster.h" 25#include "OMXUtils.h" 26#include <android/IOMXBufferSource.h> 27 28#include <OMX_Component.h> 29#include <OMX_IndexExt.h> 30#include <OMX_VideoExt.h> 31#include <OMX_AsString.h> 32 33#include <binder/IMemory.h> 34#include <cutils/properties.h> 35#include <gui/BufferQueue.h> 36#include <HardwareAPI.h> 37#include <media/stagefright/foundation/ADebug.h> 38#include <media/stagefright/foundation/ABuffer.h> 39#include <media/stagefright/foundation/ColorUtils.h> 40#include <media/stagefright/MediaErrors.h> 41#include <utils/misc.h> 42#include <utils/NativeHandle.h> 43#include <media/OMXBuffer.h> 44 45static const OMX_U32 kPortIndexInput = 0; 46static const OMX_U32 kPortIndexOutput = 1; 47 48// Quirk still supported, even though deprecated 49enum Quirks { 50 kRequiresAllocateBufferOnInputPorts = 1, 51 kRequiresAllocateBufferOnOutputPorts = 2, 52 53 kQuirksMask = kRequiresAllocateBufferOnInputPorts 54 | kRequiresAllocateBufferOnOutputPorts, 55}; 56 57#define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__) 58 59#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \ 60 ALOGE_IF(cond, #fn "(%p:%s, " fmt ") ERROR: %s(%#x)", \ 61 mHandle, mName, ##__VA_ARGS__, asString(err), err) 62#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__) 63#define CLOG_IF_ERROR(fn, err, fmt, ...) \ 64 CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__) 65 66#define CLOGI_(level, fn, fmt, ...) \ 67 ALOGI_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__) 68#define CLOGD_(level, fn, fmt, ...) \ 69 ALOGD_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__) 70 71#define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__) 72#define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__) 73#define CLOG_CONFIG(fn, fmt, ...) CLOGI_(ADebug::kDebugConfig, fn, fmt, ##__VA_ARGS__) 74#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__) 75 76#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \ 77 ALOGD_IF(cond, #fn "(%p, " fmt ")", mHandle, ##__VA_ARGS__) 78 79#define CLOG_BUFFER(fn, fmt, ...) \ 80 CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 81#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \ 82 CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 83 84/* buffer formatting */ 85#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__ 86#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \ 87 BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id)) 88 89#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data)) 90#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \ 91 NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data)) 92 93#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \ 94 (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd) 95#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \ 96 (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \ 97 (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd) 98 99#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \ 100 mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \ 101 mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput] 102// TRICKY: this is needed so formatting macros expand before substitution 103#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__) 104 105namespace android { 106 107struct BufferMeta { 108 explicit BufferMeta( 109 const sp<IMemory> &mem, OMX_U32 portIndex, bool copy, OMX_U8 *backup) 110 : mMem(mem), 111 mCopyFromOmx(portIndex == kPortIndexOutput && copy), 112 mCopyToOmx(portIndex == kPortIndexInput && copy), 113 mPortIndex(portIndex), 114 mBackup(backup) { 115 } 116 117 explicit BufferMeta(OMX_U32 portIndex) 118 : mCopyFromOmx(false), 119 mCopyToOmx(false), 120 mPortIndex(portIndex), 121 mBackup(NULL) { 122 } 123 124 explicit BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex) 125 : mGraphicBuffer(graphicBuffer), 126 mCopyFromOmx(false), 127 mCopyToOmx(false), 128 mPortIndex(portIndex), 129 mBackup(NULL) { 130 } 131 132 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 133 if (!mCopyFromOmx) { 134 return; 135 } 136 137 // check component returns proper range 138 sp<ABuffer> codec = getBuffer(header, true /* limit */); 139 140 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size()); 141 } 142 143 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 144 if (!mCopyToOmx) { 145 return; 146 } 147 148 memcpy(header->pBuffer + header->nOffset, 149 (const OMX_U8 *)mMem->pointer() + header->nOffset, 150 header->nFilledLen); 151 } 152 153 // return the codec buffer 154 sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool limit) { 155 sp<ABuffer> buf = new ABuffer(header->pBuffer, header->nAllocLen); 156 if (limit) { 157 if (header->nOffset + header->nFilledLen > header->nOffset 158 && header->nOffset + header->nFilledLen <= header->nAllocLen) { 159 buf->setRange(header->nOffset, header->nFilledLen); 160 } else { 161 buf->setRange(0, 0); 162 } 163 } 164 return buf; 165 } 166 167 void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { 168 mGraphicBuffer = graphicBuffer; 169 } 170 171 void setNativeHandle(const sp<NativeHandle> &nativeHandle) { 172 mNativeHandle = nativeHandle; 173 } 174 175 OMX_U32 getPortIndex() { 176 return mPortIndex; 177 } 178 179 ~BufferMeta() { 180 delete[] mBackup; 181 } 182 183private: 184 sp<GraphicBuffer> mGraphicBuffer; 185 sp<NativeHandle> mNativeHandle; 186 sp<IMemory> mMem; 187 bool mCopyFromOmx; 188 bool mCopyToOmx; 189 OMX_U32 mPortIndex; 190 OMX_U8 *mBackup; 191 192 BufferMeta(const BufferMeta &); 193 BufferMeta &operator=(const BufferMeta &); 194}; 195 196// static 197OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 198 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 199}; 200 201static inline const char *portString(OMX_U32 portIndex) { 202 switch (portIndex) { 203 case kPortIndexInput: return "Input"; 204 case kPortIndexOutput: return "Output"; 205 case ~0U: return "All"; 206 default: return "port"; 207 } 208} 209 210//////////////////////////////////////////////////////////////////////////////// 211 212// This provides the underlying Thread used by CallbackDispatcher. 213// Note that deriving CallbackDispatcher from Thread does not work. 214 215struct OMXNodeInstance::CallbackDispatcherThread : public Thread { 216 explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher) 217 : mDispatcher(dispatcher) { 218 } 219 220private: 221 CallbackDispatcher *mDispatcher; 222 223 bool threadLoop(); 224 225 CallbackDispatcherThread(const CallbackDispatcherThread &); 226 CallbackDispatcherThread &operator=(const CallbackDispatcherThread &); 227}; 228 229//////////////////////////////////////////////////////////////////////////////// 230 231struct OMXNodeInstance::CallbackDispatcher : public RefBase { 232 explicit CallbackDispatcher(const sp<OMXNodeInstance> &owner); 233 234 // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified 235 // that a new message is available on the queue. Otherwise, the message stays on the queue, but 236 // the listener is not notified of it. It will process this message when a subsequent message 237 // is posted with |realTime| set to true. 238 void post(const omx_message &msg, bool realTime = true); 239 240 bool loop(); 241 242protected: 243 virtual ~CallbackDispatcher(); 244 245private: 246 Mutex mLock; 247 248 sp<OMXNodeInstance> const mOwner; 249 bool mDone; 250 Condition mQueueChanged; 251 std::list<omx_message> mQueue; 252 253 sp<CallbackDispatcherThread> mThread; 254 255 void dispatch(std::list<omx_message> &messages); 256 257 CallbackDispatcher(const CallbackDispatcher &); 258 CallbackDispatcher &operator=(const CallbackDispatcher &); 259}; 260 261OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner) 262 : mOwner(owner), 263 mDone(false) { 264 mThread = new CallbackDispatcherThread(this); 265 mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND); 266} 267 268OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() { 269 { 270 Mutex::Autolock autoLock(mLock); 271 272 mDone = true; 273 mQueueChanged.signal(); 274 } 275 276 // A join on self can happen if the last ref to CallbackDispatcher 277 // is released within the CallbackDispatcherThread loop 278 status_t status = mThread->join(); 279 if (status != WOULD_BLOCK) { 280 // Other than join to self, the only other error return codes are 281 // whatever readyToRun() returns, and we don't override that 282 CHECK_EQ(status, (status_t)NO_ERROR); 283 } 284} 285 286void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool realTime) { 287 Mutex::Autolock autoLock(mLock); 288 289 mQueue.push_back(msg); 290 if (realTime) { 291 mQueueChanged.signal(); 292 } 293} 294 295void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messages) { 296 if (mOwner == NULL) { 297 ALOGV("Would have dispatched a message to a node that's already gone."); 298 return; 299 } 300 mOwner->onMessages(messages); 301} 302 303bool OMXNodeInstance::CallbackDispatcher::loop() { 304 for (;;) { 305 std::list<omx_message> messages; 306 307 { 308 Mutex::Autolock autoLock(mLock); 309 while (!mDone && mQueue.empty()) { 310 mQueueChanged.wait(mLock); 311 } 312 313 if (mDone) { 314 break; 315 } 316 317 messages.swap(mQueue); 318 } 319 320 dispatch(messages); 321 } 322 323 return false; 324} 325 326//////////////////////////////////////////////////////////////////////////////// 327 328bool OMXNodeInstance::CallbackDispatcherThread::threadLoop() { 329 return mDispatcher->loop(); 330} 331 332//////////////////////////////////////////////////////////////////////////////// 333 334OMXNodeInstance::OMXNodeInstance( 335 OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name) 336 : mOwner(owner), 337 mHandle(NULL), 338 mObserver(observer), 339 mDying(false), 340 mSailed(false), 341 mQueriedProhibitedExtensions(false), 342 mQuirks(0), 343 mBufferIDCount(0), 344 mRestorePtsFailed(false), 345 mMaxTimestampGapUs(-1ll), 346 mPrevOriginalTimeUs(-1ll), 347 mPrevModifiedTimeUs(-1ll) 348{ 349 mName = ADebug::GetDebugName(name); 350 DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug"); 351 ALOGV("debug level for %s is %d", name, DEBUG); 352 DEBUG_BUMP = DEBUG; 353 mNumPortBuffers[0] = 0; 354 mNumPortBuffers[1] = 0; 355 mDebugLevelBumpPendingBuffers[0] = 0; 356 mDebugLevelBumpPendingBuffers[1] = 0; 357 mMetadataType[0] = kMetadataBufferTypeInvalid; 358 mMetadataType[1] = kMetadataBufferTypeInvalid; 359 mPortMode[0] = IOMX::kPortModePresetByteBuffer; 360 mPortMode[1] = IOMX::kPortModePresetByteBuffer; 361 mSecureBufferType[0] = kSecureBufferTypeUnknown; 362 mSecureBufferType[1] = kSecureBufferTypeUnknown; 363 mIsSecure = AString(name).endsWith(".secure"); 364 mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive"); 365} 366 367OMXNodeInstance::~OMXNodeInstance() { 368 free(mName); 369 CHECK(mHandle == NULL); 370} 371 372void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) { 373 CLOG_LIFE(allocateNode, "handle=%p", handle); 374 CHECK(mHandle == NULL); 375 mHandle = handle; 376 if (handle != NULL) { 377 mDispatcher = new CallbackDispatcher(this); 378 } 379} 380 381sp<IOMXBufferSource> OMXNodeInstance::getBufferSource() { 382 Mutex::Autolock autoLock(mOMXBufferSourceLock); 383 return mOMXBufferSource; 384} 385 386void OMXNodeInstance::setBufferSource(const sp<IOMXBufferSource>& bufferSource) { 387 Mutex::Autolock autoLock(mOMXBufferSourceLock); 388 CLOG_INTERNAL(setBufferSource, "%p", bufferSource.get()); 389 mOMXBufferSource = bufferSource; 390} 391 392OMX_HANDLETYPE OMXNodeInstance::handle() { 393 return mHandle; 394} 395 396sp<IOMXObserver> OMXNodeInstance::observer() { 397 return mObserver; 398} 399 400status_t OMXNodeInstance::freeNode() { 401 402 CLOG_LIFE(freeNode, "handle=%p", mHandle); 403 static int32_t kMaxNumIterations = 10; 404 405 // exit if we have already freed the node 406 if (mHandle == NULL) { 407 return mOwner->freeNode(this); 408 } 409 410 // Transition the node from its current state all the way down 411 // to "Loaded". 412 // This ensures that all active buffers are properly freed even 413 // for components that don't do this themselves on a call to 414 // "FreeHandle". 415 416 // The code below may trigger some more events to be dispatched 417 // by the OMX component - we want to ignore them as our client 418 // does not expect them. 419 mDying = true; 420 421 OMX_STATETYPE state; 422 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 423 switch (state) { 424 case OMX_StateExecuting: 425 { 426 ALOGV("forcing Executing->Idle"); 427 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 428 OMX_ERRORTYPE err; 429 int32_t iteration = 0; 430 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 431 && state != OMX_StateIdle 432 && state != OMX_StateInvalid) { 433 if (++iteration > kMaxNumIterations) { 434 CLOGW("failed to enter Idle state (now %s(%d), aborting.", 435 asString(state), state); 436 state = OMX_StateInvalid; 437 break; 438 } 439 440 usleep(100000); 441 } 442 CHECK_EQ(err, OMX_ErrorNone); 443 444 if (state == OMX_StateInvalid) { 445 break; 446 } 447 448 // fall through 449 } 450 451 case OMX_StateIdle: 452 { 453 ALOGV("forcing Idle->Loaded"); 454 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 455 456 freeActiveBuffers(); 457 458 OMX_ERRORTYPE err; 459 int32_t iteration = 0; 460 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 461 && state != OMX_StateLoaded 462 && state != OMX_StateInvalid) { 463 if (++iteration > kMaxNumIterations) { 464 CLOGW("failed to enter Loaded state (now %s(%d), aborting.", 465 asString(state), state); 466 state = OMX_StateInvalid; 467 break; 468 } 469 470 ALOGV("waiting for Loaded state..."); 471 usleep(100000); 472 } 473 CHECK_EQ(err, OMX_ErrorNone); 474 475 // fall through 476 } 477 478 case OMX_StateLoaded: 479 case OMX_StateInvalid: 480 break; 481 482 default: 483 LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state); 484 break; 485 } 486 status_t err = mOwner->freeNode(this); 487 488 mDispatcher.clear(); 489 mOMXBufferSource.clear(); 490 491 mHandle = NULL; 492 CLOG_IF_ERROR(freeNode, err, ""); 493 free(mName); 494 mName = NULL; 495 496 ALOGV("OMXNodeInstance going away."); 497 498 return err; 499} 500 501status_t OMXNodeInstance::sendCommand( 502 OMX_COMMANDTYPE cmd, OMX_S32 param) { 503 const sp<IOMXBufferSource> bufferSource(getBufferSource()); 504 if (bufferSource != NULL && cmd == OMX_CommandStateSet) { 505 if (param == OMX_StateIdle) { 506 // Initiating transition from Executing -> Idle 507 // ACodec is waiting for all buffers to be returned, do NOT 508 // submit any more buffers to the codec. 509 bufferSource->onOmxIdle(); 510 } else if (param == OMX_StateLoaded) { 511 // Initiating transition from Idle/Executing -> Loaded 512 // Buffers are about to be freed. 513 bufferSource->onOmxLoaded(); 514 setBufferSource(NULL); 515 } 516 517 // fall through 518 } 519 520 Mutex::Autolock autoLock(mLock); 521 522 if (cmd == OMX_CommandStateSet) { 523 // There are no configurations past first StateSet command. 524 mSailed = true; 525 } 526 527 // bump internal-state debug level for 2 input and output frames past a command 528 { 529 Mutex::Autolock _l(mDebugLock); 530 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 531 } 532 533 const char *paramString = 534 cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param); 535 CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 536 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 537 CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 538 return StatusFromOMXError(err); 539} 540 541bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) { 542 // these extensions can only be used from OMXNodeInstance, not by clients directly. 543 static const char *restricted_extensions[] = { 544 "OMX.google.android.index.storeMetaDataInBuffers", 545 "OMX.google.android.index.storeANWBufferInMetadata", 546 "OMX.google.android.index.prepareForAdaptivePlayback", 547 "OMX.google.android.index.configureVideoTunnelMode", 548 "OMX.google.android.index.useAndroidNativeBuffer2", 549 "OMX.google.android.index.useAndroidNativeBuffer", 550 "OMX.google.android.index.enableAndroidNativeBuffers", 551 "OMX.google.android.index.allocateNativeHandle", 552 "OMX.google.android.index.getAndroidNativeBufferUsage", 553 }; 554 555 if ((index > OMX_IndexComponentStartUnused && index < OMX_IndexComponentEndUnused) 556 || (index > OMX_IndexPortStartUnused && index < OMX_IndexPortEndUnused) 557 || (index > OMX_IndexAudioStartUnused && index < OMX_IndexAudioEndUnused) 558 || (index > OMX_IndexVideoStartUnused && index < OMX_IndexVideoEndUnused) 559 || (index > OMX_IndexCommonStartUnused && index < OMX_IndexCommonEndUnused) 560 || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused 561 && index < (OMX_INDEXTYPE)OMX_IndexExtAudioEndUnused) 562 || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused 563 && index < (OMX_INDEXTYPE)OMX_IndexExtVideoEndUnused) 564 || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused 565 && index < (OMX_INDEXTYPE)OMX_IndexExtOtherEndUnused)) { 566 return false; 567 } 568 569 if (!mQueriedProhibitedExtensions) { 570 for (size_t i = 0; i < NELEM(restricted_extensions); ++i) { 571 OMX_INDEXTYPE ext; 572 if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) { 573 mProhibitedExtensions.add(ext); 574 } 575 } 576 mQueriedProhibitedExtensions = true; 577 } 578 579 return mProhibitedExtensions.indexOf(index) >= 0; 580} 581 582status_t OMXNodeInstance::getParameter( 583 OMX_INDEXTYPE index, void *params, size_t /* size */) { 584 Mutex::Autolock autoLock(mLock); 585 586 if (isProhibitedIndex_l(index)) { 587 android_errorWriteLog(0x534e4554, "29422020"); 588 return BAD_INDEX; 589 } 590 591 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 592 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 593 // some errors are expected for getParameter 594 if (err != OMX_ErrorNoMore) { 595 CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index); 596 } 597 return StatusFromOMXError(err); 598} 599 600status_t OMXNodeInstance::setParameter( 601 OMX_INDEXTYPE index, const void *params, size_t size) { 602 Mutex::Autolock autoLock(mLock); 603 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 604 CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 605 606 if (extIndex == OMX_IndexParamMaxFrameDurationForBitrateControl) { 607 return setMaxPtsGapUs(params, size); 608 } 609 610 if (isProhibitedIndex_l(index)) { 611 android_errorWriteLog(0x534e4554, "29422020"); 612 return BAD_INDEX; 613 } 614 615 OMX_ERRORTYPE err = OMX_SetParameter( 616 mHandle, index, const_cast<void *>(params)); 617 CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index); 618 return StatusFromOMXError(err); 619} 620 621status_t OMXNodeInstance::getConfig( 622 OMX_INDEXTYPE index, void *params, size_t /* size */) { 623 Mutex::Autolock autoLock(mLock); 624 625 if (isProhibitedIndex_l(index)) { 626 android_errorWriteLog(0x534e4554, "29422020"); 627 return BAD_INDEX; 628 } 629 630 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 631 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 632 // some errors are expected for getConfig 633 if (err != OMX_ErrorNoMore) { 634 CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index); 635 } 636 return StatusFromOMXError(err); 637} 638 639status_t OMXNodeInstance::setConfig( 640 OMX_INDEXTYPE index, const void *params, size_t size) { 641 Mutex::Autolock autoLock(mLock); 642 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 643 CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 644 645 if (isProhibitedIndex_l(index)) { 646 android_errorWriteLog(0x534e4554, "29422020"); 647 return BAD_INDEX; 648 } 649 650 OMX_ERRORTYPE err = OMX_SetConfig( 651 mHandle, index, const_cast<void *>(params)); 652 CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index); 653 return StatusFromOMXError(err); 654} 655 656status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) { 657 Mutex::Autolock autoLock(mLock); 658 659 if (portIndex >= NELEM(mPortMode)) { 660 ALOGE("b/31385713, portIndex(%u)", portIndex); 661 android_errorWriteLog(0x534e4554, "31385713"); 662 return BAD_VALUE; 663 } 664 665 CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex); 666 667 switch (mode) { 668 case IOMX::kPortModeDynamicANWBuffer: 669 { 670 if (portIndex == kPortIndexOutput) { 671 if (mLegacyAdaptiveExperiment) { 672 CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: " 673 "not setting port mode to %s(%d) on output", 674 asString(mode), mode); 675 return StatusFromOMXError(OMX_ErrorUnsupportedIndex); 676 } 677 678 status_t err = enableNativeBuffers_l( 679 portIndex, OMX_TRUE /*graphic*/, OMX_TRUE); 680 if (err != OK) { 681 return err; 682 } 683 } 684 (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE); 685 return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL); 686 } 687 688 case IOMX::kPortModeDynamicNativeHandle: 689 { 690 if (portIndex != kPortIndexInput) { 691 CLOG_ERROR(setPortMode, BAD_VALUE, 692 "%s(%d) mode is only supported on input port", asString(mode), mode); 693 return BAD_VALUE; 694 } 695 (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE); 696 (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE); 697 698 MetadataBufferType metaType = kMetadataBufferTypeNativeHandleSource; 699 return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType); 700 } 701 702 case IOMX::kPortModePresetSecureBuffer: 703 { 704 // Allow on both input and output. 705 (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL); 706 (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE); 707 return enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE); 708 } 709 710 case IOMX::kPortModePresetANWBuffer: 711 { 712 if (portIndex != kPortIndexOutput) { 713 CLOG_ERROR(setPortMode, BAD_VALUE, 714 "%s(%d) mode is only supported on output port", asString(mode), mode); 715 return BAD_VALUE; 716 } 717 718 // Check if we're simulating legacy mode with metadata mode, 719 // if so, enable metadata mode. 720 if (mLegacyAdaptiveExperiment) { 721 if (storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL) == OK) { 722 CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: " 723 "metdata mode enabled successfully"); 724 return OK; 725 } 726 727 CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: " 728 "unable to enable metadata mode on output"); 729 730 mLegacyAdaptiveExperiment = false; 731 } 732 733 // Disable secure buffer and enable graphic buffer 734 (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE); 735 status_t err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE); 736 if (err != OK) { 737 return err; 738 } 739 740 // Not running experiment, or metadata is not supported. 741 // Disable metadata mode and use legacy mode. 742 (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL); 743 return OK; 744 } 745 746 case IOMX::kPortModePresetByteBuffer: 747 { 748 // Disable secure buffer, native buffer and metadata. 749 (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE); 750 (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE); 751 (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL); 752 return OK; 753 } 754 755 default: 756 break; 757 } 758 759 CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode); 760 return BAD_VALUE; 761} 762 763status_t OMXNodeInstance::enableNativeBuffers_l( 764 OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) { 765 if (portIndex >= NELEM(mSecureBufferType)) { 766 ALOGE("b/31385713, portIndex(%u)", portIndex); 767 android_errorWriteLog(0x534e4554, "31385713"); 768 return BAD_VALUE; 769 } 770 771 CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex, 772 graphic ? ", graphic" : "", enable); 773 OMX_STRING name = const_cast<OMX_STRING>( 774 graphic ? "OMX.google.android.index.enableAndroidNativeBuffers" 775 : "OMX.google.android.index.allocateNativeHandle"); 776 777 OMX_INDEXTYPE index; 778 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 779 780 if (err == OMX_ErrorNone) { 781 EnableAndroidNativeBuffersParams params; 782 InitOMXParams(¶ms); 783 params.nPortIndex = portIndex; 784 params.enable = enable; 785 786 err = OMX_SetParameter(mHandle, index, ¶ms); 787 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index, 788 portString(portIndex), portIndex, enable); 789 if (!graphic) { 790 if (err == OMX_ErrorNone) { 791 mSecureBufferType[portIndex] = 792 enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque; 793 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) { 794 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque; 795 } 796 } 797 } else { 798 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 799 if (!graphic) { 800 // Extension not supported, check for manual override with system property 801 // This is a temporary workaround until partners support the OMX extension 802 char value[PROPERTY_VALUE_MAX]; 803 if (property_get("media.mediadrmservice.enable", value, NULL) 804 && (!strcmp("1", value) || !strcasecmp("true", value))) { 805 CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles"); 806 mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle; 807 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) { 808 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque; 809 } 810 err = OMX_ErrorNone; 811 } 812 } 813 814 return StatusFromOMXError(err); 815} 816 817status_t OMXNodeInstance::getGraphicBufferUsage( 818 OMX_U32 portIndex, OMX_U32* usage) { 819 Mutex::Autolock autoLock(mLock); 820 821 OMX_INDEXTYPE index; 822 OMX_STRING name = const_cast<OMX_STRING>( 823 "OMX.google.android.index.getAndroidNativeBufferUsage"); 824 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 825 826 if (err != OMX_ErrorNone) { 827 CLOG_ERROR(getExtensionIndex, err, "%s", name); 828 return StatusFromOMXError(err); 829 } 830 831 GetAndroidNativeBufferUsageParams params; 832 InitOMXParams(¶ms); 833 params.nPortIndex = portIndex; 834 835 err = OMX_GetParameter(mHandle, index, ¶ms); 836 if (err != OMX_ErrorNone) { 837 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index, 838 portString(portIndex), portIndex); 839 return StatusFromOMXError(err); 840 } 841 842 *usage = params.nUsage; 843 844 return OK; 845} 846 847status_t OMXNodeInstance::storeMetaDataInBuffers_l( 848 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { 849 if (mSailed) { 850 android_errorWriteLog(0x534e4554, "29422020"); 851 return INVALID_OPERATION; 852 } 853 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 854 android_errorWriteLog(0x534e4554, "26324358"); 855 if (type != NULL) { 856 *type = kMetadataBufferTypeInvalid; 857 } 858 return BAD_VALUE; 859 } 860 861 OMX_INDEXTYPE index; 862 OMX_STRING name = const_cast<OMX_STRING>( 863 "OMX.google.android.index.storeMetaDataInBuffers"); 864 865 OMX_STRING nativeBufferName = const_cast<OMX_STRING>( 866 "OMX.google.android.index.storeANWBufferInMetadata"); 867 MetadataBufferType negotiatedType; 868 MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer; 869 870 StoreMetaDataInBuffersParams params; 871 InitOMXParams(¶ms); 872 params.nPortIndex = portIndex; 873 params.bStoreMetaData = enable; 874 875 OMX_ERRORTYPE err = 876 requestedType == kMetadataBufferTypeANWBuffer 877 ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index) 878 : OMX_ErrorUnsupportedIndex; 879 OMX_ERRORTYPE xerr = err; 880 if (err == OMX_ErrorNone) { 881 err = OMX_SetParameter(mHandle, index, ¶ms); 882 if (err == OMX_ErrorNone) { 883 name = nativeBufferName; // set name for debugging 884 negotiatedType = requestedType; 885 } 886 } 887 if (err != OMX_ErrorNone) { 888 err = OMX_GetExtensionIndex(mHandle, name, &index); 889 xerr = err; 890 if (err == OMX_ErrorNone) { 891 negotiatedType = 892 requestedType == kMetadataBufferTypeANWBuffer 893 ? kMetadataBufferTypeGrallocSource : requestedType; 894 err = OMX_SetParameter(mHandle, index, ¶ms); 895 } 896 } 897 898 // don't log loud error if component does not support metadata mode on the output 899 if (err != OMX_ErrorNone) { 900 if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) { 901 CLOGW("component does not support metadata mode; using fallback"); 902 } else if (xerr != OMX_ErrorNone) { 903 CLOG_ERROR(getExtensionIndex, xerr, "%s", name); 904 } else { 905 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index, 906 portString(portIndex), portIndex, enable, negotiatedType); 907 } 908 negotiatedType = mMetadataType[portIndex]; 909 } else { 910 if (!enable) { 911 negotiatedType = kMetadataBufferTypeInvalid; 912 } 913 mMetadataType[portIndex] = negotiatedType; 914 } 915 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d", 916 portString(portIndex), portIndex, enable ? "" : "UN", 917 asString(requestedType), requestedType, asString(negotiatedType), negotiatedType); 918 919 if (type != NULL) { 920 *type = negotiatedType; 921 } 922 923 return StatusFromOMXError(err); 924} 925 926status_t OMXNodeInstance::prepareForAdaptivePlayback( 927 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, 928 OMX_U32 maxFrameHeight) { 929 Mutex::Autolock autolock(mLock); 930 if (mSailed) { 931 android_errorWriteLog(0x534e4554, "29422020"); 932 return INVALID_OPERATION; 933 } 934 CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u", 935 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 936 937 if (mLegacyAdaptiveExperiment) { 938 CLOG_INTERNAL(prepareForAdaptivePlayback, 939 "Legacy adaptive experiment: reporting success"); 940 return OK; 941 } 942 943 OMX_INDEXTYPE index; 944 OMX_STRING name = const_cast<OMX_STRING>( 945 "OMX.google.android.index.prepareForAdaptivePlayback"); 946 947 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 948 if (err != OMX_ErrorNone) { 949 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 950 return StatusFromOMXError(err); 951 } 952 953 PrepareForAdaptivePlaybackParams params; 954 InitOMXParams(¶ms); 955 params.nPortIndex = portIndex; 956 params.bEnable = enable; 957 params.nMaxFrameWidth = maxFrameWidth; 958 params.nMaxFrameHeight = maxFrameHeight; 959 960 err = OMX_SetParameter(mHandle, index, ¶ms); 961 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index, 962 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 963 return StatusFromOMXError(err); 964} 965 966status_t OMXNodeInstance::configureVideoTunnelMode( 967 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, 968 native_handle_t **sidebandHandle) { 969 Mutex::Autolock autolock(mLock); 970 if (mSailed) { 971 android_errorWriteLog(0x534e4554, "29422020"); 972 return INVALID_OPERATION; 973 } 974 CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u", 975 portString(portIndex), portIndex, tunneled, audioHwSync); 976 977 OMX_INDEXTYPE index; 978 OMX_STRING name = const_cast<OMX_STRING>( 979 "OMX.google.android.index.configureVideoTunnelMode"); 980 981 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 982 if (err != OMX_ErrorNone) { 983 CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name); 984 return StatusFromOMXError(err); 985 } 986 987 ConfigureVideoTunnelModeParams tunnelParams; 988 InitOMXParams(&tunnelParams); 989 tunnelParams.nPortIndex = portIndex; 990 tunnelParams.bTunneled = tunneled; 991 tunnelParams.nAudioHwSync = audioHwSync; 992 err = OMX_SetParameter(mHandle, index, &tunnelParams); 993 if (err != OMX_ErrorNone) { 994 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 995 portString(portIndex), portIndex, tunneled, audioHwSync); 996 return StatusFromOMXError(err); 997 } 998 999 err = OMX_GetParameter(mHandle, index, &tunnelParams); 1000 if (err != OMX_ErrorNone) { 1001 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 1002 portString(portIndex), portIndex, tunneled, audioHwSync); 1003 return StatusFromOMXError(err); 1004 } 1005 if (sidebandHandle) { 1006 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; 1007 } 1008 1009 return OK; 1010} 1011 1012status_t OMXNodeInstance::useBuffer( 1013 OMX_U32 portIndex, const OMXBuffer &omxBuffer, IOMX::buffer_id *buffer) { 1014 if (buffer == NULL) { 1015 ALOGE("b/25884056"); 1016 return BAD_VALUE; 1017 } 1018 1019 if (portIndex >= NELEM(mNumPortBuffers)) { 1020 return BAD_VALUE; 1021 } 1022 1023 Mutex::Autolock autoLock(mLock); 1024 1025 switch (omxBuffer.mBufferType) { 1026 case OMXBuffer::kBufferTypePreset: 1027 return useBuffer_l(portIndex, NULL, buffer); 1028 1029 case OMXBuffer::kBufferTypeSharedMem: 1030 return useBuffer_l(portIndex, omxBuffer.mMem, buffer); 1031 1032 case OMXBuffer::kBufferTypeANWBuffer: 1033 return useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer); 1034 1035 default: 1036 break; 1037 } 1038 1039 return BAD_VALUE; 1040} 1041 1042status_t OMXNodeInstance::useBuffer_l( 1043 OMX_U32 portIndex, const sp<IMemory> ¶ms, IOMX::buffer_id *buffer) { 1044 BufferMeta *buffer_meta; 1045 OMX_BUFFERHEADERTYPE *header; 1046 OMX_ERRORTYPE err = OMX_ErrorNone; 1047 bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid; 1048 1049 OMX_U32 allottedSize; 1050 if (isMetadata) { 1051 if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource) { 1052 allottedSize = sizeof(VideoGrallocMetadata); 1053 } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer) { 1054 allottedSize = sizeof(VideoNativeMetadata); 1055 } else if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource) { 1056 allottedSize = sizeof(VideoNativeHandleMetadata); 1057 } else { 1058 return BAD_VALUE; 1059 } 1060 } else { 1061 // NULL params is allowed only in metadata mode. 1062 if (params == NULL) { 1063 ALOGE("b/25884056"); 1064 return BAD_VALUE; 1065 } 1066 allottedSize = params->size(); 1067 } 1068 1069 bool isOutputGraphicMetadata = (portIndex == kPortIndexOutput) && 1070 (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource || 1071 mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer); 1072 1073 uint32_t requiresAllocateBufferBit = 1074 (portIndex == kPortIndexInput) 1075 ? kRequiresAllocateBufferOnInputPorts 1076 : kRequiresAllocateBufferOnOutputPorts; 1077 1078 // we use useBuffer for output metadata regardless of quirks 1079 if (!isOutputGraphicMetadata && (mQuirks & requiresAllocateBufferBit)) { 1080 // metadata buffers are not connected cross process; only copy if not meta. 1081 buffer_meta = new BufferMeta( 1082 params, portIndex, !isMetadata /* copy */, NULL /* data */); 1083 1084 err = OMX_AllocateBuffer( 1085 mHandle, &header, portIndex, buffer_meta, allottedSize); 1086 1087 if (err != OMX_ErrorNone) { 1088 CLOG_ERROR(allocateBuffer, err, 1089 SIMPLE_BUFFER(portIndex, (size_t)allottedSize, 1090 params != NULL ? params->pointer() : NULL)); 1091 } 1092 } else { 1093 OMX_U8 *data = NULL; 1094 1095 // metadata buffers are not connected cross process 1096 // use a backup buffer instead of the actual buffer 1097 if (isMetadata) { 1098 data = new (std::nothrow) OMX_U8[allottedSize]; 1099 if (data == NULL) { 1100 return NO_MEMORY; 1101 } 1102 memset(data, 0, allottedSize); 1103 1104 buffer_meta = new BufferMeta( 1105 params, portIndex, false /* copy */, data); 1106 } else { 1107 data = static_cast<OMX_U8 *>(params->pointer()); 1108 1109 buffer_meta = new BufferMeta( 1110 params, portIndex, false /* copy */, NULL); 1111 } 1112 1113 err = OMX_UseBuffer( 1114 mHandle, &header, portIndex, buffer_meta, 1115 allottedSize, data); 1116 1117 if (err != OMX_ErrorNone) { 1118 CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER( 1119 portIndex, (size_t)allottedSize, data)); 1120 } 1121 } 1122 1123 if (err != OMX_ErrorNone) { 1124 delete buffer_meta; 1125 buffer_meta = NULL; 1126 1127 *buffer = 0; 1128 1129 return StatusFromOMXError(err); 1130 } 1131 1132 CHECK_EQ(header->pAppPrivate, buffer_meta); 1133 1134 *buffer = makeBufferID(header); 1135 1136 addActiveBuffer(portIndex, *buffer); 1137 1138 sp<IOMXBufferSource> bufferSource(getBufferSource()); 1139 if (bufferSource != NULL && portIndex == kPortIndexInput) { 1140 bufferSource->onInputBufferAdded(*buffer); 1141 } 1142 1143 CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT( 1144 *buffer, portIndex, "%u(%zu)@%p", allottedSize, params->size(), params->pointer())); 1145 return OK; 1146} 1147 1148status_t OMXNodeInstance::useGraphicBuffer2_l( 1149 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 1150 IOMX::buffer_id *buffer) { 1151 if (graphicBuffer == NULL || buffer == NULL) { 1152 ALOGE("b/25884056"); 1153 return BAD_VALUE; 1154 } 1155 1156 // port definition 1157 OMX_PARAM_PORTDEFINITIONTYPE def; 1158 InitOMXParams(&def); 1159 def.nPortIndex = portIndex; 1160 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 1161 if (err != OMX_ErrorNone) { 1162 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 1163 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", 1164 asString(index), index, portString(portIndex), portIndex); 1165 return UNKNOWN_ERROR; 1166 } 1167 1168 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); 1169 1170 OMX_BUFFERHEADERTYPE *header = NULL; 1171 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 1172 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 1173 1174 err = OMX_UseBuffer( 1175 mHandle, 1176 &header, 1177 portIndex, 1178 bufferMeta, 1179 def.nBufferSize, 1180 bufferHandle); 1181 1182 if (err != OMX_ErrorNone) { 1183 CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 1184 delete bufferMeta; 1185 bufferMeta = NULL; 1186 *buffer = 0; 1187 return StatusFromOMXError(err); 1188 } 1189 1190 CHECK_EQ(header->pBuffer, bufferHandle); 1191 CHECK_EQ(header->pAppPrivate, bufferMeta); 1192 1193 *buffer = makeBufferID(header); 1194 1195 addActiveBuffer(portIndex, *buffer); 1196 CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT( 1197 *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 1198 return OK; 1199} 1200 1201// XXX: This function is here for backwards compatibility. Once the OMX 1202// implementations have been updated this can be removed and useGraphicBuffer2 1203// can be renamed to useGraphicBuffer. 1204status_t OMXNodeInstance::useGraphicBuffer_l( 1205 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 1206 IOMX::buffer_id *buffer) { 1207 if (graphicBuffer == NULL || buffer == NULL) { 1208 ALOGE("b/25884056"); 1209 return BAD_VALUE; 1210 } 1211 1212 // First, see if we're in metadata mode. We could be running an experiment to simulate 1213 // legacy behavior (preallocated buffers) on devices that supports meta. 1214 if (mMetadataType[portIndex] != kMetadataBufferTypeInvalid) { 1215 return useGraphicBufferWithMetadata_l( 1216 portIndex, graphicBuffer, buffer); 1217 } 1218 1219 // See if the newer version of the extension is present. 1220 OMX_INDEXTYPE index; 1221 if (OMX_GetExtensionIndex( 1222 mHandle, 1223 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 1224 &index) == OMX_ErrorNone) { 1225 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 1226 } 1227 1228 OMX_STRING name = const_cast<OMX_STRING>( 1229 "OMX.google.android.index.useAndroidNativeBuffer"); 1230 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 1231 if (err != OMX_ErrorNone) { 1232 CLOG_ERROR(getExtensionIndex, err, "%s", name); 1233 return StatusFromOMXError(err); 1234 } 1235 1236 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); 1237 1238 OMX_BUFFERHEADERTYPE *header; 1239 1240 OMX_VERSIONTYPE ver; 1241 ver.s.nVersionMajor = 1; 1242 ver.s.nVersionMinor = 0; 1243 ver.s.nRevision = 0; 1244 ver.s.nStep = 0; 1245 UseAndroidNativeBufferParams params = { 1246 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 1247 &header, graphicBuffer, 1248 }; 1249 1250 err = OMX_SetParameter(mHandle, index, ¶ms); 1251 1252 if (err != OMX_ErrorNone) { 1253 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index, 1254 portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle); 1255 1256 delete bufferMeta; 1257 bufferMeta = NULL; 1258 1259 *buffer = 0; 1260 1261 return StatusFromOMXError(err); 1262 } 1263 1264 CHECK_EQ(header->pAppPrivate, bufferMeta); 1265 1266 *buffer = makeBufferID(header); 1267 1268 addActiveBuffer(portIndex, *buffer); 1269 CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT( 1270 *buffer, portIndex, "GB=%p", graphicBuffer->handle)); 1271 return OK; 1272} 1273 1274status_t OMXNodeInstance::useGraphicBufferWithMetadata_l( 1275 OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer, 1276 IOMX::buffer_id *buffer) { 1277 if (portIndex != kPortIndexOutput) { 1278 return BAD_VALUE; 1279 } 1280 1281 if (mMetadataType[portIndex] != kMetadataBufferTypeGrallocSource && 1282 mMetadataType[portIndex] != kMetadataBufferTypeANWBuffer) { 1283 return BAD_VALUE; 1284 } 1285 1286 status_t err = useBuffer_l(portIndex, NULL, buffer); 1287 if (err != OK) { 1288 return err; 1289 } 1290 1291 OMX_BUFFERHEADERTYPE *header = findBufferHeader(*buffer, portIndex); 1292 1293 return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, *buffer, header); 1294 1295} 1296 1297status_t OMXNodeInstance::updateGraphicBufferInMeta_l( 1298 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 1299 IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) { 1300 // No need to check |graphicBuffer| since NULL is valid for it as below. 1301 if (header == NULL) { 1302 ALOGE("b/25884056"); 1303 return BAD_VALUE; 1304 } 1305 1306 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 1307 return BAD_VALUE; 1308 } 1309 1310 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 1311 sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */); 1312 bufferMeta->setGraphicBuffer(graphicBuffer); 1313 MetadataBufferType metaType = mMetadataType[portIndex]; 1314 if (metaType == kMetadataBufferTypeGrallocSource 1315 && data->capacity() >= sizeof(VideoGrallocMetadata)) { 1316 VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data()); 1317 metadata.eType = kMetadataBufferTypeGrallocSource; 1318 metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle; 1319 } else if (metaType == kMetadataBufferTypeANWBuffer 1320 && data->capacity() >= sizeof(VideoNativeMetadata)) { 1321 VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data()); 1322 metadata.eType = kMetadataBufferTypeANWBuffer; 1323 metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer(); 1324 metadata.nFenceFd = -1; 1325 } else { 1326 CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)", 1327 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen); 1328 return BAD_VALUE; 1329 } 1330 1331 CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p", 1332 portString(portIndex), portIndex, buffer, 1333 graphicBuffer == NULL ? NULL : graphicBuffer->handle); 1334 return OK; 1335} 1336 1337status_t OMXNodeInstance::updateNativeHandleInMeta_l( 1338 OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle, 1339 IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) { 1340 // No need to check |nativeHandle| since NULL is valid for it as below. 1341 if (header == NULL) { 1342 ALOGE("b/25884056"); 1343 return BAD_VALUE; 1344 } 1345 1346 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 1347 return BAD_VALUE; 1348 } 1349 1350 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 1351 sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */); 1352 bufferMeta->setNativeHandle(nativeHandle); 1353 if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource 1354 && data->capacity() >= sizeof(VideoNativeHandleMetadata)) { 1355 VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data()); 1356 metadata.eType = mMetadataType[portIndex]; 1357 metadata.pHandle = 1358 nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle()); 1359 } else { 1360 CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)", 1361 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity()); 1362 return BAD_VALUE; 1363 } 1364 1365 CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p", 1366 portString(portIndex), portIndex, buffer, 1367 nativeHandle == NULL ? NULL : nativeHandle->handle()); 1368 return OK; 1369} 1370 1371status_t OMXNodeInstance::setInputSurface( 1372 const sp<IOMXBufferSource> &bufferSource) { 1373 Mutex::Autolock autolock(mLock); 1374 1375 status_t err; 1376 1377 // only allow graphic source on input port, when there are no allocated buffers yet 1378 if (mNumPortBuffers[kPortIndexInput] > 0) { 1379 android_errorWriteLog(0x534e4554, "29422020"); 1380 return INVALID_OPERATION; 1381 } 1382 1383 if (getBufferSource() != NULL) { 1384 return ALREADY_EXISTS; 1385 } 1386 1387 err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL); 1388 if (err != OK) { 1389 return err; 1390 } 1391 1392 // Retrieve the width and height of the graphic buffer, set when the 1393 // codec was configured. 1394 OMX_PARAM_PORTDEFINITIONTYPE def; 1395 InitOMXParams(&def); 1396 def.nPortIndex = kPortIndexInput; 1397 OMX_ERRORTYPE oerr = OMX_GetParameter( 1398 mHandle, OMX_IndexParamPortDefinition, &def); 1399 if (oerr != OMX_ErrorNone) { 1400 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 1401 CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index), 1402 index, portString(kPortIndexInput), kPortIndexInput); 1403 return UNKNOWN_ERROR; 1404 } 1405 1406 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 1407 CLOGW("createInputSurface requires COLOR_FormatSurface " 1408 "(AndroidOpaque) color format instead of %s(%#x)", 1409 asString(def.format.video.eColorFormat), def.format.video.eColorFormat); 1410 return INVALID_OPERATION; 1411 } 1412 1413 if (def.format.video.nFrameWidth == 0 1414 || def.format.video.nFrameHeight == 0) { 1415 ALOGE("Invalid video dimension %ux%u", 1416 def.format.video.nFrameWidth, 1417 def.format.video.nFrameHeight); 1418 return BAD_VALUE; 1419 } 1420 1421 setBufferSource(bufferSource); 1422 return OK; 1423} 1424 1425status_t OMXNodeInstance::allocateSecureBuffer( 1426 OMX_U32 portIndex, size_t size, IOMX::buffer_id *buffer, 1427 void **buffer_data, sp<NativeHandle> *native_handle) { 1428 if (buffer == NULL || buffer_data == NULL || native_handle == NULL) { 1429 ALOGE("b/25884056"); 1430 return BAD_VALUE; 1431 } 1432 1433 if (portIndex >= NELEM(mSecureBufferType)) { 1434 ALOGE("b/31385713, portIndex(%u)", portIndex); 1435 android_errorWriteLog(0x534e4554, "31385713"); 1436 return BAD_VALUE; 1437 } 1438 1439 Mutex::Autolock autoLock(mLock); 1440 1441 BufferMeta *buffer_meta = new BufferMeta(portIndex); 1442 1443 OMX_BUFFERHEADERTYPE *header; 1444 1445 OMX_ERRORTYPE err = OMX_AllocateBuffer( 1446 mHandle, &header, portIndex, buffer_meta, size); 1447 1448 if (err != OMX_ErrorNone) { 1449 CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size)); 1450 delete buffer_meta; 1451 buffer_meta = NULL; 1452 1453 *buffer = 0; 1454 1455 return StatusFromOMXError(err); 1456 } 1457 1458 CHECK_EQ(header->pAppPrivate, buffer_meta); 1459 1460 *buffer = makeBufferID(header); 1461 if (mSecureBufferType[portIndex] == kSecureBufferTypeNativeHandle) { 1462 *buffer_data = NULL; 1463 *native_handle = NativeHandle::create( 1464 (native_handle_t *)header->pBuffer, false /* ownsHandle */); 1465 } else { 1466 *buffer_data = header->pBuffer; 1467 *native_handle = NULL; 1468 } 1469 1470 addActiveBuffer(portIndex, *buffer); 1471 1472 sp<IOMXBufferSource> bufferSource(getBufferSource()); 1473 if (bufferSource != NULL && portIndex == kPortIndexInput) { 1474 bufferSource->onInputBufferAdded(*buffer); 1475 } 1476 CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT( 1477 *buffer, portIndex, "%zu@%p:%p", size, *buffer_data, 1478 *native_handle == NULL ? NULL : (*native_handle)->handle())); 1479 1480 return OK; 1481} 1482 1483status_t OMXNodeInstance::freeBuffer( 1484 OMX_U32 portIndex, IOMX::buffer_id buffer) { 1485 Mutex::Autolock autoLock(mLock); 1486 CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1487 1488 removeActiveBuffer(portIndex, buffer); 1489 1490 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); 1491 if (header == NULL) { 1492 ALOGE("b/25884056"); 1493 return BAD_VALUE; 1494 } 1495 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 1496 1497 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 1498 CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1499 1500 delete buffer_meta; 1501 buffer_meta = NULL; 1502 invalidateBufferID(buffer); 1503 1504 return StatusFromOMXError(err); 1505} 1506 1507status_t OMXNodeInstance::fillBuffer( 1508 IOMX::buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) { 1509 Mutex::Autolock autoLock(mLock); 1510 1511 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput); 1512 if (header == NULL) { 1513 ALOGE("b/25884056"); 1514 return BAD_VALUE; 1515 } 1516 1517 if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) { 1518 status_t err = updateGraphicBufferInMeta_l( 1519 kPortIndexOutput, omxBuffer.mGraphicBuffer, buffer, header); 1520 1521 if (err != OK) { 1522 CLOG_ERROR(fillBuffer, err, FULL_BUFFER( 1523 (intptr_t)header->pBuffer, header, fenceFd)); 1524 return err; 1525 } 1526 } else if (omxBuffer.mBufferType != OMXBuffer::kBufferTypePreset) { 1527 return BAD_VALUE; 1528 } 1529 1530 header->nFilledLen = 0; 1531 header->nOffset = 0; 1532 header->nFlags = 0; 1533 1534 // meta now owns fenceFd 1535 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput); 1536 if (res != OK) { 1537 CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd)); 1538 return res; 1539 } 1540 1541 { 1542 Mutex::Autolock _l(mDebugLock); 1543 mOutputBuffersWithCodec.add(header); 1544 CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd))); 1545 } 1546 1547 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 1548 if (err != OMX_ErrorNone) { 1549 CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd)); 1550 Mutex::Autolock _l(mDebugLock); 1551 mOutputBuffersWithCodec.remove(header); 1552 } 1553 return StatusFromOMXError(err); 1554} 1555 1556status_t OMXNodeInstance::emptyBuffer( 1557 buffer_id buffer, const OMXBuffer &omxBuffer, 1558 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1559 Mutex::Autolock autoLock(mLock); 1560 1561 switch (omxBuffer.mBufferType) { 1562 case OMXBuffer::kBufferTypePreset: 1563 return emptyBuffer_l( 1564 buffer, 0, omxBuffer.mRangeLength, flags, timestamp, fenceFd); 1565 1566 case OMXBuffer::kBufferTypeANWBuffer: 1567 return emptyGraphicBuffer_l( 1568 buffer, omxBuffer.mGraphicBuffer, flags, timestamp, fenceFd); 1569 1570 case OMXBuffer::kBufferTypeNativeHandle: 1571 return emptyNativeHandleBuffer_l( 1572 buffer, omxBuffer.mNativeHandle, flags, timestamp, fenceFd); 1573 1574 default: 1575 break; 1576 } 1577 1578 return BAD_VALUE; 1579} 1580 1581status_t OMXNodeInstance::emptyBuffer_l( 1582 IOMX::buffer_id buffer, 1583 OMX_U32 rangeOffset, OMX_U32 rangeLength, 1584 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1585 1586 // no emptybuffer if using input surface 1587 if (getBufferSource() != NULL) { 1588 android_errorWriteLog(0x534e4554, "29422020"); 1589 return INVALID_OPERATION; 1590 } 1591 1592 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); 1593 if (header == NULL) { 1594 ALOGE("b/25884056"); 1595 return BAD_VALUE; 1596 } 1597 BufferMeta *buffer_meta = 1598 static_cast<BufferMeta *>(header->pAppPrivate); 1599 1600 // set up proper filled length if component is configured for gralloc metadata mode 1601 // ignore rangeOffset in this case (as client may be assuming ANW meta buffers). 1602 if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) { 1603 header->nFilledLen = rangeLength ? sizeof(VideoGrallocMetadata) : 0; 1604 header->nOffset = 0; 1605 } else { 1606 // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. 1607 // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. 1608 if (rangeOffset > header->nAllocLen 1609 || rangeLength > header->nAllocLen - rangeOffset) { 1610 CLOG_ERROR(emptyBuffer, OMX_ErrorBadParameter, FULL_BUFFER(NULL, header, fenceFd)); 1611 if (fenceFd >= 0) { 1612 ::close(fenceFd); 1613 } 1614 return BAD_VALUE; 1615 } 1616 header->nFilledLen = rangeLength; 1617 header->nOffset = rangeOffset; 1618 1619 buffer_meta->CopyToOMX(header); 1620 } 1621 1622 return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd); 1623} 1624 1625// log queued buffer activity for the next few input and/or output frames 1626// if logging at internal state level 1627void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) { 1628 if (DEBUG == ADebug::kDebugInternalState) { 1629 DEBUG_BUMP = ADebug::kDebugAll; 1630 if (numInputBuffers > 0) { 1631 mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers; 1632 } 1633 if (numOutputBuffers > 0) { 1634 mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers; 1635 } 1636 } 1637} 1638 1639void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) { 1640 if (mDebugLevelBumpPendingBuffers[portIndex]) { 1641 --mDebugLevelBumpPendingBuffers[portIndex]; 1642 } 1643 if (!mDebugLevelBumpPendingBuffers[0] 1644 && !mDebugLevelBumpPendingBuffers[1]) { 1645 DEBUG_BUMP = DEBUG; 1646 } 1647} 1648 1649status_t OMXNodeInstance::storeFenceInMeta_l( 1650 OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) { 1651 // propagate fence if component supports it; wait for it otherwise 1652 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen; 1653 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1654 && metaSize >= sizeof(VideoNativeMetadata)) { 1655 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1656 if (nativeMeta.nFenceFd >= 0) { 1657 ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd); 1658 if (fenceFd >= 0) { 1659 ::close(fenceFd); 1660 } 1661 return ALREADY_EXISTS; 1662 } 1663 nativeMeta.nFenceFd = fenceFd; 1664 } else if (fenceFd >= 0) { 1665 CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd); 1666 sp<Fence> fence = new Fence(fenceFd); 1667 return fence->wait(IOMX::kFenceTimeoutMs); 1668 } 1669 return OK; 1670} 1671 1672int OMXNodeInstance::retrieveFenceFromMeta_l( 1673 OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) { 1674 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen; 1675 int fenceFd = -1; 1676 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1677 && header->nAllocLen >= sizeof(VideoNativeMetadata)) { 1678 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1679 if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 1680 fenceFd = nativeMeta.nFenceFd; 1681 nativeMeta.nFenceFd = -1; 1682 } 1683 if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) { 1684 CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER( 1685 NULL, header, nativeMeta.nFenceFd)); 1686 fenceFd = -1; 1687 } 1688 } 1689 return fenceFd; 1690} 1691 1692status_t OMXNodeInstance::emptyBuffer_l( 1693 OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, 1694 intptr_t debugAddr, int fenceFd) { 1695 header->nFlags = flags; 1696 header->nTimeStamp = timestamp; 1697 1698 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput); 1699 if (res != OK) { 1700 CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS( 1701 FULL_BUFFER(debugAddr, header, fenceFd))); 1702 return res; 1703 } 1704 1705 { 1706 Mutex::Autolock _l(mDebugLock); 1707 mInputBuffersWithCodec.add(header); 1708 1709 // bump internal-state debug level for 2 input frames past a buffer with CSD 1710 if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) { 1711 bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */); 1712 } 1713 1714 CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd))); 1715 } 1716 1717 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 1718 CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd)); 1719 1720 { 1721 Mutex::Autolock _l(mDebugLock); 1722 if (err != OMX_ErrorNone) { 1723 mInputBuffersWithCodec.remove(header); 1724 } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1725 unbumpDebugLevel_l(kPortIndexInput); 1726 } 1727 } 1728 1729 return StatusFromOMXError(err); 1730} 1731 1732// like emptyBuffer, but the data is already in header->pBuffer 1733status_t OMXNodeInstance::emptyGraphicBuffer_l( 1734 IOMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer, 1735 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1736 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); 1737 if (header == NULL) { 1738 ALOGE("b/25884056"); 1739 return BAD_VALUE; 1740 } 1741 1742 status_t err = updateGraphicBufferInMeta_l( 1743 kPortIndexInput, graphicBuffer, buffer, header); 1744 if (err != OK) { 1745 CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER( 1746 (intptr_t)header->pBuffer, header, fenceFd)); 1747 return err; 1748 } 1749 1750 int64_t codecTimeUs = getCodecTimestamp(timestamp); 1751 1752 header->nOffset = 0; 1753 if (graphicBuffer == NULL) { 1754 header->nFilledLen = 0; 1755 } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) { 1756 header->nFilledLen = sizeof(VideoGrallocMetadata); 1757 } else { 1758 header->nFilledLen = sizeof(VideoNativeMetadata); 1759 } 1760 return emptyBuffer_l(header, flags, codecTimeUs, (intptr_t)header->pBuffer, fenceFd); 1761} 1762 1763status_t OMXNodeInstance::setMaxPtsGapUs(const void *params, size_t size) { 1764 if (params == NULL || size != sizeof(OMX_PARAM_U32TYPE)) { 1765 CLOG_ERROR(setMaxPtsGapUs, BAD_VALUE, "invalid params (%p,%zu)", params, size); 1766 return BAD_VALUE; 1767 } 1768 1769 mMaxTimestampGapUs = (int64_t)((OMX_PARAM_U32TYPE*)params)->nU32; 1770 1771 return OK; 1772} 1773 1774int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) { 1775 int64_t originalTimeUs = timestamp; 1776 1777 if (mMaxTimestampGapUs > 0ll) { 1778 /* Cap timestamp gap between adjacent frames to specified max 1779 * 1780 * In the scenario of cast mirroring, encoding could be suspended for 1781 * prolonged periods. Limiting the pts gap to workaround the problem 1782 * where encoder's rate control logic produces huge frames after a 1783 * long period of suspension. 1784 */ 1785 if (mPrevOriginalTimeUs >= 0ll) { 1786 int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs; 1787 timestamp = (timestampGapUs < mMaxTimestampGapUs ? 1788 timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs; 1789 } 1790 ALOGV("IN timestamp: %lld -> %lld", 1791 static_cast<long long>(originalTimeUs), 1792 static_cast<long long>(timestamp)); 1793 } 1794 1795 mPrevOriginalTimeUs = originalTimeUs; 1796 mPrevModifiedTimeUs = timestamp; 1797 1798 if (mMaxTimestampGapUs > 0ll && !mRestorePtsFailed) { 1799 mOriginalTimeUs.add(timestamp, originalTimeUs); 1800 } 1801 1802 return timestamp; 1803} 1804 1805status_t OMXNodeInstance::emptyNativeHandleBuffer_l( 1806 IOMX::buffer_id buffer, const sp<NativeHandle> &nativeHandle, 1807 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1808 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); 1809 if (header == NULL) { 1810 ALOGE("b/25884056"); 1811 return BAD_VALUE; 1812 } 1813 1814 status_t err = updateNativeHandleInMeta_l( 1815 kPortIndexInput, nativeHandle, buffer, header); 1816 if (err != OK) { 1817 CLOG_ERROR(emptyNativeHandleBuffer_l, err, FULL_BUFFER( 1818 (intptr_t)header->pBuffer, header, fenceFd)); 1819 return err; 1820 } 1821 1822 header->nOffset = 0; 1823 header->nFilledLen = (nativeHandle == NULL) ? 0 : sizeof(VideoNativeMetadata); 1824 1825 return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd); 1826} 1827 1828void OMXNodeInstance::codecBufferFilled(omx_message &msg) { 1829 Mutex::Autolock autoLock(mBufferIDLock); 1830 1831 if (mMaxTimestampGapUs <= 0ll || mRestorePtsFailed) { 1832 return; 1833 } 1834 1835 OMX_U32 &flags = msg.u.extended_buffer_data.flags; 1836 OMX_TICKS ×tamp = msg.u.extended_buffer_data.timestamp; 1837 1838 if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1839 ssize_t index = mOriginalTimeUs.indexOfKey(timestamp); 1840 if (index >= 0) { 1841 ALOGV("OUT timestamp: %lld -> %lld", 1842 static_cast<long long>(timestamp), 1843 static_cast<long long>(mOriginalTimeUs[index])); 1844 timestamp = mOriginalTimeUs[index]; 1845 mOriginalTimeUs.removeItemsAt(index); 1846 } else { 1847 // giving up the effort as encoder doesn't appear to preserve pts 1848 ALOGW("giving up limiting timestamp gap (pts = %lld)", timestamp); 1849 mRestorePtsFailed = true; 1850 } 1851 } 1852} 1853 1854status_t OMXNodeInstance::getExtensionIndex( 1855 const char *parameterName, OMX_INDEXTYPE *index) { 1856 Mutex::Autolock autoLock(mLock); 1857 1858 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 1859 mHandle, const_cast<char *>(parameterName), index); 1860 1861 return StatusFromOMXError(err); 1862} 1863 1864status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) { 1865 mDispatcher->post(msg, true /*realTime*/); 1866 return OK; 1867} 1868 1869status_t OMXNodeInstance::setQuirks(OMX_U32 quirks) { 1870 if (quirks & ~kQuirksMask) { 1871 return BAD_VALUE; 1872 } 1873 1874 mQuirks = quirks; 1875 1876 return OK; 1877} 1878 1879bool OMXNodeInstance::handleMessage(omx_message &msg) { 1880 if (msg.type == omx_message::FILL_BUFFER_DONE) { 1881 OMX_BUFFERHEADERTYPE *buffer = 1882 findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput); 1883 if (buffer == NULL) { 1884 ALOGE("b/25884056"); 1885 return false; 1886 } 1887 1888 { 1889 Mutex::Autolock _l(mDebugLock); 1890 mOutputBuffersWithCodec.remove(buffer); 1891 1892 CLOG_BUMPED_BUFFER( 1893 FBD, WITH_STATS(FULL_BUFFER( 1894 msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd))); 1895 1896 unbumpDebugLevel_l(kPortIndexOutput); 1897 } 1898 1899 BufferMeta *buffer_meta = 1900 static_cast<BufferMeta *>(buffer->pAppPrivate); 1901 1902 if (buffer->nOffset + buffer->nFilledLen < buffer->nOffset 1903 || buffer->nOffset + buffer->nFilledLen > buffer->nAllocLen) { 1904 CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter, 1905 FULL_BUFFER(NULL, buffer, msg.fenceFd)); 1906 } 1907 buffer_meta->CopyFromOMX(buffer); 1908 1909 // fix up the buffer info (especially timestamp) if needed 1910 codecBufferFilled(msg); 1911 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 1912 OMX_BUFFERHEADERTYPE *buffer = 1913 findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput); 1914 if (buffer == NULL) { 1915 return false; 1916 } 1917 1918 { 1919 Mutex::Autolock _l(mDebugLock); 1920 mInputBuffersWithCodec.remove(buffer); 1921 1922 CLOG_BUMPED_BUFFER( 1923 EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd))); 1924 } 1925 1926 const sp<IOMXBufferSource> bufferSource(getBufferSource()); 1927 1928 if (bufferSource != NULL) { 1929 // This is one of the buffers used exclusively by IOMXBufferSource. 1930 // Don't dispatch a message back to ACodec, since it doesn't 1931 // know that anyone asked to have the buffer emptied and will 1932 // be very confused. 1933 bufferSource->onInputBufferEmptied( 1934 msg.u.buffer_data.buffer, OMXFenceParcelable(msg.fenceFd)); 1935 return true; 1936 } 1937 } else if (msg.type == omx_message::EVENT && 1938 msg.u.event_data.event == OMX_EventDataSpaceChanged) { 1939 handleDataSpaceChanged(msg); 1940 } 1941 1942 return false; 1943} 1944 1945bool OMXNodeInstance::handleDataSpaceChanged(omx_message &msg) { 1946 android_dataspace dataSpace = (android_dataspace) msg.u.event_data.data1; 1947 android_dataspace origDataSpace = dataSpace; 1948 1949 if (!ColorUtils::convertDataSpaceToV0(dataSpace)) { 1950 // Do not process the data space change, don't notify client either 1951 return true; 1952 } 1953 1954 android_pixel_format pixelFormat = (android_pixel_format)msg.u.event_data.data3; 1955 1956 ColorAspects requestedAspects = ColorUtils::unpackToColorAspects(msg.u.event_data.data2); 1957 ColorAspects aspects = requestedAspects; // initially requested aspects 1958 1959 // request color aspects to encode 1960 OMX_INDEXTYPE index; 1961 status_t err = getExtensionIndex( 1962 "OMX.google.android.index.describeColorAspects", &index); 1963 if (err == OK) { 1964 // V0 dataspace 1965 DescribeColorAspectsParams params; 1966 InitOMXParams(¶ms); 1967 params.nPortIndex = kPortIndexInput; 1968 params.nDataSpace = origDataSpace; 1969 params.nPixelFormat = pixelFormat; 1970 params.bDataSpaceChanged = OMX_TRUE; 1971 params.sAspects = requestedAspects; 1972 1973 err = getConfig(index, ¶ms, sizeof(params)); 1974 if (err == OK) { 1975 aspects = params.sAspects; 1976 ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 1977 params.sAspects.mRange, asString(params.sAspects.mRange), 1978 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 1979 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 1980 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 1981 err, asString(err)); 1982 } else { 1983 params.sAspects = aspects; 1984 err = OK; 1985 } 1986 params.bDataSpaceChanged = OMX_FALSE; 1987 for (int triesLeft = 2; --triesLeft >= 0; ) { 1988 status_t err = setConfig(index, ¶ms, sizeof(params)); 1989 if (err == OK) { 1990 err = getConfig(index, ¶ms, sizeof(params)); 1991 } 1992 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 1993 params.sAspects, aspects)) { 1994 // if we can't set or get color aspects, still communicate dataspace to client 1995 break; 1996 } 1997 1998 ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects."); 1999 } 2000 } 2001 2002 ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 2003 aspects.mRange, asString(aspects.mRange), 2004 aspects.mPrimaries, asString(aspects.mPrimaries), 2005 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 2006 aspects.mTransfer, asString(aspects.mTransfer), 2007 err, asString(err)); 2008 2009 // signal client that the dataspace has changed; this will update the output format 2010 // TODO: we should tie this to an output buffer somehow, and signal the change 2011 // just before the output buffer is returned to the client, but there are many 2012 // ways this could fail (e.g. flushing), and we are not yet supporting this scenario. 2013 2014 msg.u.event_data.data1 = (OMX_U32) dataSpace; 2015 msg.u.event_data.data2 = (OMX_U32) ColorUtils::packToU32(aspects); 2016 2017 return false; 2018} 2019 2020void OMXNodeInstance::onMessages(std::list<omx_message> &messages) { 2021 for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) { 2022 if (handleMessage(*it)) { 2023 messages.erase(it++); 2024 } else { 2025 ++it; 2026 } 2027 } 2028 2029 if (!messages.empty()) { 2030 mObserver->onMessages(messages); 2031 } 2032} 2033 2034void OMXNodeInstance::onObserverDied() { 2035 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 2036 2037 // Try to force shutdown of the node and hope for the best. 2038 freeNode(); 2039} 2040 2041// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 2042// Don't try to acquire mLock here -- in rare circumstances this will hang. 2043void OMXNodeInstance::onEvent( 2044 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 2045 const char *arg1String = "??"; 2046 const char *arg2String = "??"; 2047 ADebug::Level level = ADebug::kDebugInternalState; 2048 2049 switch (event) { 2050 case OMX_EventCmdComplete: 2051 arg1String = asString((OMX_COMMANDTYPE)arg1); 2052 switch (arg1) { 2053 case OMX_CommandStateSet: 2054 arg2String = asString((OMX_STATETYPE)arg2); 2055 level = ADebug::kDebugState; 2056 break; 2057 case OMX_CommandFlush: 2058 case OMX_CommandPortEnable: 2059 { 2060 // bump internal-state debug level for 2 input and output frames 2061 Mutex::Autolock _l(mDebugLock); 2062 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 2063 } 2064 // fall through 2065 default: 2066 arg2String = portString(arg2); 2067 } 2068 break; 2069 case OMX_EventError: 2070 arg1String = asString((OMX_ERRORTYPE)arg1); 2071 level = ADebug::kDebugLifeCycle; 2072 break; 2073 case OMX_EventPortSettingsChanged: 2074 arg2String = asString((OMX_INDEXEXTTYPE)arg2); 2075 // fall through 2076 default: 2077 arg1String = portString(arg1); 2078 } 2079 2080 CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)", 2081 asString(event), event, arg1String, arg1, arg2String, arg2); 2082 const sp<IOMXBufferSource> bufferSource(getBufferSource()); 2083 2084 if (bufferSource != NULL 2085 && event == OMX_EventCmdComplete 2086 && arg1 == OMX_CommandStateSet 2087 && arg2 == OMX_StateExecuting) { 2088 bufferSource->onOmxExecuting(); 2089 } 2090 2091 // allow configuration if we return to the loaded state 2092 if (event == OMX_EventCmdComplete 2093 && arg1 == OMX_CommandStateSet 2094 && arg2 == OMX_StateLoaded) { 2095 mSailed = false; 2096 } 2097} 2098 2099// static 2100OMX_ERRORTYPE OMXNodeInstance::OnEvent( 2101 OMX_IN OMX_HANDLETYPE /* hComponent */, 2102 OMX_IN OMX_PTR pAppData, 2103 OMX_IN OMX_EVENTTYPE eEvent, 2104 OMX_IN OMX_U32 nData1, 2105 OMX_IN OMX_U32 nData2, 2106 OMX_IN OMX_PTR pEventData) { 2107 if (pAppData == NULL) { 2108 ALOGE("b/25884056"); 2109 return OMX_ErrorBadParameter; 2110 } 2111 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 2112 if (instance->mDying) { 2113 return OMX_ErrorNone; 2114 } 2115 2116 instance->onEvent(eEvent, nData1, nData2); 2117 2118 // output rendered events are not processed as regular events until they hit the observer 2119 if (eEvent == OMX_EventOutputRendered) { 2120 if (pEventData == NULL) { 2121 return OMX_ErrorBadParameter; 2122 } 2123 2124 // process data from array 2125 OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData; 2126 for (size_t i = 0; i < nData1; ++i) { 2127 omx_message msg; 2128 msg.type = omx_message::FRAME_RENDERED; 2129 msg.fenceFd = -1; 2130 msg.u.render_data.timestamp = renderData[i].nMediaTimeUs; 2131 msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs; 2132 2133 instance->mDispatcher->post(msg, false /* realTime */); 2134 } 2135 return OMX_ErrorNone; 2136 } 2137 2138 omx_message msg; 2139 msg.type = omx_message::EVENT; 2140 msg.fenceFd = -1; 2141 msg.u.event_data.event = eEvent; 2142 msg.u.event_data.data1 = nData1; 2143 msg.u.event_data.data2 = nData2; 2144 2145 instance->mDispatcher->post(msg, true /* realTime */); 2146 2147 return OMX_ErrorNone; 2148} 2149 2150// static 2151OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 2152 OMX_IN OMX_HANDLETYPE /* hComponent */, 2153 OMX_IN OMX_PTR pAppData, 2154 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 2155 if (pAppData == NULL) { 2156 ALOGE("b/25884056"); 2157 return OMX_ErrorBadParameter; 2158 } 2159 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 2160 if (instance->mDying) { 2161 return OMX_ErrorNone; 2162 } 2163 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 2164 2165 omx_message msg; 2166 msg.type = omx_message::EMPTY_BUFFER_DONE; 2167 msg.fenceFd = fenceFd; 2168 msg.u.buffer_data.buffer = instance->findBufferID(pBuffer); 2169 instance->mDispatcher->post(msg); 2170 2171 return OMX_ErrorNone; 2172} 2173 2174// static 2175OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 2176 OMX_IN OMX_HANDLETYPE /* hComponent */, 2177 OMX_IN OMX_PTR pAppData, 2178 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 2179 if (pAppData == NULL) { 2180 ALOGE("b/25884056"); 2181 return OMX_ErrorBadParameter; 2182 } 2183 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 2184 if (instance->mDying) { 2185 return OMX_ErrorNone; 2186 } 2187 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 2188 2189 omx_message msg; 2190 msg.type = omx_message::FILL_BUFFER_DONE; 2191 msg.fenceFd = fenceFd; 2192 msg.u.extended_buffer_data.buffer = instance->findBufferID(pBuffer); 2193 msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; 2194 msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; 2195 msg.u.extended_buffer_data.flags = pBuffer->nFlags; 2196 msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; 2197 instance->mDispatcher->post(msg); 2198 2199 return OMX_ErrorNone; 2200} 2201 2202void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, IOMX::buffer_id id) { 2203 ActiveBuffer active; 2204 active.mPortIndex = portIndex; 2205 active.mID = id; 2206 mActiveBuffers.push(active); 2207 2208 if (portIndex < NELEM(mNumPortBuffers)) { 2209 ++mNumPortBuffers[portIndex]; 2210 } 2211} 2212 2213void OMXNodeInstance::removeActiveBuffer( 2214 OMX_U32 portIndex, IOMX::buffer_id id) { 2215 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 2216 if (mActiveBuffers[i].mPortIndex == portIndex 2217 && mActiveBuffers[i].mID == id) { 2218 mActiveBuffers.removeItemsAt(i); 2219 2220 if (portIndex < NELEM(mNumPortBuffers)) { 2221 --mNumPortBuffers[portIndex]; 2222 } 2223 return; 2224 } 2225 } 2226 2227 CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id); 2228} 2229 2230void OMXNodeInstance::freeActiveBuffers() { 2231 // Make sure to count down here, as freeBuffer will in turn remove 2232 // the active buffer from the vector... 2233 for (size_t i = mActiveBuffers.size(); i > 0;) { 2234 i--; 2235 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 2236 } 2237} 2238 2239IOMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 2240 if (bufferHeader == NULL) { 2241 return 0; 2242 } 2243 Mutex::Autolock autoLock(mBufferIDLock); 2244 IOMX::buffer_id buffer; 2245 do { // handle the very unlikely case of ID overflow 2246 if (++mBufferIDCount == 0) { 2247 ++mBufferIDCount; 2248 } 2249 buffer = (IOMX::buffer_id)mBufferIDCount; 2250 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); 2251 mBufferIDToBufferHeader.add(buffer, bufferHeader); 2252 mBufferHeaderToBufferID.add(bufferHeader, buffer); 2253 return buffer; 2254} 2255 2256OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader( 2257 IOMX::buffer_id buffer, OMX_U32 portIndex) { 2258 if (buffer == 0) { 2259 return NULL; 2260 } 2261 Mutex::Autolock autoLock(mBufferIDLock); 2262 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer); 2263 if (index < 0) { 2264 CLOGW("findBufferHeader: buffer %u not found", buffer); 2265 return NULL; 2266 } 2267 OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index); 2268 BufferMeta *buffer_meta = 2269 static_cast<BufferMeta *>(header->pAppPrivate); 2270 if (buffer_meta->getPortIndex() != portIndex) { 2271 CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer); 2272 android_errorWriteLog(0x534e4554, "28816827"); 2273 return NULL; 2274 } 2275 return header; 2276} 2277 2278IOMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 2279 if (bufferHeader == NULL) { 2280 return 0; 2281 } 2282 Mutex::Autolock autoLock(mBufferIDLock); 2283 ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader); 2284 if (index < 0) { 2285 CLOGW("findBufferID: bufferHeader %p not found", bufferHeader); 2286 return 0; 2287 } 2288 return mBufferHeaderToBufferID.valueAt(index); 2289} 2290 2291void OMXNodeInstance::invalidateBufferID(IOMX::buffer_id buffer) { 2292 if (buffer == 0) { 2293 return; 2294 } 2295 Mutex::Autolock autoLock(mBufferIDLock); 2296 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer); 2297 if (index < 0) { 2298 CLOGW("invalidateBufferID: buffer %u not found", buffer); 2299 return; 2300 } 2301 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index)); 2302 mBufferIDToBufferHeader.removeItemsAt(index); 2303} 2304 2305} // namespace android 2306