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