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 
getSupportedProfileLevels(Vector<ProfileLevel> * profileLevels) const31 void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
32         Vector<ProfileLevel> *profileLevels) const {
33     profileLevels->clear();
34     profileLevels->appendVector(mProfileLevels);
35 }
36 
getSupportedColorFormats(Vector<uint32_t> * colorFormats) const37 void MediaCodecInfo::Capabilities::getSupportedColorFormats(
38         Vector<uint32_t> *colorFormats) const {
39     colorFormats->clear();
40     colorFormats->appendVector(mColorFormats);
41 }
42 
getFlags() const43 uint32_t MediaCodecInfo::Capabilities::getFlags() const {
44     return mFlags;
45 }
46 
getDetails() const47 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
48     return mDetails;
49 }
50 
Capabilities()51 MediaCodecInfo::Capabilities::Capabilities()
52   : mFlags(0) {
53     mDetails = new AMessage;
54 }
55 
56 // static
FromParcel(const Parcel & parcel)57 sp<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);
78     if (details == NULL)
79         return NULL;
80     if (caps != NULL) {
81         caps->mFlags = flags;
82         caps->mDetails = details;
83     }
84     return caps;
85 }
86 
writeToParcel(Parcel * parcel) const87 status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
88     CHECK_LE(mProfileLevels.size(), static_cast<size_t>(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(), static_cast<size_t>(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 
addDetail(const char * key,const char * value)104 void MediaCodecInfo::CapabilitiesWriter::addDetail(
105         const char* key, const char* value) {
106     mCap->mDetails->setString(key, value);
107 }
108 
addDetail(const char * key,int32_t value)109 void MediaCodecInfo::CapabilitiesWriter::addDetail(
110         const char* key, int32_t value) {
111     mCap->mDetails->setInt32(key, value);
112 }
113 
addProfileLevel(uint32_t profile,uint32_t level)114 void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
115         uint32_t profile, uint32_t level) {
116     ProfileLevel profileLevel;
117     profileLevel.mProfile = profile;
118     profileLevel.mLevel = level;
119     if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
120         mCap->mProfileLevels.push_back(profileLevel);
121         mCap->mProfileLevelsSorted.add(profileLevel);
122     }
123 }
124 
addColorFormat(uint32_t format)125 void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
126     if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
127         mCap->mColorFormats.push(format);
128         mCap->mColorFormatsSorted.add(format);
129     }
130 }
131 
addFlags(uint32_t flags)132 void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
133     mCap->mFlags |= flags;
134 }
135 
CapabilitiesWriter(MediaCodecInfo::Capabilities * cap)136 MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
137         MediaCodecInfo::Capabilities* cap) : mCap(cap) {
138 }
139 
isEncoder() const140 bool MediaCodecInfo::isEncoder() const {
141     return mIsEncoder;
142 }
143 
rank() const144 uint32_t MediaCodecInfo::rank() const {
145     return mRank;
146 }
147 
getSupportedMimes(Vector<AString> * mimes) const148 void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
149     mimes->clear();
150     for (size_t ix = 0; ix < mCaps.size(); ix++) {
151         mimes->push_back(mCaps.keyAt(ix));
152     }
153 }
154 
155 const sp<MediaCodecInfo::Capabilities>
getCapabilitiesFor(const char * mime) const156 MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
157     ssize_t ix = getCapabilityIndex(mime);
158     if (ix >= 0) {
159         return mCaps.valueAt(ix);
160     }
161     return NULL;
162 }
163 
getCodecName() const164 const char *MediaCodecInfo::getCodecName() const {
165     return mName.c_str();
166 }
167 
getOwnerName() const168 const char *MediaCodecInfo::getOwnerName() const {
169     return mOwner.c_str();
170 }
171 
172 // static
FromParcel(const Parcel & parcel)173 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
174     AString name = AString::FromParcel(parcel);
175     AString owner = AString::FromParcel(parcel);
176     bool isEncoder = static_cast<bool>(parcel.readInt32());
177     uint32_t rank = parcel.readUint32();
178     sp<MediaCodecInfo> info = new MediaCodecInfo;
179     info->mName = name;
180     info->mOwner = owner;
181     info->mIsEncoder = isEncoder;
182     info->mRank = rank;
183     size_t size = static_cast<size_t>(parcel.readInt32());
184     for (size_t i = 0; i < size; i++) {
185         AString mime = AString::FromParcel(parcel);
186         sp<Capabilities> caps = Capabilities::FromParcel(parcel);
187         if (caps == NULL)
188             return NULL;
189         if (info != NULL) {
190             info->mCaps.add(mime, caps);
191         }
192     }
193     return info;
194 }
195 
writeToParcel(Parcel * parcel) const196 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
197     mName.writeToParcel(parcel);
198     mOwner.writeToParcel(parcel);
199     parcel->writeInt32(mIsEncoder);
200     parcel->writeUint32(mRank);
201     parcel->writeInt32(mCaps.size());
202     for (size_t i = 0; i < mCaps.size(); i++) {
203         mCaps.keyAt(i).writeToParcel(parcel);
204         mCaps.valueAt(i)->writeToParcel(parcel);
205     }
206     return OK;
207 }
208 
getCapabilityIndex(const char * mime) const209 ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
210     if (mime) {
211         for (size_t ix = 0; ix < mCaps.size(); ix++) {
212             if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
213                 return ix;
214             }
215         }
216     }
217     return -1;
218 }
219 
MediaCodecInfo()220 MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
221 }
222 
setName(const char * name)223 void MediaCodecInfoWriter::setName(const char* name) {
224     mInfo->mName = name;
225 }
226 
setOwner(const char * owner)227 void MediaCodecInfoWriter::setOwner(const char* owner) {
228     mInfo->mOwner = owner;
229 }
230 
setEncoder(bool isEncoder)231 void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
232     mInfo->mIsEncoder = isEncoder;
233 }
234 
setRank(uint32_t rank)235 void MediaCodecInfoWriter::setRank(uint32_t rank) {
236     mInfo->mRank = rank;
237 }
238 
239 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
addMime(const char * mime)240         MediaCodecInfoWriter::addMime(const char *mime) {
241     ssize_t ix = mInfo->getCapabilityIndex(mime);
242     if (ix >= 0) {
243         return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
244                 new MediaCodecInfo::CapabilitiesWriter(
245                 mInfo->mCaps.valueAt(ix).get()));
246     }
247     sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
248     mInfo->mCaps.add(AString(mime), caps);
249     return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
250             new MediaCodecInfo::CapabilitiesWriter(caps.get()));
251 }
252 
removeMime(const char * mime)253 bool MediaCodecInfoWriter::removeMime(const char *mime) {
254     ssize_t ix = mInfo->getCapabilityIndex(mime);
255     if (ix >= 0) {
256         mInfo->mCaps.removeItemsAt(ix);
257         return true;
258     }
259     return false;
260 }
261 
MediaCodecInfoWriter(MediaCodecInfo * info)262 MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
263     mInfo(info) {
264 }
265 
266 }  // namespace android
267