• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/MediaCodecInfo.h>
22 
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/AMessage.h>
25 #include "media/stagefright/foundation/AString.h"
26 #include <binder/Parcel.h>
27 
28 namespace android {
29 
30 // initialize max supported instances with default value.
31 int32_t MediaCodecInfo::sMaxSupportedInstances = 0;
32 
33 /** This redundant redeclaration is needed for C++ pre 14 */
34 constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
35 constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
36 constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
37 constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
38 constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
39 constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
40 constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
41 constexpr char MediaCodecInfo::Capabilities::FEATURE_DETACHED_SURFACE[];
42 
getSupportedProfileLevels(Vector<ProfileLevel> * profileLevels) const43 void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
44         Vector<ProfileLevel> *profileLevels) const {
45     profileLevels->clear();
46     profileLevels->appendVector(mProfileLevels);
47 }
48 
getSupportedColorFormats(Vector<uint32_t> * colorFormats) const49 void MediaCodecInfo::Capabilities::getSupportedColorFormats(
50         Vector<uint32_t> *colorFormats) const {
51     colorFormats->clear();
52     colorFormats->appendVector(mColorFormats);
53 }
54 
getDetails() const55 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
56     return mDetails;
57 }
58 
Capabilities()59 MediaCodecInfo::Capabilities::Capabilities() {
60     mDetails = new AMessage;
61 }
62 
63 // static
FromParcel(const Parcel & parcel)64 sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
65         const Parcel &parcel) {
66     sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
67     size_t size = static_cast<size_t>(parcel.readInt32());
68     for (size_t i = 0; i < size; i++) {
69         ProfileLevel profileLevel;
70         profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
71         profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
72         if (caps != NULL) {
73             caps->mProfileLevels.push_back(profileLevel);
74         }
75     }
76     size = static_cast<size_t>(parcel.readInt32());
77     for (size_t i = 0; i < size; i++) {
78         uint32_t color = static_cast<uint32_t>(parcel.readInt32());
79         if (caps != NULL) {
80             caps->mColorFormats.push_back(color);
81         }
82     }
83     sp<AMessage> details = AMessage::FromParcel(parcel);
84     if (details == NULL)
85         return NULL;
86     if (caps != NULL) {
87         caps->mDetails = details;
88     }
89     return caps;
90 }
91 
writeToParcel(Parcel * parcel) const92 status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
93     CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX));
94     parcel->writeInt32(mProfileLevels.size());
95     for (size_t i = 0; i < mProfileLevels.size(); i++) {
96         parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
97         parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
98     }
99     CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX));
100     parcel->writeInt32(mColorFormats.size());
101     for (size_t i = 0; i < mColorFormats.size(); i++) {
102         parcel->writeInt32(mColorFormats.itemAt(i));
103     }
104     mDetails->writeToParcel(parcel);
105     return OK;
106 }
107 
addDetail(const char * key,const char * value)108 void MediaCodecInfo::CapabilitiesWriter::addDetail(
109         const char* key, const char* value) {
110     mCap->mDetails->setString(key, value);
111 }
112 
addDetail(const char * key,int32_t value)113 void MediaCodecInfo::CapabilitiesWriter::addDetail(
114         const char* key, int32_t value) {
115     mCap->mDetails->setInt32(key, value);
116 }
117 
removeDetail(const char * key)118 void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
119     if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
120         ALOGD("successfully removed detail %s", key);
121     } else {
122         ALOGD("detail %s wasn't present to remove", key);
123     }
124 }
125 
addProfileLevel(uint32_t profile,uint32_t level)126 void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
127         uint32_t profile, uint32_t level) {
128     ProfileLevel profileLevel;
129     profileLevel.mProfile = profile;
130     profileLevel.mLevel = level;
131     if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
132         mCap->mProfileLevels.push_back(profileLevel);
133         mCap->mProfileLevelsSorted.add(profileLevel);
134     }
135 }
136 
addColorFormat(uint32_t format)137 void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
138     if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
139         mCap->mColorFormats.push(format);
140         mCap->mColorFormatsSorted.add(format);
141     }
142 }
143 
CapabilitiesWriter(MediaCodecInfo::Capabilities * cap)144 MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
145         MediaCodecInfo::Capabilities* cap) : mCap(cap) {
146 }
147 
getAttributes() const148 MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
149     return mAttributes;
150 }
151 
getRank() const152 uint32_t MediaCodecInfo::getRank() const {
153     return mRank;
154 }
155 
getAliases(Vector<AString> * aliases) const156 void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
157     *aliases = mAliases;
158 }
159 
getSupportedMediaTypes(Vector<AString> * mediaTypes) const160 void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
161     mediaTypes->clear();
162     for (size_t ix = 0; ix < mCaps.size(); ix++) {
163         mediaTypes->push_back(mCaps.keyAt(ix));
164     }
165 }
166 
167 const sp<MediaCodecInfo::Capabilities>
getCapabilitiesFor(const char * mediaType) const168 MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
169     ssize_t ix = getCapabilityIndex(mediaType);
170     if (ix >= 0) {
171         return mCaps.valueAt(ix);
172     }
173     return NULL;
174 }
175 
getCodecCapsFor(const char * mediaType) const176 const std::shared_ptr<CodecCapabilities> MediaCodecInfo::getCodecCapsFor(
177         const char *mediaType) const {
178     ssize_t ix = getCodecCapIndex(mediaType);
179     if (ix >= 0) {
180         return mCodecCaps.valueAt(ix);
181     }
182     return nullptr;
183 }
184 
getCodecName() const185 const char *MediaCodecInfo::getCodecName() const {
186     return mName.c_str();
187 }
188 
getHalName() const189 const char *MediaCodecInfo::getHalName() const {
190     return mHalName.c_str();
191 }
192 
getOwnerName() const193 const char *MediaCodecInfo::getOwnerName() const {
194     return mOwner.c_str();
195 }
196 
197 // static
FromParcel(const Parcel & parcel)198 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
199     sMaxSupportedInstances = parcel.readInt32();
200     AString name = AString::FromParcel(parcel);
201     AString halName = AString::FromParcel(parcel);
202     AString owner = AString::FromParcel(parcel);
203     Attributes attributes = static_cast<Attributes>(parcel.readInt32());
204     uint32_t rank = parcel.readUint32();
205     sp<MediaCodecInfo> info = new MediaCodecInfo;
206     info->mName = name;
207     info->mHalName = halName;
208     info->mOwner = owner;
209     info->mAttributes = attributes;
210     info->mRank = rank;
211     size_t numAliases = static_cast<size_t>(parcel.readInt32());
212     for (size_t i = 0; i < numAliases; i++) {
213         AString alias = AString::FromParcel(parcel);
214         info->mAliases.add(alias);
215     }
216     size_t size = static_cast<size_t>(parcel.readInt32());
217     for (size_t i = 0; i < size; i++) {
218         AString mediaType = AString::FromParcel(parcel);
219         sp<Capabilities> caps = Capabilities::FromParcel(parcel);
220         if (caps == NULL)
221             return NULL;
222         if (info != NULL) {
223             info->mCaps.add(mediaType, caps);
224             std::shared_ptr<CodecCapabilities> codecCaps
225                     = MediaCodecInfoWriter::BuildCodecCapabilities(
226                             mediaType.c_str(), caps, info->isEncoder());
227             info->mCodecCaps.add(mediaType, codecCaps);
228         }
229     }
230     return info;
231 }
232 
writeToParcel(Parcel * parcel) const233 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
234     parcel->writeInt32(sMaxSupportedInstances);
235     mName.writeToParcel(parcel);
236     mHalName.writeToParcel(parcel);
237     mOwner.writeToParcel(parcel);
238     parcel->writeInt32(mAttributes);
239     parcel->writeUint32(mRank);
240     parcel->writeInt32(mAliases.size());
241     for (const AString &alias : mAliases) {
242         alias.writeToParcel(parcel);
243     }
244     parcel->writeInt32(mCaps.size());
245     for (size_t i = 0; i < mCaps.size(); i++) {
246         mCaps.keyAt(i).writeToParcel(parcel);
247         mCaps.valueAt(i)->writeToParcel(parcel);
248     }
249     return OK;
250 }
251 
getCapabilityIndex(const char * mediaType) const252 ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
253     if (mediaType) {
254         for (size_t ix = 0; ix < mCaps.size(); ix++) {
255             if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
256                 return ix;
257             }
258         }
259     }
260     return -1;
261 }
262 
getCodecCapIndex(const char * mediaType) const263 ssize_t MediaCodecInfo::getCodecCapIndex(const char *mediaType) const {
264     if (mediaType == nullptr) {
265         return -1;
266     }
267 
268     if (mCodecCaps.size() != mCaps.size()) {
269         ALOGE("Size of mCodecCaps and mCaps do not match, which are %zu and %zu",
270                 mCodecCaps.size(), mCaps.size());
271     }
272 
273     for (size_t ix = 0; ix < mCodecCaps.size(); ix++) {
274         if (mCodecCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
275             return ix;
276         }
277     }
278 
279     return -1;
280 }
281 
MediaCodecInfo()282 MediaCodecInfo::MediaCodecInfo()
283     : mAttributes((MediaCodecInfo::Attributes)0),
284       mRank(0x100) {
285 }
286 
setName(const char * name)287 void MediaCodecInfoWriter::setName(const char* name) {
288     mInfo->mName = name;
289     // Upon creation, we use the same name for HAL and info and
290     // only distinguish them during collision resolution.
291     mInfo->mHalName = name;
292 }
293 
addAlias(const char * name)294 void MediaCodecInfoWriter::addAlias(const char* name) {
295     mInfo->mAliases.add(name);
296 }
297 
setOwner(const char * owner)298 void MediaCodecInfoWriter::setOwner(const char* owner) {
299     mInfo->mOwner = owner;
300 }
301 
setAttributes(typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes)302 void MediaCodecInfoWriter::setAttributes(
303         typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
304     mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
305 }
306 
setRank(uint32_t rank)307 void MediaCodecInfoWriter::setRank(uint32_t rank) {
308     mInfo->mRank = rank;
309 }
310 
311 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
addMediaType(const char * mediaType)312         MediaCodecInfoWriter::addMediaType(const char *mediaType) {
313     ssize_t ix = mInfo->getCapabilityIndex(mediaType);
314     if (ix >= 0) {
315         return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
316                 new MediaCodecInfo::CapabilitiesWriter(
317                 mInfo->mCaps.valueAt(ix).get()));
318     }
319     sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
320     mInfo->mCaps.add(AString(mediaType), caps);
321     return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
322             new MediaCodecInfo::CapabilitiesWriter(caps.get()));
323 }
324 
removeMediaType(const char * mediaType)325 bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
326     ssize_t ix = mInfo->getCapabilityIndex(mediaType);
327     if (ix >= 0) {
328         mInfo->mCaps.removeItemsAt(ix);
329         return true;
330     }
331     return false;
332 }
333 
createCodecCaps()334 void MediaCodecInfoWriter::createCodecCaps() {
335     mInfo->mCodecCaps.clear();
336     for (size_t ix = 0; ix < mInfo->mCaps.size(); ix++) {
337         AString mediaType = mInfo->mCaps.keyAt(ix);
338         sp<MediaCodecInfo::Capabilities> caps = mInfo->mCaps.valueAt(ix);
339         mInfo->mCodecCaps.add(mediaType,
340                 BuildCodecCapabilities(mediaType.c_str(), caps, mInfo->isEncoder(),
341                 MediaCodecInfo::sMaxSupportedInstances));
342     }
343 }
344 
splitOutType(const char * mediaType,const char * newName) const345 sp<MediaCodecInfo> MediaCodecInfo::splitOutType(const char *mediaType,
346         const char *newName) const {
347     sp<MediaCodecInfo> newInfo = new MediaCodecInfo;
348     newInfo->mName = newName;
349     newInfo->mHalName = mHalName;
350     newInfo->mOwner = mOwner;
351     newInfo->mAttributes = mAttributes;
352     newInfo->mRank = mRank;
353     newInfo->mAliases = mAliases;
354     // allow an alias from the (old) HAL name. If there is a collision, this will be ignored.
355     newInfo->mAliases.add(mHalName);
356 
357     // note: mediaType is always a supported type. valueAt() will abort otherwise.
358     newInfo->mCaps.add(AString(mediaType), mCaps.valueAt(getCapabilityIndex(mediaType)));
359     newInfo->mCodecCaps.add(AString(mediaType), mCodecCaps.valueAt(getCodecCapIndex(mediaType)));
360     return newInfo;
361 }
362 
363 // static
BuildCodecCapabilities(const char * mediaType,sp<MediaCodecInfo::Capabilities> caps,bool isEncoder,int32_t maxSupportedInstances)364 std::shared_ptr<CodecCapabilities> MediaCodecInfoWriter::BuildCodecCapabilities(
365         const char *mediaType, sp<MediaCodecInfo::Capabilities> caps, bool isEncoder,
366         int32_t maxSupportedInstances) {
367     Vector<ProfileLevel> profileLevels_;
368     Vector<uint32_t> colorFormats_;
369     caps->getSupportedProfileLevels(&profileLevels_);
370     caps->getSupportedColorFormats(&colorFormats_);
371 
372     std::vector<ProfileLevel> profileLevels;
373     std::vector<uint32_t> colorFormats;
374     for (ProfileLevel pl : profileLevels_) {
375         profileLevels.push_back(pl);
376     }
377     for (uint32_t cf : colorFormats_) {
378         colorFormats.push_back(cf);
379     }
380 
381     sp<AMessage> defaultFormat = new AMessage();
382     defaultFormat->setString("mime", mediaType);
383 
384     sp<AMessage> capabilitiesInfo = caps->getDetails();
385 
386     std::shared_ptr<CodecCapabilities> codecCaps = std::make_shared<CodecCapabilities>();
387     codecCaps->init(profileLevels, colorFormats, isEncoder, defaultFormat,
388             capabilitiesInfo, maxSupportedInstances);
389 
390     return codecCaps;
391 }
392 
393 // static
SetMaxSupportedInstances(int32_t maxSupportedInstances)394 void MediaCodecInfoWriter::SetMaxSupportedInstances(int32_t maxSupportedInstances) {
395     MediaCodecInfo::sMaxSupportedInstances = maxSupportedInstances;
396 }
397 
MediaCodecInfoWriter(MediaCodecInfo * info)398 MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
399     mInfo(info) {
400 }
401 
402 }  // namespace android
403