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         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