Home | History | Annotate | Download | only in omx
      1 /*
      2  * Copyright (C) 2016 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 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "OMXUtils"
     19 
     20 #include <string.h>
     21 
     22 #include <media/stagefright/omx/OMXUtils.h>
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/foundation/AUtils.h>
     25 #include <media/stagefright/MediaErrors.h>
     26 #include <media/hardware/HardwareAPI.h>
     27 #include <media/MediaDefs.h>
     28 #include <system/graphics-base.h>
     29 
     30 namespace android {
     31 
     32 status_t StatusFromOMXError(OMX_ERRORTYPE err) {
     33     switch (err) {
     34         case OMX_ErrorNone:
     35             return OK;
     36         case OMX_ErrorNoMore:
     37             return NOT_ENOUGH_DATA;
     38         case OMX_ErrorUnsupportedSetting:
     39         case OMX_ErrorUnsupportedIndex:
     40             return ERROR_UNSUPPORTED; // this is a media specific error
     41         case OMX_ErrorBadParameter:
     42             return BAD_VALUE;
     43         case OMX_ErrorInsufficientResources:
     44             return NO_MEMORY;
     45         case OMX_ErrorInvalidComponentName:
     46         case OMX_ErrorComponentNotFound:
     47             return NAME_NOT_FOUND;
     48         default:
     49             return UNKNOWN_ERROR;
     50     }
     51 }
     52 
     53 /**************************************************************************************************/
     54 
     55 DescribeColorFormatParams::DescribeColorFormatParams(const DescribeColorFormat2Params &params) {
     56     InitOMXParams(this);
     57 
     58     eColorFormat = params.eColorFormat;
     59     nFrameWidth = params.nFrameWidth;
     60     nFrameHeight = params.nFrameHeight;
     61     nStride = params.nStride;
     62     nSliceHeight = params.nSliceHeight;
     63     bUsingNativeBuffers = params.bUsingNativeBuffers;
     64     // we don't copy media images as this conversion is only used pre-query
     65 };
     66 
     67 void DescribeColorFormat2Params::initFromV1(const DescribeColorFormatParams &params) {
     68     InitOMXParams(this);
     69 
     70     eColorFormat = params.eColorFormat;
     71     nFrameWidth = params.nFrameWidth;
     72     nFrameHeight = params.nFrameHeight;
     73     nStride = params.nStride;
     74     nSliceHeight = params.nSliceHeight;
     75     bUsingNativeBuffers = params.bUsingNativeBuffers;
     76     sMediaImage.initFromV1(params.sMediaImage);
     77 };
     78 
     79 void MediaImage2::initFromV1(const MediaImage &image) {
     80     memset(this, 0, sizeof(*this));
     81 
     82     if (image.mType != MediaImage::MEDIA_IMAGE_TYPE_YUV) {
     83         mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
     84         return;
     85     }
     86 
     87     for (size_t ix = 0; ix < image.mNumPlanes; ++ix) {
     88         if (image.mPlane[ix].mHorizSubsampling > INT32_MAX
     89                 || image.mPlane[ix].mVertSubsampling > INT32_MAX) {
     90             mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
     91             return;
     92         }
     93     }
     94 
     95     mType = (MediaImage2::Type)image.mType;
     96     mNumPlanes = image.mNumPlanes;
     97     mWidth = image.mWidth;
     98     mHeight = image.mHeight;
     99     mBitDepth = image.mBitDepth;
    100     mBitDepthAllocated = 8;
    101     for (size_t ix = 0; ix < image.mNumPlanes; ++ix) {
    102         mPlane[ix].mOffset = image.mPlane[ix].mOffset;
    103         mPlane[ix].mColInc = image.mPlane[ix].mColInc;
    104         mPlane[ix].mRowInc = image.mPlane[ix].mRowInc;
    105         mPlane[ix].mHorizSubsampling = (int32_t)image.mPlane[ix].mHorizSubsampling;
    106         mPlane[ix].mVertSubsampling = (int32_t)image.mPlane[ix].mVertSubsampling;
    107     }
    108 }
    109 
    110 /**************************************************************************************************/
    111 
    112 const char *GetComponentRole(bool isEncoder, const char *mime) {
    113     struct MimeToRole {
    114         const char *mime;
    115         const char *decoderRole;
    116         const char *encoderRole;
    117     };
    118 
    119     static const MimeToRole kMimeToRole[] = {
    120         { MEDIA_MIMETYPE_AUDIO_MPEG,
    121             "audio_decoder.mp3", "audio_encoder.mp3" },
    122         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
    123             "audio_decoder.mp1", "audio_encoder.mp1" },
    124         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
    125             "audio_decoder.mp2", "audio_encoder.mp2" },
    126         { MEDIA_MIMETYPE_AUDIO_AMR_NB,
    127             "audio_decoder.amrnb", "audio_encoder.amrnb" },
    128         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
    129             "audio_decoder.amrwb", "audio_encoder.amrwb" },
    130         { MEDIA_MIMETYPE_AUDIO_AAC,
    131             "audio_decoder.aac", "audio_encoder.aac" },
    132         { MEDIA_MIMETYPE_AUDIO_VORBIS,
    133             "audio_decoder.vorbis", "audio_encoder.vorbis" },
    134         { MEDIA_MIMETYPE_AUDIO_OPUS,
    135             "audio_decoder.opus", "audio_encoder.opus" },
    136         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
    137             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
    138         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
    139             "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
    140         { MEDIA_MIMETYPE_VIDEO_AVC,
    141             "video_decoder.avc", "video_encoder.avc" },
    142         { MEDIA_MIMETYPE_VIDEO_HEVC,
    143             "video_decoder.hevc", "video_encoder.hevc" },
    144         { MEDIA_MIMETYPE_VIDEO_MPEG4,
    145             "video_decoder.mpeg4", "video_encoder.mpeg4" },
    146         { MEDIA_MIMETYPE_VIDEO_H263,
    147             "video_decoder.h263", "video_encoder.h263" },
    148         { MEDIA_MIMETYPE_VIDEO_VP8,
    149             "video_decoder.vp8", "video_encoder.vp8" },
    150         { MEDIA_MIMETYPE_VIDEO_VP9,
    151             "video_decoder.vp9", "video_encoder.vp9" },
    152         { MEDIA_MIMETYPE_AUDIO_RAW,
    153             "audio_decoder.raw", "audio_encoder.raw" },
    154         { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
    155             "video_decoder.dolby-vision", "video_encoder.dolby-vision" },
    156         { MEDIA_MIMETYPE_AUDIO_FLAC,
    157             "audio_decoder.flac", "audio_encoder.flac" },
    158         { MEDIA_MIMETYPE_AUDIO_MSGSM,
    159             "audio_decoder.gsm", "audio_encoder.gsm" },
    160         { MEDIA_MIMETYPE_VIDEO_MPEG2,
    161             "video_decoder.mpeg2", "video_encoder.mpeg2" },
    162         { MEDIA_MIMETYPE_AUDIO_AC3,
    163             "audio_decoder.ac3", "audio_encoder.ac3" },
    164         { MEDIA_MIMETYPE_AUDIO_EAC3,
    165             "audio_decoder.eac3", "audio_encoder.eac3" },
    166     };
    167 
    168     static const size_t kNumMimeToRole =
    169         sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
    170 
    171     size_t i;
    172     for (i = 0; i < kNumMimeToRole; ++i) {
    173         if (!strcasecmp(mime, kMimeToRole[i].mime)) {
    174             break;
    175         }
    176     }
    177 
    178     if (i == kNumMimeToRole) {
    179         return NULL;
    180     }
    181 
    182     return isEncoder ? kMimeToRole[i].encoderRole
    183                   : kMimeToRole[i].decoderRole;
    184 }
    185 
    186 status_t SetComponentRole(const sp<IOMXNode> &omxNode, const char *role) {
    187     OMX_PARAM_COMPONENTROLETYPE roleParams;
    188     InitOMXParams(&roleParams);
    189 
    190     strncpy((char *)roleParams.cRole,
    191             role, OMX_MAX_STRINGNAME_SIZE - 1);
    192 
    193     roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
    194 
    195     return omxNode->setParameter(
    196             OMX_IndexParamStandardComponentRole,
    197             &roleParams, sizeof(roleParams));
    198 }
    199 
    200 bool DescribeDefaultColorFormat(DescribeColorFormat2Params &params) {
    201     MediaImage2 &image = params.sMediaImage;
    202     memset(&image, 0, sizeof(image));
    203 
    204     image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
    205     image.mNumPlanes = 0;
    206 
    207     const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
    208     image.mWidth = params.nFrameWidth;
    209     image.mHeight = params.nFrameHeight;
    210 
    211     // only supporting YUV420
    212     if (fmt != OMX_COLOR_FormatYUV420Planar &&
    213         fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
    214         fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
    215         fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
    216         fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) {
    217         ALOGW("do not know color format 0x%x = %d", fmt, fmt);
    218         return false;
    219     }
    220 
    221     // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
    222     if (params.nStride != 0 && params.nSliceHeight == 0) {
    223         ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
    224                 params.nFrameHeight);
    225         params.nSliceHeight = params.nFrameHeight;
    226     }
    227 
    228     // we need stride and slice-height to be non-zero and sensible. These values were chosen to
    229     // prevent integer overflows further down the line, and do not indicate support for
    230     // 32kx32k video.
    231     if (params.nStride == 0 || params.nSliceHeight == 0
    232             || params.nStride > 32768 || params.nSliceHeight > 32768) {
    233         ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
    234                 fmt, fmt, params.nStride, params.nSliceHeight);
    235         return false;
    236     }
    237 
    238     // set-up YUV format
    239     image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
    240     image.mNumPlanes = 3;
    241     image.mBitDepth = 8;
    242     image.mBitDepthAllocated = 8;
    243     image.mPlane[image.Y].mOffset = 0;
    244     image.mPlane[image.Y].mColInc = 1;
    245     image.mPlane[image.Y].mRowInc = params.nStride;
    246     image.mPlane[image.Y].mHorizSubsampling = 1;
    247     image.mPlane[image.Y].mVertSubsampling = 1;
    248 
    249     switch ((int)fmt) {
    250         case HAL_PIXEL_FORMAT_YV12:
    251             if (params.bUsingNativeBuffers) {
    252                 size_t ystride = align(params.nStride, 16);
    253                 size_t cstride = align(params.nStride / 2, 16);
    254                 image.mPlane[image.Y].mRowInc = ystride;
    255 
    256                 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
    257                 image.mPlane[image.V].mColInc = 1;
    258                 image.mPlane[image.V].mRowInc = cstride;
    259                 image.mPlane[image.V].mHorizSubsampling = 2;
    260                 image.mPlane[image.V].mVertSubsampling = 2;
    261 
    262                 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
    263                         + (cstride * params.nSliceHeight / 2);
    264                 image.mPlane[image.U].mColInc = 1;
    265                 image.mPlane[image.U].mRowInc = cstride;
    266                 image.mPlane[image.U].mHorizSubsampling = 2;
    267                 image.mPlane[image.U].mVertSubsampling = 2;
    268                 break;
    269             } else {
    270                 // fall through as YV12 is used for YUV420Planar by some codecs
    271             }
    272 
    273         case OMX_COLOR_FormatYUV420Planar:
    274         case OMX_COLOR_FormatYUV420PackedPlanar:
    275             image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
    276             image.mPlane[image.U].mColInc = 1;
    277             image.mPlane[image.U].mRowInc = params.nStride / 2;
    278             image.mPlane[image.U].mHorizSubsampling = 2;
    279             image.mPlane[image.U].mVertSubsampling = 2;
    280 
    281             image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
    282                     + (params.nStride * params.nSliceHeight / 4);
    283             image.mPlane[image.V].mColInc = 1;
    284             image.mPlane[image.V].mRowInc = params.nStride / 2;
    285             image.mPlane[image.V].mHorizSubsampling = 2;
    286             image.mPlane[image.V].mVertSubsampling = 2;
    287             break;
    288 
    289         case OMX_COLOR_FormatYUV420SemiPlanar:
    290             // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
    291         case OMX_COLOR_FormatYUV420PackedSemiPlanar:
    292             // NV12
    293             image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
    294             image.mPlane[image.U].mColInc = 2;
    295             image.mPlane[image.U].mRowInc = params.nStride;
    296             image.mPlane[image.U].mHorizSubsampling = 2;
    297             image.mPlane[image.U].mVertSubsampling = 2;
    298 
    299             image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
    300             image.mPlane[image.V].mColInc = 2;
    301             image.mPlane[image.V].mRowInc = params.nStride;
    302             image.mPlane[image.V].mHorizSubsampling = 2;
    303             image.mPlane[image.V].mVertSubsampling = 2;
    304             break;
    305 
    306         default:
    307             TRESPASS();
    308     }
    309     return true;
    310 }
    311 
    312 bool DescribeColorFormat(
    313         const sp<IOMXNode> &omxNode,
    314         DescribeColorFormat2Params &describeParams)
    315 {
    316     OMX_INDEXTYPE describeColorFormatIndex;
    317     if (omxNode->getExtensionIndex(
    318             "OMX.google.android.index.describeColorFormat",
    319             &describeColorFormatIndex) == OK) {
    320         DescribeColorFormatParams describeParamsV1(describeParams);
    321         if (omxNode->getParameter(
    322                 describeColorFormatIndex,
    323                 &describeParamsV1, sizeof(describeParamsV1)) == OK) {
    324             describeParams.initFromV1(describeParamsV1);
    325             return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
    326         }
    327     } else if (omxNode->getExtensionIndex(
    328             "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
    329                && omxNode->getParameter(
    330                        describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
    331         return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
    332     }
    333 
    334     return DescribeDefaultColorFormat(describeParams);
    335 }
    336 
    337 // static
    338 bool IsFlexibleColorFormat(
    339          const sp<IOMXNode> &omxNode,
    340          uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
    341     DescribeColorFormat2Params describeParams;
    342     InitOMXParams(&describeParams);
    343     describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
    344     // reasonable dummy values
    345     describeParams.nFrameWidth = 128;
    346     describeParams.nFrameHeight = 128;
    347     describeParams.nStride = 128;
    348     describeParams.nSliceHeight = 128;
    349     describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
    350 
    351     CHECK(flexibleEquivalent != NULL);
    352 
    353     if (!DescribeColorFormat(omxNode, describeParams)) {
    354         return false;
    355     }
    356 
    357     const MediaImage2 &img = describeParams.sMediaImage;
    358     if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
    359         if (img.mNumPlanes != 3
    360                 || img.mPlane[img.Y].mHorizSubsampling != 1
    361                 || img.mPlane[img.Y].mVertSubsampling != 1) {
    362             return false;
    363         }
    364 
    365         // YUV 420
    366         if (img.mPlane[img.U].mHorizSubsampling == 2
    367                 && img.mPlane[img.U].mVertSubsampling == 2
    368                 && img.mPlane[img.V].mHorizSubsampling == 2
    369                 && img.mPlane[img.V].mVertSubsampling == 2) {
    370             // possible flexible YUV420 format
    371             if (img.mBitDepth <= 8) {
    372                *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
    373                return true;
    374             }
    375         }
    376     }
    377     return false;
    378 }
    379 
    380 }  // namespace android
    381 
    382