MediaCodecInfo.cpp revision b8c35f94470d1518e2def0582aaec4e038c92af0
1/*
2 * Copyright 2014, 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//#define LOG_NDEBUG 0
18#define LOG_TAG "MediaCodecInfo"
19#include <utils/Log.h>
20
21#include <media/IOMX.h>
22
23#include <media/MediaCodecInfo.h>
24
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <binder/Parcel.h>
28
29namespace android {
30
31void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
32        Vector<ProfileLevel> *profileLevels) const {
33    profileLevels->clear();
34    profileLevels->appendVector(mProfileLevels);
35}
36
37void MediaCodecInfo::Capabilities::getSupportedColorFormats(
38        Vector<uint32_t> *colorFormats) const {
39    colorFormats->clear();
40    colorFormats->appendVector(mColorFormats);
41}
42
43uint32_t MediaCodecInfo::Capabilities::getFlags() const {
44    return mFlags;
45}
46
47const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
48    return mDetails;
49}
50
51MediaCodecInfo::Capabilities::Capabilities()
52  : mFlags(0) {
53    mDetails = new AMessage;
54}
55
56// static
57sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
58        const Parcel &parcel) {
59    sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
60    size_t size = static_cast<size_t>(parcel.readInt32());
61    for (size_t i = 0; i < size; i++) {
62        ProfileLevel profileLevel;
63        profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
64        profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
65        if (caps != NULL) {
66            caps->mProfileLevels.push_back(profileLevel);
67        }
68    }
69    size = static_cast<size_t>(parcel.readInt32());
70    for (size_t i = 0; i < size; i++) {
71        uint32_t color = static_cast<uint32_t>(parcel.readInt32());
72        if (caps != NULL) {
73            caps->mColorFormats.push_back(color);
74        }
75    }
76    uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
77    sp<AMessage> details = AMessage::FromParcel(parcel);
78    if (details == NULL)
79        return NULL;
80    if (caps != NULL) {
81        caps->mFlags = flags;
82        caps->mDetails = details;
83    }
84    return caps;
85}
86
87status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
88    CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX));
89    parcel->writeInt32(mProfileLevels.size());
90    for (size_t i = 0; i < mProfileLevels.size(); i++) {
91        parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
92        parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
93    }
94    CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX));
95    parcel->writeInt32(mColorFormats.size());
96    for (size_t i = 0; i < mColorFormats.size(); i++) {
97        parcel->writeInt32(mColorFormats.itemAt(i));
98    }
99    parcel->writeInt32(mFlags);
100    mDetails->writeToParcel(parcel);
101    return OK;
102}
103
104void MediaCodecInfo::CapabilitiesBuilder::addProfileLevel(uint32_t profile, uint32_t level) {
105    ProfileLevel profileLevel;
106    profileLevel.mProfile = profile;
107    profileLevel.mLevel = level;
108    mProfileLevels.push_back(profileLevel);
109}
110
111void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) {
112    mColorFormats.push(format);
113}
114
115void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) {
116    mFlags |= flags;
117}
118
119bool MediaCodecInfo::isEncoder() const {
120    return mIsEncoder;
121}
122
123bool MediaCodecInfo::hasQuirk(const char *name) const {
124    if (name) {
125        for (size_t ix = 0; ix < mQuirks.size(); ix++) {
126            if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
127                return true;
128            }
129        }
130    }
131    return false;
132}
133
134void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
135    mimes->clear();
136    for (size_t ix = 0; ix < mCaps.size(); ix++) {
137        mimes->push_back(mCaps.keyAt(ix));
138    }
139}
140
141const sp<MediaCodecInfo::Capabilities>
142MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
143    ssize_t ix = getCapabilityIndex(mime);
144    if (ix >= 0) {
145        return mCaps.valueAt(ix);
146    }
147    return NULL;
148}
149
150const char *MediaCodecInfo::getCodecName() const {
151    return mName.c_str();
152}
153
154// static
155sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
156    AString name = AString::FromParcel(parcel);
157    bool isEncoder = static_cast<bool>(parcel.readInt32());
158    sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
159    size_t size = static_cast<size_t>(parcel.readInt32());
160    for (size_t i = 0; i < size; i++) {
161        AString quirk = AString::FromParcel(parcel);
162        if (info != NULL) {
163            info->mQuirks.push_back(quirk);
164        }
165    }
166    size = static_cast<size_t>(parcel.readInt32());
167    for (size_t i = 0; i < size; i++) {
168        AString mime = AString::FromParcel(parcel);
169        sp<Capabilities> caps = Capabilities::FromParcel(parcel);
170        if (caps == NULL)
171            return NULL;
172        if (info != NULL) {
173            info->mCaps.add(mime, caps);
174        }
175    }
176    return info;
177}
178
179status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
180    mName.writeToParcel(parcel);
181    parcel->writeInt32(mIsEncoder);
182    parcel->writeInt32(mQuirks.size());
183    for (size_t i = 0; i < mQuirks.size(); i++) {
184        mQuirks.itemAt(i).writeToParcel(parcel);
185    }
186    parcel->writeInt32(mCaps.size());
187    for (size_t i = 0; i < mCaps.size(); i++) {
188        mCaps.keyAt(i).writeToParcel(parcel);
189        mCaps.valueAt(i)->writeToParcel(parcel);
190    }
191    return OK;
192}
193
194ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
195    if (mime) {
196        for (size_t ix = 0; ix < mCaps.size(); ix++) {
197            if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
198                return ix;
199            }
200        }
201    }
202    return -1;
203}
204
205MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
206    : mName(name),
207      mIsEncoder(encoder),
208      mHasSoleMime(false) {
209    if (mime != NULL) {
210        addMime(mime);
211        mHasSoleMime = true;
212    }
213}
214
215status_t MediaCodecInfo::addMime(const char *mime) {
216    if (mHasSoleMime) {
217        ALOGE("Codec '%s' already had its type specified", mName.c_str());
218        return -EINVAL;
219    }
220    ssize_t ix = getCapabilityIndex(mime);
221    if (ix >= 0) {
222        mCurrentCaps = mCaps.valueAt(ix);
223    } else {
224        mCurrentCaps = new Capabilities();
225        mCaps.add(AString(mime), mCurrentCaps);
226    }
227    return OK;
228}
229
230status_t MediaCodecInfo::updateMime(const char *mime) {
231    ssize_t ix = getCapabilityIndex(mime);
232    if (ix < 0) {
233        ALOGE("updateMime mime not found %s", mime);
234        return -EINVAL;
235    }
236
237    mCurrentCaps = mCaps.valueAt(ix);
238    return OK;
239}
240
241void MediaCodecInfo::removeMime(const char *mime) {
242    ssize_t ix = getCapabilityIndex(mime);
243    if (ix >= 0) {
244        mCaps.removeItemsAt(ix);
245        // mCurrentCaps will be removed when completed
246    }
247}
248
249status_t MediaCodecInfo::initializeCapabilities(const sp<Capabilities> &caps) {
250    // TRICKY: copy data to mCurrentCaps as it is a reference to
251    // an element of the capabilites map.
252    mCurrentCaps->mColorFormats.clear();
253    mCurrentCaps->mColorFormats.appendVector(caps->mColorFormats);
254    mCurrentCaps->mProfileLevels.clear();
255    mCurrentCaps->mProfileLevels.appendVector(caps->mProfileLevels);
256    mCurrentCaps->mFlags = caps->mFlags;
257    mCurrentCaps->mDetails = caps->mDetails;
258    return OK;
259}
260
261void MediaCodecInfo::addQuirk(const char *name) {
262    if (!hasQuirk(name)) {
263        mQuirks.push(name);
264    }
265}
266
267void MediaCodecInfo::complete() {
268    mCurrentCaps = NULL;
269}
270
271void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
272    mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
273}
274
275void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
276    AString tag = "feature-";
277    tag.append(key);
278    mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
279}
280
281void MediaCodecInfo::addFeature(const AString &key, const char *value) {
282    AString tag = "feature-";
283    tag.append(key);
284    mCurrentCaps->mDetails->setString(tag.c_str(), value);
285}
286
287}  // namespace android
288