MediaCodecInfo.cpp revision 5b05e49e6550cb2abf1a88272d6cd460b8957176
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 (caps != NULL) {
79        caps->mFlags = flags;
80        caps->mDetails = details;
81    }
82    return caps;
83}
84
85status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
86    CHECK_LE(mProfileLevels.size(), INT32_MAX);
87    parcel->writeInt32(mProfileLevels.size());
88    for (size_t i = 0; i < mProfileLevels.size(); i++) {
89        parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
90        parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
91    }
92    CHECK_LE(mColorFormats.size(), INT32_MAX);
93    parcel->writeInt32(mColorFormats.size());
94    for (size_t i = 0; i < mColorFormats.size(); i++) {
95        parcel->writeInt32(mColorFormats.itemAt(i));
96    }
97    parcel->writeInt32(mFlags);
98    mDetails->writeToParcel(parcel);
99    return OK;
100}
101
102void MediaCodecInfo::CapabilitiesBuilder::addProfileLevel(uint32_t profile, uint32_t level) {
103    ProfileLevel profileLevel;
104    profileLevel.mProfile = profile;
105    profileLevel.mLevel = level;
106    mProfileLevels.push_back(profileLevel);
107}
108
109void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) {
110    mColorFormats.push(format);
111}
112
113void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) {
114    mFlags |= flags;
115}
116
117bool MediaCodecInfo::isEncoder() const {
118    return mIsEncoder;
119}
120
121bool MediaCodecInfo::hasQuirk(const char *name) const {
122    for (size_t ix = 0; ix < mQuirks.size(); ix++) {
123        if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
124            return true;
125        }
126    }
127    return false;
128}
129
130void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
131    mimes->clear();
132    for (size_t ix = 0; ix < mCaps.size(); ix++) {
133        mimes->push_back(mCaps.keyAt(ix));
134    }
135}
136
137const sp<MediaCodecInfo::Capabilities>
138MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
139    ssize_t ix = getCapabilityIndex(mime);
140    if (ix >= 0) {
141        return mCaps.valueAt(ix);
142    }
143    return NULL;
144}
145
146const char *MediaCodecInfo::getCodecName() const {
147    return mName.c_str();
148}
149
150// static
151sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
152    AString name = AString::FromParcel(parcel);
153    bool isEncoder = static_cast<bool>(parcel.readInt32());
154    sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
155    size_t size = static_cast<size_t>(parcel.readInt32());
156    for (size_t i = 0; i < size; i++) {
157        AString quirk = AString::FromParcel(parcel);
158        if (info != NULL) {
159            info->mQuirks.push_back(quirk);
160        }
161    }
162    size = static_cast<size_t>(parcel.readInt32());
163    for (size_t i = 0; i < size; i++) {
164        AString mime = AString::FromParcel(parcel);
165        sp<Capabilities> caps = Capabilities::FromParcel(parcel);
166        if (info != NULL) {
167            info->mCaps.add(mime, caps);
168        }
169    }
170    return info;
171}
172
173status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
174    mName.writeToParcel(parcel);
175    parcel->writeInt32(mIsEncoder);
176    parcel->writeInt32(mQuirks.size());
177    for (size_t i = 0; i < mQuirks.size(); i++) {
178        mQuirks.itemAt(i).writeToParcel(parcel);
179    }
180    parcel->writeInt32(mCaps.size());
181    for (size_t i = 0; i < mCaps.size(); i++) {
182        mCaps.keyAt(i).writeToParcel(parcel);
183        mCaps.valueAt(i)->writeToParcel(parcel);
184    }
185    return OK;
186}
187
188ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
189    for (size_t ix = 0; ix < mCaps.size(); ix++) {
190        if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
191            return ix;
192        }
193    }
194    return -1;
195}
196
197MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
198    : mName(name),
199      mIsEncoder(encoder),
200      mHasSoleMime(false) {
201    if (mime != NULL) {
202        addMime(mime);
203        mHasSoleMime = true;
204    }
205}
206
207status_t MediaCodecInfo::addMime(const char *mime) {
208    if (mHasSoleMime) {
209        ALOGE("Codec '%s' already had its type specified", mName.c_str());
210        return -EINVAL;
211    }
212    ssize_t ix = getCapabilityIndex(mime);
213    if (ix >= 0) {
214        mCurrentCaps = mCaps.valueAt(ix);
215    } else {
216        mCurrentCaps = new Capabilities();
217        mCaps.add(AString(mime), mCurrentCaps);
218    }
219    return OK;
220}
221
222status_t MediaCodecInfo::updateMime(const char *mime) {
223    ssize_t ix = getCapabilityIndex(mime);
224    if (ix < 0) {
225        ALOGE("updateMime mime not found %s", mime);
226        return -EINVAL;
227    }
228
229    mCurrentCaps = mCaps.valueAt(ix);
230    return OK;
231}
232
233void MediaCodecInfo::removeMime(const char *mime) {
234    ssize_t ix = getCapabilityIndex(mime);
235    if (ix >= 0) {
236        mCaps.removeItemsAt(ix);
237        // mCurrentCaps will be removed when completed
238    }
239}
240
241status_t MediaCodecInfo::setCapabilities(const sp<Capabilities> &caps) {
242    mCurrentCaps = caps;
243    return OK;
244}
245
246void MediaCodecInfo::addQuirk(const char *name) {
247    if (!hasQuirk(name)) {
248        mQuirks.push(name);
249    }
250}
251
252void MediaCodecInfo::complete() {
253    mCurrentCaps = NULL;
254}
255
256void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
257    mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
258}
259
260void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
261    AString tag = "feature-";
262    tag.append(key);
263    mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
264}
265
266void MediaCodecInfo::addFeature(const AString &key, const char *value) {
267    AString tag = "feature-";
268    tag.append(key);
269    mCurrentCaps->mDetails->setString(tag.c_str(), value);
270}
271
272}  // namespace android
273