MediaCodecInfo.cpp revision fbe70ae7f251d159ed83ab61587a88003f20d44b
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::CapabilitiesWriter::addDetail(
105        const char* key, const char* value) {
106    mCap->mDetails->setString(key, value);
107}
108
109void MediaCodecInfo::CapabilitiesWriter::addDetail(
110        const char* key, int32_t value) {
111    mCap->mDetails->setInt32(key, value);
112}
113
114void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
115        uint32_t profile, uint32_t level) {
116    ProfileLevel profileLevel;
117    profileLevel.mProfile = profile;
118    profileLevel.mLevel = level;
119    if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
120        mCap->mProfileLevels.push_back(profileLevel);
121        mCap->mProfileLevelsSorted.add(profileLevel);
122    }
123}
124
125void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
126    if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
127        mCap->mColorFormats.push(format);
128        mCap->mColorFormatsSorted.add(format);
129    }
130}
131
132void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
133    mCap->mFlags |= flags;
134}
135
136MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
137        MediaCodecInfo::Capabilities* cap) : mCap(cap) {
138}
139
140bool MediaCodecInfo::isEncoder() const {
141    return mIsEncoder;
142}
143
144void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
145    mimes->clear();
146    for (size_t ix = 0; ix < mCaps.size(); ix++) {
147        mimes->push_back(mCaps.keyAt(ix));
148    }
149}
150
151const sp<MediaCodecInfo::Capabilities>
152MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
153    ssize_t ix = getCapabilityIndex(mime);
154    if (ix >= 0) {
155        return mCaps.valueAt(ix);
156    }
157    return NULL;
158}
159
160const char *MediaCodecInfo::getCodecName() const {
161    return mName.c_str();
162}
163
164const char *MediaCodecInfo::getOwnerName() const {
165    return mOwner.c_str();
166}
167
168// static
169sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
170    AString name = AString::FromParcel(parcel);
171    AString owner = AString::FromParcel(parcel);
172    bool isEncoder = static_cast<bool>(parcel.readInt32());
173    sp<MediaCodecInfo> info = new MediaCodecInfo;
174    info->mName = name;
175    info->mOwner = owner;
176    info->mIsEncoder = isEncoder;
177    size_t size = static_cast<size_t>(parcel.readInt32());
178    for (size_t i = 0; i < size; i++) {
179        AString mime = AString::FromParcel(parcel);
180        sp<Capabilities> caps = Capabilities::FromParcel(parcel);
181        if (caps == NULL)
182            return NULL;
183        if (info != NULL) {
184            info->mCaps.add(mime, caps);
185        }
186    }
187    return info;
188}
189
190status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
191    mName.writeToParcel(parcel);
192    mOwner.writeToParcel(parcel);
193    parcel->writeInt32(mIsEncoder);
194    parcel->writeInt32(mCaps.size());
195    for (size_t i = 0; i < mCaps.size(); i++) {
196        mCaps.keyAt(i).writeToParcel(parcel);
197        mCaps.valueAt(i)->writeToParcel(parcel);
198    }
199    return OK;
200}
201
202ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
203    if (mime) {
204        for (size_t ix = 0; ix < mCaps.size(); ix++) {
205            if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
206                return ix;
207            }
208        }
209    }
210    return -1;
211}
212
213MediaCodecInfo::MediaCodecInfo() {
214}
215
216void MediaCodecInfoWriter::setName(const char* name) {
217    mInfo->mName = name;
218}
219
220void MediaCodecInfoWriter::setOwner(const char* owner) {
221    mInfo->mOwner = owner;
222}
223
224void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
225    mInfo->mIsEncoder = isEncoder;
226}
227
228std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
229        MediaCodecInfoWriter::addMime(const char *mime) {
230    ssize_t ix = mInfo->getCapabilityIndex(mime);
231    if (ix >= 0) {
232        return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
233                new MediaCodecInfo::CapabilitiesWriter(
234                mInfo->mCaps.valueAt(ix).get()));
235    }
236    sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
237    mInfo->mCaps.add(AString(mime), caps);
238    return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
239            new MediaCodecInfo::CapabilitiesWriter(caps.get()));
240}
241
242bool MediaCodecInfoWriter::removeMime(const char *mime) {
243    ssize_t ix = mInfo->getCapabilityIndex(mime);
244    if (ix >= 0) {
245        mInfo->mCaps.removeItemsAt(ix);
246        return true;
247    }
248    return false;
249}
250
251MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
252    mInfo(info) {
253}
254
255}  // namespace android
256