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