Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright (C) 2011 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 "sles_allinclusive.h"
     18 
     19 #include <media/IMediaPlayerService.h>
     20 #include <media/stagefright/OMXClient.h>
     21 #include <media/stagefright/OMXCodec.h>
     22 #include <media/IOMX.h>
     23 #include <media/stagefright/MediaDefs.h>
     24 
     25 
     26 namespace android {
     27 
     28 // listed in same order as VideoCodecIds[] in file "../devices.c" with ANDROID defined
     29 static const char *kVideoMimeTypes[] = {
     30         MEDIA_MIMETYPE_VIDEO_MPEG2,
     31         MEDIA_MIMETYPE_VIDEO_H263,
     32         MEDIA_MIMETYPE_VIDEO_MPEG4,
     33         MEDIA_MIMETYPE_VIDEO_AVC,
     34         MEDIA_MIMETYPE_VIDEO_VP8,
     35         MEDIA_MIMETYPE_VIDEO_VP9
     36 };
     37 // must == kMaxVideoDecoders
     38 static const size_t kNbVideoMimeTypes = sizeof(kVideoMimeTypes) / sizeof(kVideoMimeTypes[0]);
     39 
     40 // codec capabilities in the following arrays maps to the mime types defined in kVideoMimeTypes
     41 // CodecCapabilities is from OMXCodec.h
     42 static Vector<CodecCapabilities> VideoDecoderCapabilities[kNbVideoMimeTypes];
     43 static XAuint32 VideoDecoderNbProfLevel[kNbVideoMimeTypes];
     44 
     45 static XAuint32 NbSupportedDecoderTypes = 0;
     46 
     47 
     48 XAuint32 convertOpenMaxIlToAl(OMX_U32 ilVideoProfileOrLevel) {
     49     // For video codec profiles and levels, the number of trailing zeroes in OpenMAX IL
     50     // are equal to the matching OpenMAX AL constant value plus 1, for example:
     51     //    XA_VIDEOPROFILE_H263_BACKWARDCOMPATIBLE ((XAuint32) 0x00000003)
     52     //        matches
     53     //    OMX_VIDEO_H263ProfileBackwardCompatible  = 0x04
     54     return (XAuint32) (__builtin_ctz(ilVideoProfileOrLevel) + 1);
     55 }
     56 
     57 
     58 bool android_videoCodec_expose() {
     59     SL_LOGV("android_videoCodec_expose()");
     60 
     61     sp<IMediaPlayerService> service(IMediaDeathNotifier::getMediaPlayerService());
     62     if (service == NULL) {
     63         // no need to SL_LOGE; getMediaPlayerService already will have done so
     64         return false;
     65     }
     66 
     67     sp<IOMX> omx(service->getOMX());
     68     if (omx.get() == NULL) {
     69         ALOGE("android_videoCodec_expose() couldn't access OMX interface");
     70         return false;
     71     }
     72 
     73     // used to check whether no codecs were found, which is a sign of failure
     74     NbSupportedDecoderTypes = 0;
     75     for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
     76         // QueryCodecs is from OMXCodec.h
     77         if (OK == QueryCodecs(omx, kVideoMimeTypes[m], true /* queryDecoders */,
     78                 true /* hwCodecOnly */, &VideoDecoderCapabilities[m])) {
     79             if (VideoDecoderCapabilities[m].empty()) {
     80                 VideoDecoderNbProfLevel[m] = 0;
     81             } else {
     82                 // get the number of profiles and levels for the first codec implementation
     83                 // for a given decoder ID / MIME type
     84                 Vector<CodecProfileLevel> &profileLevels =
     85                         VideoDecoderCapabilities[m].editItemAt(0).mProfileLevels;
     86 #if 0   // Intentionally disabled example of making modifications to profile / level combinations
     87                 if (VideoDecoderIds[m] == XA_VIDEOCODEC_AVC) {
     88                     // remove non-core profile / level combinations
     89                     for (size_t i = 0, size = profileLevels.size(); i < size; ) {
     90                         CodecProfileLevel profileLevel = profileLevels.itemAt(i);
     91                         if (profileLevel.mProfile == XA_VIDEOPROFILE_AVC_BASELINE) {
     92                             // either skip past this item and don't change vector size
     93                             ++i;
     94                         } else {
     95                             // or remove this item, decrement the vector size,
     96                             // and next time through the loop check a different item at same index
     97                             profileLevels.removeAt(i);
     98                             --size;
     99                         }
    100                     }
    101                 }
    102 #endif
    103                 if ((VideoDecoderNbProfLevel[m] = profileLevels.size()) > 0) {
    104                     NbSupportedDecoderTypes++;
    105                 } else {
    106                     VideoDecoderCapabilities[m].clear();
    107                 }
    108             }
    109         }
    110     }
    111 
    112     return (NbSupportedDecoderTypes > 0);
    113 }
    114 
    115 
    116 void android_videoCodec_deinit() {
    117     SL_LOGV("android_videoCodec_deinit()");
    118     for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
    119         VideoDecoderCapabilities[m].clear();
    120     }
    121     // not needed
    122     // memset(VideoDecoderNbProfLevel, 0, sizeof(VideoDecoderNbProfLevel));
    123     // NbSupportedDecoderTypes = 0;
    124 }
    125 
    126 
    127 XAuint32 android_videoCodec_getNbDecoders() {
    128     return NbSupportedDecoderTypes;
    129 }
    130 
    131 
    132 void android_videoCodec_getDecoderIds(XAuint32 nbDecoders, XAuint32 *pDecoderIds) {
    133     XAuint32 *pIds = pDecoderIds;
    134     XAuint32 nbFound = 0;
    135     for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
    136         if (!VideoDecoderCapabilities[m].empty()) {
    137             *pIds = VideoDecoderIds[m];
    138             pIds++;
    139             nbFound++;
    140         }
    141         // range check: function can be called for fewer codecs than there are
    142         if (nbFound == nbDecoders) {
    143             break;
    144         }
    145     }
    146 }
    147 
    148 
    149 SLresult android_videoCodec_getProfileLevelCombinationNb(XAuint32 decoderId, XAuint32 *pNb)
    150 {
    151     // translate a decoder ID to an index in the codec table
    152     size_t decoderIndex = 0;
    153     while (decoderIndex < kNbVideoMimeTypes) {
    154         if (decoderId == VideoDecoderIds[decoderIndex]) {
    155             *pNb = VideoDecoderNbProfLevel[decoderIndex];
    156             return XA_RESULT_SUCCESS;
    157         }
    158         decoderIndex++;
    159     }
    160 
    161     // spec doesn't allow a decoder to report zero profile/level combinations
    162     *pNb = 0;
    163     return XA_RESULT_PARAMETER_INVALID;
    164 }
    165 
    166 
    167 SLresult android_videoCodec_getProfileLevelCombination(XAuint32 decoderId, XAuint32 plIndex,
    168         XAVideoCodecDescriptor *pDescr)
    169 {
    170     // translate a decoder ID to an index in the codec table
    171     size_t decoderIndex = 0;
    172     while (decoderIndex < kNbVideoMimeTypes) {
    173         if (decoderId == VideoDecoderIds[decoderIndex]) {
    174             // We only look at the first codec implementation for a given decoder ID / MIME type.
    175             // OpenMAX AL doesn't let you expose the capabilities of multiple codec implementations.
    176             if (!(plIndex < VideoDecoderCapabilities[decoderIndex].itemAt(0).mProfileLevels.size()))
    177             {
    178                 // asking for invalid profile/level
    179                 return XA_RESULT_PARAMETER_INVALID;
    180             }
    181             //     set the fields we know about
    182             pDescr->codecId = decoderId;
    183             pDescr->profileSetting = convertOpenMaxIlToAl(VideoDecoderCapabilities[decoderIndex].
    184                     itemAt(0).mProfileLevels.itemAt(plIndex).mProfile);
    185             pDescr->levelSetting = convertOpenMaxIlToAl(VideoDecoderCapabilities[decoderIndex].
    186                     itemAt(0).mProfileLevels.itemAt(plIndex).mLevel);
    187             //     initialize the fields we don't know about
    188             pDescr->maxWidth = 0;
    189             pDescr->maxHeight = 0;
    190             pDescr->maxFrameRate = 0;
    191             pDescr->maxBitRate = 0;
    192             pDescr->rateControlSupported = 0;
    193             break;
    194         }
    195         decoderIndex++;
    196     }
    197     return (decoderIndex < kNbVideoMimeTypes) ? XA_RESULT_SUCCESS : XA_RESULT_PARAMETER_INVALID;
    198 }
    199 
    200 } // namespace android
    201