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