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