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 namespace android {
     30 
     31 void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
     32         Vector<ProfileLevel> *profileLevels) const {
     33     profileLevels->clear();
     34     profileLevels->appendVector(mProfileLevels);
     35 }
     36 
     37 void MediaCodecInfo::Capabilities::getSupportedColorFormats(
     38         Vector<uint32_t> *colorFormats) const {
     39     colorFormats->clear();
     40     colorFormats->appendVector(mColorFormats);
     41 }
     42 
     43 uint32_t MediaCodecInfo::Capabilities::getFlags() const {
     44     return mFlags;
     45 }
     46 
     47 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
     48     return mDetails;
     49 }
     50 
     51 MediaCodecInfo::Capabilities::Capabilities()
     52   : mFlags(0) {
     53     mDetails = new AMessage;
     54 }
     55 
     56 // static
     57 sp<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 
     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 void 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 
    111 void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) {
    112     mColorFormats.push(format);
    113 }
    114 
    115 void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) {
    116     mFlags |= flags;
    117 }
    118 
    119 bool MediaCodecInfo::isEncoder() const {
    120     return mIsEncoder;
    121 }
    122 
    123 bool 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 
    134 void 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 
    141 const sp<MediaCodecInfo::Capabilities>
    142 MediaCodecInfo::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 
    150 const char *MediaCodecInfo::getCodecName() const {
    151     return mName.c_str();
    152 }
    153 
    154 // static
    155 sp<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 
    179 status_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 
    194 ssize_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 
    205 MediaCodecInfo::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 
    215 status_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 
    230 status_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 
    241 void 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 
    249 status_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 
    261 void MediaCodecInfo::addQuirk(const char *name) {
    262     if (!hasQuirk(name)) {
    263         mQuirks.push(name);
    264     }
    265 }
    266 
    267 void MediaCodecInfo::complete() {
    268     mCurrentCaps = NULL;
    269 }
    270 
    271 void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
    272     mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
    273 }
    274 
    275 void 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 
    281 void 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