Home | History | Annotate | Download | only in omx
      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         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 
     78 void 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 
     88 void 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 
    150 void 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 
    183 uint32_t SoftVideoDecoderOMXComponent::outputBufferWidth() {
    184     return mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
    185 }
    186 
    187 uint32_t SoftVideoDecoderOMXComponent::outputBufferHeight() {
    188     return mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
    189 }
    190 
    191 void 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 
    251 void 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 
    259 bool 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 
    270 void 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 
    290 status_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 
    304 void 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 
    333 OMX_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 
    396 OMX_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 
    525 OMX_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 
    573 OMX_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 
    607 OMX_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 
    621 bool SoftVideoDecoderOMXComponent::supportsDescribeColorAspects() {
    622     return getColorAspectPreference() != kNotSupported;
    623 }
    624 
    625 int SoftVideoDecoderOMXComponent::getColorAspectPreference() {
    626     return kNotSupported;
    627 }
    628 
    629 void SoftVideoDecoderOMXComponent::onReset() {
    630     mOutputPortSettingsChange = NONE;
    631 }
    632 
    633 void 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