1/* 2 * Copyright (C) 2013 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#include <inttypes.h> 18 19//#define LOG_NDEBUG 0 20#define LOG_TAG "SoftVideoDecoderOMXComponent" 21#include <utils/Log.h> 22 23#include "include/SoftVideoDecoderOMXComponent.h" 24 25#include <media/hardware/HardwareAPI.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/ALooper.h> 28#include <media/stagefright/foundation/AMessage.h> 29#include <media/stagefright/foundation/AUtils.h> 30#include <media/stagefright/MediaDefs.h> 31 32namespace android { 33 34template<class T> 35static void InitOMXParams(T *params) { 36 params->nSize = sizeof(T); 37 params->nVersion.s.nVersionMajor = 1; 38 params->nVersion.s.nVersionMinor = 0; 39 params->nVersion.s.nRevision = 0; 40 params->nVersion.s.nStep = 0; 41} 42 43SoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent( 44 const char *name, 45 const char *componentRole, 46 OMX_VIDEO_CODINGTYPE codingType, 47 const CodecProfileLevel *profileLevels, 48 size_t numProfileLevels, 49 int32_t width, 50 int32_t height, 51 const OMX_CALLBACKTYPE *callbacks, 52 OMX_PTR appData, 53 OMX_COMPONENTTYPE **component) 54 : SimpleSoftOMXComponent(name, callbacks, appData, component), 55 mIsAdaptive(false), 56 mAdaptiveMaxWidth(0), 57 mAdaptiveMaxHeight(0), 58 mWidth(width), 59 mHeight(height), 60 mCropLeft(0), 61 mCropTop(0), 62 mCropWidth(width), 63 mCropHeight(height), 64 mOutputPortSettingsChange(NONE), 65 mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock 66 mMinCompressionRatio(1), // max input size is normally the output size 67 mComponentRole(componentRole), 68 mCodingType(codingType), 69 mProfileLevels(profileLevels), 70 mNumProfileLevels(numProfileLevels) { 71 72 // init all the color aspects to be Unspecified. 73 memset(&mDefaultColorAspects, 0, sizeof(ColorAspects)); 74 memset(&mBitstreamColorAspects, 0, sizeof(ColorAspects)); 75 memset(&mFinalColorAspects, 0, sizeof(ColorAspects)); 76} 77 78void SoftVideoDecoderOMXComponent::initPorts( 79 OMX_U32 numInputBuffers, 80 OMX_U32 inputBufferSize, 81 OMX_U32 numOutputBuffers, 82 const char *mimeType, 83 OMX_U32 minCompressionRatio) { 84 initPorts(numInputBuffers, numInputBuffers, inputBufferSize, 85 numOutputBuffers, numOutputBuffers, mimeType, minCompressionRatio); 86} 87 88void SoftVideoDecoderOMXComponent::initPorts( 89 OMX_U32 numMinInputBuffers, 90 OMX_U32 numInputBuffers, 91 OMX_U32 inputBufferSize, 92 OMX_U32 numMinOutputBuffers, 93 OMX_U32 numOutputBuffers, 94 const char *mimeType, 95 OMX_U32 minCompressionRatio) { 96 mMinInputBufferSize = inputBufferSize; 97 mMinCompressionRatio = minCompressionRatio; 98 99 OMX_PARAM_PORTDEFINITIONTYPE def; 100 InitOMXParams(&def); 101 102 def.nPortIndex = kInputPortIndex; 103 def.eDir = OMX_DirInput; 104 def.nBufferCountMin = numMinInputBuffers; 105 def.nBufferCountActual = numInputBuffers; 106 def.nBufferSize = inputBufferSize; 107 def.bEnabled = OMX_TRUE; 108 def.bPopulated = OMX_FALSE; 109 def.eDomain = OMX_PortDomainVideo; 110 def.bBuffersContiguous = OMX_FALSE; 111 def.nBufferAlignment = 1; 112 113 def.format.video.cMIMEType = const_cast<char *>(mimeType); 114 def.format.video.pNativeRender = NULL; 115 /* size is initialized in updatePortDefinitions() */ 116 def.format.video.nBitrate = 0; 117 def.format.video.xFramerate = 0; 118 def.format.video.bFlagErrorConcealment = OMX_FALSE; 119 def.format.video.eCompressionFormat = mCodingType; 120 def.format.video.eColorFormat = OMX_COLOR_FormatUnused; 121 def.format.video.pNativeWindow = NULL; 122 123 addPort(def); 124 125 def.nPortIndex = kOutputPortIndex; 126 def.eDir = OMX_DirOutput; 127 def.nBufferCountMin = numMinOutputBuffers; 128 def.nBufferCountActual = numOutputBuffers; 129 def.bEnabled = OMX_TRUE; 130 def.bPopulated = OMX_FALSE; 131 def.eDomain = OMX_PortDomainVideo; 132 def.bBuffersContiguous = OMX_FALSE; 133 def.nBufferAlignment = 2; 134 135 def.format.video.cMIMEType = const_cast<char *>("video/raw"); 136 def.format.video.pNativeRender = NULL; 137 /* size is initialized in updatePortDefinitions() */ 138 def.format.video.nBitrate = 0; 139 def.format.video.xFramerate = 0; 140 def.format.video.bFlagErrorConcealment = OMX_FALSE; 141 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 142 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 143 def.format.video.pNativeWindow = NULL; 144 145 addPort(def); 146 147 updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); 148} 149 150void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) { 151 OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef; 152 outDef->format.video.nFrameWidth = outputBufferWidth(); 153 outDef->format.video.nFrameHeight = outputBufferHeight(); 154 outDef->format.video.nStride = outDef->format.video.nFrameWidth; 155 outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight; 156 157 outDef->nBufferSize = 158 (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2; 159 160 OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef; 161 inDef->format.video.nFrameWidth = mWidth; 162 inDef->format.video.nFrameHeight = mHeight; 163 // input port is compressed, hence it has no stride 164 inDef->format.video.nStride = 0; 165 inDef->format.video.nSliceHeight = 0; 166 167 // when output format changes, input buffer size does not actually change 168 if (updateInputSize) { 169 inDef->nBufferSize = max( 170 outDef->nBufferSize / mMinCompressionRatio, 171 max(mMinInputBufferSize, inDef->nBufferSize)); 172 } 173 174 if (updateCrop) { 175 mCropLeft = 0; 176 mCropTop = 0; 177 mCropWidth = mWidth; 178 mCropHeight = mHeight; 179 } 180} 181 182 183uint32_t SoftVideoDecoderOMXComponent::outputBufferWidth() { 184 return mIsAdaptive ? mAdaptiveMaxWidth : mWidth; 185} 186 187uint32_t SoftVideoDecoderOMXComponent::outputBufferHeight() { 188 return mIsAdaptive ? mAdaptiveMaxHeight : mHeight; 189} 190 191void SoftVideoDecoderOMXComponent::handlePortSettingsChange( 192 bool *portWillReset, uint32_t width, uint32_t height, 193 CropSettingsMode cropSettingsMode, bool fakeStride) { 194 *portWillReset = false; 195 bool sizeChanged = (width != mWidth || height != mHeight); 196 bool updateCrop = (cropSettingsMode == kCropUnSet); 197 bool cropChanged = (cropSettingsMode == kCropChanged); 198 bool strideChanged = false; 199 if (fakeStride) { 200 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; 201 if (def->format.video.nStride != (OMX_S32)width 202 || def->format.video.nSliceHeight != (OMX_U32)height) { 203 strideChanged = true; 204 } 205 } 206 207 if (sizeChanged || cropChanged || strideChanged) { 208 mWidth = width; 209 mHeight = height; 210 211 if ((sizeChanged && !mIsAdaptive) 212 || width > mAdaptiveMaxWidth 213 || height > mAdaptiveMaxHeight) { 214 if (mIsAdaptive) { 215 if (width > mAdaptiveMaxWidth) { 216 mAdaptiveMaxWidth = width; 217 } 218 if (height > mAdaptiveMaxHeight) { 219 mAdaptiveMaxHeight = height; 220 } 221 } 222 updatePortDefinitions(updateCrop); 223 notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL); 224 mOutputPortSettingsChange = AWAITING_DISABLED; 225 *portWillReset = true; 226 } else { 227 updatePortDefinitions(updateCrop); 228 229 if (fakeStride) { 230 // MAJOR HACK that is not pretty, it's just to fool the renderer to read the correct 231 // data. 232 // Some software decoders (e.g. SoftMPEG4) fill decoded frame directly to output 233 // buffer without considering the output buffer stride and slice height. So this is 234 // used to signal how the buffer is arranged. The alternative is to re-arrange the 235 // output buffer in SoftMPEG4, but that results in memcopies. 236 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; 237 def->format.video.nStride = mWidth; 238 def->format.video.nSliceHeight = mHeight; 239 } 240 241 notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 242 OMX_IndexConfigCommonOutputCrop, NULL); 243 } 244 } else if (mUpdateColorAspects) { 245 notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 246 kDescribeColorAspectsIndex, NULL); 247 mUpdateColorAspects = false; 248 } 249} 250 251void SoftVideoDecoderOMXComponent::dumpColorAspects(const ColorAspects &colorAspects) { 252 ALOGD("dumpColorAspects: (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) ", 253 colorAspects.mRange, asString(colorAspects.mRange), 254 colorAspects.mPrimaries, asString(colorAspects.mPrimaries), 255 colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs), 256 colorAspects.mTransfer, asString(colorAspects.mTransfer)); 257} 258 259bool SoftVideoDecoderOMXComponent::colorAspectsDiffer( 260 const ColorAspects &a, const ColorAspects &b) { 261 if (a.mRange != b.mRange 262 || a.mPrimaries != b.mPrimaries 263 || a.mTransfer != b.mTransfer 264 || a.mMatrixCoeffs != b.mMatrixCoeffs) { 265 return true; 266 } 267 return false; 268} 269 270void SoftVideoDecoderOMXComponent::updateFinalColorAspects( 271 const ColorAspects &otherAspects, const ColorAspects &preferredAspects) { 272 Mutex::Autolock autoLock(mColorAspectsLock); 273 ColorAspects newAspects; 274 newAspects.mRange = preferredAspects.mRange != ColorAspects::RangeUnspecified ? 275 preferredAspects.mRange : otherAspects.mRange; 276 newAspects.mPrimaries = preferredAspects.mPrimaries != ColorAspects::PrimariesUnspecified ? 277 preferredAspects.mPrimaries : otherAspects.mPrimaries; 278 newAspects.mTransfer = preferredAspects.mTransfer != ColorAspects::TransferUnspecified ? 279 preferredAspects.mTransfer : otherAspects.mTransfer; 280 newAspects.mMatrixCoeffs = preferredAspects.mMatrixCoeffs != ColorAspects::MatrixUnspecified ? 281 preferredAspects.mMatrixCoeffs : otherAspects.mMatrixCoeffs; 282 283 // Check to see if need update mFinalColorAspects. 284 if (colorAspectsDiffer(mFinalColorAspects, newAspects)) { 285 mFinalColorAspects = newAspects; 286 mUpdateColorAspects = true; 287 } 288} 289 290status_t SoftVideoDecoderOMXComponent::handleColorAspectsChange() { 291 int perference = getColorAspectPreference(); 292 ALOGD("Color Aspects preference: %d ", perference); 293 294 if (perference == kPreferBitstream) { 295 updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects); 296 } else if (perference == kPreferContainer) { 297 updateFinalColorAspects(mBitstreamColorAspects, mDefaultColorAspects); 298 } else { 299 return OMX_ErrorUnsupportedSetting; 300 } 301 return OK; 302} 303 304void SoftVideoDecoderOMXComponent::copyYV12FrameToOutputBuffer( 305 uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV, 306 size_t srcYStride, size_t srcUStride, size_t srcVStride) { 307 size_t dstYStride = outputBufferWidth(); 308 size_t dstUVStride = dstYStride / 2; 309 size_t dstHeight = outputBufferHeight(); 310 uint8_t *dstStart = dst; 311 312 for (size_t i = 0; i < mHeight; ++i) { 313 memcpy(dst, srcY, mWidth); 314 srcY += srcYStride; 315 dst += dstYStride; 316 } 317 318 dst = dstStart + dstYStride * dstHeight; 319 for (size_t i = 0; i < mHeight / 2; ++i) { 320 memcpy(dst, srcU, mWidth / 2); 321 srcU += srcUStride; 322 dst += dstUVStride; 323 } 324 325 dst = dstStart + (5 * dstYStride * dstHeight) / 4; 326 for (size_t i = 0; i < mHeight / 2; ++i) { 327 memcpy(dst, srcV, mWidth / 2); 328 srcV += srcVStride; 329 dst += dstUVStride; 330 } 331} 332 333OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter( 334 OMX_INDEXTYPE index, OMX_PTR params) { 335 switch (index) { 336 case OMX_IndexParamVideoPortFormat: 337 { 338 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 339 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 340 341 if (!isValidOMXParam(formatParams)) { 342 return OMX_ErrorBadParameter; 343 } 344 345 if (formatParams->nPortIndex > kMaxPortIndex) { 346 return OMX_ErrorBadPortIndex; 347 } 348 349 if (formatParams->nIndex != 0) { 350 return OMX_ErrorNoMore; 351 } 352 353 if (formatParams->nPortIndex == kInputPortIndex) { 354 formatParams->eCompressionFormat = mCodingType; 355 formatParams->eColorFormat = OMX_COLOR_FormatUnused; 356 formatParams->xFramerate = 0; 357 } else { 358 CHECK_EQ(formatParams->nPortIndex, 1u); 359 360 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; 361 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; 362 formatParams->xFramerate = 0; 363 } 364 365 return OMX_ErrorNone; 366 } 367 368 case OMX_IndexParamVideoProfileLevelQuerySupported: 369 { 370 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = 371 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params; 372 373 if (!isValidOMXParam(profileLevel)) { 374 return OMX_ErrorBadParameter; 375 } 376 377 if (profileLevel->nPortIndex != kInputPortIndex) { 378 ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex); 379 return OMX_ErrorUnsupportedIndex; 380 } 381 382 if (profileLevel->nProfileIndex >= mNumProfileLevels) { 383 return OMX_ErrorNoMore; 384 } 385 386 profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile; 387 profileLevel->eLevel = mProfileLevels[profileLevel->nProfileIndex].mLevel; 388 return OMX_ErrorNone; 389 } 390 391 default: 392 return SimpleSoftOMXComponent::internalGetParameter(index, params); 393 } 394} 395 396OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( 397 OMX_INDEXTYPE index, const OMX_PTR params) { 398 // Include extension index OMX_INDEXEXTTYPE. 399 const int32_t indexFull = index; 400 401 switch (indexFull) { 402 case OMX_IndexParamStandardComponentRole: 403 { 404 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 405 (const OMX_PARAM_COMPONENTROLETYPE *)params; 406 407 if (!isValidOMXParam(roleParams)) { 408 return OMX_ErrorBadParameter; 409 } 410 411 if (strncmp((const char *)roleParams->cRole, 412 mComponentRole, 413 OMX_MAX_STRINGNAME_SIZE - 1)) { 414 return OMX_ErrorUndefined; 415 } 416 417 return OMX_ErrorNone; 418 } 419 420 case OMX_IndexParamVideoPortFormat: 421 { 422 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 423 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 424 425 if (!isValidOMXParam(formatParams)) { 426 return OMX_ErrorBadParameter; 427 } 428 429 if (formatParams->nPortIndex > kMaxPortIndex) { 430 return OMX_ErrorBadPortIndex; 431 } 432 433 if (formatParams->nIndex != 0) { 434 return OMX_ErrorNoMore; 435 } 436 437 if (formatParams->nPortIndex == kInputPortIndex) { 438 if (formatParams->eCompressionFormat != mCodingType 439 || formatParams->eColorFormat != OMX_COLOR_FormatUnused) { 440 return OMX_ErrorUnsupportedSetting; 441 } 442 } else { 443 if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused 444 || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) { 445 return OMX_ErrorUnsupportedSetting; 446 } 447 } 448 449 return OMX_ErrorNone; 450 } 451 452 case kPrepareForAdaptivePlaybackIndex: 453 { 454 const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams = 455 (const PrepareForAdaptivePlaybackParams *)params; 456 457 if (!isValidOMXParam(adaptivePlaybackParams)) { 458 return OMX_ErrorBadParameter; 459 } 460 461 mIsAdaptive = adaptivePlaybackParams->bEnable; 462 if (mIsAdaptive) { 463 mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth; 464 mAdaptiveMaxHeight = adaptivePlaybackParams->nMaxFrameHeight; 465 mWidth = mAdaptiveMaxWidth; 466 mHeight = mAdaptiveMaxHeight; 467 } else { 468 mAdaptiveMaxWidth = 0; 469 mAdaptiveMaxHeight = 0; 470 } 471 updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); 472 return OMX_ErrorNone; 473 } 474 475 case OMX_IndexParamPortDefinition: 476 { 477 OMX_PARAM_PORTDEFINITIONTYPE *newParams = 478 (OMX_PARAM_PORTDEFINITIONTYPE *)params; 479 480 if (!isValidOMXParam(newParams)) { 481 return OMX_ErrorBadParameter; 482 } 483 484 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video; 485 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef; 486 487 uint32_t oldWidth = def->format.video.nFrameWidth; 488 uint32_t oldHeight = def->format.video.nFrameHeight; 489 uint32_t newWidth = video_def->nFrameWidth; 490 uint32_t newHeight = video_def->nFrameHeight; 491 // We need width, height, stride and slice-height to be non-zero and sensible. 492 // These values were chosen to prevent integer overflows further down the line, and do 493 // not indicate support for 32kx32k video. 494 if (newWidth > 32768 || newHeight > 32768 495 || video_def->nStride > 32768 || video_def->nSliceHeight > 32768) { 496 ALOGE("b/22885421"); 497 return OMX_ErrorBadParameter; 498 } 499 if (newWidth != oldWidth || newHeight != oldHeight) { 500 bool outputPort = (newParams->nPortIndex == kOutputPortIndex); 501 if (outputPort) { 502 // only update (essentially crop) if size changes 503 mWidth = newWidth; 504 mHeight = newHeight; 505 506 updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); 507 // reset buffer size based on frame size 508 newParams->nBufferSize = def->nBufferSize; 509 } else { 510 // For input port, we only set nFrameWidth and nFrameHeight. Buffer size 511 // is updated when configuring the output port using the max-frame-size, 512 // though client can still request a larger size. 513 def->format.video.nFrameWidth = newWidth; 514 def->format.video.nFrameHeight = newHeight; 515 } 516 } 517 return SimpleSoftOMXComponent::internalSetParameter(index, params); 518 } 519 520 default: 521 return SimpleSoftOMXComponent::internalSetParameter(index, params); 522 } 523} 524 525OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig( 526 OMX_INDEXTYPE index, OMX_PTR params) { 527 switch ((int)index) { 528 case OMX_IndexConfigCommonOutputCrop: 529 { 530 OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params; 531 532 if (!isValidOMXParam(rectParams)) { 533 return OMX_ErrorBadParameter; 534 } 535 536 if (rectParams->nPortIndex != kOutputPortIndex) { 537 return OMX_ErrorUndefined; 538 } 539 540 rectParams->nLeft = mCropLeft; 541 rectParams->nTop = mCropTop; 542 rectParams->nWidth = mCropWidth; 543 rectParams->nHeight = mCropHeight; 544 545 return OMX_ErrorNone; 546 } 547 case kDescribeColorAspectsIndex: 548 { 549 if (!supportsDescribeColorAspects()) { 550 return OMX_ErrorUnsupportedIndex; 551 } 552 553 DescribeColorAspectsParams* colorAspectsParams = 554 (DescribeColorAspectsParams *)params; 555 556 if (colorAspectsParams->nPortIndex != kOutputPortIndex) { 557 return OMX_ErrorBadParameter; 558 } 559 560 colorAspectsParams->sAspects = mFinalColorAspects; 561 if (colorAspectsParams->bRequestingDataSpace || colorAspectsParams->bDataSpaceChanged) { 562 return OMX_ErrorUnsupportedSetting; 563 } 564 565 return OMX_ErrorNone; 566 } 567 568 default: 569 return OMX_ErrorUnsupportedIndex; 570 } 571} 572 573OMX_ERRORTYPE SoftVideoDecoderOMXComponent::setConfig( 574 OMX_INDEXTYPE index, const OMX_PTR params){ 575 switch ((int)index) { 576 case kDescribeColorAspectsIndex: 577 { 578 if (!supportsDescribeColorAspects()) { 579 return OMX_ErrorUnsupportedIndex; 580 } 581 const DescribeColorAspectsParams* colorAspectsParams = 582 (const DescribeColorAspectsParams *)params; 583 584 if (!isValidOMXParam(colorAspectsParams)) { 585 return OMX_ErrorBadParameter; 586 } 587 588 if (colorAspectsParams->nPortIndex != kOutputPortIndex) { 589 return OMX_ErrorBadParameter; 590 } 591 592 // Update color aspects if necessary. 593 if (colorAspectsDiffer(colorAspectsParams->sAspects, mDefaultColorAspects)) { 594 mDefaultColorAspects = colorAspectsParams->sAspects; 595 status_t err = handleColorAspectsChange(); 596 CHECK(err == OK); 597 } 598 return OMX_ErrorNone; 599 } 600 601 default: 602 return OMX_ErrorUnsupportedIndex; 603 } 604} 605 606 607OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getExtensionIndex( 608 const char *name, OMX_INDEXTYPE *index) { 609 if (!strcmp(name, "OMX.google.android.index.prepareForAdaptivePlayback")) { 610 *(int32_t*)index = kPrepareForAdaptivePlaybackIndex; 611 return OMX_ErrorNone; 612 } else if (!strcmp(name, "OMX.google.android.index.describeColorAspects") 613 && supportsDescribeColorAspects()) { 614 *(int32_t*)index = kDescribeColorAspectsIndex; 615 return OMX_ErrorNone; 616 } 617 618 return SimpleSoftOMXComponent::getExtensionIndex(name, index); 619} 620 621bool SoftVideoDecoderOMXComponent::supportsDescribeColorAspects() { 622 return getColorAspectPreference() != kNotSupported; 623} 624 625int SoftVideoDecoderOMXComponent::getColorAspectPreference() { 626 return kNotSupported; 627} 628 629void SoftVideoDecoderOMXComponent::onReset() { 630 mOutputPortSettingsChange = NONE; 631} 632 633void SoftVideoDecoderOMXComponent::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 634 if (portIndex != kOutputPortIndex) { 635 return; 636 } 637 638 switch (mOutputPortSettingsChange) { 639 case NONE: 640 break; 641 642 case AWAITING_DISABLED: 643 { 644 CHECK(!enabled); 645 mOutputPortSettingsChange = AWAITING_ENABLED; 646 break; 647 } 648 649 default: 650 { 651 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 652 CHECK(enabled); 653 mOutputPortSettingsChange = NONE; 654 break; 655 } 656 } 657} 658 659} // namespace android 660