| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 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 |  | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 29 | namespace android { | 
|  | 30 |  | 
|  | 31 | void MediaCodecInfo::Capabilities::getSupportedProfileLevels( | 
|  | 32 | Vector<ProfileLevel> *profileLevels) const { | 
|  | 33 | profileLevels->clear(); | 
|  | 34 | profileLevels->appendVector(mProfileLevels); | 
|  | 35 | } | 
|  | 36 |  | 
|  | 37 | void MediaCodecInfo::Capabilities::getSupportedColorFormats( | 
|  | 38 | Vector<uint32_t> *colorFormats) const { | 
|  | 39 | colorFormats->clear(); | 
|  | 40 | colorFormats->appendVector(mColorFormats); | 
|  | 41 | } | 
|  | 42 |  | 
|  | 43 | uint32_t MediaCodecInfo::Capabilities::getFlags() const { | 
|  | 44 | return mFlags; | 
|  | 45 | } | 
|  | 46 |  | 
| Lajos Molnar | 2461e0c | 2014-08-12 08:55:25 -0700 | [diff] [blame] | 47 | const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const { | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 48 | return mDetails; | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | MediaCodecInfo::Capabilities::Capabilities() | 
|  | 52 | : mFlags(0) { | 
|  | 53 | mDetails = new AMessage; | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | // static | 
|  | 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); | 
| Pawin Vongmasa | 8dab1730 | 2016-05-02 16:08:39 -0700 | [diff] [blame] | 78 | if (details == NULL) | 
|  | 79 | return NULL; | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 80 | if (caps != NULL) { | 
|  | 81 | caps->mFlags = flags; | 
|  | 82 | caps->mDetails = details; | 
|  | 83 | } | 
|  | 84 | return caps; | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { | 
| Colin Cross | b8c35f9 | 2017-04-27 16:15:51 -0700 | [diff] [blame] | 88 | CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX)); | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 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 | } | 
| Colin Cross | b8c35f9 | 2017-04-27 16:15:51 -0700 | [diff] [blame] | 94 | CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX)); | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 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 |  | 
| Lajos Molnar | 5b05e49 | 2016-02-04 18:57:45 -0800 | [diff] [blame] | 104 | void MediaCodecInfo::CapabilitiesBuilder::addProfileLevel(uint32_t profile, uint32_t level) { | 
|  | 105 | ProfileLevel profileLevel; | 
|  | 106 | profileLevel.mProfile = profile; | 
|  | 107 | profileLevel.mLevel = level; | 
| Lajos Molnar | 06e9836 | 2017-08-14 15:57:57 -0700 | [diff] [blame^] | 108 | if (mProfileLevelsSorted.indexOf(profileLevel) < 0) { | 
|  | 109 | mProfileLevels.push_back(profileLevel); | 
|  | 110 | mProfileLevelsSorted.add(profileLevel); | 
|  | 111 | } | 
| Lajos Molnar | 5b05e49 | 2016-02-04 18:57:45 -0800 | [diff] [blame] | 112 | } | 
|  | 113 |  | 
|  | 114 | void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) { | 
| Lajos Molnar | 06e9836 | 2017-08-14 15:57:57 -0700 | [diff] [blame^] | 115 | if (mColorFormatsSorted.indexOf(format) < 0) { | 
|  | 116 | mColorFormats.push(format); | 
|  | 117 | mColorFormatsSorted.add(format); | 
|  | 118 | } | 
| Lajos Molnar | 5b05e49 | 2016-02-04 18:57:45 -0800 | [diff] [blame] | 119 | } | 
|  | 120 |  | 
|  | 121 | void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) { | 
|  | 122 | mFlags |= flags; | 
|  | 123 | } | 
|  | 124 |  | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 125 | bool MediaCodecInfo::isEncoder() const { | 
|  | 126 | return mIsEncoder; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | bool MediaCodecInfo::hasQuirk(const char *name) const { | 
| Marco Nelissen | 89b2a0a | 2016-05-03 11:10:42 -0700 | [diff] [blame] | 130 | if (name) { | 
|  | 131 | for (size_t ix = 0; ix < mQuirks.size(); ix++) { | 
|  | 132 | if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) { | 
|  | 133 | return true; | 
|  | 134 | } | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 135 | } | 
|  | 136 | } | 
|  | 137 | return false; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | void 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 Molnar | 2461e0c | 2014-08-12 08:55:25 -0700 | [diff] [blame] | 147 | const sp<MediaCodecInfo::Capabilities> | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 148 | MediaCodecInfo::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 |  | 
|  | 156 | const char *MediaCodecInfo::getCodecName() const { | 
|  | 157 | return mName.c_str(); | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | // static | 
|  | 161 | sp<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 Vongmasa | 8dab1730 | 2016-05-02 16:08:39 -0700 | [diff] [blame] | 176 | if (caps == NULL) | 
|  | 177 | return NULL; | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 178 | if (info != NULL) { | 
|  | 179 | info->mCaps.add(mime, caps); | 
|  | 180 | } | 
|  | 181 | } | 
|  | 182 | return info; | 
|  | 183 | } | 
|  | 184 |  | 
|  | 185 | status_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 |  | 
|  | 200 | ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const { | 
| Marco Nelissen | 89b2a0a | 2016-05-03 11:10:42 -0700 | [diff] [blame] | 201 | if (mime) { | 
|  | 202 | for (size_t ix = 0; ix < mCaps.size(); ix++) { | 
|  | 203 | if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) { | 
|  | 204 | return ix; | 
|  | 205 | } | 
| Lajos Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 206 | } | 
|  | 207 | } | 
|  | 208 | return -1; | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | MediaCodecInfo::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 |  | 
|  | 221 | status_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 Wu | 9e6955a | 2015-03-26 13:52:57 -0700 | [diff] [blame] | 236 | status_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 Molnar | 6ff58f0 | 2014-08-11 16:46:15 -0700 | [diff] [blame] | 247 | void 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 Molnar | 0a4427b | 2016-02-11 19:42:52 -0800 | [diff] [blame] | 255 | status_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 Molnar | 7f2262f | 2016-02-11 10:35:37 -0800 | [diff] [blame] | 258 | mCurrentCaps->mColorFormats.clear(); | 
| Lajos Molnar | 0a4427b | 2016-02-11 19:42:52 -0800 | [diff] [blame] | 259 | 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 Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 264 | return OK; | 
|  | 265 | } | 
|  | 266 |  | 
|  | 267 | void MediaCodecInfo::addQuirk(const char *name) { | 
|  | 268 | if (!hasQuirk(name)) { | 
|  | 269 | mQuirks.push(name); | 
|  | 270 | } | 
|  | 271 | } | 
|  | 272 |  | 
|  | 273 | void MediaCodecInfo::complete() { | 
|  | 274 | mCurrentCaps = NULL; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | void MediaCodecInfo::addDetail(const AString &key, const AString &value) { | 
|  | 278 | mCurrentCaps->mDetails->setString(key.c_str(), value.c_str()); | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | void 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 Molnar | 732c6d9 | 2014-08-14 19:54:08 -0700 | [diff] [blame] | 287 | void 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 Molnar | 60b1c0e | 2014-08-06 16:55:46 -0700 | [diff] [blame] | 293 | }  // namespace android |