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