OMXNodeInstance.cpp revision 6cf9a1238986880536de705255f7c2c91c1ba719
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "OMXNodeInstance" 19#include <utils/Log.h> 20 21#include <inttypes.h> 22 23#include "../include/OMXNodeInstance.h" 24#include "OMXMaster.h" 25#include "OMXUtils.h" 26#include "GraphicBufferSource.h" 27 28#include <OMX_Component.h> 29#include <OMX_IndexExt.h> 30#include <OMX_AsString.h> 31 32#include <binder/IMemory.h> 33#include <cutils/properties.h> 34#include <gui/BufferQueue.h> 35#include <HardwareAPI.h> 36#include <media/stagefright/foundation/ADebug.h> 37#include <media/stagefright/foundation/ABuffer.h> 38#include <media/stagefright/foundation/ColorUtils.h> 39#include <media/stagefright/MediaErrors.h> 40#include <utils/misc.h> 41#include <utils/NativeHandle.h> 42 43static const OMX_U32 kPortIndexInput = 0; 44static const OMX_U32 kPortIndexOutput = 1; 45 46#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__) 47 48#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \ 49 ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \ 50 mNodeID, mName, ##__VA_ARGS__, asString(err), err) 51#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__) 52#define CLOG_IF_ERROR(fn, err, fmt, ...) \ 53 CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__) 54 55#define CLOGI_(level, fn, fmt, ...) \ 56 ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__) 57#define CLOGD_(level, fn, fmt, ...) \ 58 ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__) 59 60#define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__) 61#define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__) 62#define CLOG_CONFIG(fn, fmt, ...) CLOGI_(ADebug::kDebugConfig, fn, fmt, ##__VA_ARGS__) 63#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__) 64 65#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \ 66 ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__) 67 68#define CLOG_BUFFER(fn, fmt, ...) \ 69 CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 70#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \ 71 CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__) 72 73/* buffer formatting */ 74#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__ 75#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \ 76 BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id)) 77 78#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data)) 79#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \ 80 NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data)) 81 82#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \ 83 (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd) 84#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \ 85 (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \ 86 (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd) 87 88#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \ 89 mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \ 90 mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput] 91// TRICKY: this is needed so formatting macros expand before substitution 92#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__) 93 94namespace android { 95 96struct BufferMeta { 97 explicit BufferMeta(const sp<IMemory> &mem, OMX_U32 portIndex, bool is_backup = false) 98 : mMem(mem), 99 mIsBackup(is_backup), 100 mPortIndex(portIndex) { 101 } 102 103 explicit BufferMeta(size_t size, OMX_U32 portIndex) 104 : mSize(size), 105 mIsBackup(false), 106 mPortIndex(portIndex) { 107 } 108 109 explicit BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex) 110 : mGraphicBuffer(graphicBuffer), 111 mIsBackup(false), 112 mPortIndex(portIndex) { 113 } 114 115 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 116 if (!mIsBackup) { 117 return; 118 } 119 120 // check component returns proper range 121 sp<ABuffer> codec = getBuffer(header, false /* backup */, true /* limit */); 122 123 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size()); 124 } 125 126 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 127 if (!mIsBackup) { 128 return; 129 } 130 131 memcpy(header->pBuffer + header->nOffset, 132 (const OMX_U8 *)mMem->pointer() + header->nOffset, 133 header->nFilledLen); 134 } 135 136 // return either the codec or the backup buffer 137 sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup, bool limit) { 138 sp<ABuffer> buf; 139 if (backup && mMem != NULL) { 140 buf = new ABuffer(mMem->pointer(), mMem->size()); 141 } else { 142 buf = new ABuffer(header->pBuffer, header->nAllocLen); 143 } 144 if (limit) { 145 if (header->nOffset + header->nFilledLen > header->nOffset 146 && header->nOffset + header->nFilledLen <= header->nAllocLen) { 147 buf->setRange(header->nOffset, header->nFilledLen); 148 } else { 149 buf->setRange(0, 0); 150 } 151 } 152 return buf; 153 } 154 155 void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { 156 mGraphicBuffer = graphicBuffer; 157 } 158 159 void setNativeHandle(const sp<NativeHandle> &nativeHandle) { 160 mNativeHandle = nativeHandle; 161 } 162 163 OMX_U32 getPortIndex() { 164 return mPortIndex; 165 } 166 167private: 168 sp<GraphicBuffer> mGraphicBuffer; 169 sp<NativeHandle> mNativeHandle; 170 sp<IMemory> mMem; 171 size_t mSize; 172 bool mIsBackup; 173 OMX_U32 mPortIndex; 174 175 BufferMeta(const BufferMeta &); 176 BufferMeta &operator=(const BufferMeta &); 177}; 178 179// static 180OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 181 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 182}; 183 184static inline const char *portString(OMX_U32 portIndex) { 185 switch (portIndex) { 186 case kPortIndexInput: return "Input"; 187 case kPortIndexOutput: return "Output"; 188 case ~0U: return "All"; 189 default: return "port"; 190 } 191} 192 193OMXNodeInstance::OMXNodeInstance( 194 OMX *owner, const sp<IOMXObserver> &observer, const char *name) 195 : mOwner(owner), 196 mNodeID(0), 197 mHandle(NULL), 198 mObserver(observer), 199 mDying(false), 200 mBufferIDCount(0) 201{ 202 mName = ADebug::GetDebugName(name); 203 DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug"); 204 ALOGV("debug level for %s is %d", name, DEBUG); 205 DEBUG_BUMP = DEBUG; 206 mNumPortBuffers[0] = 0; 207 mNumPortBuffers[1] = 0; 208 mDebugLevelBumpPendingBuffers[0] = 0; 209 mDebugLevelBumpPendingBuffers[1] = 0; 210 mMetadataType[0] = kMetadataBufferTypeInvalid; 211 mMetadataType[1] = kMetadataBufferTypeInvalid; 212 mSecureBufferType[0] = kSecureBufferTypeUnknown; 213 mSecureBufferType[1] = kSecureBufferTypeUnknown; 214 mIsSecure = AString(name).endsWith(".secure"); 215} 216 217OMXNodeInstance::~OMXNodeInstance() { 218 free(mName); 219 CHECK(mHandle == NULL); 220} 221 222void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 223 mNodeID = node_id; 224 CLOG_LIFE(allocateNode, "handle=%p", handle); 225 CHECK(mHandle == NULL); 226 mHandle = handle; 227} 228 229sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() { 230 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 231 return mGraphicBufferSource; 232} 233 234void OMXNodeInstance::setGraphicBufferSource( 235 const sp<GraphicBufferSource>& bufferSource) { 236 Mutex::Autolock autoLock(mGraphicBufferSourceLock); 237 CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get()); 238 mGraphicBufferSource = bufferSource; 239} 240 241OMX *OMXNodeInstance::owner() { 242 return mOwner; 243} 244 245sp<IOMXObserver> OMXNodeInstance::observer() { 246 return mObserver; 247} 248 249OMX::node_id OMXNodeInstance::nodeID() { 250 return mNodeID; 251} 252 253status_t OMXNodeInstance::freeNode(OMXMaster *master) { 254 CLOG_LIFE(freeNode, "handle=%p", mHandle); 255 static int32_t kMaxNumIterations = 10; 256 257 // exit if we have already freed the node 258 if (mHandle == NULL) { 259 return OK; 260 } 261 262 // Transition the node from its current state all the way down 263 // to "Loaded". 264 // This ensures that all active buffers are properly freed even 265 // for components that don't do this themselves on a call to 266 // "FreeHandle". 267 268 // The code below may trigger some more events to be dispatched 269 // by the OMX component - we want to ignore them as our client 270 // does not expect them. 271 mDying = true; 272 273 OMX_STATETYPE state; 274 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 275 switch (state) { 276 case OMX_StateExecuting: 277 { 278 ALOGV("forcing Executing->Idle"); 279 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 280 OMX_ERRORTYPE err; 281 int32_t iteration = 0; 282 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 283 && state != OMX_StateIdle 284 && state != OMX_StateInvalid) { 285 if (++iteration > kMaxNumIterations) { 286 CLOGW("failed to enter Idle state (now %s(%d), aborting.", 287 asString(state), state); 288 state = OMX_StateInvalid; 289 break; 290 } 291 292 usleep(100000); 293 } 294 CHECK_EQ(err, OMX_ErrorNone); 295 296 if (state == OMX_StateInvalid) { 297 break; 298 } 299 300 // fall through 301 } 302 303 case OMX_StateIdle: 304 { 305 ALOGV("forcing Idle->Loaded"); 306 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 307 308 freeActiveBuffers(); 309 310 OMX_ERRORTYPE err; 311 int32_t iteration = 0; 312 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 313 && state != OMX_StateLoaded 314 && state != OMX_StateInvalid) { 315 if (++iteration > kMaxNumIterations) { 316 CLOGW("failed to enter Loaded state (now %s(%d), aborting.", 317 asString(state), state); 318 state = OMX_StateInvalid; 319 break; 320 } 321 322 ALOGV("waiting for Loaded state..."); 323 usleep(100000); 324 } 325 CHECK_EQ(err, OMX_ErrorNone); 326 327 // fall through 328 } 329 330 case OMX_StateLoaded: 331 case OMX_StateInvalid: 332 break; 333 334 default: 335 LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state); 336 break; 337 } 338 339 ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName); 340 OMX_ERRORTYPE err = master->destroyComponentInstance( 341 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 342 343 mHandle = NULL; 344 CLOG_IF_ERROR(freeNode, err, ""); 345 free(mName); 346 mName = NULL; 347 348 mOwner->invalidateNodeID(mNodeID); 349 mNodeID = 0; 350 351 ALOGV("OMXNodeInstance going away."); 352 delete this; 353 354 return StatusFromOMXError(err); 355} 356 357status_t OMXNodeInstance::sendCommand( 358 OMX_COMMANDTYPE cmd, OMX_S32 param) { 359 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 360 if (bufferSource != NULL && cmd == OMX_CommandStateSet) { 361 if (param == OMX_StateIdle) { 362 // Initiating transition from Executing -> Idle 363 // ACodec is waiting for all buffers to be returned, do NOT 364 // submit any more buffers to the codec. 365 bufferSource->omxIdle(); 366 } else if (param == OMX_StateLoaded) { 367 // Initiating transition from Idle/Executing -> Loaded 368 // Buffers are about to be freed. 369 bufferSource->omxLoaded(); 370 setGraphicBufferSource(NULL); 371 } 372 373 // fall through 374 } 375 376 Mutex::Autolock autoLock(mLock); 377 378 // bump internal-state debug level for 2 input and output frames past a command 379 { 380 Mutex::Autolock _l(mDebugLock); 381 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 382 } 383 384 const char *paramString = 385 cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param); 386 CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 387 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 388 CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param); 389 return StatusFromOMXError(err); 390} 391 392status_t OMXNodeInstance::getParameter( 393 OMX_INDEXTYPE index, void *params, size_t /* size */) { 394 Mutex::Autolock autoLock(mLock); 395 396 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 397 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 398 // some errors are expected for getParameter 399 if (err != OMX_ErrorNoMore) { 400 CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index); 401 } 402 return StatusFromOMXError(err); 403} 404 405status_t OMXNodeInstance::setParameter( 406 OMX_INDEXTYPE index, const void *params, size_t size) { 407 Mutex::Autolock autoLock(mLock); 408 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 409 CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 410 411 OMX_ERRORTYPE err = OMX_SetParameter( 412 mHandle, index, const_cast<void *>(params)); 413 CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index); 414 return StatusFromOMXError(err); 415} 416 417status_t OMXNodeInstance::getConfig( 418 OMX_INDEXTYPE index, void *params, size_t /* size */) { 419 Mutex::Autolock autoLock(mLock); 420 421 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 422 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 423 // some errors are expected for getConfig 424 if (err != OMX_ErrorNoMore) { 425 CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index); 426 } 427 return StatusFromOMXError(err); 428} 429 430status_t OMXNodeInstance::setConfig( 431 OMX_INDEXTYPE index, const void *params, size_t size) { 432 Mutex::Autolock autoLock(mLock); 433 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; 434 CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); 435 436 OMX_ERRORTYPE err = OMX_SetConfig( 437 mHandle, index, const_cast<void *>(params)); 438 CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index); 439 return StatusFromOMXError(err); 440} 441 442status_t OMXNodeInstance::getState(OMX_STATETYPE* state) { 443 Mutex::Autolock autoLock(mLock); 444 445 OMX_ERRORTYPE err = OMX_GetState(mHandle, state); 446 CLOG_IF_ERROR(getState, err, ""); 447 return StatusFromOMXError(err); 448} 449 450status_t OMXNodeInstance::enableNativeBuffers( 451 OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) { 452 Mutex::Autolock autoLock(mLock); 453 CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex, 454 graphic ? ", graphic" : "", enable); 455 OMX_STRING name = const_cast<OMX_STRING>( 456 graphic ? "OMX.google.android.index.enableAndroidNativeBuffers" 457 : "OMX.google.android.index.allocateNativeHandle"); 458 459 OMX_INDEXTYPE index; 460 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 461 462 if (err == OMX_ErrorNone) { 463 EnableAndroidNativeBuffersParams params; 464 InitOMXParams(¶ms); 465 params.nPortIndex = portIndex; 466 params.enable = enable; 467 468 err = OMX_SetParameter(mHandle, index, ¶ms); 469 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index, 470 portString(portIndex), portIndex, enable); 471 if (!graphic) { 472 if (err == OMX_ErrorNone) { 473 mSecureBufferType[portIndex] = 474 enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque; 475 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) { 476 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque; 477 } 478 } 479 } else { 480 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 481 if (!graphic) { 482 // Extension not supported, check for manual override with system property 483 // This is a temporary workaround until partners support the OMX extension 484 char value[PROPERTY_VALUE_MAX]; 485 if (property_get("media.mediadrmservice.enable", value, NULL) 486 && (!strcmp("1", value) || !strcasecmp("true", value))) { 487 CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles"); 488 mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle; 489 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) { 490 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque; 491 } 492 err = OMX_ErrorNone; 493 } 494 } 495 496 return StatusFromOMXError(err); 497} 498 499status_t OMXNodeInstance::getGraphicBufferUsage( 500 OMX_U32 portIndex, OMX_U32* usage) { 501 Mutex::Autolock autoLock(mLock); 502 503 OMX_INDEXTYPE index; 504 OMX_STRING name = const_cast<OMX_STRING>( 505 "OMX.google.android.index.getAndroidNativeBufferUsage"); 506 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 507 508 if (err != OMX_ErrorNone) { 509 CLOG_ERROR(getExtensionIndex, err, "%s", name); 510 return StatusFromOMXError(err); 511 } 512 513 GetAndroidNativeBufferUsageParams params; 514 InitOMXParams(¶ms); 515 params.nPortIndex = portIndex; 516 517 err = OMX_GetParameter(mHandle, index, ¶ms); 518 if (err != OMX_ErrorNone) { 519 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index, 520 portString(portIndex), portIndex); 521 return StatusFromOMXError(err); 522 } 523 524 *usage = params.nUsage; 525 526 return OK; 527} 528 529status_t OMXNodeInstance::storeMetaDataInBuffers( 530 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { 531 Mutex::Autolock autolock(mLock); 532 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable); 533 return storeMetaDataInBuffers_l(portIndex, enable, type); 534} 535 536status_t OMXNodeInstance::storeMetaDataInBuffers_l( 537 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { 538 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 539 android_errorWriteLog(0x534e4554, "26324358"); 540 if (type != NULL) { 541 *type = kMetadataBufferTypeInvalid; 542 } 543 return BAD_VALUE; 544 } 545 546 OMX_INDEXTYPE index; 547 OMX_STRING name = const_cast<OMX_STRING>( 548 "OMX.google.android.index.storeMetaDataInBuffers"); 549 550 OMX_STRING nativeBufferName = const_cast<OMX_STRING>( 551 "OMX.google.android.index.storeANWBufferInMetadata"); 552 MetadataBufferType negotiatedType; 553 MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer; 554 555 StoreMetaDataInBuffersParams params; 556 InitOMXParams(¶ms); 557 params.nPortIndex = portIndex; 558 params.bStoreMetaData = enable; 559 560 OMX_ERRORTYPE err = 561 requestedType == kMetadataBufferTypeANWBuffer 562 ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index) 563 : OMX_ErrorUnsupportedIndex; 564 OMX_ERRORTYPE xerr = err; 565 if (err == OMX_ErrorNone) { 566 err = OMX_SetParameter(mHandle, index, ¶ms); 567 if (err == OMX_ErrorNone) { 568 name = nativeBufferName; // set name for debugging 569 negotiatedType = requestedType; 570 } 571 } 572 if (err != OMX_ErrorNone) { 573 err = OMX_GetExtensionIndex(mHandle, name, &index); 574 xerr = err; 575 if (err == OMX_ErrorNone) { 576 negotiatedType = 577 requestedType == kMetadataBufferTypeANWBuffer 578 ? kMetadataBufferTypeGrallocSource : requestedType; 579 err = OMX_SetParameter(mHandle, index, ¶ms); 580 } 581 } 582 583 // don't log loud error if component does not support metadata mode on the output 584 if (err != OMX_ErrorNone) { 585 if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) { 586 CLOGW("component does not support metadata mode; using fallback"); 587 } else if (xerr != OMX_ErrorNone) { 588 CLOG_ERROR(getExtensionIndex, xerr, "%s", name); 589 } else { 590 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index, 591 portString(portIndex), portIndex, enable, negotiatedType); 592 } 593 negotiatedType = mMetadataType[portIndex]; 594 } else { 595 if (!enable) { 596 negotiatedType = kMetadataBufferTypeInvalid; 597 } 598 mMetadataType[portIndex] = negotiatedType; 599 } 600 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d", 601 portString(portIndex), portIndex, enable ? "" : "UN", 602 asString(requestedType), requestedType, asString(negotiatedType), negotiatedType); 603 604 if (type != NULL) { 605 *type = negotiatedType; 606 } 607 608 return StatusFromOMXError(err); 609} 610 611status_t OMXNodeInstance::prepareForAdaptivePlayback( 612 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, 613 OMX_U32 maxFrameHeight) { 614 Mutex::Autolock autolock(mLock); 615 CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u", 616 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 617 618 OMX_INDEXTYPE index; 619 OMX_STRING name = const_cast<OMX_STRING>( 620 "OMX.google.android.index.prepareForAdaptivePlayback"); 621 622 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 623 if (err != OMX_ErrorNone) { 624 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name); 625 return StatusFromOMXError(err); 626 } 627 628 PrepareForAdaptivePlaybackParams params; 629 InitOMXParams(¶ms); 630 params.nPortIndex = portIndex; 631 params.bEnable = enable; 632 params.nMaxFrameWidth = maxFrameWidth; 633 params.nMaxFrameHeight = maxFrameHeight; 634 635 err = OMX_SetParameter(mHandle, index, ¶ms); 636 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index, 637 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); 638 return StatusFromOMXError(err); 639} 640 641status_t OMXNodeInstance::configureVideoTunnelMode( 642 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, 643 native_handle_t **sidebandHandle) { 644 Mutex::Autolock autolock(mLock); 645 CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u", 646 portString(portIndex), portIndex, tunneled, audioHwSync); 647 648 OMX_INDEXTYPE index; 649 OMX_STRING name = const_cast<OMX_STRING>( 650 "OMX.google.android.index.configureVideoTunnelMode"); 651 652 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 653 if (err != OMX_ErrorNone) { 654 CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name); 655 return StatusFromOMXError(err); 656 } 657 658 ConfigureVideoTunnelModeParams tunnelParams; 659 InitOMXParams(&tunnelParams); 660 tunnelParams.nPortIndex = portIndex; 661 tunnelParams.bTunneled = tunneled; 662 tunnelParams.nAudioHwSync = audioHwSync; 663 err = OMX_SetParameter(mHandle, index, &tunnelParams); 664 if (err != OMX_ErrorNone) { 665 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 666 portString(portIndex), portIndex, tunneled, audioHwSync); 667 return StatusFromOMXError(err); 668 } 669 670 err = OMX_GetParameter(mHandle, index, &tunnelParams); 671 if (err != OMX_ErrorNone) { 672 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index, 673 portString(portIndex), portIndex, tunneled, audioHwSync); 674 return StatusFromOMXError(err); 675 } 676 if (sidebandHandle) { 677 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; 678 } 679 680 return OK; 681} 682 683status_t OMXNodeInstance::useBuffer( 684 OMX_U32 portIndex, const sp<IMemory> ¶ms, 685 OMX::buffer_id *buffer, OMX_U32 allottedSize) { 686 if (params == NULL || buffer == NULL) { 687 ALOGE("b/25884056"); 688 return BAD_VALUE; 689 } 690 691 Mutex::Autolock autoLock(mLock); 692 if (allottedSize > params->size()) { 693 return BAD_VALUE; 694 } 695 696 BufferMeta *buffer_meta = new BufferMeta(params, portIndex); 697 698 OMX_BUFFERHEADERTYPE *header; 699 700 OMX_ERRORTYPE err = OMX_UseBuffer( 701 mHandle, &header, portIndex, buffer_meta, 702 allottedSize, static_cast<OMX_U8 *>(params->pointer())); 703 704 if (err != OMX_ErrorNone) { 705 CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER( 706 portIndex, (size_t)allottedSize, params->pointer())); 707 708 delete buffer_meta; 709 buffer_meta = NULL; 710 711 *buffer = 0; 712 713 return StatusFromOMXError(err); 714 } 715 716 CHECK_EQ(header->pAppPrivate, buffer_meta); 717 718 *buffer = makeBufferID(header); 719 720 addActiveBuffer(portIndex, *buffer); 721 722 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 723 if (bufferSource != NULL && portIndex == kPortIndexInput) { 724 bufferSource->addCodecBuffer(*buffer); 725 } 726 727 CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT( 728 *buffer, portIndex, "%u(%zu)@%p", allottedSize, params->size(), params->pointer())); 729 return OK; 730} 731 732status_t OMXNodeInstance::useGraphicBuffer2_l( 733 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 734 OMX::buffer_id *buffer) { 735 if (graphicBuffer == NULL || buffer == NULL) { 736 ALOGE("b/25884056"); 737 return BAD_VALUE; 738 } 739 740 // port definition 741 OMX_PARAM_PORTDEFINITIONTYPE def; 742 InitOMXParams(&def); 743 def.nPortIndex = portIndex; 744 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def); 745 if (err != OMX_ErrorNone) { 746 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 747 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", 748 asString(index), index, portString(portIndex), portIndex); 749 return UNKNOWN_ERROR; 750 } 751 752 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); 753 754 OMX_BUFFERHEADERTYPE *header = NULL; 755 OMX_U8* bufferHandle = const_cast<OMX_U8*>( 756 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle)); 757 758 err = OMX_UseBuffer( 759 mHandle, 760 &header, 761 portIndex, 762 bufferMeta, 763 def.nBufferSize, 764 bufferHandle); 765 766 if (err != OMX_ErrorNone) { 767 CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 768 delete bufferMeta; 769 bufferMeta = NULL; 770 *buffer = 0; 771 return StatusFromOMXError(err); 772 } 773 774 CHECK_EQ(header->pBuffer, bufferHandle); 775 CHECK_EQ(header->pAppPrivate, bufferMeta); 776 777 *buffer = makeBufferID(header); 778 779 addActiveBuffer(portIndex, *buffer); 780 CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT( 781 *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle)); 782 return OK; 783} 784 785// XXX: This function is here for backwards compatibility. Once the OMX 786// implementations have been updated this can be removed and useGraphicBuffer2 787// can be renamed to useGraphicBuffer. 788status_t OMXNodeInstance::useGraphicBuffer( 789 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 790 OMX::buffer_id *buffer) { 791 if (graphicBuffer == NULL || buffer == NULL) { 792 ALOGE("b/25884056"); 793 return BAD_VALUE; 794 } 795 Mutex::Autolock autoLock(mLock); 796 797 // See if the newer version of the extension is present. 798 OMX_INDEXTYPE index; 799 if (OMX_GetExtensionIndex( 800 mHandle, 801 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), 802 &index) == OMX_ErrorNone) { 803 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); 804 } 805 806 OMX_STRING name = const_cast<OMX_STRING>( 807 "OMX.google.android.index.useAndroidNativeBuffer"); 808 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); 809 if (err != OMX_ErrorNone) { 810 CLOG_ERROR(getExtensionIndex, err, "%s", name); 811 return StatusFromOMXError(err); 812 } 813 814 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); 815 816 OMX_BUFFERHEADERTYPE *header; 817 818 OMX_VERSIONTYPE ver; 819 ver.s.nVersionMajor = 1; 820 ver.s.nVersionMinor = 0; 821 ver.s.nRevision = 0; 822 ver.s.nStep = 0; 823 UseAndroidNativeBufferParams params = { 824 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, 825 &header, graphicBuffer, 826 }; 827 828 err = OMX_SetParameter(mHandle, index, ¶ms); 829 830 if (err != OMX_ErrorNone) { 831 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index, 832 portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle); 833 834 delete bufferMeta; 835 bufferMeta = NULL; 836 837 *buffer = 0; 838 839 return StatusFromOMXError(err); 840 } 841 842 CHECK_EQ(header->pAppPrivate, bufferMeta); 843 844 *buffer = makeBufferID(header); 845 846 addActiveBuffer(portIndex, *buffer); 847 CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT( 848 *buffer, portIndex, "GB=%p", graphicBuffer->handle)); 849 return OK; 850} 851 852status_t OMXNodeInstance::updateGraphicBufferInMeta_l( 853 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 854 OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) { 855 // No need to check |graphicBuffer| since NULL is valid for it as below. 856 if (header == NULL) { 857 ALOGE("b/25884056"); 858 return BAD_VALUE; 859 } 860 861 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 862 return BAD_VALUE; 863 } 864 865 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 866 sp<ABuffer> data = bufferMeta->getBuffer( 867 header, !updateCodecBuffer /* backup */, false /* limit */); 868 bufferMeta->setGraphicBuffer(graphicBuffer); 869 MetadataBufferType metaType = mMetadataType[portIndex]; 870 // we use gralloc source only in the codec buffers 871 if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) { 872 metaType = kMetadataBufferTypeANWBuffer; 873 } 874 if (metaType == kMetadataBufferTypeGrallocSource 875 && data->capacity() >= sizeof(VideoGrallocMetadata)) { 876 VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data()); 877 metadata.eType = kMetadataBufferTypeGrallocSource; 878 metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle; 879 } else if (metaType == kMetadataBufferTypeANWBuffer 880 && data->capacity() >= sizeof(VideoNativeMetadata)) { 881 VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data()); 882 metadata.eType = kMetadataBufferTypeANWBuffer; 883 metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer(); 884 metadata.nFenceFd = -1; 885 } else { 886 CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)", 887 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen); 888 return BAD_VALUE; 889 } 890 891 CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p", 892 portString(portIndex), portIndex, buffer, 893 graphicBuffer == NULL ? NULL : graphicBuffer->handle); 894 return OK; 895} 896 897status_t OMXNodeInstance::updateGraphicBufferInMeta( 898 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, 899 OMX::buffer_id buffer) { 900 Mutex::Autolock autoLock(mLock); 901 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); 902 // update backup buffer for input, codec buffer for output 903 return updateGraphicBufferInMeta_l( 904 portIndex, graphicBuffer, buffer, header, 905 portIndex == kPortIndexOutput /* updateCodecBuffer */); 906} 907 908status_t OMXNodeInstance::updateNativeHandleInMeta( 909 OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle, OMX::buffer_id buffer) { 910 Mutex::Autolock autoLock(mLock); 911 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); 912 // No need to check |nativeHandle| since NULL is valid for it as below. 913 if (header == NULL) { 914 ALOGE("b/25884056"); 915 return BAD_VALUE; 916 } 917 918 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { 919 return BAD_VALUE; 920 } 921 922 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); 923 // update backup buffer for input, codec buffer for output 924 sp<ABuffer> data = bufferMeta->getBuffer( 925 header, portIndex == kPortIndexInput /* backup */, false /* limit */); 926 bufferMeta->setNativeHandle(nativeHandle); 927 if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource 928 && data->capacity() >= sizeof(VideoNativeHandleMetadata)) { 929 VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data()); 930 metadata.eType = mMetadataType[portIndex]; 931 metadata.pHandle = 932 nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle()); 933 } else { 934 CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)", 935 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity()); 936 return BAD_VALUE; 937 } 938 939 CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p", 940 portString(portIndex), portIndex, buffer, 941 nativeHandle == NULL ? NULL : nativeHandle->handle()); 942 return OK; 943} 944 945status_t OMXNodeInstance::createGraphicBufferSource( 946 OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) { 947 status_t err; 948 949 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); 950 if (surfaceCheck != NULL) { 951 if (portIndex < NELEM(mMetadataType) && type != NULL) { 952 *type = mMetadataType[portIndex]; 953 } 954 return ALREADY_EXISTS; 955 } 956 957 // Input buffers will hold meta-data (ANativeWindowBuffer references). 958 if (type != NULL) { 959 *type = kMetadataBufferTypeANWBuffer; 960 } 961 err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type); 962 if (err != OK) { 963 return err; 964 } 965 966 // Retrieve the width and height of the graphic buffer, set when the 967 // codec was configured. 968 OMX_PARAM_PORTDEFINITIONTYPE def; 969 InitOMXParams(&def); 970 def.nPortIndex = portIndex; 971 OMX_ERRORTYPE oerr = OMX_GetParameter( 972 mHandle, OMX_IndexParamPortDefinition, &def); 973 if (oerr != OMX_ErrorNone) { 974 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition; 975 CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", 976 asString(index), index, portString(portIndex), portIndex); 977 return UNKNOWN_ERROR; 978 } 979 980 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) { 981 CLOGW("createInputSurface requires COLOR_FormatSurface " 982 "(AndroidOpaque) color format instead of %s(%#x)", 983 asString(def.format.video.eColorFormat), def.format.video.eColorFormat); 984 return INVALID_OPERATION; 985 } 986 987 uint32_t usageBits; 988 oerr = OMX_GetParameter( 989 mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits); 990 if (oerr != OMX_ErrorNone) { 991 usageBits = 0; 992 } 993 994 sp<GraphicBufferSource> bufferSource = new GraphicBufferSource( 995 mOwner, 996 mNodeID, 997 def.format.video.nFrameWidth, 998 def.format.video.nFrameHeight, 999 def.nBufferCountActual, 1000 usageBits, 1001 bufferConsumer); 1002 1003 if ((err = bufferSource->initCheck()) != OK) { 1004 return err; 1005 } 1006 setGraphicBufferSource(bufferSource); 1007 1008 return OK; 1009} 1010 1011status_t OMXNodeInstance::createInputSurface( 1012 OMX_U32 portIndex, android_dataspace dataSpace, 1013 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) { 1014 if (bufferProducer == NULL) { 1015 ALOGE("b/25884056"); 1016 return BAD_VALUE; 1017 } 1018 1019 Mutex::Autolock autolock(mLock); 1020 status_t err = createGraphicBufferSource(portIndex, NULL /* bufferConsumer */, type); 1021 1022 if (err != OK) { 1023 return err; 1024 } 1025 1026 mGraphicBufferSource->setDefaultDataSpace(dataSpace); 1027 1028 *bufferProducer = mGraphicBufferSource->getIGraphicBufferProducer(); 1029 return OK; 1030} 1031 1032//static 1033status_t OMXNodeInstance::createPersistentInputSurface( 1034 sp<IGraphicBufferProducer> *bufferProducer, 1035 sp<IGraphicBufferConsumer> *bufferConsumer) { 1036 if (bufferProducer == NULL || bufferConsumer == NULL) { 1037 ALOGE("b/25884056"); 1038 return BAD_VALUE; 1039 } 1040 String8 name("GraphicBufferSource"); 1041 1042 sp<IGraphicBufferProducer> producer; 1043 sp<IGraphicBufferConsumer> consumer; 1044 BufferQueue::createBufferQueue(&producer, &consumer); 1045 consumer->setConsumerName(name); 1046 consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); 1047 1048 sp<BufferQueue::ProxyConsumerListener> proxy = 1049 new BufferQueue::ProxyConsumerListener(NULL); 1050 status_t err = consumer->consumerConnect(proxy, false); 1051 if (err != NO_ERROR) { 1052 ALOGE("Error connecting to BufferQueue: %s (%d)", 1053 strerror(-err), err); 1054 return err; 1055 } 1056 1057 *bufferProducer = producer; 1058 *bufferConsumer = consumer; 1059 1060 return OK; 1061} 1062 1063status_t OMXNodeInstance::setInputSurface( 1064 OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer, 1065 MetadataBufferType *type) { 1066 Mutex::Autolock autolock(mLock); 1067 return createGraphicBufferSource(portIndex, bufferConsumer, type); 1068} 1069 1070status_t OMXNodeInstance::signalEndOfInputStream() { 1071 // For non-Surface input, the MediaCodec should convert the call to a 1072 // pair of requests (dequeue input buffer, queue input buffer with EOS 1073 // flag set). Seems easier than doing the equivalent from here. 1074 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 1075 if (bufferSource == NULL) { 1076 CLOGW("signalEndOfInputStream can only be used with Surface input"); 1077 return INVALID_OPERATION; 1078 } 1079 return bufferSource->signalEndOfInputStream(); 1080} 1081 1082status_t OMXNodeInstance::allocateSecureBuffer( 1083 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer, 1084 void **buffer_data, sp<NativeHandle> *native_handle) { 1085 if (buffer == NULL || buffer_data == NULL || native_handle == NULL) { 1086 ALOGE("b/25884056"); 1087 return BAD_VALUE; 1088 } 1089 1090 Mutex::Autolock autoLock(mLock); 1091 1092 BufferMeta *buffer_meta = new BufferMeta(size, portIndex); 1093 1094 OMX_BUFFERHEADERTYPE *header; 1095 1096 OMX_ERRORTYPE err = OMX_AllocateBuffer( 1097 mHandle, &header, portIndex, buffer_meta, size); 1098 1099 if (err != OMX_ErrorNone) { 1100 CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size)); 1101 delete buffer_meta; 1102 buffer_meta = NULL; 1103 1104 *buffer = 0; 1105 1106 return StatusFromOMXError(err); 1107 } 1108 1109 CHECK_EQ(header->pAppPrivate, buffer_meta); 1110 1111 *buffer = makeBufferID(header); 1112 if (mSecureBufferType[portIndex] == kSecureBufferTypeNativeHandle) { 1113 *buffer_data = NULL; 1114 *native_handle = NativeHandle::create( 1115 (native_handle_t *)header->pBuffer, false /* ownsHandle */); 1116 } else { 1117 *buffer_data = header->pBuffer; 1118 *native_handle = NULL; 1119 } 1120 1121 addActiveBuffer(portIndex, *buffer); 1122 1123 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 1124 if (bufferSource != NULL && portIndex == kPortIndexInput) { 1125 bufferSource->addCodecBuffer(*buffer); 1126 } 1127 CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT( 1128 *buffer, portIndex, "%zu@%p:%p", size, *buffer_data, 1129 *native_handle == NULL ? NULL : (*native_handle)->handle())); 1130 1131 return OK; 1132} 1133 1134status_t OMXNodeInstance::allocateBufferWithBackup( 1135 OMX_U32 portIndex, const sp<IMemory> ¶ms, 1136 OMX::buffer_id *buffer, OMX_U32 allottedSize) { 1137 if (params == NULL || buffer == NULL) { 1138 ALOGE("b/25884056"); 1139 return BAD_VALUE; 1140 } 1141 1142 Mutex::Autolock autoLock(mLock); 1143 if (allottedSize > params->size()) { 1144 return BAD_VALUE; 1145 } 1146 1147 BufferMeta *buffer_meta = new BufferMeta(params, portIndex, true); 1148 1149 OMX_BUFFERHEADERTYPE *header; 1150 1151 OMX_ERRORTYPE err = OMX_AllocateBuffer( 1152 mHandle, &header, portIndex, buffer_meta, allottedSize); 1153 if (err != OMX_ErrorNone) { 1154 CLOG_ERROR(allocateBufferWithBackup, err, 1155 SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer())); 1156 delete buffer_meta; 1157 buffer_meta = NULL; 1158 1159 *buffer = 0; 1160 1161 return StatusFromOMXError(err); 1162 } 1163 1164 CHECK_EQ(header->pAppPrivate, buffer_meta); 1165 1166 *buffer = makeBufferID(header); 1167 1168 addActiveBuffer(portIndex, *buffer); 1169 1170 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); 1171 if (bufferSource != NULL && portIndex == kPortIndexInput) { 1172 bufferSource->addCodecBuffer(*buffer); 1173 } 1174 1175 CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p", 1176 params->size(), params->pointer(), allottedSize, header->pBuffer)); 1177 1178 return OK; 1179} 1180 1181status_t OMXNodeInstance::freeBuffer( 1182 OMX_U32 portIndex, OMX::buffer_id buffer) { 1183 Mutex::Autolock autoLock(mLock); 1184 CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1185 1186 removeActiveBuffer(portIndex, buffer); 1187 1188 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); 1189 if (header == NULL) { 1190 ALOGE("b/25884056"); 1191 return BAD_VALUE; 1192 } 1193 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 1194 1195 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 1196 CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer); 1197 1198 delete buffer_meta; 1199 buffer_meta = NULL; 1200 invalidateBufferID(buffer); 1201 1202 return StatusFromOMXError(err); 1203} 1204 1205status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) { 1206 Mutex::Autolock autoLock(mLock); 1207 1208 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput); 1209 if (header == NULL) { 1210 ALOGE("b/25884056"); 1211 return BAD_VALUE; 1212 } 1213 header->nFilledLen = 0; 1214 header->nOffset = 0; 1215 header->nFlags = 0; 1216 1217 // meta now owns fenceFd 1218 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput); 1219 if (res != OK) { 1220 CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd)); 1221 return res; 1222 } 1223 1224 { 1225 Mutex::Autolock _l(mDebugLock); 1226 mOutputBuffersWithCodec.add(header); 1227 CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd))); 1228 } 1229 1230 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 1231 if (err != OMX_ErrorNone) { 1232 CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd)); 1233 Mutex::Autolock _l(mDebugLock); 1234 mOutputBuffersWithCodec.remove(header); 1235 } 1236 return StatusFromOMXError(err); 1237} 1238 1239status_t OMXNodeInstance::emptyBuffer( 1240 OMX::buffer_id buffer, 1241 OMX_U32 rangeOffset, OMX_U32 rangeLength, 1242 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1243 Mutex::Autolock autoLock(mLock); 1244 1245 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); 1246 if (header == NULL) { 1247 ALOGE("b/25884056"); 1248 return BAD_VALUE; 1249 } 1250 BufferMeta *buffer_meta = 1251 static_cast<BufferMeta *>(header->pAppPrivate); 1252 sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */, false /* limit */); 1253 sp<ABuffer> codec = buffer_meta->getBuffer(header, false /* backup */, false /* limit */); 1254 1255 // convert incoming ANW meta buffers if component is configured for gralloc metadata mode 1256 // ignore rangeOffset in this case 1257 if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource 1258 && backup->capacity() >= sizeof(VideoNativeMetadata) 1259 && codec->capacity() >= sizeof(VideoGrallocMetadata) 1260 && ((VideoNativeMetadata *)backup->base())->eType 1261 == kMetadataBufferTypeANWBuffer) { 1262 VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base(); 1263 VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base(); 1264 CLOG_BUFFER(emptyBuffer, "converting ANWB %p to handle %p", 1265 backupMeta.pBuffer, backupMeta.pBuffer->handle); 1266 codecMeta.pHandle = backupMeta.pBuffer != NULL ? backupMeta.pBuffer->handle : NULL; 1267 codecMeta.eType = kMetadataBufferTypeGrallocSource; 1268 header->nFilledLen = rangeLength ? sizeof(codecMeta) : 0; 1269 header->nOffset = 0; 1270 } else { 1271 // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. 1272 // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. 1273 if (rangeOffset > header->nAllocLen 1274 || rangeLength > header->nAllocLen - rangeOffset) { 1275 CLOG_ERROR(emptyBuffer, OMX_ErrorBadParameter, FULL_BUFFER(NULL, header, fenceFd)); 1276 if (fenceFd >= 0) { 1277 ::close(fenceFd); 1278 } 1279 return BAD_VALUE; 1280 } 1281 header->nFilledLen = rangeLength; 1282 header->nOffset = rangeOffset; 1283 1284 buffer_meta->CopyToOMX(header); 1285 } 1286 1287 return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd); 1288} 1289 1290// log queued buffer activity for the next few input and/or output frames 1291// if logging at internal state level 1292void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) { 1293 if (DEBUG == ADebug::kDebugInternalState) { 1294 DEBUG_BUMP = ADebug::kDebugAll; 1295 if (numInputBuffers > 0) { 1296 mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers; 1297 } 1298 if (numOutputBuffers > 0) { 1299 mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers; 1300 } 1301 } 1302} 1303 1304void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) { 1305 if (mDebugLevelBumpPendingBuffers[portIndex]) { 1306 --mDebugLevelBumpPendingBuffers[portIndex]; 1307 } 1308 if (!mDebugLevelBumpPendingBuffers[0] 1309 && !mDebugLevelBumpPendingBuffers[1]) { 1310 DEBUG_BUMP = DEBUG; 1311 } 1312} 1313 1314status_t OMXNodeInstance::storeFenceInMeta_l( 1315 OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) { 1316 // propagate fence if component supports it; wait for it otherwise 1317 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen; 1318 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1319 && metaSize >= sizeof(VideoNativeMetadata)) { 1320 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1321 if (nativeMeta.nFenceFd >= 0) { 1322 ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd); 1323 if (fenceFd >= 0) { 1324 ::close(fenceFd); 1325 } 1326 return ALREADY_EXISTS; 1327 } 1328 nativeMeta.nFenceFd = fenceFd; 1329 } else if (fenceFd >= 0) { 1330 CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd); 1331 sp<Fence> fence = new Fence(fenceFd); 1332 return fence->wait(IOMX::kFenceTimeoutMs); 1333 } 1334 return OK; 1335} 1336 1337int OMXNodeInstance::retrieveFenceFromMeta_l( 1338 OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) { 1339 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen; 1340 int fenceFd = -1; 1341 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer 1342 && header->nAllocLen >= sizeof(VideoNativeMetadata)) { 1343 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); 1344 if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 1345 fenceFd = nativeMeta.nFenceFd; 1346 nativeMeta.nFenceFd = -1; 1347 } 1348 if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) { 1349 CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER( 1350 NULL, header, nativeMeta.nFenceFd)); 1351 fenceFd = -1; 1352 } 1353 } 1354 return fenceFd; 1355} 1356 1357status_t OMXNodeInstance::emptyBuffer_l( 1358 OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, 1359 intptr_t debugAddr, int fenceFd) { 1360 header->nFlags = flags; 1361 header->nTimeStamp = timestamp; 1362 1363 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput); 1364 if (res != OK) { 1365 CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS( 1366 FULL_BUFFER(debugAddr, header, fenceFd))); 1367 return res; 1368 } 1369 1370 { 1371 Mutex::Autolock _l(mDebugLock); 1372 mInputBuffersWithCodec.add(header); 1373 1374 // bump internal-state debug level for 2 input frames past a buffer with CSD 1375 if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) { 1376 bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */); 1377 } 1378 1379 CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd))); 1380 } 1381 1382 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 1383 CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd)); 1384 1385 { 1386 Mutex::Autolock _l(mDebugLock); 1387 if (err != OMX_ErrorNone) { 1388 mInputBuffersWithCodec.remove(header); 1389 } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1390 unbumpDebugLevel_l(kPortIndexInput); 1391 } 1392 } 1393 1394 return StatusFromOMXError(err); 1395} 1396 1397// like emptyBuffer, but the data is already in header->pBuffer 1398status_t OMXNodeInstance::emptyGraphicBuffer( 1399 OMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer, 1400 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 1401 Mutex::Autolock autoLock(mLock); 1402 1403 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); 1404 if (header == NULL) { 1405 ALOGE("b/25884056"); 1406 return BAD_VALUE; 1407 } 1408 1409 status_t err = updateGraphicBufferInMeta_l( 1410 kPortIndexInput, graphicBuffer, buffer, header, 1411 true /* updateCodecBuffer */); 1412 if (err != OK) { 1413 CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER( 1414 (intptr_t)header->pBuffer, header, fenceFd)); 1415 return err; 1416 } 1417 1418 header->nOffset = 0; 1419 if (graphicBuffer == NULL) { 1420 header->nFilledLen = 0; 1421 } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) { 1422 header->nFilledLen = sizeof(VideoGrallocMetadata); 1423 } else { 1424 header->nFilledLen = sizeof(VideoNativeMetadata); 1425 } 1426 return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd); 1427} 1428 1429status_t OMXNodeInstance::getExtensionIndex( 1430 const char *parameterName, OMX_INDEXTYPE *index) { 1431 Mutex::Autolock autoLock(mLock); 1432 1433 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 1434 mHandle, const_cast<char *>(parameterName), index); 1435 1436 return StatusFromOMXError(err); 1437} 1438 1439inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") { 1440 switch (i) { 1441 case IOMX::INTERNAL_OPTION_SUSPEND: return "SUSPEND"; 1442 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 1443 return "REPEAT_PREVIOUS_FRAME_DELAY"; 1444 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP"; 1445 case IOMX::INTERNAL_OPTION_MAX_FPS: return "MAX_FPS"; 1446 case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME"; 1447 case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE"; 1448 default: return def; 1449 } 1450} 1451 1452template<typename T> 1453static bool getInternalOption( 1454 const void *data, size_t size, T *out) { 1455 if (size != sizeof(T)) { 1456 return false; 1457 } 1458 *out = *(T*)data; 1459 return true; 1460} 1461 1462status_t OMXNodeInstance::setInternalOption( 1463 OMX_U32 portIndex, 1464 IOMX::InternalOptionType type, 1465 const void *data, 1466 size_t size) { 1467 CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p", 1468 asString(type), type, portString(portIndex), portIndex, size, data); 1469 switch (type) { 1470 case IOMX::INTERNAL_OPTION_SUSPEND: 1471 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: 1472 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: 1473 case IOMX::INTERNAL_OPTION_MAX_FPS: 1474 case IOMX::INTERNAL_OPTION_START_TIME: 1475 case IOMX::INTERNAL_OPTION_TIME_LAPSE: 1476 case IOMX::INTERNAL_OPTION_COLOR_ASPECTS: 1477 { 1478 const sp<GraphicBufferSource> &bufferSource = 1479 getGraphicBufferSource(); 1480 1481 if (bufferSource == NULL || portIndex != kPortIndexInput) { 1482 CLOGW("setInternalOption is only for Surface input"); 1483 return ERROR_UNSUPPORTED; 1484 } 1485 1486 if (type == IOMX::INTERNAL_OPTION_SUSPEND) { 1487 bool suspend; 1488 if (!getInternalOption(data, size, &suspend)) { 1489 return INVALID_OPERATION; 1490 } 1491 1492 CLOG_CONFIG(setInternalOption, "suspend=%d", suspend); 1493 bufferSource->suspend(suspend); 1494 } else if (type == IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY) { 1495 int64_t delayUs; 1496 if (!getInternalOption(data, size, &delayUs)) { 1497 return INVALID_OPERATION; 1498 } 1499 1500 CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs); 1501 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs); 1502 } else if (type == IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP) { 1503 int64_t maxGapUs; 1504 if (!getInternalOption(data, size, &maxGapUs)) { 1505 return INVALID_OPERATION; 1506 } 1507 1508 CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs); 1509 return bufferSource->setMaxTimestampGapUs(maxGapUs); 1510 } else if (type == IOMX::INTERNAL_OPTION_MAX_FPS) { 1511 float maxFps; 1512 if (!getInternalOption(data, size, &maxFps)) { 1513 return INVALID_OPERATION; 1514 } 1515 1516 CLOG_CONFIG(setInternalOption, "maxFps=%f", maxFps); 1517 return bufferSource->setMaxFps(maxFps); 1518 } else if (type == IOMX::INTERNAL_OPTION_START_TIME) { 1519 int64_t skipFramesBeforeUs; 1520 if (!getInternalOption(data, size, &skipFramesBeforeUs)) { 1521 return INVALID_OPERATION; 1522 } 1523 1524 CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs); 1525 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs); 1526 } else if (type == IOMX::INTERNAL_OPTION_TIME_LAPSE) { 1527 GraphicBufferSource::TimeLapseConfig config; 1528 if (!getInternalOption(data, size, &config)) { 1529 return INVALID_OPERATION; 1530 } 1531 1532 CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld", 1533 (long long)config.mTimePerFrameUs, (long long)config.mTimePerCaptureUs); 1534 1535 return bufferSource->setTimeLapseConfig(config); 1536 } else if (type == IOMX::INTERNAL_OPTION_COLOR_ASPECTS) { 1537 ColorAspects aspects; 1538 if (!getInternalOption(data, size, &aspects)) { 1539 return INVALID_OPERATION; 1540 } 1541 1542 CLOG_CONFIG(setInternalOption, "setting color aspects"); 1543 bufferSource->setColorAspects(aspects); 1544 } 1545 1546 return OK; 1547 } 1548 1549 default: 1550 return ERROR_UNSUPPORTED; 1551 } 1552} 1553 1554bool OMXNodeInstance::handleMessage(omx_message &msg) { 1555 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1556 1557 if (msg.type == omx_message::FILL_BUFFER_DONE) { 1558 OMX_BUFFERHEADERTYPE *buffer = 1559 findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput); 1560 if (buffer == NULL) { 1561 ALOGE("b/25884056"); 1562 return false; 1563 } 1564 1565 { 1566 Mutex::Autolock _l(mDebugLock); 1567 mOutputBuffersWithCodec.remove(buffer); 1568 1569 CLOG_BUMPED_BUFFER( 1570 FBD, WITH_STATS(FULL_BUFFER( 1571 msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd))); 1572 1573 unbumpDebugLevel_l(kPortIndexOutput); 1574 } 1575 1576 BufferMeta *buffer_meta = 1577 static_cast<BufferMeta *>(buffer->pAppPrivate); 1578 1579 if (buffer->nOffset + buffer->nFilledLen < buffer->nOffset 1580 || buffer->nOffset + buffer->nFilledLen > buffer->nAllocLen) { 1581 CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter, 1582 FULL_BUFFER(NULL, buffer, msg.fenceFd)); 1583 } 1584 buffer_meta->CopyFromOMX(buffer); 1585 1586 if (bufferSource != NULL) { 1587 // fix up the buffer info (especially timestamp) if needed 1588 bufferSource->codecBufferFilled(msg); 1589 } 1590 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { 1591 OMX_BUFFERHEADERTYPE *buffer = 1592 findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput); 1593 if (buffer == NULL) { 1594 return false; 1595 } 1596 1597 { 1598 Mutex::Autolock _l(mDebugLock); 1599 mInputBuffersWithCodec.remove(buffer); 1600 1601 CLOG_BUMPED_BUFFER( 1602 EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd))); 1603 } 1604 1605 if (bufferSource != NULL) { 1606 // This is one of the buffers used exclusively by 1607 // GraphicBufferSource. 1608 // Don't dispatch a message back to ACodec, since it doesn't 1609 // know that anyone asked to have the buffer emptied and will 1610 // be very confused. 1611 bufferSource->codecBufferEmptied(msg); 1612 return true; 1613 } 1614 } else if (msg.type == omx_message::EVENT && 1615 msg.u.event_data.event == OMX_EventDataSpaceChanged) { 1616 handleDataSpaceChanged(msg); 1617 } 1618 1619 return false; 1620} 1621 1622bool OMXNodeInstance::handleDataSpaceChanged(omx_message &msg) { 1623 android_dataspace dataSpace = (android_dataspace) msg.u.event_data.data1; 1624 android_dataspace origDataSpace = dataSpace; 1625 1626 if (!ColorUtils::convertDataSpaceToV0(dataSpace)) { 1627 // Do not process the data space change, don't notify client either 1628 return true; 1629 } 1630 1631 android_pixel_format pixelFormat = (android_pixel_format)msg.u.event_data.data3; 1632 1633 ColorAspects requestedAspects = ColorUtils::unpackToColorAspects(msg.u.event_data.data2); 1634 ColorAspects aspects = requestedAspects; // initially requested aspects 1635 1636 // request color aspects to encode 1637 OMX_INDEXTYPE index; 1638 status_t err = getExtensionIndex( 1639 "OMX.google.android.index.describeColorAspects", &index); 1640 if (err == OK) { 1641 // V0 dataspace 1642 DescribeColorAspectsParams params; 1643 InitOMXParams(¶ms); 1644 params.nPortIndex = kPortIndexInput; 1645 params.nDataSpace = origDataSpace; 1646 params.nPixelFormat = pixelFormat; 1647 params.bDataSpaceChanged = OMX_TRUE; 1648 params.sAspects = requestedAspects; 1649 1650 err = getConfig(index, ¶ms, sizeof(params)); 1651 if (err == OK) { 1652 aspects = params.sAspects; 1653 ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 1654 params.sAspects.mRange, asString(params.sAspects.mRange), 1655 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 1656 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 1657 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 1658 err, asString(err)); 1659 } else { 1660 params.sAspects = aspects; 1661 err = OK; 1662 } 1663 params.bDataSpaceChanged = OMX_FALSE; 1664 for (int triesLeft = 2; --triesLeft >= 0; ) { 1665 status_t err = setConfig(index, ¶ms, sizeof(params)); 1666 if (err == OK) { 1667 err = getConfig(index, ¶ms, sizeof(params)); 1668 } 1669 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 1670 params.sAspects, aspects)) { 1671 // if we can't set or get color aspects, still communicate dataspace to client 1672 break; 1673 } 1674 1675 ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects."); 1676 } 1677 } 1678 1679 ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 1680 aspects.mRange, asString(aspects.mRange), 1681 aspects.mPrimaries, asString(aspects.mPrimaries), 1682 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 1683 aspects.mTransfer, asString(aspects.mTransfer), 1684 err, asString(err)); 1685 1686 // signal client that the dataspace has changed; this will update the output format 1687 // TODO: we should tie this to an output buffer somehow, and signal the change 1688 // just before the output buffer is returned to the client, but there are many 1689 // ways this could fail (e.g. flushing), and we are not yet supporting this scenario. 1690 1691 msg.u.event_data.data1 = (OMX_U32) dataSpace; 1692 msg.u.event_data.data2 = (OMX_U32) ColorUtils::packToU32(aspects); 1693 1694 return false; 1695} 1696 1697void OMXNodeInstance::onMessages(std::list<omx_message> &messages) { 1698 for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) { 1699 if (handleMessage(*it)) { 1700 messages.erase(it++); 1701 } else { 1702 ++it; 1703 } 1704 } 1705 1706 if (!messages.empty()) { 1707 mObserver->onMessages(messages); 1708 } 1709} 1710 1711void OMXNodeInstance::onObserverDied(OMXMaster *master) { 1712 ALOGE("!!! Observer died. Quickly, do something, ... anything..."); 1713 1714 // Try to force shutdown of the node and hope for the best. 1715 freeNode(master); 1716} 1717 1718void OMXNodeInstance::onGetHandleFailed() { 1719 delete this; 1720} 1721 1722// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here. 1723// Don't try to acquire mLock here -- in rare circumstances this will hang. 1724void OMXNodeInstance::onEvent( 1725 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) { 1726 const char *arg1String = "??"; 1727 const char *arg2String = "??"; 1728 ADebug::Level level = ADebug::kDebugInternalState; 1729 1730 switch (event) { 1731 case OMX_EventCmdComplete: 1732 arg1String = asString((OMX_COMMANDTYPE)arg1); 1733 switch (arg1) { 1734 case OMX_CommandStateSet: 1735 arg2String = asString((OMX_STATETYPE)arg2); 1736 level = ADebug::kDebugState; 1737 break; 1738 case OMX_CommandFlush: 1739 case OMX_CommandPortEnable: 1740 { 1741 // bump internal-state debug level for 2 input and output frames 1742 Mutex::Autolock _l(mDebugLock); 1743 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */); 1744 } 1745 // fall through 1746 default: 1747 arg2String = portString(arg2); 1748 } 1749 break; 1750 case OMX_EventError: 1751 arg1String = asString((OMX_ERRORTYPE)arg1); 1752 level = ADebug::kDebugLifeCycle; 1753 break; 1754 case OMX_EventPortSettingsChanged: 1755 arg2String = asString((OMX_INDEXEXTTYPE)arg2); 1756 // fall through 1757 default: 1758 arg1String = portString(arg1); 1759 } 1760 1761 CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)", 1762 asString(event), event, arg1String, arg1, arg2String, arg2); 1763 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); 1764 1765 if (bufferSource != NULL 1766 && event == OMX_EventCmdComplete 1767 && arg1 == OMX_CommandStateSet 1768 && arg2 == OMX_StateExecuting) { 1769 bufferSource->omxExecuting(); 1770 } 1771} 1772 1773// static 1774OMX_ERRORTYPE OMXNodeInstance::OnEvent( 1775 OMX_IN OMX_HANDLETYPE /* hComponent */, 1776 OMX_IN OMX_PTR pAppData, 1777 OMX_IN OMX_EVENTTYPE eEvent, 1778 OMX_IN OMX_U32 nData1, 1779 OMX_IN OMX_U32 nData2, 1780 OMX_IN OMX_PTR pEventData) { 1781 if (pAppData == NULL) { 1782 ALOGE("b/25884056"); 1783 return OMX_ErrorBadParameter; 1784 } 1785 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1786 if (instance->mDying) { 1787 return OMX_ErrorNone; 1788 } 1789 return instance->owner()->OnEvent( 1790 instance->nodeID(), eEvent, nData1, nData2, pEventData); 1791} 1792 1793// static 1794OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 1795 OMX_IN OMX_HANDLETYPE /* hComponent */, 1796 OMX_IN OMX_PTR pAppData, 1797 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1798 if (pAppData == NULL) { 1799 ALOGE("b/25884056"); 1800 return OMX_ErrorBadParameter; 1801 } 1802 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1803 if (instance->mDying) { 1804 return OMX_ErrorNone; 1805 } 1806 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 1807 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), 1808 instance->findBufferID(pBuffer), pBuffer, fenceFd); 1809} 1810 1811// static 1812OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 1813 OMX_IN OMX_HANDLETYPE /* hComponent */, 1814 OMX_IN OMX_PTR pAppData, 1815 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 1816 if (pAppData == NULL) { 1817 ALOGE("b/25884056"); 1818 return OMX_ErrorBadParameter; 1819 } 1820 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 1821 if (instance->mDying) { 1822 return OMX_ErrorNone; 1823 } 1824 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); 1825 return instance->owner()->OnFillBufferDone(instance->nodeID(), 1826 instance->findBufferID(pBuffer), pBuffer, fenceFd); 1827} 1828 1829void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 1830 ActiveBuffer active; 1831 active.mPortIndex = portIndex; 1832 active.mID = id; 1833 mActiveBuffers.push(active); 1834 1835 if (portIndex < NELEM(mNumPortBuffers)) { 1836 ++mNumPortBuffers[portIndex]; 1837 } 1838} 1839 1840void OMXNodeInstance::removeActiveBuffer( 1841 OMX_U32 portIndex, OMX::buffer_id id) { 1842 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 1843 if (mActiveBuffers[i].mPortIndex == portIndex 1844 && mActiveBuffers[i].mID == id) { 1845 mActiveBuffers.removeItemsAt(i); 1846 1847 if (portIndex < NELEM(mNumPortBuffers)) { 1848 --mNumPortBuffers[portIndex]; 1849 } 1850 return; 1851 } 1852 } 1853 1854 CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id); 1855} 1856 1857void OMXNodeInstance::freeActiveBuffers() { 1858 // Make sure to count down here, as freeBuffer will in turn remove 1859 // the active buffer from the vector... 1860 for (size_t i = mActiveBuffers.size(); i > 0;) { 1861 i--; 1862 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 1863 } 1864} 1865 1866OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1867 if (bufferHeader == NULL) { 1868 return 0; 1869 } 1870 Mutex::Autolock autoLock(mBufferIDLock); 1871 OMX::buffer_id buffer; 1872 do { // handle the very unlikely case of ID overflow 1873 if (++mBufferIDCount == 0) { 1874 ++mBufferIDCount; 1875 } 1876 buffer = (OMX::buffer_id)mBufferIDCount; 1877 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); 1878 mBufferIDToBufferHeader.add(buffer, bufferHeader); 1879 mBufferHeaderToBufferID.add(bufferHeader, buffer); 1880 return buffer; 1881} 1882 1883OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader( 1884 OMX::buffer_id buffer, OMX_U32 portIndex) { 1885 if (buffer == 0) { 1886 return NULL; 1887 } 1888 Mutex::Autolock autoLock(mBufferIDLock); 1889 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer); 1890 if (index < 0) { 1891 CLOGW("findBufferHeader: buffer %u not found", buffer); 1892 return NULL; 1893 } 1894 OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index); 1895 BufferMeta *buffer_meta = 1896 static_cast<BufferMeta *>(header->pAppPrivate); 1897 if (buffer_meta->getPortIndex() != portIndex) { 1898 CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer); 1899 android_errorWriteLog(0x534e4554, "28816827"); 1900 return NULL; 1901 } 1902 return header; 1903} 1904 1905OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { 1906 if (bufferHeader == NULL) { 1907 return 0; 1908 } 1909 Mutex::Autolock autoLock(mBufferIDLock); 1910 ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader); 1911 if (index < 0) { 1912 CLOGW("findBufferID: bufferHeader %p not found", bufferHeader); 1913 return 0; 1914 } 1915 return mBufferHeaderToBufferID.valueAt(index); 1916} 1917 1918void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) { 1919 if (buffer == 0) { 1920 return; 1921 } 1922 Mutex::Autolock autoLock(mBufferIDLock); 1923 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer); 1924 if (index < 0) { 1925 CLOGW("invalidateBufferID: buffer %u not found", buffer); 1926 return; 1927 } 1928 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index)); 1929 mBufferIDToBufferHeader.removeItemsAt(index); 1930} 1931 1932} // namespace android 1933