Home | History | Annotate | Download | only in libmedia
      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