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