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