VideoCodec_to_android.cpp revision b47c7beddecd38ae565d84b72da526843bfdd43e
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_VPX
35};
36// must == kMaxVideoDecoders
37static 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
41static Vector<CodecCapabilities> VideoDecoderCapabilities[kNbVideoMimeTypes];
42static XAuint32 VideoDecoderNbProfLevel[kNbVideoMimeTypes];
43
44static XAuint32 NbSupportedDecoderTypes = 0;
45
46
47XAuint32 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
57bool 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
115void 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
126XAuint32 android_videoCodec_getNbDecoders() {
127    return NbSupportedDecoderTypes;
128}
129
130
131void 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
148SLresult 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
166SLresult 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