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 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 47 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const { 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); 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 87 status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { 88 CHECK_LE(mProfileLevels.size(), 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(), 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 104 void MediaCodecInfo::CapabilitiesBuilder::addProfileLevel(uint32_t profile, uint32_t level) { 105 ProfileLevel profileLevel; 106 profileLevel.mProfile = profile; 107 profileLevel.mLevel = level; 108 mProfileLevels.push_back(profileLevel); 109 } 110 111 void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) { 112 mColorFormats.push(format); 113 } 114 115 void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) { 116 mFlags |= flags; 117 } 118 119 bool MediaCodecInfo::isEncoder() const { 120 return mIsEncoder; 121 } 122 123 bool MediaCodecInfo::hasQuirk(const char *name) const { 124 for (size_t ix = 0; ix < mQuirks.size(); ix++) { 125 if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) { 126 return true; 127 } 128 } 129 return false; 130 } 131 132 void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const { 133 mimes->clear(); 134 for (size_t ix = 0; ix < mCaps.size(); ix++) { 135 mimes->push_back(mCaps.keyAt(ix)); 136 } 137 } 138 139 const sp<MediaCodecInfo::Capabilities> 140 MediaCodecInfo::getCapabilitiesFor(const char *mime) const { 141 ssize_t ix = getCapabilityIndex(mime); 142 if (ix >= 0) { 143 return mCaps.valueAt(ix); 144 } 145 return NULL; 146 } 147 148 const char *MediaCodecInfo::getCodecName() const { 149 return mName.c_str(); 150 } 151 152 // static 153 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) { 154 AString name = AString::FromParcel(parcel); 155 bool isEncoder = static_cast<bool>(parcel.readInt32()); 156 sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL); 157 size_t size = static_cast<size_t>(parcel.readInt32()); 158 for (size_t i = 0; i < size; i++) { 159 AString quirk = AString::FromParcel(parcel); 160 if (info != NULL) { 161 info->mQuirks.push_back(quirk); 162 } 163 } 164 size = static_cast<size_t>(parcel.readInt32()); 165 for (size_t i = 0; i < size; i++) { 166 AString mime = AString::FromParcel(parcel); 167 sp<Capabilities> caps = Capabilities::FromParcel(parcel); 168 if (caps == NULL) 169 return NULL; 170 if (info != NULL) { 171 info->mCaps.add(mime, caps); 172 } 173 } 174 return info; 175 } 176 177 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const { 178 mName.writeToParcel(parcel); 179 parcel->writeInt32(mIsEncoder); 180 parcel->writeInt32(mQuirks.size()); 181 for (size_t i = 0; i < mQuirks.size(); i++) { 182 mQuirks.itemAt(i).writeToParcel(parcel); 183 } 184 parcel->writeInt32(mCaps.size()); 185 for (size_t i = 0; i < mCaps.size(); i++) { 186 mCaps.keyAt(i).writeToParcel(parcel); 187 mCaps.valueAt(i)->writeToParcel(parcel); 188 } 189 return OK; 190 } 191 192 ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const { 193 for (size_t ix = 0; ix < mCaps.size(); ix++) { 194 if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) { 195 return ix; 196 } 197 } 198 return -1; 199 } 200 201 MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime) 202 : mName(name), 203 mIsEncoder(encoder), 204 mHasSoleMime(false) { 205 if (mime != NULL) { 206 addMime(mime); 207 mHasSoleMime = true; 208 } 209 } 210 211 status_t MediaCodecInfo::addMime(const char *mime) { 212 if (mHasSoleMime) { 213 ALOGE("Codec '%s' already had its type specified", mName.c_str()); 214 return -EINVAL; 215 } 216 ssize_t ix = getCapabilityIndex(mime); 217 if (ix >= 0) { 218 mCurrentCaps = mCaps.valueAt(ix); 219 } else { 220 mCurrentCaps = new Capabilities(); 221 mCaps.add(AString(mime), mCurrentCaps); 222 } 223 return OK; 224 } 225 226 status_t MediaCodecInfo::updateMime(const char *mime) { 227 ssize_t ix = getCapabilityIndex(mime); 228 if (ix < 0) { 229 ALOGE("updateMime mime not found %s", mime); 230 return -EINVAL; 231 } 232 233 mCurrentCaps = mCaps.valueAt(ix); 234 return OK; 235 } 236 237 void MediaCodecInfo::removeMime(const char *mime) { 238 ssize_t ix = getCapabilityIndex(mime); 239 if (ix >= 0) { 240 mCaps.removeItemsAt(ix); 241 // mCurrentCaps will be removed when completed 242 } 243 } 244 245 status_t MediaCodecInfo::initializeCapabilities(const sp<Capabilities> &caps) { 246 // TRICKY: copy data to mCurrentCaps as it is a reference to 247 // an element of the capabilites map. 248 mCurrentCaps->mColorFormats.clear(); 249 mCurrentCaps->mColorFormats.appendVector(caps->mColorFormats); 250 mCurrentCaps->mProfileLevels.clear(); 251 mCurrentCaps->mProfileLevels.appendVector(caps->mProfileLevels); 252 mCurrentCaps->mFlags = caps->mFlags; 253 mCurrentCaps->mDetails = caps->mDetails; 254 return OK; 255 } 256 257 void MediaCodecInfo::addQuirk(const char *name) { 258 if (!hasQuirk(name)) { 259 mQuirks.push(name); 260 } 261 } 262 263 void MediaCodecInfo::complete() { 264 mCurrentCaps = NULL; 265 } 266 267 void MediaCodecInfo::addDetail(const AString &key, const AString &value) { 268 mCurrentCaps->mDetails->setString(key.c_str(), value.c_str()); 269 } 270 271 void MediaCodecInfo::addFeature(const AString &key, int32_t value) { 272 AString tag = "feature-"; 273 tag.append(key); 274 mCurrentCaps->mDetails->setInt32(tag.c_str(), value); 275 } 276 277 void MediaCodecInfo::addFeature(const AString &key, const char *value) { 278 AString tag = "feature-"; 279 tag.append(key); 280 mCurrentCaps->mDetails->setString(tag.c_str(), value); 281 } 282 283 } // namespace android 284