OMXNodeInstance.cpp revision 15ab4996019387f27a48b81cb4774c21502bc0e5
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 "GraphicBufferSource.h" 26 27#include <OMX_Component.h> 28#include <OMX_IndexExt.h> 29#include <OMX_AsString.h> 30 31#include <binder/IMemory.h> 32#include <gui/BufferQueue.h> 33#include <HardwareAPI.h> 34#include <media/stagefright/foundation/ADebug.h> 35#include <media/stagefright/foundation/ABuffer.h> 36#include <media/stagefright/MediaErrors.h> 37 38#include <utils/misc.h> 39 40static const OMX_U32 kPortIndexInput = 0; 41static const OMX_U32 kPortIndexOutput = 1; 42 43#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__) 44 45#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \ 46 ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \ 47 mNodeID, mName, ##__VA_ARGS__, asString(err), err) 48#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__) 49#define CLOG_IF_ERROR(fn, err, fmt, ...) \ 50 CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__) 51 52#define CLOGI_(level, fn, fmt, ...) \ 53 ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__) 54#define CLOGD_(level, fn, fmt, ...) \ 55 ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__) 56 57#define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__) 58#define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__) 59#define CLOG_CONFIG(fn, fmt, ...) CLOGI_(ADebug::kDebugConfig, fn, fmt, ##__VA_ARGS__) 60#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__) 61 62#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \ 63 ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__) 64 65#define CLOG_BUFFER(fn, fmt, ...) \ 66 CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 67#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \ 68 CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 69 70/* buffer formatting */ 71#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__ 72#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \ 73 BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id)) 74 75#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data)) 76#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \ 77 NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data)) 78 79#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \ 80 (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd) 81#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \ 82 (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \ 83 (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd) 84 85#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \ 86 mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \ 87 mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput] 88// TRICKY: this is needed so formatting macros expand before substitution 89#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__) 90 91template<class T> 92static void InitOMXParams(T *params) { 93 memset(params, 0, sizeof(T)); 94 params->nSize = sizeof(T); 95 params->nVersion.s.nVersionMajor = 1; 96 params->nVersion.s.nVersionMinor = 0; 97 params->nVersion.s.nRevision = 0; 98 params->nVersion.s.nStep = 0; 99} 100 101namespace android { 102 103struct BufferMeta { 104 BufferMeta(const sp<IMemory> &mem, bool is_backup = false) 105 : mMem(mem), 106 mIsBackup(is_backup) { 107 } 108 109 BufferMeta(size_t size) 110 : mSize(size), 111 mIsBackup(false) { 112 } 113 114 BufferMeta(const sp<GraphicBuffer> &graphicBuffer) 115 : mGraphicBuffer(graphicBuffer), 116 mIsBackup(false) { 117 } 118 119 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 120 if (!mIsBackup) { 121 return; 122 } 123 124 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 125 header->pBuffer + header->nOffset, 126 header->nFilledLen); 127 } 128 129 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 130 if (!mIsBackup) { 131 return; 132 } 133 134 memcpy(header->pBuffer + header->nOffset, 135 (const OMX_U8 *)mMem->pointer() + header->nOffset, 136 header->nFilledLen); 137 } 138 139 // return either the codec or the backup buffer 140 sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup) { 141 sp<ABuffer> buf; 142 if (backup && mMem != NULL) { 143 buf = new ABuffer(mMem->pointer(), mMem->size()); 144 } else { 145 buf = new ABuffer(header->pBuffer, header->nAllocLen); 146 } 147 buf->setRange(header->nOffset, header->nFilledLen); 148 return buf; 149 } 150 151 void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { 152 mGraphicBuffer = graphicBuffer; 153 } 154 155private: 156 sp<GraphicBuffer> mGraphicBuffer; 157 sp<IMemory> mMem; 158 size_t mSize; 159 bool mIsBackup; 160 161 BufferMeta(const BufferMeta &); 162 BufferMeta &operator=(const BufferMeta &); 163}; 164 165// static 166OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 167 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 168}; 169 170static inline const char *portString(OMX_U32 portIndex) { 171 switch (portIndex) { 172 case kPortIndexInput: return "Input"; 173 case kPortIndexOutput: return "Output"; 174 case ~0U: return "All"; 175 default: return "port"; 176 } 177} 178 179OMXNodeInstance::OMXNodeInstance( 180 OMX *owner, const sp<IOMXObserver> &observer, const char *name) 181 : mOwner(owner), 182 mNodeID(0), 183 mHandle(NULL), 184 mObserver(observer), 185 mDying(false), 186 mBufferIDCount(0) 187{ 188 mName = ADebug::GetDebugName(name); 189 DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug"); 190 ALOGV("debug level for %s is %d", name, DEBUG); 191 DEBUG_BUMP = DEBUG; 192 mNumPortBuffers[0] = 0; 193 mNumPortBuffers[1] = 0; 194 mDebugLevelBumpPendingBuffers[0] = 0; 195 mDebugLevelBumpPendingBuffers[1] = 0; 196 mMetadataType[0] = kMetadataBufferTypeInvalid; 197 mMetadataType[1] = kMetadataBufferTypeInvalid; 198} 199 200OMXNodeInstance::~OMXNodeInstance() { 201 free(mName); 202 CHECK(mHandle == NULL); 203} 204 205void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 206 mNodeID = node_id; 207 CLOG_LIFE(allocateNode, "handle=%p", handle); 208 CHECK(mHandle == NULL); 209 mHandle = handle; 210} 211 212sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() { 213 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 214 return mGraphicBufferSource; 215} 216 217void OMXNodeInstance::setGraphicBufferSource( 218 const sp<GraphicBufferSource>& bufferSource) { 219 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 220 CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get()); 221 mGraphicBufferSource = bufferSource; 222} 223 224OMX *OMXNodeInstance::owner() { 225 return mOwner; 226} 227 228sp<IOMXObserver> OMXNodeInstance::observer() { 229 return mObserver; 230} 231 232OMX::node_id OMXNodeInstance::nodeID() { 233 return mNodeID; 234} 235 236status_t StatusFromOMXError(OMX_ERRORTYPE err) { 237 switch (err) { 238 case OMX_ErrorNone: 239 return OK; 240 case OMX_ErrorUnsupportedSetting: 241 case OMX_ErrorUnsupportedIndex: 242 return ERROR_UNSUPPORTED; 243 case OMX_ErrorInsufficientResources: 244 return NO_MEMORY; 245 default: 246 return UNKNOWN_ERROR; 247 } 248} 249 250status_t OMXNodeInstance::freeNode(OMXMaster *master) { 251 CLOG_LIFE(freeNode, "handle=%p", mHandle); 252 static int32_t kMaxNumIterations = 10; 253 254 // exit if we have already freed the node 255 if (mHandle == NULL) { 256 return OK; 257 } 258 259 // Transition the node from its current state all the way down 260 // to "Loaded". 261 // This ensures that all active buffers are properly freed even 262 // for components that don't do this themselves on a call to 263 // "FreeHandle". 264 265 // The code below may trigger some more events to be dispatched 266 // by the OMX component - we want to ignore them as our client 267 // does not expect them. 268 mDying = true; 269 270 OMX_STATETYPE state; 271 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 272 switch (state) { 273 case OMX_StateExecuting: 274 { 275 ALOGV("forcing Executing->Idle"); 276 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 277 OMX_ERRORTYPE err; 278 int32_t iteration = 0; 279 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 280 && state != OMX_StateIdle 281 && state != OMX_StateInvalid) { 282 if (++iteration > kMaxNumIterations) { 283 CLOGW("failed to enter Idle state (now %s(%d), aborting.", 284 asString(state), state); 285 state = OMX_StateInvalid; 286 break; 287 } 288 289 usleep(100000); 290 } 291 CHECK_EQ(err, OMX_ErrorNone); 292 293 if (state == OMX_StateInvalid) { 294 break; 295 } 296 297 // fall through 298 } 299 300 case OMX_StateIdle: 301 { 302 ALOGV("forcing Idle->Loaded"); 303 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 304 305 freeActiveBuffers(); 306 307 OMX_ERRORTYPE err; 308 int32_t iteration = 0; 309 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 310 && state != OMX_StateLoaded 311 && state != OMX_StateInvalid) { 312 if (++iteration > kMaxNumIterations) { 313 CLOGW("failed to enter Loaded state (now %s(%d), aborting.", 314 asString(state), state); 315 state = OMX_StateInvalid; 316 break; 317 } 318 319 ALOGV("waiting for Loaded state..."); 320 usleep(100000); 321 } 322 CHECK_EQ(err, OMX_ErrorNone); 323 324 // fall through 325 } 326 327 case OMX_StateLoaded: 328 case OMX_StateInvalid: 329 break; 330 331 default: 332 LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state); 333 break; 334 } 335 336 ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName); 337 OMX_ERRORTYPE err = master->destroyComponentInstance( 338 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 339 340 mHandle = NULL; 341 CLOG_IF_ERROR(freeNode, err, ""); 342 free(mName); 343 mName = NULL; 344 345 mOwner->invalidateNodeID(mNodeID); 346 mNodeID = 0; 347 348 ALOGV("OMXNodeInstance going away."); 349 delete this; 350 351 return StatusFromOMXError(err); 352} 353 354status_t OMXNodeInstance::sendCommand( 355 OMX_COMMANDTYPE cmd, OMX_S32 param) { 356 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 357 if (bufferSource != NULL && cmd == OMX_CommandStateSet) { 358 if (param == OMX_StateIdle) { 359 // Initiating transition from Executing -> Idle 360 // ACodec is waiting for all buffers to be returned, do NOT 361 // submit any more buffers to the codec. 362 bufferSource->omxIdle(); 363 } else if (param == OMX_StateLoaded) { 364 // Initiating transition from Idle/Executing -> Loaded 365 // Buffers are about to be freed. 366 bufferSource->omxLoaded(); 367 setGraphicBufferSource(NULL); 368 } 369 370 // fall through 371 } 372 373 Mutex::Autolock autoLock(mLock); 374 375 // bump internal-state debug level for 2 input and output frames past a command 376 { 377 Mutex::Autolock _l(mDebugLock); 378 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 379 } 380 381 const char *paramString = 382 cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param); 383 CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 384 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 385 CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 386 return StatusFromOMXError(err); 387} 388 389status_t OMXNodeInstance::getParameter( 390 OMX_INDEXTYPE index, void *params, size_t /* size */) { 391 Mutex::Autolock autoLock(mLock); 392 393 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 394 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 395 // some errors are expected for getParameter 396 if (err != OMX_ErrorNoMore) { 397 CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index); 398 } 399 return StatusFromOMXError(err); 400} 401 402status_t OMXNodeInstance::setParameter( 403 OMX_INDEXTYPE index, const void *params, size_t size) { 404 Mutex::Autolock autoLock(mLock); 405 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 406 CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 407 408 OMX_ERRORTYPE err = OMX_SetParameter( 409 mHandle, index, const_cast<void *>(params)); 410 CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index); 411 return StatusFromOMXError(err); 412} 413 414status_t OMXNodeInstance::getConfig( 415 OMX_INDEXTYPE index, void *params, size_t /* size */) { 416 Mutex::Autolock autoLock(mLock); 417 418 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 419 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 420 // some errors are expected for getConfig 421 if (err != OMX_ErrorNoMore) { 422 CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index); 423 } 424 return StatusFromOMXError(err); 425} 426 427status_t OMXNodeInstance::setConfig( 428 OMX_INDEXTYPE index, const void *params, size_t size) { 429 Mutex::Autolock autoLock(mLock); 430 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 431 CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 432 433 OMX_ERRORTYPE err = OMX_SetConfig( 434 mHandle, index, const_cast<void *>(params)); 435 CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index); 436 return StatusFromOMXError(err); 437} 438 439status_t OMXNodeInstance::getState(OMX_STATETYPE* state) { 440 Mutex::Autolock autoLock(mLock); 441 442 OMX_ERRORTYPE err = OMX_GetState(mHandle, state); 443 CLOG_IF_ERROR(getState, err, ""); 444 return StatusFromOMXError(err); 445} 446 447status_t OMXNodeInstance::enableGraphicBuffers( 448 OMX_U32 portIndex, OMX_BOOL enable) { 449 Mutex::Autolock autoLock(mLock); 450 CLOG_CONFIG(enableGraphicBuffers, "%s:%u, %d", portString(portIndex), portIndex, enable); 451 OMX_STRING name = const_cast<OMX_STRING>( 452 "OMX.google.android.index.enableAndroidNativeBuffers"); 453 454 OMX_INDEXTYPE index; 455 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 456 457 if (err != OMX_ErrorNone) { 458 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 459 return StatusFromOMXError(err); 460 } 461 462 EnableAndroidNativeBuffersParams params; 463 InitOMXParams(¶ms); 464 params.nPortIndex = portIndex; 465 params.enable = enable; 466 467 err = OMX_SetParameter(mHandle, index, ¶ms); 468 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index, 469 portString(portIndex), portIndex, enable); 470 return StatusFromOMXError(err); 471} 472 473status_t OMXNodeInstance::getGraphicBufferUsage( 474 OMX_U32 portIndex, OMX_U32* usage) { 475 Mutex::Autolock autoLock(mLock); 476 477 OMX_INDEXTYPE index; 478 OMX_STRING name = const_cast<OMX_STRING>( 479 "OMX.google.android.index.getAndroidNativeBufferUsage"); 480 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 481 482 if (err != OMX_ErrorNone) { 483 CLOG_ERROR(getExtensionIndex, err, "%s", name); 484 return StatusFromOMXError(err); 485 } 486 487 GetAndroidNativeBufferUsageParams params; 488 InitOMXParams(¶ms); 489 params.nPortIndex = portIndex; 490 491 err = OMX_GetParameter(mHandle, index, ¶ms); 492 if (err != OMX_ErrorNone) { 493 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index, 494 portString(portIndex), portIndex); 495 return StatusFromOMXError(err); 496 } 497 498 *usage = params.nUsage; 499 500 return OK; 501} 502 503status_t OMXNodeInstance::storeMetaDataInBuffers( 504 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { 505 Mutex::Autolock autolock(mLock); 506 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable); 507 return storeMetaDataInBuffers_l(portIndex, enable, type); 508} 509 510status_t OMXNodeInstance::storeMetaDataInBuffers_l( 511 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { 512 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 513 return BAD_VALUE; 514 } 515 516 OMX_INDEXTYPE index; 517 OMX_STRING name = const_cast<OMX_STRING>( 518 "OMX.google.android.index.storeMetaDataInBuffers"); 519 520 OMX_STRING nativeBufferName = const_cast<OMX_STRING>( 521 "OMX.google.android.index.storeANWBufferInMetadata"); 522 MetadataBufferType negotiatedType; 523 524 StoreMetaDataInBuffersParams params; 525 InitOMXParams(¶ms); 526 params.nPortIndex = portIndex; 527 params.bStoreMetaData = enable; 528 529 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, nativeBufferName, &index); 530 OMX_ERRORTYPE xerr = err; 531 if (err == OMX_ErrorNone) { 532 err = OMX_SetParameter(mHandle, index, ¶ms); 533 if (err == OMX_ErrorNone) { 534 name = nativeBufferName; // set name for debugging 535 negotiatedType = kMetadataBufferTypeANWBuffer; 536 } 537 } 538 if (err != OMX_ErrorNone) { 539 err = OMX_GetExtensionIndex(mHandle, name, &index); 540 xerr = err; 541 if (err == OMX_ErrorNone) { 542 negotiatedType = kMetadataBufferTypeGrallocSource; 543 err = OMX_SetParameter(mHandle, index, ¶ms); 544 } 545 } 546 547 // don't log loud error if component does not support metadata mode on the output 548 if (err != OMX_ErrorNone) { 549 if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) { 550 CLOGW("component does not support metadata mode; using fallback"); 551 } else if (xerr != OMX_ErrorNone) { 552 CLOG_ERROR(getExtensionIndex, xerr, "%s", name); 553 } else { 554 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index, 555 portString(portIndex), portIndex, enable, negotiatedType); 556 } 557 negotiatedType = mMetadataType[portIndex]; 558 } else { 559 if (!enable) { 560 negotiatedType = kMetadataBufferTypeInvalid; 561 } 562 mMetadataType[portIndex] = negotiatedType; 563 } 564 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u negotiated %s:%d", 565 portString(portIndex), portIndex, asString(negotiatedType), negotiatedType); 566 567 if (type != NULL) { 568 *type = negotiatedType; 569 } 570 571 return StatusFromOMXError(err); 572} 573 574status_t OMXNodeInstance::prepareForAdaptivePlayback( 575 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, 576 OMX_U32 maxFrameHeight) { 577 Mutex::Autolock autolock(mLock); 578 CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u", 579 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 580 581 OMX_INDEXTYPE index; 582 OMX_STRING name = const_cast<OMX_STRING>( 583 "OMX.google.android.index.prepareForAdaptivePlayback"); 584 585 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 586 if (err != OMX_ErrorNone) { 587 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 588 return StatusFromOMXError(err); 589 } 590 591 PrepareForAdaptivePlaybackParams params; 592 InitOMXParams(¶ms); 593 params.nPortIndex = portIndex; 594 params.bEnable = enable; 595 params.nMaxFrameWidth = maxFrameWidth; 596 params.nMaxFrameHeight = maxFrameHeight; 597 598 err = OMX_SetParameter(mHandle, index, ¶ms); 599 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index, 600 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 601 return StatusFromOMXError(err); 602} 603 604status_t OMXNodeInstance::configureVideoTunnelMode( 605 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, 606 native_handle_t **sidebandHandle) { 607 Mutex::Autolock autolock(mLock); 608 CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u", 609 portString(portIndex), portIndex, tunneled, audioHwSync); 610 611 OMX_INDEXTYPE index; 612 OMX_STRING name = const_cast<OMX_STRING>( 613 "OMX.google.android.index.configureVideoTunnelMode"); 614 615 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 616 if (err != OMX_ErrorNone) { 617 CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name); 618 return StatusFromOMXError(err); 619 } 620 621 ConfigureVideoTunnelModeParams tunnelParams; 622 InitOMXParams(&tunnelParams); 623 tunnelParams.nPortIndex = portIndex; 624 tunnelParams.bTunneled = tunneled; 625 tunnelParams.nAudioHwSync = audioHwSync; 626 err = OMX_SetParameter(mHandle, index, &tunnelParams); 627 if (err != OMX_ErrorNone) { 628 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 629 portString(portIndex), portIndex, tunneled, audioHwSync); 630 return StatusFromOMXError(err); 631 } 632 633 err = OMX_GetParameter(mHandle, index, &tunnelParams); 634 if (err != OMX_ErrorNone) { 635 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 636 portString(portIndex), portIndex, tunneled, audioHwSync); 637 return StatusFromOMXError(err); 638 } 639 if (sidebandHandle) { 640 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; 641 } 642 643 return OK; 644} 645 646status_t OMXNodeInstance::useBuffer( 647 OMX_U32 portIndex, const sp<IMemory> ¶ms, 648 OMX::buffer_id *buffer, OMX_U32 allottedSize) { 649 Mutex::Autolock autoLock(mLock); 650 if (allottedSize > params->size()) { 651 return BAD_VALUE; 652 } 653 654 BufferMeta *buffer_meta = new BufferMeta(params); 655 656 OMX_BUFFERHEADERTYPE *header; 657 658 OMX_ERRORTYPE err = OMX_UseBuffer( 659 mHandle, &header, portIndex, buffer_meta, 660 allottedSize, static_cast<OMX_U8 *>(params->pointer())); 661 662 if (err != OMX_ErrorNone) { 663 CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER( 664 portIndex, (size_t)allottedSize, params->pointer())); 665 666 delete buffer_meta; 667 buffer_meta = NULL; 668 669 *buffer = 0; 670 671 return StatusFromOMXError(err); 672 } 673 674 CHECK_EQ(header->pAppPrivate, buffer_meta); 675 676 *buffer = makeBufferID(header); 677 678 addActiveBuffer(portIndex, *buffer); 679 680 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 681 if (bufferSource != NULL && portIndex == kPortIndexInput) { 682 bufferSource->addCodecBuffer(header); 683 } 684 685 CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT( 686 *buffer, portIndex, "%u@%p", allottedSize, params->pointer())); 687 return OK; 688} 689 690status_t OMXNodeInstance::useGraphicBuffer2_l( 691 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 692 OMX::buffer_id *buffer) { 693 694 // port definition 695 OMX_PARAM_PORTDEFINITIONTYPE def; 696 InitOMXParams(&def); 697 def.nPortIndex = portIndex; 698 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 699 if (err != OMX_ErrorNone) { 700 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 701 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", 702 asString(index), index, portString(portIndex), portIndex); 703 return UNKNOWN_ERROR; 704 } 705 706 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 707 708 OMX_BUFFERHEADERTYPE *header = NULL; 709 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 710 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 711 712 err = OMX_UseBuffer( 713 mHandle, 714 &header, 715 portIndex, 716 bufferMeta, 717 def.nBufferSize, 718 bufferHandle); 719 720 if (err != OMX_ErrorNone) { 721 CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 722 delete bufferMeta; 723 bufferMeta = NULL; 724 *buffer = 0; 725 return StatusFromOMXError(err); 726 } 727 728 CHECK_EQ(header->pBuffer, bufferHandle); 729 CHECK_EQ(header->pAppPrivate, bufferMeta); 730 731 *buffer = makeBufferID(header); 732 733 addActiveBuffer(portIndex, *buffer); 734 CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT( 735 *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 736 return OK; 737} 738 739// XXX: This function is here for backwards compatibility. Once the OMX 740// implementations have been updated this can be removed and useGraphicBuffer2 741// can be renamed to useGraphicBuffer. 742status_t OMXNodeInstance::useGraphicBuffer( 743 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 744 OMX::buffer_id *buffer) { 745 Mutex::Autolock autoLock(mLock); 746 747 // See if the newer version of the extension is present. 748 OMX_INDEXTYPE index; 749 if (OMX_GetExtensionIndex( 750 mHandle, 751 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 752 &index) == OMX_ErrorNone) { 753 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 754 } 755 756 OMX_STRING name = const_cast<OMX_STRING>( 757 "OMX.google.android.index.useAndroidNativeBuffer"); 758 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 759 if (err != OMX_ErrorNone) { 760 CLOG_ERROR(getExtensionIndex, err, "%s", name); 761 return StatusFromOMXError(err); 762 } 763 764 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); 765 766 OMX_BUFFERHEADERTYPE *header; 767 768 OMX_VERSIONTYPE ver; 769 ver.s.nVersionMajor = 1; 770 ver.s.nVersionMinor = 0; 771 ver.s.nRevision = 0; 772 ver.s.nStep = 0; 773 UseAndroidNativeBufferParams params = { 774 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 775 &header, graphicBuffer, 776 }; 777 778 err = OMX_SetParameter(mHandle, index, ¶ms); 779 780 if (err != OMX_ErrorNone) { 781 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index, 782 portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle); 783 784 delete bufferMeta; 785 bufferMeta = NULL; 786 787 *buffer = 0; 788 789 return StatusFromOMXError(err); 790 } 791 792 CHECK_EQ(header->pAppPrivate, bufferMeta); 793 794 *buffer = makeBufferID(header); 795 796 addActiveBuffer(portIndex, *buffer); 797 CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT( 798 *buffer, portIndex, "GB=%p", graphicBuffer->handle)); 799 return OK; 800} 801 802status_t OMXNodeInstance::updateGraphicBufferInMeta_l( 803 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 804 OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) { 805 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 806 return BAD_VALUE; 807 } 808 809 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 810 bufferMeta->setGraphicBuffer(graphicBuffer); 811 if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource 812 && header->nAllocLen >= sizeof(VideoGrallocMetadata)) { 813 VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(header->pBuffer); 814 metadata.eType = kMetadataBufferTypeGrallocSource; 815 metadata.hHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle; 816 } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 817 && header->nAllocLen >= sizeof(VideoNativeMetadata)) { 818 VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(header->pBuffer); 819 metadata.eType = kMetadataBufferTypeANWBuffer; 820 metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer(); 821 metadata.nFenceFd = -1; 822 } else { 823 CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x bad type (%d) or size (%u)", 824 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen); 825 return BAD_VALUE; 826 } 827 828 CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p", 829 portString(portIndex), portIndex, buffer, graphicBuffer->handle); 830 return OK; 831} 832 833status_t OMXNodeInstance::updateGraphicBufferInMeta( 834 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 835 OMX::buffer_id buffer) { 836 Mutex::Autolock autoLock(mLock); 837 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 838 return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header); 839} 840 841status_t OMXNodeInstance::createGraphicBufferSource( 842 OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) { 843 status_t err; 844 845 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); 846 if (surfaceCheck != NULL) { 847 if (portIndex < NELEM(mMetadataType) && type != NULL) { 848 *type = mMetadataType[portIndex]; 849 } 850 return ALREADY_EXISTS; 851 } 852 853 // Input buffers will hold meta-data (ANativeWindowBuffer references). 854 err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type); 855 if (err != OK) { 856 return err; 857 } 858 859 // Retrieve the width and height of the graphic buffer, set when the 860 // codec was configured. 861 OMX_PARAM_PORTDEFINITIONTYPE def; 862 InitOMXParams(&def); 863 def.nPortIndex = portIndex; 864 OMX_ERRORTYPE oerr = OMX_GetParameter( 865 mHandle, OMX_IndexParamPortDefinition, &def); 866 if (oerr != OMX_ErrorNone) { 867 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 868 CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", 869 asString(index), index, portString(portIndex), portIndex); 870 return UNKNOWN_ERROR; 871 } 872 873 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 874 CLOGW("createInputSurface requires COLOR_FormatSurface " 875 "(AndroidOpaque) color format instead of %s(%#x)", 876 asString(def.format.video.eColorFormat), def.format.video.eColorFormat); 877 return INVALID_OPERATION; 878 } 879 880 sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this, 881 def.format.video.nFrameWidth, 882 def.format.video.nFrameHeight, 883 def.nBufferCountActual, 884 bufferConsumer); 885 886 if ((err = bufferSource->initCheck()) != OK) { 887 return err; 888 } 889 setGraphicBufferSource(bufferSource); 890 891 return OK; 892} 893 894status_t OMXNodeInstance::createInputSurface( 895 OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) { 896 Mutex::Autolock autolock(mLock); 897 status_t err = createGraphicBufferSource(portIndex, NULL /* bufferConsumer */, type); 898 899 if (err != OK) { 900 return err; 901 } 902 903 *bufferProducer = mGraphicBufferSource->getIGraphicBufferProducer(); 904 return OK; 905} 906 907//static 908status_t OMXNodeInstance::createPersistentInputSurface( 909 sp<IGraphicBufferProducer> *bufferProducer, 910 sp<IGraphicBufferConsumer> *bufferConsumer) { 911 String8 name("GraphicBufferSource"); 912 913 sp<IGraphicBufferProducer> producer; 914 sp<IGraphicBufferConsumer> consumer; 915 BufferQueue::createBufferQueue(&producer, &consumer); 916 consumer->setConsumerName(name); 917 consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); 918 919 sp<BufferQueue::ProxyConsumerListener> proxy = 920 new BufferQueue::ProxyConsumerListener(NULL); 921 status_t err = consumer->consumerConnect(proxy, false); 922 if (err != NO_ERROR) { 923 ALOGE("Error connecting to BufferQueue: %s (%d)", 924 strerror(-err), err); 925 return err; 926 } 927 928 *bufferProducer = producer; 929 *bufferConsumer = consumer; 930 931 return OK; 932} 933 934status_t OMXNodeInstance::setInputSurface( 935 OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer, 936 MetadataBufferType *type) { 937 Mutex::Autolock autolock(mLock); 938 return createGraphicBufferSource(portIndex, bufferConsumer, type); 939} 940 941status_t OMXNodeInstance::signalEndOfInputStream() { 942 // For non-Surface input, the MediaCodec should convert the call to a 943 // pair of requests (dequeue input buffer, queue input buffer with EOS 944 // flag set). Seems easier than doing the equivalent from here. 945 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 946 if (bufferSource == NULL) { 947 CLOGW("signalEndOfInputStream can only be used with Surface input"); 948 return INVALID_OPERATION; 949 } 950 return bufferSource->signalEndOfInputStream(); 951} 952 953status_t OMXNodeInstance::allocateBuffer( 954 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 955 void **buffer_data) { 956 Mutex::Autolock autoLock(mLock); 957 958 BufferMeta *buffer_meta = new BufferMeta(size); 959 960 OMX_BUFFERHEADERTYPE *header; 961 962 OMX_ERRORTYPE err = OMX_AllocateBuffer( 963 mHandle, &header, portIndex, buffer_meta, size); 964 965 if (err != OMX_ErrorNone) { 966 CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size)); 967 delete buffer_meta; 968 buffer_meta = NULL; 969 970 *buffer = 0; 971 972 return StatusFromOMXError(err); 973 } 974 975 CHECK_EQ(header->pAppPrivate, buffer_meta); 976 977 *buffer = makeBufferID(header); 978 *buffer_data = header->pBuffer; 979 980 addActiveBuffer(portIndex, *buffer); 981 982 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 983 if (bufferSource != NULL && portIndex == kPortIndexInput) { 984 bufferSource->addCodecBuffer(header); 985 } 986 CLOG_BUFFER(allocateBuffer, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p", size, *buffer_data)); 987 988 return OK; 989} 990 991status_t OMXNodeInstance::allocateBufferWithBackup( 992 OMX_U32 portIndex, const sp<IMemory> ¶ms, 993 OMX::buffer_id *buffer, OMX_U32 allottedSize) { 994 Mutex::Autolock autoLock(mLock); 995 if (allottedSize > params->size()) { 996 return BAD_VALUE; 997 } 998 999 BufferMeta *buffer_meta = new BufferMeta(params, true); 1000 1001 OMX_BUFFERHEADERTYPE *header; 1002 1003 OMX_ERRORTYPE err = OMX_AllocateBuffer( 1004 mHandle, &header, portIndex, buffer_meta, allottedSize); 1005 if (err != OMX_ErrorNone) { 1006 CLOG_ERROR(allocateBufferWithBackup, err, 1007 SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer())); 1008 delete buffer_meta; 1009 buffer_meta = NULL; 1010 1011 *buffer = 0; 1012 1013 return StatusFromOMXError(err); 1014 } 1015 1016 CHECK_EQ(header->pAppPrivate, buffer_meta); 1017 1018 *buffer = makeBufferID(header); 1019 1020 addActiveBuffer(portIndex, *buffer); 1021 1022 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 1023 if (bufferSource != NULL && portIndex == kPortIndexInput) { 1024 bufferSource->addCodecBuffer(header); 1025 } 1026 1027 CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%u@%p :> %p", 1028 allottedSize, params->pointer(), header->pBuffer)); 1029 1030 return OK; 1031} 1032 1033status_t OMXNodeInstance::freeBuffer( 1034 OMX_U32 portIndex, OMX::buffer_id buffer) { 1035 Mutex::Autolock autoLock(mLock); 1036 CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1037 1038 removeActiveBuffer(portIndex, buffer); 1039 1040 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 1041 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 1042 1043 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 1044 CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1045 1046 delete buffer_meta; 1047 buffer_meta = NULL; 1048 invalidateBufferID(buffer); 1049 1050 return StatusFromOMXError(err); 1051} 1052 1053status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) { 1054 Mutex::Autolock autoLock(mLock); 1055 1056 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 1057 header->nFilledLen = 0; 1058 header->nOffset = 0; 1059 header->nFlags = 0; 1060 1061 // meta now owns fenceFd 1062 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput); 1063 if (res != OK) { 1064 CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd)); 1065 return res; 1066 } 1067 1068 { 1069 Mutex::Autolock _l(mDebugLock); 1070 mOutputBuffersWithCodec.add(header); 1071 CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd))); 1072 } 1073 1074 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 1075 if (err != OMX_ErrorNone) { 1076 CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd)); 1077 Mutex::Autolock _l(mDebugLock); 1078 mOutputBuffersWithCodec.remove(header); 1079 } 1080 return StatusFromOMXError(err); 1081} 1082 1083status_t OMXNodeInstance::emptyBuffer( 1084 OMX::buffer_id buffer, 1085 OMX_U32 rangeOffset, OMX_U32 rangeLength, 1086 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1087 Mutex::Autolock autoLock(mLock); 1088 1089 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); 1090 // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. 1091 // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. 1092 if (rangeOffset > header->nAllocLen 1093 || rangeLength > header->nAllocLen - rangeOffset) { 1094 if (fenceFd >= 0) { 1095 ::close(fenceFd); 1096 } 1097 return BAD_VALUE; 1098 } 1099 header->nFilledLen = rangeLength; 1100 header->nOffset = rangeOffset; 1101 1102 BufferMeta *buffer_meta = 1103 static_cast<BufferMeta *>(header->pAppPrivate); 1104 sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */); 1105 sp<ABuffer> codec = buffer_meta->getBuffer(header, false /* backup */); 1106 1107 // convert incoming ANW meta buffers if component is configured for gralloc metadata mode 1108 if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource 1109 && backup->capacity() >= sizeof(VideoNativeMetadata) 1110 && codec->capacity() >= sizeof(VideoGrallocMetadata) 1111 && ((VideoNativeMetadata *)backup->base())->eType 1112 == kMetadataBufferTypeANWBuffer) { 1113 VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base(); 1114 VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base(); 1115 ALOGV("converting ANWB %p to handle %p", backupMeta.pBuffer, backupMeta.pBuffer->handle); 1116 codecMeta.hHandle = backupMeta.pBuffer->handle; 1117 codecMeta.eType = kMetadataBufferTypeGrallocSource; 1118 header->nFilledLen = sizeof(codecMeta); 1119 } else { 1120 buffer_meta->CopyToOMX(header); 1121 } 1122 1123 return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd); 1124} 1125 1126// log queued buffer activity for the next few input and/or output frames 1127// if logging at internal state level 1128void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) { 1129 if (DEBUG == ADebug::kDebugInternalState) { 1130 DEBUG_BUMP = ADebug::kDebugAll; 1131 if (numInputBuffers > 0) { 1132 mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers; 1133 } 1134 if (numOutputBuffers > 0) { 1135 mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers; 1136 } 1137 } 1138} 1139 1140void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) { 1141 if (mDebugLevelBumpPendingBuffers[portIndex]) { 1142 --mDebugLevelBumpPendingBuffers[portIndex]; 1143 } 1144 if (!mDebugLevelBumpPendingBuffers[0] 1145 && !mDebugLevelBumpPendingBuffers[1]) { 1146 DEBUG_BUMP = DEBUG; 1147 } 1148} 1149 1150status_t OMXNodeInstance::storeFenceInMeta_l( 1151 OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) { 1152 // propagate fence if component supports it; wait for it otherwise 1153 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen; 1154 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1155 && metaSize >= sizeof(VideoNativeMetadata)) { 1156 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1157 if (nativeMeta.nFenceFd >= 0) { 1158 ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd); 1159 if (fenceFd >= 0) { 1160 ::close(fenceFd); 1161 } 1162 return ALREADY_EXISTS; 1163 } 1164 nativeMeta.nFenceFd = fenceFd; 1165 } else if (fenceFd >= 0) { 1166 CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd); 1167 sp<Fence> fence = new Fence(fenceFd); 1168 return fence->wait(IOMX::kFenceTimeoutMs); 1169 } 1170 return OK; 1171} 1172 1173int OMXNodeInstance::retrieveFenceFromMeta_l( 1174 OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) { 1175 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen; 1176 int fenceFd = -1; 1177 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1178 && header->nAllocLen >= sizeof(VideoNativeMetadata)) { 1179 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1180 if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 1181 fenceFd = nativeMeta.nFenceFd; 1182 nativeMeta.nFenceFd = -1; 1183 } 1184 if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) { 1185 CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER( 1186 NULL, header, nativeMeta.nFenceFd)); 1187 fenceFd = -1; 1188 } 1189 } 1190 return fenceFd; 1191} 1192 1193status_t OMXNodeInstance::emptyBuffer_l( 1194 OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, 1195 intptr_t debugAddr, int fenceFd) { 1196 header->nFlags = flags; 1197 header->nTimeStamp = timestamp; 1198 1199 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput); 1200 if (res != OK) { 1201 CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS( 1202 FULL_BUFFER(debugAddr, header, fenceFd))); 1203 return res; 1204 } 1205 1206 { 1207 Mutex::Autolock _l(mDebugLock); 1208 mInputBuffersWithCodec.add(header); 1209 1210 // bump internal-state debug level for 2 input frames past a buffer with CSD 1211 if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) { 1212 bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */); 1213 } 1214 1215 CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd))); 1216 } 1217 1218 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 1219 CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd)); 1220 1221 { 1222 Mutex::Autolock _l(mDebugLock); 1223 if (err != OMX_ErrorNone) { 1224 mInputBuffersWithCodec.remove(header); 1225 } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1226 unbumpDebugLevel_l(kPortIndexInput); 1227 } 1228 } 1229 1230 return StatusFromOMXError(err); 1231} 1232 1233// like emptyBuffer, but the data is already in header->pBuffer 1234status_t OMXNodeInstance::emptyGraphicBuffer( 1235 OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &graphicBuffer, 1236 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1237 Mutex::Autolock autoLock(mLock); 1238 OMX::buffer_id buffer = findBufferID(header); 1239 status_t err = updateGraphicBufferInMeta_l(kPortIndexInput, graphicBuffer, buffer, header); 1240 if (err != OK) { 1241 CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER( 1242 (intptr_t)header->pBuffer, header, fenceFd)); 1243 return err; 1244 } 1245 1246 header->nOffset = 0; 1247 header->nFilledLen = graphicBuffer == NULL ? 0 : header->nAllocLen; 1248 return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd); 1249} 1250 1251status_t OMXNodeInstance::getExtensionIndex( 1252 const char *parameterName, OMX_INDEXTYPE *index) { 1253 Mutex::Autolock autoLock(mLock); 1254 1255 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 1256 mHandle, const_cast<char *>(parameterName), index); 1257 1258 return StatusFromOMXError(err); 1259} 1260 1261inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") { 1262 switch (i) { 1263 case IOMX::INTERNAL_OPTION_SUSPEND: return "SUSPEND"; 1264 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 1265 return "REPEAT_PREVIOUS_FRAME_DELAY"; 1266 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP"; 1267 case IOMX::INTERNAL_OPTION_MAX_FPS: return "MAX_FPS"; 1268 case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME"; 1269 case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE"; 1270 default: return def; 1271 } 1272} 1273 1274status_t OMXNodeInstance::setInternalOption( 1275 OMX_U32 portIndex, 1276 IOMX::InternalOptionType type, 1277 const void *data, 1278 size_t size) { 1279 CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p", 1280 asString(type), type, portString(portIndex), portIndex, size, data); 1281 switch (type) { 1282 case IOMX::INTERNAL_OPTION_SUSPEND: 1283 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 1284 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: 1285 case IOMX::INTERNAL_OPTION_MAX_FPS: 1286 case IOMX::INTERNAL_OPTION_START_TIME: 1287 case IOMX::INTERNAL_OPTION_TIME_LAPSE: 1288 { 1289 const sp<GraphicBufferSource> &bufferSource = 1290 getGraphicBufferSource(); 1291 1292 if (bufferSource == NULL || portIndex != kPortIndexInput) { 1293 CLOGW("setInternalOption is only for Surface input"); 1294 return ERROR_UNSUPPORTED; 1295 } 1296 1297 if (type == IOMX::INTERNAL_OPTION_SUSPEND) { 1298 if (size != sizeof(bool)) { 1299 return INVALID_OPERATION; 1300 } 1301 1302 bool suspend = *(bool *)data; 1303 CLOG_CONFIG(setInternalOption, "suspend=%d", suspend); 1304 bufferSource->suspend(suspend); 1305 } else if (type == 1306 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){ 1307 if (size != sizeof(int64_t)) { 1308 return INVALID_OPERATION; 1309 } 1310 1311 int64_t delayUs = *(int64_t *)data; 1312 CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs); 1313 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs); 1314 } else if (type == 1315 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){ 1316 if (size != sizeof(int64_t)) { 1317 return INVALID_OPERATION; 1318 } 1319 1320 int64_t maxGapUs = *(int64_t *)data; 1321 CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs); 1322 return bufferSource->setMaxTimestampGapUs(maxGapUs); 1323 } else if (type == IOMX::INTERNAL_OPTION_MAX_FPS) { 1324 if (size != sizeof(float)) { 1325 return INVALID_OPERATION; 1326 } 1327 1328 float maxFps = *(float *)data; 1329 CLOG_CONFIG(setInternalOption, "maxFps=%f", maxFps); 1330 return bufferSource->setMaxFps(maxFps); 1331 } else if (type == IOMX::INTERNAL_OPTION_START_TIME) { 1332 if (size != sizeof(int64_t)) { 1333 return INVALID_OPERATION; 1334 } 1335 1336 int64_t skipFramesBeforeUs = *(int64_t *)data; 1337 CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs); 1338 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs); 1339 } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE 1340 if (size != sizeof(int64_t) * 2) { 1341 return INVALID_OPERATION; 1342 } 1343 1344 int64_t timePerFrameUs = ((int64_t *)data)[0]; 1345 int64_t timePerCaptureUs = ((int64_t *)data)[1]; 1346 CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld", 1347 (long long)timePerFrameUs, (long long)timePerCaptureUs); 1348 1349 bufferSource->setTimeLapseUs((int64_t *)data); 1350 } 1351 1352 return OK; 1353 } 1354 1355 default: 1356 return ERROR_UNSUPPORTED; 1357 } 1358} 1359 1360void OMXNodeInstance::onMessage(const omx_message &msg) { 1361 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1362 1363 if (msg.type == omx_message::FILL_BUFFER_DONE) { 1364 OMX_BUFFERHEADERTYPE *buffer = 1365 findBufferHeader(msg.u.extended_buffer_data.buffer); 1366 1367 { 1368 Mutex::Autolock _l(mDebugLock); 1369 mOutputBuffersWithCodec.remove(buffer); 1370 1371 CLOG_BUMPED_BUFFER( 1372 FBD, WITH_STATS(FULL_BUFFER( 1373 msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd))); 1374 1375 unbumpDebugLevel_l(kPortIndexOutput); 1376 } 1377 1378 BufferMeta *buffer_meta = 1379 static_cast<BufferMeta *>(buffer->pAppPrivate); 1380 1381 buffer_meta->CopyFromOMX(buffer); 1382 1383 if (bufferSource != NULL) { 1384 // fix up the buffer info (especially timestamp) if needed 1385 bufferSource->codecBufferFilled(buffer); 1386 1387 omx_message newMsg = msg; 1388 newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp; 1389 mObserver->onMessage(newMsg); 1390 return; 1391 } 1392 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 1393 OMX_BUFFERHEADERTYPE *buffer = 1394 findBufferHeader(msg.u.buffer_data.buffer); 1395 1396 { 1397 Mutex::Autolock _l(mDebugLock); 1398 mInputBuffersWithCodec.remove(buffer); 1399 1400 CLOG_BUMPED_BUFFER( 1401 EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd))); 1402 } 1403 1404 if (bufferSource != NULL) { 1405 // This is one of the buffers used exclusively by 1406 // GraphicBufferSource. 1407 // Don't dispatch a message back to ACodec, since it doesn't 1408 // know that anyone asked to have the buffer emptied and will 1409 // be very confused. 1410 bufferSource->codecBufferEmptied(buffer, msg.fenceFd); 1411 return; 1412 } 1413 } 1414 1415 mObserver->onMessage(msg); 1416} 1417 1418void OMXNodeInstance::onObserverDied(OMXMaster *master) { 1419 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 1420 1421 // Try to force shutdown of the node and hope for the best. 1422 freeNode(master); 1423} 1424 1425void OMXNodeInstance::onGetHandleFailed() { 1426 delete this; 1427} 1428 1429// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 1430// Don't try to acquire mLock here -- in rare circumstances this will hang. 1431void OMXNodeInstance::onEvent( 1432 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 1433 const char *arg1String = "??"; 1434 const char *arg2String = "??"; 1435 ADebug::Level level = ADebug::kDebugInternalState; 1436 1437 switch (event) { 1438 case OMX_EventCmdComplete: 1439 arg1String = asString((OMX_COMMANDTYPE)arg1); 1440 switch (arg1) { 1441 case OMX_CommandStateSet: 1442 arg2String = asString((OMX_STATETYPE)arg2); 1443 level = ADebug::kDebugState; 1444 break; 1445 case OMX_CommandFlush: 1446 case OMX_CommandPortEnable: 1447 { 1448 // bump internal-state debug level for 2 input and output frames 1449 Mutex::Autolock _l(mDebugLock); 1450 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 1451 } 1452 // fall through 1453 default: 1454 arg2String = portString(arg2); 1455 } 1456 break; 1457 case OMX_EventError: 1458 arg1String = asString((OMX_ERRORTYPE)arg1); 1459 level = ADebug::kDebugLifeCycle; 1460 break; 1461 case OMX_EventPortSettingsChanged: 1462 arg2String = asString((OMX_INDEXEXTTYPE)arg2); 1463 // fall through 1464 default: 1465 arg1String = portString(arg1); 1466 } 1467 1468 CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)", 1469 asString(event), event, arg1String, arg1, arg2String, arg2); 1470 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1471 1472 if (bufferSource != NULL 1473 && event == OMX_EventCmdComplete 1474 && arg1 == OMX_CommandStateSet 1475 && arg2 == OMX_StateExecuting) { 1476 bufferSource->omxExecuting(); 1477 } 1478} 1479 1480// static 1481OMX_ERRORTYPE OMXNodeInstance::OnEvent( 1482 OMX_IN OMX_HANDLETYPE /* hComponent */, 1483 OMX_IN OMX_PTR pAppData, 1484 OMX_IN OMX_EVENTTYPE eEvent, 1485 OMX_IN OMX_U32 nData1, 1486 OMX_IN OMX_U32 nData2, 1487 OMX_IN OMX_PTR pEventData) { 1488 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1489 if (instance->mDying) { 1490 return OMX_ErrorNone; 1491 } 1492 return instance->owner()->OnEvent( 1493 instance->nodeID(), eEvent, nData1, nData2, pEventData); 1494} 1495 1496// static 1497OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 1498 OMX_IN OMX_HANDLETYPE /* hComponent */, 1499 OMX_IN OMX_PTR pAppData, 1500 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1501 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1502 if (instance->mDying) { 1503 return OMX_ErrorNone; 1504 } 1505 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 1506 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), 1507 instance->findBufferID(pBuffer), pBuffer, fenceFd); 1508} 1509 1510// static 1511OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 1512 OMX_IN OMX_HANDLETYPE /* hComponent */, 1513 OMX_IN OMX_PTR pAppData, 1514 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1515 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1516 if (instance->mDying) { 1517 return OMX_ErrorNone; 1518 } 1519 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 1520 return instance->owner()->OnFillBufferDone(instance->nodeID(), 1521 instance->findBufferID(pBuffer), pBuffer, fenceFd); 1522} 1523 1524void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 1525 ActiveBuffer active; 1526 active.mPortIndex = portIndex; 1527 active.mID = id; 1528 mActiveBuffers.push(active); 1529 1530 if (portIndex < NELEM(mNumPortBuffers)) { 1531 ++mNumPortBuffers[portIndex]; 1532 } 1533} 1534 1535void OMXNodeInstance::removeActiveBuffer( 1536 OMX_U32 portIndex, OMX::buffer_id id) { 1537 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 1538 if (mActiveBuffers[i].mPortIndex == portIndex 1539 && mActiveBuffers[i].mID == id) { 1540 mActiveBuffers.removeItemsAt(i); 1541 1542 if (portIndex < NELEM(mNumPortBuffers)) { 1543 --mNumPortBuffers[portIndex]; 1544 } 1545 return; 1546 } 1547 } 1548 1549 CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id); 1550} 1551 1552void OMXNodeInstance::freeActiveBuffers() { 1553 // Make sure to count down here, as freeBuffer will in turn remove 1554 // the active buffer from the vector... 1555 for (size_t i = mActiveBuffers.size(); i--;) { 1556 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 1557 } 1558} 1559 1560OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1561 if (bufferHeader == NULL) { 1562 return 0; 1563 } 1564 Mutex::Autolock autoLock(mBufferIDLock); 1565 OMX::buffer_id buffer; 1566 do { // handle the very unlikely case of ID overflow 1567 if (++mBufferIDCount == 0) { 1568 ++mBufferIDCount; 1569 } 1570 buffer = (OMX::buffer_id)mBufferIDCount; 1571 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); 1572 mBufferIDToBufferHeader.add(buffer, bufferHeader); 1573 mBufferHeaderToBufferID.add(bufferHeader, buffer); 1574 return buffer; 1575} 1576 1577OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { 1578 if (buffer == 0) { 1579 return NULL; 1580 } 1581 Mutex::Autolock autoLock(mBufferIDLock); 1582 return mBufferIDToBufferHeader.valueFor(buffer); 1583} 1584 1585OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1586 if (bufferHeader == NULL) { 1587 return 0; 1588 } 1589 Mutex::Autolock autoLock(mBufferIDLock); 1590 return mBufferHeaderToBufferID.valueFor(bufferHeader); 1591} 1592 1593void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) { 1594 if (buffer == 0) { 1595 return; 1596 } 1597 Mutex::Autolock autoLock(mBufferIDLock); 1598 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer)); 1599 mBufferIDToBufferHeader.removeItem(buffer); 1600} 1601 1602} // namespace android 1603