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