MediaCodecInfo.cpp revision 2461e0cf6ae3fe5c9b52ce9e3ac764f4aff5e5eb
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
29#include <media/stagefright/OMXCodec.h>
30
31namespace android {
32
33void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
34        Vector<ProfileLevel> *profileLevels) const {
35    profileLevels->clear();
36    profileLevels->appendVector(mProfileLevels);
37}
38
39void MediaCodecInfo::Capabilities::getSupportedColorFormats(
40        Vector<uint32_t> *colorFormats) const {
41    colorFormats->clear();
42    colorFormats->appendVector(mColorFormats);
43}
44
45uint32_t MediaCodecInfo::Capabilities::getFlags() const {
46    return mFlags;
47}
48
49const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
50    return mDetails;
51}
52
53MediaCodecInfo::Capabilities::Capabilities()
54  : mFlags(0) {
55    mDetails = new AMessage;
56}
57
58// static
59sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
60        const Parcel &parcel) {
61    sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
62    size_t size = static_cast<size_t>(parcel.readInt32());
63    for (size_t i = 0; i < size; i++) {
64        ProfileLevel profileLevel;
65        profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
66        profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
67        if (caps != NULL) {
68            caps->mProfileLevels.push_back(profileLevel);
69        }
70    }
71    size = static_cast<size_t>(parcel.readInt32());
72    for (size_t i = 0; i < size; i++) {
73        uint32_t color = static_cast<uint32_t>(parcel.readInt32());
74        if (caps != NULL) {
75            caps->mColorFormats.push_back(color);
76        }
77    }
78    uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
79    sp<AMessage> details = AMessage::FromParcel(parcel);
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(), 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(), 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
104bool MediaCodecInfo::isEncoder() const {
105    return mIsEncoder;
106}
107
108bool MediaCodecInfo::hasQuirk(const char *name) const {
109    for (size_t ix = 0; ix < mQuirks.size(); ix++) {
110        if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
111            return true;
112        }
113    }
114    return false;
115}
116
117void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
118    mimes->clear();
119    for (size_t ix = 0; ix < mCaps.size(); ix++) {
120        mimes->push_back(mCaps.keyAt(ix));
121    }
122}
123
124const sp<MediaCodecInfo::Capabilities>
125MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
126    ssize_t ix = getCapabilityIndex(mime);
127    if (ix >= 0) {
128        return mCaps.valueAt(ix);
129    }
130    return NULL;
131}
132
133const char *MediaCodecInfo::getCodecName() const {
134    return mName.c_str();
135}
136
137// static
138sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
139    AString name = AString::FromParcel(parcel);
140    bool isEncoder = static_cast<bool>(parcel.readInt32());
141    sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
142    size_t size = static_cast<size_t>(parcel.readInt32());
143    for (size_t i = 0; i < size; i++) {
144        AString quirk = AString::FromParcel(parcel);
145        if (info != NULL) {
146            info->mQuirks.push_back(quirk);
147        }
148    }
149    size = static_cast<size_t>(parcel.readInt32());
150    for (size_t i = 0; i < size; i++) {
151        AString mime = AString::FromParcel(parcel);
152        sp<Capabilities> caps = Capabilities::FromParcel(parcel);
153        if (info != NULL) {
154            info->mCaps.add(mime, caps);
155        }
156    }
157    return info;
158}
159
160status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
161    mName.writeToParcel(parcel);
162    parcel->writeInt32(mIsEncoder);
163    parcel->writeInt32(mQuirks.size());
164    for (size_t i = 0; i < mQuirks.size(); i++) {
165        mQuirks.itemAt(i).writeToParcel(parcel);
166    }
167    parcel->writeInt32(mCaps.size());
168    for (size_t i = 0; i < mCaps.size(); i++) {
169        mCaps.keyAt(i).writeToParcel(parcel);
170        mCaps.valueAt(i)->writeToParcel(parcel);
171    }
172    return OK;
173}
174
175ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
176    for (size_t ix = 0; ix < mCaps.size(); ix++) {
177        if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
178            return ix;
179        }
180    }
181    return -1;
182}
183
184MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
185    : mName(name),
186      mIsEncoder(encoder),
187      mHasSoleMime(false) {
188    if (mime != NULL) {
189        addMime(mime);
190        mHasSoleMime = true;
191    }
192}
193
194status_t MediaCodecInfo::addMime(const char *mime) {
195    if (mHasSoleMime) {
196        ALOGE("Codec '%s' already had its type specified", mName.c_str());
197        return -EINVAL;
198    }
199    ssize_t ix = getCapabilityIndex(mime);
200    if (ix >= 0) {
201        mCurrentCaps = mCaps.valueAt(ix);
202    } else {
203        mCurrentCaps = new Capabilities();
204        mCaps.add(AString(mime), mCurrentCaps);
205    }
206    return OK;
207}
208
209status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) {
210    mCurrentCaps->mProfileLevels.clear();
211    mCurrentCaps->mColorFormats.clear();
212
213    for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
214        const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
215
216        ProfileLevel profileLevel;
217        profileLevel.mProfile = src.mProfile;
218        profileLevel.mLevel = src.mLevel;
219        mCurrentCaps->mProfileLevels.push_back(profileLevel);
220    }
221
222    for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
223        mCurrentCaps->mColorFormats.push_back(caps.mColorFormats.itemAt(i));
224    }
225
226    mCurrentCaps->mFlags = caps.mFlags;
227    mCurrentCaps->mDetails = new AMessage;
228
229    return OK;
230}
231
232void MediaCodecInfo::addQuirk(const char *name) {
233    if (!hasQuirk(name)) {
234        mQuirks.push(name);
235    }
236}
237
238void MediaCodecInfo::complete() {
239    mCurrentCaps = NULL;
240}
241
242void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
243    mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
244}
245
246void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
247    AString tag = "feature-";
248    tag.append(key);
249    mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
250}
251
252}  // namespace android
253