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