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