blob: 2a7451280e887326de48f4b99d4edbed6536da07 [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 Molnar60b1c0e2014-08-06 16:55:46 -070029namespace 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
Lajos Molnar2461e0c2014-08-12 08:55:25 -070047const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070048 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);
Pawin Vongmasa8dab17302016-05-02 16:08:39 -070078 if (details == NULL)
79 return NULL;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070080 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 {
Colin Crossb8c35f92017-04-27 16:15:51 -070088 CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070089 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 }
Colin Crossb8c35f92017-04-27 16:15:51 -070094 CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070095 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;
Lajos Molnar06e98362017-08-14 15:57:57 -0700108 if (mProfileLevelsSorted.indexOf(profileLevel) < 0) {
109 mProfileLevels.push_back(profileLevel);
110 mProfileLevelsSorted.add(profileLevel);
111 }
Lajos Molnar5b05e492016-02-04 18:57:45 -0800112}
113
114void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) {
Lajos Molnar06e98362017-08-14 15:57:57 -0700115 if (mColorFormatsSorted.indexOf(format) < 0) {
116 mColorFormats.push(format);
117 mColorFormatsSorted.add(format);
118 }
Lajos Molnar5b05e492016-02-04 18:57:45 -0800119}
120
121void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) {
122 mFlags |= flags;
123}
124
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700125bool MediaCodecInfo::isEncoder() const {
126 return mIsEncoder;
127}
128
129bool MediaCodecInfo::hasQuirk(const char *name) const {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -0700130 if (name) {
131 for (size_t ix = 0; ix < mQuirks.size(); ix++) {
132 if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
133 return true;
134 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700135 }
136 }
137 return false;
138}
139
140void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
141 mimes->clear();
142 for (size_t ix = 0; ix < mCaps.size(); ix++) {
143 mimes->push_back(mCaps.keyAt(ix));
144 }
145}
146
Lajos Molnar2461e0c2014-08-12 08:55:25 -0700147const sp<MediaCodecInfo::Capabilities>
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700148MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
149 ssize_t ix = getCapabilityIndex(mime);
150 if (ix >= 0) {
151 return mCaps.valueAt(ix);
152 }
153 return NULL;
154}
155
156const char *MediaCodecInfo::getCodecName() const {
157 return mName.c_str();
158}
159
160// static
161sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
162 AString name = AString::FromParcel(parcel);
163 bool isEncoder = static_cast<bool>(parcel.readInt32());
164 sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
165 size_t size = static_cast<size_t>(parcel.readInt32());
166 for (size_t i = 0; i < size; i++) {
167 AString quirk = AString::FromParcel(parcel);
168 if (info != NULL) {
169 info->mQuirks.push_back(quirk);
170 }
171 }
172 size = static_cast<size_t>(parcel.readInt32());
173 for (size_t i = 0; i < size; i++) {
174 AString mime = AString::FromParcel(parcel);
175 sp<Capabilities> caps = Capabilities::FromParcel(parcel);
Pawin Vongmasa8dab17302016-05-02 16:08:39 -0700176 if (caps == NULL)
177 return NULL;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700178 if (info != NULL) {
179 info->mCaps.add(mime, caps);
180 }
181 }
182 return info;
183}
184
185status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
186 mName.writeToParcel(parcel);
187 parcel->writeInt32(mIsEncoder);
188 parcel->writeInt32(mQuirks.size());
189 for (size_t i = 0; i < mQuirks.size(); i++) {
190 mQuirks.itemAt(i).writeToParcel(parcel);
191 }
192 parcel->writeInt32(mCaps.size());
193 for (size_t i = 0; i < mCaps.size(); i++) {
194 mCaps.keyAt(i).writeToParcel(parcel);
195 mCaps.valueAt(i)->writeToParcel(parcel);
196 }
197 return OK;
198}
199
200ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -0700201 if (mime) {
202 for (size_t ix = 0; ix < mCaps.size(); ix++) {
203 if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
204 return ix;
205 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700206 }
207 }
208 return -1;
209}
210
211MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
212 : mName(name),
213 mIsEncoder(encoder),
214 mHasSoleMime(false) {
215 if (mime != NULL) {
216 addMime(mime);
217 mHasSoleMime = true;
218 }
219}
220
221status_t MediaCodecInfo::addMime(const char *mime) {
222 if (mHasSoleMime) {
223 ALOGE("Codec '%s' already had its type specified", mName.c_str());
224 return -EINVAL;
225 }
226 ssize_t ix = getCapabilityIndex(mime);
227 if (ix >= 0) {
228 mCurrentCaps = mCaps.valueAt(ix);
229 } else {
230 mCurrentCaps = new Capabilities();
231 mCaps.add(AString(mime), mCurrentCaps);
232 }
233 return OK;
234}
235
Ronghua Wu9e6955a2015-03-26 13:52:57 -0700236status_t MediaCodecInfo::updateMime(const char *mime) {
237 ssize_t ix = getCapabilityIndex(mime);
238 if (ix < 0) {
239 ALOGE("updateMime mime not found %s", mime);
240 return -EINVAL;
241 }
242
243 mCurrentCaps = mCaps.valueAt(ix);
244 return OK;
245}
246
Lajos Molnar6ff58f02014-08-11 16:46:15 -0700247void MediaCodecInfo::removeMime(const char *mime) {
248 ssize_t ix = getCapabilityIndex(mime);
249 if (ix >= 0) {
250 mCaps.removeItemsAt(ix);
251 // mCurrentCaps will be removed when completed
252 }
253}
254
Lajos Molnar0a4427b2016-02-11 19:42:52 -0800255status_t MediaCodecInfo::initializeCapabilities(const sp<Capabilities> &caps) {
256 // TRICKY: copy data to mCurrentCaps as it is a reference to
257 // an element of the capabilites map.
Lajos Molnar7f2262f2016-02-11 10:35:37 -0800258 mCurrentCaps->mColorFormats.clear();
Lajos Molnar0a4427b2016-02-11 19:42:52 -0800259 mCurrentCaps->mColorFormats.appendVector(caps->mColorFormats);
260 mCurrentCaps->mProfileLevels.clear();
261 mCurrentCaps->mProfileLevels.appendVector(caps->mProfileLevels);
262 mCurrentCaps->mFlags = caps->mFlags;
263 mCurrentCaps->mDetails = caps->mDetails;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700264 return OK;
265}
266
267void MediaCodecInfo::addQuirk(const char *name) {
268 if (!hasQuirk(name)) {
269 mQuirks.push(name);
270 }
271}
272
273void MediaCodecInfo::complete() {
274 mCurrentCaps = NULL;
275}
276
277void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
278 mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
279}
280
281void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
282 AString tag = "feature-";
283 tag.append(key);
284 mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
285}
286
Lajos Molnar732c6d92014-08-14 19:54:08 -0700287void MediaCodecInfo::addFeature(const AString &key, const char *value) {
288 AString tag = "feature-";
289 tag.append(key);
290 mCurrentCaps->mDetails->setString(tag.c_str(), value);
291}
292
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700293} // namespace android