MediaCodecInfo.cpp revision 732c6d955524ead6c31e6e1bafbd41ea4cee525d
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 31namespace android { 32 33void MediaCodecInfo::Capabilities::getSupportedProfileLevels( 34 Vector<ProfileLevel> *profileLevels) const { 35 profileLevels->clear(); 36 profileLevels->appendVector(mProfileLevels); 37} 38 39void MediaCodecInfo::Capabilities::getSupportedColorFormats( 40 Vector<uint32_t> *colorFormats) const { 41 colorFormats->clear(); 42 colorFormats->appendVector(mColorFormats); 43} 44 45uint32_t MediaCodecInfo::Capabilities::getFlags() const { 46 return mFlags; 47} 48 49const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const { 50 return mDetails; 51} 52 53MediaCodecInfo::Capabilities::Capabilities() 54 : mFlags(0) { 55 mDetails = new AMessage; 56} 57 58// static 59sp<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 87status_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 104bool MediaCodecInfo::isEncoder() const { 105 return mIsEncoder; 106} 107 108bool 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 117void 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 124const sp<MediaCodecInfo::Capabilities> 125MediaCodecInfo::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 133const char *MediaCodecInfo::getCodecName() const { 134 return mName.c_str(); 135} 136 137// static 138sp<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 160status_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 175ssize_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 184MediaCodecInfo::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 194status_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 209void 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 217status_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 240void MediaCodecInfo::addQuirk(const char *name) { 241 if (!hasQuirk(name)) { 242 mQuirks.push(name); 243 } 244} 245 246void MediaCodecInfo::complete() { 247 mCurrentCaps = NULL; 248} 249 250void MediaCodecInfo::addDetail(const AString &key, const AString &value) { 251 mCurrentCaps->mDetails->setString(key.c_str(), value.c_str()); 252} 253 254void 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 260void 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