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 #include <media/stagefright/OMXCodec.h> 30 31 namespace android { 32 33 void MediaCodecInfo::Capabilities::getSupportedProfileLevels( 34 Vector<ProfileLevel> *profileLevels) const { 35 profileLevels->clear(); 36 profileLevels->appendVector(mProfileLevels); 37 } 38 39 void MediaCodecInfo::Capabilities::getSupportedColorFormats( 40 Vector<uint32_t> *colorFormats) const { 41 colorFormats->clear(); 42 colorFormats->appendVector(mColorFormats); 43 } 44 45 uint32_t MediaCodecInfo::Capabilities::getFlags() const { 46 return mFlags; 47 } 48 49 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const { 50 return mDetails; 51 } 52 53 MediaCodecInfo::Capabilities::Capabilities() 54 : mFlags(0) { 55 mDetails = new AMessage; 56 } 57 58 // static 59 sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel( 60 const Parcel &parcel) { 61 sp<MediaCodecInfo::Capabilities> caps = new Capabilities(); 62 size_t size = static_cast<size_t>(parcel.readInt32()); 63 for (size_t i = 0; i < size; i++) { 64 ProfileLevel profileLevel; 65 profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32()); 66 profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32()); 67 if (caps != NULL) { 68 caps->mProfileLevels.push_back(profileLevel); 69 } 70 } 71 size = static_cast<size_t>(parcel.readInt32()); 72 for (size_t i = 0; i < size; i++) { 73 uint32_t color = static_cast<uint32_t>(parcel.readInt32()); 74 if (caps != NULL) { 75 caps->mColorFormats.push_back(color); 76 } 77 } 78 uint32_t flags = static_cast<uint32_t>(parcel.readInt32()); 79 sp<AMessage> details = AMessage::FromParcel(parcel); 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 bool MediaCodecInfo::isEncoder() const { 105 return mIsEncoder; 106 } 107 108 bool MediaCodecInfo::hasQuirk(const char *name) const { 109 for (size_t ix = 0; ix < mQuirks.size(); ix++) { 110 if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) { 111 return true; 112 } 113 } 114 return false; 115 } 116 117 void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const { 118 mimes->clear(); 119 for (size_t ix = 0; ix < mCaps.size(); ix++) { 120 mimes->push_back(mCaps.keyAt(ix)); 121 } 122 } 123 124 const sp<MediaCodecInfo::Capabilities> 125 MediaCodecInfo::getCapabilitiesFor(const char *mime) const { 126 ssize_t ix = getCapabilityIndex(mime); 127 if (ix >= 0) { 128 return mCaps.valueAt(ix); 129 } 130 return NULL; 131 } 132 133 const char *MediaCodecInfo::getCodecName() const { 134 return mName.c_str(); 135 } 136 137 // static 138 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) { 139 AString name = AString::FromParcel(parcel); 140 bool isEncoder = static_cast<bool>(parcel.readInt32()); 141 sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL); 142 size_t size = static_cast<size_t>(parcel.readInt32()); 143 for (size_t i = 0; i < size; i++) { 144 AString quirk = AString::FromParcel(parcel); 145 if (info != NULL) { 146 info->mQuirks.push_back(quirk); 147 } 148 } 149 size = static_cast<size_t>(parcel.readInt32()); 150 for (size_t i = 0; i < size; i++) { 151 AString mime = AString::FromParcel(parcel); 152 sp<Capabilities> caps = Capabilities::FromParcel(parcel); 153 if (info != NULL) { 154 info->mCaps.add(mime, caps); 155 } 156 } 157 return info; 158 } 159 160 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const { 161 mName.writeToParcel(parcel); 162 parcel->writeInt32(mIsEncoder); 163 parcel->writeInt32(mQuirks.size()); 164 for (size_t i = 0; i < mQuirks.size(); i++) { 165 mQuirks.itemAt(i).writeToParcel(parcel); 166 } 167 parcel->writeInt32(mCaps.size()); 168 for (size_t i = 0; i < mCaps.size(); i++) { 169 mCaps.keyAt(i).writeToParcel(parcel); 170 mCaps.valueAt(i)->writeToParcel(parcel); 171 } 172 return OK; 173 } 174 175 ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const { 176 for (size_t ix = 0; ix < mCaps.size(); ix++) { 177 if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) { 178 return ix; 179 } 180 } 181 return -1; 182 } 183 184 MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime) 185 : mName(name), 186 mIsEncoder(encoder), 187 mHasSoleMime(false) { 188 if (mime != NULL) { 189 addMime(mime); 190 mHasSoleMime = true; 191 } 192 } 193 194 status_t MediaCodecInfo::addMime(const char *mime) { 195 if (mHasSoleMime) { 196 ALOGE("Codec '%s' already had its type specified", mName.c_str()); 197 return -EINVAL; 198 } 199 ssize_t ix = getCapabilityIndex(mime); 200 if (ix >= 0) { 201 mCurrentCaps = mCaps.valueAt(ix); 202 } else { 203 mCurrentCaps = new Capabilities(); 204 mCaps.add(AString(mime), mCurrentCaps); 205 } 206 return OK; 207 } 208 209 void MediaCodecInfo::removeMime(const char *mime) { 210 ssize_t ix = getCapabilityIndex(mime); 211 if (ix >= 0) { 212 mCaps.removeItemsAt(ix); 213 // mCurrentCaps will be removed when completed 214 } 215 } 216 217 status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) { 218 mCurrentCaps->mProfileLevels.clear(); 219 mCurrentCaps->mColorFormats.clear(); 220 221 for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) { 222 const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i); 223 224 ProfileLevel profileLevel; 225 profileLevel.mProfile = src.mProfile; 226 profileLevel.mLevel = src.mLevel; 227 mCurrentCaps->mProfileLevels.push_back(profileLevel); 228 } 229 230 for (size_t i = 0; i < caps.mColorFormats.size(); ++i) { 231 mCurrentCaps->mColorFormats.push_back(caps.mColorFormats.itemAt(i)); 232 } 233 234 mCurrentCaps->mFlags = caps.mFlags; 235 mCurrentCaps->mDetails = new AMessage; 236 237 return OK; 238 } 239 240 void MediaCodecInfo::addQuirk(const char *name) { 241 if (!hasQuirk(name)) { 242 mQuirks.push(name); 243 } 244 } 245 246 void MediaCodecInfo::complete() { 247 mCurrentCaps = NULL; 248 } 249 250 void MediaCodecInfo::addDetail(const AString &key, const AString &value) { 251 mCurrentCaps->mDetails->setString(key.c_str(), value.c_str()); 252 } 253 254 void MediaCodecInfo::addFeature(const AString &key, int32_t value) { 255 AString tag = "feature-"; 256 tag.append(key); 257 mCurrentCaps->mDetails->setInt32(tag.c_str(), value); 258 } 259 260 void MediaCodecInfo::addFeature(const AString &key, const char *value) { 261 AString tag = "feature-"; 262 tag.append(key); 263 mCurrentCaps->mDetails->setString(tag.c_str(), value); 264 } 265 266 } // namespace android 267