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