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 
29 namespace android {
30 
31 /** This redundant redeclaration is needed for C++ pre 14 */
32 constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
33 constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
34 constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
35 constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
36 constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
37 constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
38 constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
39 
getSupportedProfileLevels(Vector<ProfileLevel> * profileLevels) const40 void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
41         Vector<ProfileLevel> *profileLevels) const {
42     profileLevels->clear();
43     profileLevels->appendVector(mProfileLevels);
44 }
45 
getSupportedColorFormats(Vector<uint32_t> * colorFormats) const46 void MediaCodecInfo::Capabilities::getSupportedColorFormats(
47         Vector<uint32_t> *colorFormats) const {
48     colorFormats->clear();
49     colorFormats->appendVector(mColorFormats);
50 }
51 
getDetails() const52 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
53     return mDetails;
54 }
55 
Capabilities()56 MediaCodecInfo::Capabilities::Capabilities() {
57     mDetails = new AMessage;
58 }
59 
60 // static
FromParcel(const Parcel & parcel)61 sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
62         const Parcel &parcel) {
63     sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
64     size_t size = static_cast<size_t>(parcel.readInt32());
65     for (size_t i = 0; i < size; i++) {
66         ProfileLevel profileLevel;
67         profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
68         profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
69         if (caps != NULL) {
70             caps->mProfileLevels.push_back(profileLevel);
71         }
72     }
73     size = static_cast<size_t>(parcel.readInt32());
74     for (size_t i = 0; i < size; i++) {
75         uint32_t color = static_cast<uint32_t>(parcel.readInt32());
76         if (caps != NULL) {
77             caps->mColorFormats.push_back(color);
78         }
79     }
80     sp<AMessage> details = AMessage::FromParcel(parcel);
81     if (details == NULL)
82         return NULL;
83     if (caps != NULL) {
84         caps->mDetails = details;
85     }
86     return caps;
87 }
88 
writeToParcel(Parcel * parcel) const89 status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
90     CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX));
91     parcel->writeInt32(mProfileLevels.size());
92     for (size_t i = 0; i < mProfileLevels.size(); i++) {
93         parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
94         parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
95     }
96     CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX));
97     parcel->writeInt32(mColorFormats.size());
98     for (size_t i = 0; i < mColorFormats.size(); i++) {
99         parcel->writeInt32(mColorFormats.itemAt(i));
100     }
101     mDetails->writeToParcel(parcel);
102     return OK;
103 }
104 
addDetail(const char * key,const char * value)105 void MediaCodecInfo::CapabilitiesWriter::addDetail(
106         const char* key, const char* value) {
107     mCap->mDetails->setString(key, value);
108 }
109 
addDetail(const char * key,int32_t value)110 void MediaCodecInfo::CapabilitiesWriter::addDetail(
111         const char* key, int32_t value) {
112     mCap->mDetails->setInt32(key, value);
113 }
114 
removeDetail(const char * key)115 void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
116     if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
117         ALOGD("successfully removed detail %s", key);
118     } else {
119         ALOGD("detail %s wasn't present to remove", key);
120     }
121 }
122 
addProfileLevel(uint32_t profile,uint32_t level)123 void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
124         uint32_t profile, uint32_t level) {
125     ProfileLevel profileLevel;
126     profileLevel.mProfile = profile;
127     profileLevel.mLevel = level;
128     if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
129         mCap->mProfileLevels.push_back(profileLevel);
130         mCap->mProfileLevelsSorted.add(profileLevel);
131     }
132 }
133 
addColorFormat(uint32_t format)134 void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
135     if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
136         mCap->mColorFormats.push(format);
137         mCap->mColorFormatsSorted.add(format);
138     }
139 }
140 
CapabilitiesWriter(MediaCodecInfo::Capabilities * cap)141 MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
142         MediaCodecInfo::Capabilities* cap) : mCap(cap) {
143 }
144 
getAttributes() const145 MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
146     return mAttributes;
147 }
148 
getRank() const149 uint32_t MediaCodecInfo::getRank() const {
150     return mRank;
151 }
152 
getAliases(Vector<AString> * aliases) const153 void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
154     *aliases = mAliases;
155 }
156 
getSupportedMediaTypes(Vector<AString> * mediaTypes) const157 void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
158     mediaTypes->clear();
159     for (size_t ix = 0; ix < mCaps.size(); ix++) {
160         mediaTypes->push_back(mCaps.keyAt(ix));
161     }
162 }
163 
164 const sp<MediaCodecInfo::Capabilities>
getCapabilitiesFor(const char * mediaType) const165 MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
166     ssize_t ix = getCapabilityIndex(mediaType);
167     if (ix >= 0) {
168         return mCaps.valueAt(ix);
169     }
170     return NULL;
171 }
172 
getCodecName() const173 const char *MediaCodecInfo::getCodecName() const {
174     return mName.c_str();
175 }
176 
getOwnerName() const177 const char *MediaCodecInfo::getOwnerName() const {
178     return mOwner.c_str();
179 }
180 
181 // static
FromParcel(const Parcel & parcel)182 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
183     AString name = AString::FromParcel(parcel);
184     AString owner = AString::FromParcel(parcel);
185     Attributes attributes = static_cast<Attributes>(parcel.readInt32());
186     uint32_t rank = parcel.readUint32();
187     sp<MediaCodecInfo> info = new MediaCodecInfo;
188     info->mName = name;
189     info->mOwner = owner;
190     info->mAttributes = attributes;
191     info->mRank = rank;
192     size_t numAliases = static_cast<size_t>(parcel.readInt32());
193     for (size_t i = 0; i < numAliases; i++) {
194         AString alias = AString::FromParcel(parcel);
195         info->mAliases.add(alias);
196     }
197     size_t size = static_cast<size_t>(parcel.readInt32());
198     for (size_t i = 0; i < size; i++) {
199         AString mediaType = AString::FromParcel(parcel);
200         sp<Capabilities> caps = Capabilities::FromParcel(parcel);
201         if (caps == NULL)
202             return NULL;
203         if (info != NULL) {
204             info->mCaps.add(mediaType, caps);
205         }
206     }
207     return info;
208 }
209 
writeToParcel(Parcel * parcel) const210 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
211     mName.writeToParcel(parcel);
212     mOwner.writeToParcel(parcel);
213     parcel->writeInt32(mAttributes);
214     parcel->writeUint32(mRank);
215     parcel->writeInt32(mAliases.size());
216     for (const AString &alias : mAliases) {
217         alias.writeToParcel(parcel);
218     }
219     parcel->writeInt32(mCaps.size());
220     for (size_t i = 0; i < mCaps.size(); i++) {
221         mCaps.keyAt(i).writeToParcel(parcel);
222         mCaps.valueAt(i)->writeToParcel(parcel);
223     }
224     return OK;
225 }
226 
getCapabilityIndex(const char * mediaType) const227 ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
228     if (mediaType) {
229         for (size_t ix = 0; ix < mCaps.size(); ix++) {
230             if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
231                 return ix;
232             }
233         }
234     }
235     return -1;
236 }
237 
MediaCodecInfo()238 MediaCodecInfo::MediaCodecInfo()
239     : mAttributes((MediaCodecInfo::Attributes)0),
240       mRank(0x100) {
241 }
242 
setName(const char * name)243 void MediaCodecInfoWriter::setName(const char* name) {
244     mInfo->mName = name;
245 }
246 
addAlias(const char * name)247 void MediaCodecInfoWriter::addAlias(const char* name) {
248     mInfo->mAliases.add(name);
249 }
250 
setOwner(const char * owner)251 void MediaCodecInfoWriter::setOwner(const char* owner) {
252     mInfo->mOwner = owner;
253 }
254 
setAttributes(typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes)255 void MediaCodecInfoWriter::setAttributes(
256         typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
257     mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
258 }
259 
setRank(uint32_t rank)260 void MediaCodecInfoWriter::setRank(uint32_t rank) {
261     mInfo->mRank = rank;
262 }
263 
264 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
addMediaType(const char * mediaType)265         MediaCodecInfoWriter::addMediaType(const char *mediaType) {
266     ssize_t ix = mInfo->getCapabilityIndex(mediaType);
267     if (ix >= 0) {
268         return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
269                 new MediaCodecInfo::CapabilitiesWriter(
270                 mInfo->mCaps.valueAt(ix).get()));
271     }
272     sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
273     mInfo->mCaps.add(AString(mediaType), caps);
274     return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
275             new MediaCodecInfo::CapabilitiesWriter(caps.get()));
276 }
277 
removeMediaType(const char * mediaType)278 bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
279     ssize_t ix = mInfo->getCapabilityIndex(mediaType);
280     if (ix >= 0) {
281         mInfo->mCaps.removeItemsAt(ix);
282         return true;
283     }
284     return false;
285 }
286 
MediaCodecInfoWriter(MediaCodecInfo * info)287 MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
288     mInfo(info) {
289 }
290 
291 }  // namespace android
292