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
26namespace android {
27
28// listed in same order as VideoCodecIds[] in file "../devices.c" with ANDROID defined
29static 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
38static 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
42static Vector<CodecCapabilities> VideoDecoderCapabilities[kNbVideoMimeTypes];
43static XAuint32 VideoDecoderNbProfLevel[kNbVideoMimeTypes];
44
45static XAuint32 NbSupportedDecoderTypes = 0;
46
47
48XAuint32 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
58bool 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
116void 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
127XAuint32 android_videoCodec_getNbDecoders() {
128    return NbSupportedDecoderTypes;
129}
130
131
132void 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
149SLresult 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
167SLresult 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