blob: 38342784bc0dfe1a9885db47cf49be3047996435 [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
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070021#include <media/MediaCodecInfo.h>
22
23#include <media/stagefright/foundation/ADebug.h>
24#include <media/stagefright/foundation/AMessage.h>
25#include <binder/Parcel.h>
26
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070027namespace android {
28
Songyue Han45f81942024-05-02 21:17:51 +000029// initialize max supported instances with default value.
30int32_t MediaCodecInfo::sMaxSupportedInstances = 0;
31
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -080032/** This redundant redeclaration is needed for C++ pre 14 */
33constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
34constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
35constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
36constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
37constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
38constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
39constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
Lajos Molnard55f06f2024-04-01 14:49:28 -070040constexpr char MediaCodecInfo::Capabilities::FEATURE_DETACHED_SURFACE[];
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -080041
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070042void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
43 Vector<ProfileLevel> *profileLevels) const {
44 profileLevels->clear();
45 profileLevels->appendVector(mProfileLevels);
46}
47
48void MediaCodecInfo::Capabilities::getSupportedColorFormats(
49 Vector<uint32_t> *colorFormats) const {
50 colorFormats->clear();
51 colorFormats->appendVector(mColorFormats);
52}
53
Lajos Molnar2461e0c2014-08-12 08:55:25 -070054const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070055 return mDetails;
56}
57
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -080058MediaCodecInfo::Capabilities::Capabilities() {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070059 mDetails = new AMessage;
60}
61
62// static
63sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
64 const Parcel &parcel) {
65 sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
66 size_t size = static_cast<size_t>(parcel.readInt32());
67 for (size_t i = 0; i < size; i++) {
68 ProfileLevel profileLevel;
69 profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
70 profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
71 if (caps != NULL) {
72 caps->mProfileLevels.push_back(profileLevel);
73 }
74 }
75 size = static_cast<size_t>(parcel.readInt32());
76 for (size_t i = 0; i < size; i++) {
77 uint32_t color = static_cast<uint32_t>(parcel.readInt32());
78 if (caps != NULL) {
79 caps->mColorFormats.push_back(color);
80 }
81 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070082 sp<AMessage> details = AMessage::FromParcel(parcel);
Pawin Vongmasa8dab17302016-05-02 16:08:39 -070083 if (details == NULL)
84 return NULL;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070085 if (caps != NULL) {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070086 caps->mDetails = details;
87 }
88 return caps;
89}
90
91status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
Colin Crossb8c35f92017-04-27 16:15:51 -070092 CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070093 parcel->writeInt32(mProfileLevels.size());
94 for (size_t i = 0; i < mProfileLevels.size(); i++) {
95 parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
96 parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
97 }
Colin Crossb8c35f92017-04-27 16:15:51 -070098 CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -070099 parcel->writeInt32(mColorFormats.size());
100 for (size_t i = 0; i < mColorFormats.size(); i++) {
101 parcel->writeInt32(mColorFormats.itemAt(i));
102 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700103 mDetails->writeToParcel(parcel);
104 return OK;
105}
106
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700107void MediaCodecInfo::CapabilitiesWriter::addDetail(
108 const char* key, const char* value) {
109 mCap->mDetails->setString(key, value);
110}
111
112void MediaCodecInfo::CapabilitiesWriter::addDetail(
113 const char* key, int32_t value) {
114 mCap->mDetails->setInt32(key, value);
115}
116
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800117void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
118 if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
119 ALOGD("successfully removed detail %s", key);
120 } else {
121 ALOGD("detail %s wasn't present to remove", key);
122 }
123}
124
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700125void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
126 uint32_t profile, uint32_t level) {
Lajos Molnar5b05e492016-02-04 18:57:45 -0800127 ProfileLevel profileLevel;
128 profileLevel.mProfile = profile;
129 profileLevel.mLevel = level;
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700130 if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
131 mCap->mProfileLevels.push_back(profileLevel);
132 mCap->mProfileLevelsSorted.add(profileLevel);
Lajos Molnar06e98362017-08-14 15:57:57 -0700133 }
Lajos Molnar5b05e492016-02-04 18:57:45 -0800134}
135
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700136void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
137 if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
138 mCap->mColorFormats.push(format);
139 mCap->mColorFormatsSorted.add(format);
Lajos Molnar06e98362017-08-14 15:57:57 -0700140 }
Lajos Molnar5b05e492016-02-04 18:57:45 -0800141}
142
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700143MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
144 MediaCodecInfo::Capabilities* cap) : mCap(cap) {
Lajos Molnar5b05e492016-02-04 18:57:45 -0800145}
146
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800147MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
148 return mAttributes;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700149}
150
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800151uint32_t MediaCodecInfo::getRank() const {
Wonsik Kim78165d32018-01-24 14:48:03 -0800152 return mRank;
153}
154
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800155void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
156 *aliases = mAliases;
157}
158
159void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
160 mediaTypes->clear();
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700161 for (size_t ix = 0; ix < mCaps.size(); ix++) {
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800162 mediaTypes->push_back(mCaps.keyAt(ix));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700163 }
164}
165
Lajos Molnar2461e0c2014-08-12 08:55:25 -0700166const sp<MediaCodecInfo::Capabilities>
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800167MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
168 ssize_t ix = getCapabilityIndex(mediaType);
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700169 if (ix >= 0) {
170 return mCaps.valueAt(ix);
171 }
172 return NULL;
173}
174
Songyue Han45f81942024-05-02 21:17:51 +0000175const std::shared_ptr<CodecCapabilities> MediaCodecInfo::getCodecCapsFor(
176 const char *mediaType) const {
177 ssize_t ix = getCodecCapIndex(mediaType);
178 if (ix >= 0) {
179 return mCodecCaps.valueAt(ix);
180 }
181 return nullptr;
182}
183
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700184const char *MediaCodecInfo::getCodecName() const {
185 return mName.c_str();
186}
187
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700188const char *MediaCodecInfo::getOwnerName() const {
189 return mOwner.c_str();
190}
191
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700192// static
193sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
Songyue Han45f81942024-05-02 21:17:51 +0000194 sMaxSupportedInstances = parcel.readInt32();
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700195 AString name = AString::FromParcel(parcel);
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700196 AString owner = AString::FromParcel(parcel);
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800197 Attributes attributes = static_cast<Attributes>(parcel.readInt32());
Wonsik Kim78165d32018-01-24 14:48:03 -0800198 uint32_t rank = parcel.readUint32();
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700199 sp<MediaCodecInfo> info = new MediaCodecInfo;
200 info->mName = name;
201 info->mOwner = owner;
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800202 info->mAttributes = attributes;
Wonsik Kim78165d32018-01-24 14:48:03 -0800203 info->mRank = rank;
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800204 size_t numAliases = static_cast<size_t>(parcel.readInt32());
205 for (size_t i = 0; i < numAliases; i++) {
206 AString alias = AString::FromParcel(parcel);
207 info->mAliases.add(alias);
208 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700209 size_t size = static_cast<size_t>(parcel.readInt32());
210 for (size_t i = 0; i < size; i++) {
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800211 AString mediaType = AString::FromParcel(parcel);
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700212 sp<Capabilities> caps = Capabilities::FromParcel(parcel);
Pawin Vongmasa8dab17302016-05-02 16:08:39 -0700213 if (caps == NULL)
214 return NULL;
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700215 if (info != NULL) {
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800216 info->mCaps.add(mediaType, caps);
Songyue Han45f81942024-05-02 21:17:51 +0000217 std::shared_ptr<CodecCapabilities> codecCaps
218 = MediaCodecInfoWriter::BuildCodecCapabilities(
219 mediaType.c_str(), caps, info->isEncoder());
220 info->mCodecCaps.add(mediaType, codecCaps);
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700221 }
222 }
223 return info;
224}
225
226status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
Songyue Han45f81942024-05-02 21:17:51 +0000227 parcel->writeInt32(sMaxSupportedInstances);
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700228 mName.writeToParcel(parcel);
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700229 mOwner.writeToParcel(parcel);
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800230 parcel->writeInt32(mAttributes);
Wonsik Kim78165d32018-01-24 14:48:03 -0800231 parcel->writeUint32(mRank);
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800232 parcel->writeInt32(mAliases.size());
233 for (const AString &alias : mAliases) {
234 alias.writeToParcel(parcel);
235 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700236 parcel->writeInt32(mCaps.size());
237 for (size_t i = 0; i < mCaps.size(); i++) {
238 mCaps.keyAt(i).writeToParcel(parcel);
239 mCaps.valueAt(i)->writeToParcel(parcel);
240 }
241 return OK;
242}
243
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800244ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
245 if (mediaType) {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -0700246 for (size_t ix = 0; ix < mCaps.size(); ix++) {
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800247 if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -0700248 return ix;
249 }
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700250 }
251 }
252 return -1;
253}
254
Songyue Han45f81942024-05-02 21:17:51 +0000255ssize_t MediaCodecInfo::getCodecCapIndex(const char *mediaType) const {
256 if (mediaType == nullptr) {
257 return -1;
258 }
259
260 if (mCodecCaps.size() != mCaps.size()) {
261 ALOGE("Size of mCodecCaps and mCaps do not match, which are %zu and %zu",
262 mCodecCaps.size(), mCaps.size());
263 }
264
265 for (size_t ix = 0; ix < mCodecCaps.size(); ix++) {
266 if (mCodecCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
267 return ix;
268 }
269 }
270
271 return -1;
272}
273
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800274MediaCodecInfo::MediaCodecInfo()
275 : mAttributes((MediaCodecInfo::Attributes)0),
276 mRank(0x100) {
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700277}
278
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700279void MediaCodecInfoWriter::setName(const char* name) {
280 mInfo->mName = name;
281}
282
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800283void MediaCodecInfoWriter::addAlias(const char* name) {
284 mInfo->mAliases.add(name);
285}
286
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700287void MediaCodecInfoWriter::setOwner(const char* owner) {
288 mInfo->mOwner = owner;
289}
290
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800291void MediaCodecInfoWriter::setAttributes(
292 typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
293 mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700294}
295
Wonsik Kim78165d32018-01-24 14:48:03 -0800296void MediaCodecInfoWriter::setRank(uint32_t rank) {
297 mInfo->mRank = rank;
298}
299
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700300std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800301 MediaCodecInfoWriter::addMediaType(const char *mediaType) {
302 ssize_t ix = mInfo->getCapabilityIndex(mediaType);
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700303 if (ix >= 0) {
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700304 return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
305 new MediaCodecInfo::CapabilitiesWriter(
306 mInfo->mCaps.valueAt(ix).get()));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700307 }
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700308 sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800309 mInfo->mCaps.add(AString(mediaType), caps);
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700310 return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
311 new MediaCodecInfo::CapabilitiesWriter(caps.get()));
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700312}
313
Lajos Molnar8d4bdfd2018-11-13 14:23:49 -0800314bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
315 ssize_t ix = mInfo->getCapabilityIndex(mediaType);
Lajos Molnar6ff58f02014-08-11 16:46:15 -0700316 if (ix >= 0) {
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700317 mInfo->mCaps.removeItemsAt(ix);
318 return true;
Lajos Molnar6ff58f02014-08-11 16:46:15 -0700319 }
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700320 return false;
Lajos Molnar6ff58f02014-08-11 16:46:15 -0700321}
322
Songyue Han45f81942024-05-02 21:17:51 +0000323void MediaCodecInfoWriter::createCodecCaps() {
324 mInfo->mCodecCaps.clear();
325 for (size_t ix = 0; ix < mInfo->mCaps.size(); ix++) {
326 AString mediaType = mInfo->mCaps.keyAt(ix);
327 sp<MediaCodecInfo::Capabilities> caps = mInfo->mCaps.valueAt(ix);
328 mInfo->mCodecCaps.add(mediaType,
329 BuildCodecCapabilities(mediaType.c_str(), caps, mInfo->isEncoder(),
330 MediaCodecInfo::sMaxSupportedInstances));
331 }
332}
333
334// static
335std::shared_ptr<CodecCapabilities> MediaCodecInfoWriter::BuildCodecCapabilities(
336 const char *mediaType, sp<MediaCodecInfo::Capabilities> caps, bool isEncoder,
337 int32_t maxSupportedInstances) {
338 Vector<ProfileLevel> profileLevels_;
339 Vector<uint32_t> colorFormats_;
340 caps->getSupportedProfileLevels(&profileLevels_);
341 caps->getSupportedColorFormats(&colorFormats_);
342
343 std::vector<ProfileLevel> profileLevels;
344 std::vector<uint32_t> colorFormats;
345 for (ProfileLevel pl : profileLevels_) {
346 profileLevels.push_back(pl);
347 }
348 for (uint32_t cf : colorFormats_) {
349 colorFormats.push_back(cf);
350 }
351
352 sp<AMessage> defaultFormat = new AMessage();
353 defaultFormat->setString("mime", mediaType);
354
355 sp<AMessage> capabilitiesInfo = caps->getDetails();
356
357 std::shared_ptr<CodecCapabilities> codecCaps = std::make_shared<CodecCapabilities>();
358 codecCaps->init(profileLevels, colorFormats, isEncoder, defaultFormat,
359 capabilitiesInfo, maxSupportedInstances);
360
361 return codecCaps;
362}
363
364// static
365void MediaCodecInfoWriter::SetMaxSupportedInstances(int32_t maxSupportedInstances) {
366 MediaCodecInfo::sMaxSupportedInstances = maxSupportedInstances;
367}
368
Pawin Vongmasafbe70ae2017-07-27 02:21:57 -0700369MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
370 mInfo(info) {
Lajos Molnar732c6d92014-08-14 19:54:08 -0700371}
372
Lajos Molnar60b1c0e2014-08-06 16:55:46 -0700373} // namespace android