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
convertOpenMaxIlToAl(OMX_U32 ilVideoProfileOrLevel)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
android_videoCodec_expose()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
android_videoCodec_deinit()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
android_videoCodec_getNbDecoders()126 XAuint32 android_videoCodec_getNbDecoders() {
127 return NbSupportedDecoderTypes;
128 }
129
130
android_videoCodec_getDecoderIds(XAuint32 nbDecoders,XAuint32 * pDecoderIds)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
android_videoCodec_getProfileLevelCombinationNb(XAuint32 decoderId,XAuint32 * pNb)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
android_videoCodec_getProfileLevelCombination(XAuint32 decoderId,XAuint32 plIndex,XAVideoCodecDescriptor * pDescr)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