blob: 7a16c4e1f50efde99db65f2f27c8aa3f121fefe5 [file] [log] [blame]
Lajos Molnar60b1c0e2014-08-06 16:55:46 -07001/*
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
Lajos Molnar7f2262f2016-02-11 10:35:37 -080029#include <media/stagefright/OMXCodec.h>
30
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070031namespace 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
Lajos Molnar2461e0c2014-08-12 08:55:25 -070049const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070050 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
Lajos Molnar5b05e492016-02-04 18:57:45 -0800104void 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
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700119bool MediaCodecInfo::isEncoder() const {
120 return mIsEncoder;
121}
122
123bool MediaCodecInfo::hasQuirk(const char *name) const {
124 for (size_t ix = 0; ix < mQuirks.size(); ix++) {
125 if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
126 return true;
127 }
128 }
129 return false;
130}
131
132void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
133 mimes->clear();
134 for (size_t ix = 0; ix < mCaps.size(); ix++) {
135 mimes->push_back(mCaps.keyAt(ix));
136 }
137}
138
Lajos Molnar2461e0c2014-08-12 08:55:25 -0700139const sp<MediaCodecInfo::Capabilities>
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700140MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
141 ssize_t ix = getCapabilityIndex(mime);
142 if (ix >= 0) {
143 return mCaps.valueAt(ix);
144 }
145 return NULL;
146}
147
148const char *MediaCodecInfo::getCodecName() const {
149 return mName.c_str();
150}
151
152// static
153sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
154 AString name = AString::FromParcel(parcel);
155 bool isEncoder = static_cast<bool>(parcel.readInt32());
156 sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
157 size_t size = static_cast<size_t>(parcel.readInt32());
158 for (size_t i = 0; i < size; i++) {
159 AString quirk = AString::FromParcel(parcel);
160 if (info != NULL) {
161 info->mQuirks.push_back(quirk);
162 }
163 }
164 size = static_cast<size_t>(parcel.readInt32());
165 for (size_t i = 0; i < size; i++) {
166 AString mime = AString::FromParcel(parcel);
167 sp<Capabilities> caps = Capabilities::FromParcel(parcel);
168 if (info != NULL) {
169 info->mCaps.add(mime, caps);
170 }
171 }
172 return info;
173}
174
175status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
176 mName.writeToParcel(parcel);
177 parcel->writeInt32(mIsEncoder);
178 parcel->writeInt32(mQuirks.size());
179 for (size_t i = 0; i < mQuirks.size(); i++) {
180 mQuirks.itemAt(i).writeToParcel(parcel);
181 }
182 parcel->writeInt32(mCaps.size());
183 for (size_t i = 0; i < mCaps.size(); i++) {
184 mCaps.keyAt(i).writeToParcel(parcel);
185 mCaps.valueAt(i)->writeToParcel(parcel);
186 }
187 return OK;
188}
189
190ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
191 for (size_t ix = 0; ix < mCaps.size(); ix++) {
192 if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
193 return ix;
194 }
195 }
196 return -1;
197}
198
199MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
200 : mName(name),
201 mIsEncoder(encoder),
202 mHasSoleMime(false) {
203 if (mime != NULL) {
204 addMime(mime);
205 mHasSoleMime = true;
206 }
207}
208
209status_t MediaCodecInfo::addMime(const char *mime) {
210 if (mHasSoleMime) {
211 ALOGE("Codec '%s' already had its type specified", mName.c_str());
212 return -EINVAL;
213 }
214 ssize_t ix = getCapabilityIndex(mime);
215 if (ix >= 0) {
216 mCurrentCaps = mCaps.valueAt(ix);
217 } else {
218 mCurrentCaps = new Capabilities();
219 mCaps.add(AString(mime), mCurrentCaps);
220 }
221 return OK;
222}
223
Ronghua Wu9e6955a2015-03-26 13:52:57 -0700224status_t MediaCodecInfo::updateMime(const char *mime) {
225 ssize_t ix = getCapabilityIndex(mime);
226 if (ix < 0) {
227 ALOGE("updateMime mime not found %s", mime);
228 return -EINVAL;
229 }
230
231 mCurrentCaps = mCaps.valueAt(ix);
232 return OK;
233}
234
Lajos Molnar6ff58f02014-08-11 16:46:15 -0700235void MediaCodecInfo::removeMime(const char *mime) {
236 ssize_t ix = getCapabilityIndex(mime);
237 if (ix >= 0) {
238 mCaps.removeItemsAt(ix);
239 // mCurrentCaps will be removed when completed
240 }
241}
242
Lajos Molnar7f2262f2016-02-11 10:35:37 -0800243status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) {
244 mCurrentCaps->mProfileLevels.clear();
245 mCurrentCaps->mColorFormats.clear();
246
247 for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
248 const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
249
250 ProfileLevel profileLevel;
251 profileLevel.mProfile = src.mProfile;
252 profileLevel.mLevel = src.mLevel;
253 mCurrentCaps->mProfileLevels.push_back(profileLevel);
Lajos Molnar69bebe82016-02-10 15:32:46 -0800254 }
Lajos Molnar7f2262f2016-02-11 10:35:37 -0800255
256 for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
257 mCurrentCaps->mColorFormats.push_back(caps.mColorFormats.itemAt(i));
258 }
259
260 mCurrentCaps->mFlags = caps.mFlags;
261 mCurrentCaps->mDetails = new AMessage;
262
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700263 return OK;
264}
265
266void MediaCodecInfo::addQuirk(const char *name) {
267 if (!hasQuirk(name)) {
268 mQuirks.push(name);
269 }
270}
271
272void MediaCodecInfo::complete() {
273 mCurrentCaps = NULL;
274}
275
276void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
277 mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
278}
279
280void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
281 AString tag = "feature-";
282 tag.append(key);
283 mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
284}
285
Lajos Molnar732c6d92014-08-14 19:54:08 -0700286void MediaCodecInfo::addFeature(const AString &key, const char *value) {
287 AString tag = "feature-";
288 tag.append(key);
289 mCurrentCaps->mDetails->setString(tag.c_str(), value);
290}
291
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700292} // namespace android