Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d4bdfd7 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

media/stagefright: add support for codec attributes in MediaCodecInfo

- Move away from int flags, and signal capabilities in info AMessage/Map
instead.
- Add more attributes (other than isEncoder).
- Parse aliases, attributes and performance points from XML
- Add plumbing for codec aliases and attributes
- Use proper 'mediaType' phrase for supported types.

Bug: 119631295
Bug: 112370870
Bug: 112374531

Change-Id: I41ea555ca26ab09be176fb96a3138043d960caa3
parent 26280682
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -409,12 +409,13 @@ public:
        kind_t kind; ///< component kind
        rank_t rank; ///< component rank
        C2String mediaType; ///< media type supported by the component
        C2String owner; ///< name of the component store owning this component

        /**
         * name alias(es) for backward compatibility.
         * \note Multiple components can have the same alias as long as their media-type differs.
         */
        std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
        std::vector<C2String> aliases; ///< name aliases for backward compatibility
    };

    // METHODS AVAILABLE WHEN RUNNING
+1 −0
Original line number Diff line number Diff line
@@ -557,6 +557,7 @@ const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
                for (size_t i = 0; i < t.size(); ++i) {
                    c2_status_t status = objcpy(
                            &mTraitsList[i], &mAliasesBuffer[i], t[i]);
                    mTraitsList[i].owner = mInstanceName;
                    if (status != C2_OK) {
                        ALOGE("listComponents -- corrupted output.");
                        return;
+75 −29
Original line number Diff line number Diff line
@@ -73,10 +73,10 @@ constexpr OMX_U32 kPortIndexOutput = 1;
constexpr OMX_U32 kMaxIndicesToCheck = 32;

status_t queryOmxCapabilities(
        const char* name, const char* mime, bool isEncoder,
        const char* name, const char* mediaType, bool isEncoder,
        MediaCodecInfo::CapabilitiesWriter* caps) {

    const char *role = GetComponentRole(isEncoder, mime);
    const char *role = GetComponentRole(isEncoder, mediaType);
    if (role == nullptr) {
        return BAD_VALUE;
    }
@@ -128,8 +128,8 @@ status_t queryOmxCapabilities(
        return err;
    }

    bool isVideo = hasPrefix(mime, "video/") == 0;
    bool isImage = hasPrefix(mime, "image/") == 0;
    bool isVideo = hasPrefix(mediaType, "video/") == 0;
    bool isImage = hasPrefix(mediaType, "image/") == 0;

    if (isVideo || isImage) {
        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
@@ -149,7 +149,7 @@ status_t queryOmxCapabilities(
            // AVC components may not list the constrained profiles explicitly, but
            // decoders that support a profile also support its constrained version.
            // Encoders must explicitly support constrained profiles.
            if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
            if (!isEncoder && strcasecmp(mediaType, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
                if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
                } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
@@ -193,7 +193,7 @@ status_t queryOmxCapabilities(
                        asString(portFormat.eColorFormat), portFormat.eColorFormat);
            }
        }
    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
    } else if (strcasecmp(mediaType, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
        // More audio codecs if they have profiles.
        OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
        InitOMXParams(&param);
@@ -228,14 +228,17 @@ status_t queryOmxCapabilities(
        if (omxNode->configureVideoTunnelMode(
                kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
            // tunneled playback includes adaptive playback
            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
        } else if (omxNode->setPortMode(
        } else {
            // tunneled playback is not supported
            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK);
            if (omxNode->setPortMode(
                    kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
                    omxNode->prepareForAdaptivePlayback(
                            kPortIndexOutput, OMX_TRUE,
                1280 /* width */, 720 /* height */) == OK) {
            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
                            1280 /* width */, 720 /* height */) != OK) {
                // adaptive playback is not supported
                caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
            }
        }
    }

@@ -243,11 +246,20 @@ status_t queryOmxCapabilities(
        OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
        InitOMXParams(&params);
        params.nPortIndex = kPortIndexOutput;
        // TODO: should we verify if fallback is supported?

        OMX_VIDEO_PARAM_INTRAREFRESHTYPE fallbackParams;
        InitOMXParams(&fallbackParams);
        fallbackParams.nPortIndex = kPortIndexOutput;
        fallbackParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;

        if (omxNode->getConfig(
                (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
                &params, sizeof(params)) == OK) {
            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
                &params, sizeof(params)) != OK &&
                omxNode->getParameter(
                    OMX_IndexParamVideoIntraRefresh, &fallbackParams,
                    sizeof(fallbackParams)) != OK) {
            // intra refresh is not supported
            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH);
        }
    }

@@ -270,12 +282,26 @@ void buildOmxInfo(const MediaCodecsXmlParser& parser,
                writer->addMediaCodecInfo();
        info->setName(name.c_str());
        info->setOwner("default");
        info->setEncoder(encoder);
        typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;
        if (encoder) {
            attrs |= MediaCodecInfo::kFlagIsEncoder;
        }
        // NOTE: we don't support software-only codecs in OMX
        if (!hasPrefix(name, "OMX.google.")) {
            attrs |= MediaCodecInfo::kFlagIsVendor;
            if (properties.quirkSet.find("attribute::software-codec")
                    == properties.quirkSet.end()) {
                attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
            }
        }
        info->setAttributes(attrs);
        info->setRank(omxRank);
        // OMX components don't have aliases
        for (const MediaCodecsXmlParser::Type &type : properties.typeMap) {
            const std::string &mime = type.first;
            const std::string &mediaType = type.first;

            std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
                    info->addMime(mime.c_str());
                    info->addMediaType(mediaType.c_str());
            const MediaCodecsXmlParser::AttributeMap &attrMap = type.second;
            for (const MediaCodecsXmlParser::Attribute& attr : attrMap) {
                const std::string &key = attr.first;
@@ -289,13 +315,13 @@ void buildOmxInfo(const MediaCodecsXmlParser& parser,
            }
            status_t err = queryOmxCapabilities(
                    name.c_str(),
                    mime.c_str(),
                    mediaType.c_str(),
                    encoder,
                    caps.get());
            if (err != OK) {
                ALOGE("Failed to query capabilities for %s (mime: %s). Error: %d",
                ALOGI("Failed to query capabilities for %s (media type: %s). Error: %d",
                        name.c_str(),
                        mime.c_str(),
                        mediaType.c_str(),
                        static_cast<int>(err));
            }
        }
@@ -407,20 +433,40 @@ status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
            break;
        }

        ALOGV("canonName = %s", canonName.c_str());
        std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
        codecInfo->setName(trait.name.c_str());
        codecInfo->setOwner("codec2");
        codecInfo->setOwner(("codec2::" + trait.owner).c_str());
        const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(canonName);

        bool encoder = trait.kind == C2Component::KIND_ENCODER;
        codecInfo->setEncoder(encoder);
        typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;

        if (encoder) {
            attrs |= MediaCodecInfo::kFlagIsEncoder;
        }
        if (trait.owner == "software") {
            attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
        } else {
            attrs |= MediaCodecInfo::kFlagIsVendor;
            if (trait.owner == "vendor-software") {
                attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
            } else if (codec.quirkSet.find("attribute::software-codec") == codec.quirkSet.end()) {
                attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
            }
        }
        codecInfo->setAttributes(attrs);
        codecInfo->setRank(rank);
        const MediaCodecsXmlParser::CodecProperties &codec =
            parser.getCodecMap().at(canonName);

        for (const std::string &alias : codec.aliases) {
            codecInfo->addAlias(alias.c_str());
        }

        for (auto typeIt = codec.typeMap.begin(); typeIt != codec.typeMap.end(); ++typeIt) {
            const std::string &mediaType = typeIt->first;
            const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
            std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
                codecInfo->addMime(mediaType.c_str());
                codecInfo->addMediaType(mediaType.c_str());
            for (auto attrIt = attrMap.begin(); attrIt != attrMap.end(); ++attrIt) {
                std::string key, value;
                std::tie(key, value) = *attrIt;
+62 −37
Original line number Diff line number Diff line
@@ -28,6 +28,15 @@

namespace android {

/** This redundant redeclaration is needed for C++ pre 14 */
constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];

void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
        Vector<ProfileLevel> *profileLevels) const {
    profileLevels->clear();
@@ -40,16 +49,11 @@ void MediaCodecInfo::Capabilities::getSupportedColorFormats(
    colorFormats->appendVector(mColorFormats);
}

uint32_t MediaCodecInfo::Capabilities::getFlags() const {
    return mFlags;
}

const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
    return mDetails;
}

MediaCodecInfo::Capabilities::Capabilities()
  : mFlags(0) {
MediaCodecInfo::Capabilities::Capabilities() {
    mDetails = new AMessage;
}

@@ -73,12 +77,10 @@ sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
            caps->mColorFormats.push_back(color);
        }
    }
    uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
    sp<AMessage> details = AMessage::FromParcel(parcel);
    if (details == NULL)
        return NULL;
    if (caps != NULL) {
        caps->mFlags = flags;
        caps->mDetails = details;
    }
    return caps;
@@ -96,7 +98,6 @@ status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
    for (size_t i = 0; i < mColorFormats.size(); i++) {
        parcel->writeInt32(mColorFormats.itemAt(i));
    }
    parcel->writeInt32(mFlags);
    mDetails->writeToParcel(parcel);
    return OK;
}
@@ -111,6 +112,14 @@ void MediaCodecInfo::CapabilitiesWriter::addDetail(
    mCap->mDetails->setInt32(key, value);
}

void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
    if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
        ALOGD("successfully removed detail %s", key);
    } else {
        ALOGD("detail %s wasn't present to remove", key);
    }
}

void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
        uint32_t profile, uint32_t level) {
    ProfileLevel profileLevel;
@@ -129,32 +138,32 @@ void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
    }
}

void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
    mCap->mFlags |= flags;
}

MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
        MediaCodecInfo::Capabilities* cap) : mCap(cap) {
}

bool MediaCodecInfo::isEncoder() const {
    return mIsEncoder;
MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
    return mAttributes;
}

uint32_t MediaCodecInfo::rank() const {
uint32_t MediaCodecInfo::getRank() const {
    return mRank;
}

void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
    mimes->clear();
void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
    *aliases = mAliases;
}

void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
    mediaTypes->clear();
    for (size_t ix = 0; ix < mCaps.size(); ix++) {
        mimes->push_back(mCaps.keyAt(ix));
        mediaTypes->push_back(mCaps.keyAt(ix));
    }
}

const sp<MediaCodecInfo::Capabilities>
MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
    ssize_t ix = getCapabilityIndex(mime);
MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
    ssize_t ix = getCapabilityIndex(mediaType);
    if (ix >= 0) {
        return mCaps.valueAt(ix);
    }
@@ -173,21 +182,26 @@ const char *MediaCodecInfo::getOwnerName() const {
sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
    AString name = AString::FromParcel(parcel);
    AString owner = AString::FromParcel(parcel);
    bool isEncoder = static_cast<bool>(parcel.readInt32());
    Attributes attributes = static_cast<Attributes>(parcel.readInt32());
    uint32_t rank = parcel.readUint32();
    sp<MediaCodecInfo> info = new MediaCodecInfo;
    info->mName = name;
    info->mOwner = owner;
    info->mIsEncoder = isEncoder;
    info->mAttributes = attributes;
    info->mRank = rank;
    size_t numAliases = static_cast<size_t>(parcel.readInt32());
    for (size_t i = 0; i < numAliases; i++) {
        AString alias = AString::FromParcel(parcel);
        info->mAliases.add(alias);
    }
    size_t size = static_cast<size_t>(parcel.readInt32());
    for (size_t i = 0; i < size; i++) {
        AString mime = AString::FromParcel(parcel);
        AString mediaType = AString::FromParcel(parcel);
        sp<Capabilities> caps = Capabilities::FromParcel(parcel);
        if (caps == NULL)
            return NULL;
        if (info != NULL) {
            info->mCaps.add(mime, caps);
            info->mCaps.add(mediaType, caps);
        }
    }
    return info;
@@ -196,8 +210,12 @@ sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
    mName.writeToParcel(parcel);
    mOwner.writeToParcel(parcel);
    parcel->writeInt32(mIsEncoder);
    parcel->writeInt32(mAttributes);
    parcel->writeUint32(mRank);
    parcel->writeInt32(mAliases.size());
    for (const AString &alias : mAliases) {
        alias.writeToParcel(parcel);
    }
    parcel->writeInt32(mCaps.size());
    for (size_t i = 0; i < mCaps.size(); i++) {
        mCaps.keyAt(i).writeToParcel(parcel);
@@ -206,10 +224,10 @@ status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
    return OK;
}

ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
    if (mime) {
ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
    if (mediaType) {
        for (size_t ix = 0; ix < mCaps.size(); ix++) {
            if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
            if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
                return ix;
            }
        }
@@ -217,19 +235,26 @@ ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
    return -1;
}

MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
MediaCodecInfo::MediaCodecInfo()
    : mAttributes((MediaCodecInfo::Attributes)0),
      mRank(0x100) {
}

void MediaCodecInfoWriter::setName(const char* name) {
    mInfo->mName = name;
}

void MediaCodecInfoWriter::addAlias(const char* name) {
    mInfo->mAliases.add(name);
}

void MediaCodecInfoWriter::setOwner(const char* owner) {
    mInfo->mOwner = owner;
}

void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
    mInfo->mIsEncoder = isEncoder;
void MediaCodecInfoWriter::setAttributes(
        typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
    mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
}

void MediaCodecInfoWriter::setRank(uint32_t rank) {
@@ -237,21 +262,21 @@ void MediaCodecInfoWriter::setRank(uint32_t rank) {
}

std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
        MediaCodecInfoWriter::addMime(const char *mime) {
    ssize_t ix = mInfo->getCapabilityIndex(mime);
        MediaCodecInfoWriter::addMediaType(const char *mediaType) {
    ssize_t ix = mInfo->getCapabilityIndex(mediaType);
    if (ix >= 0) {
        return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
                new MediaCodecInfo::CapabilitiesWriter(
                mInfo->mCaps.valueAt(ix).get()));
    }
    sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
    mInfo->mCaps.add(AString(mime), caps);
    mInfo->mCaps.add(AString(mediaType), caps);
    return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
            new MediaCodecInfo::CapabilitiesWriter(caps.get()));
}

bool MediaCodecInfoWriter::removeMime(const char *mime) {
    ssize_t ix = mInfo->getCapabilityIndex(mime);
bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
    ssize_t ix = mInfo->getCapabilityIndex(mediaType);
    if (ix >= 0) {
        mInfo->mCaps.removeItemsAt(ix);
        return true;
+100 −42
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#include <utils/Vector.h>
#include <utils/StrongPointer.h>

#include <type_traits>

namespace android {

struct AMessage;
@@ -51,21 +53,47 @@ struct MediaCodecInfo : public RefBase {

    struct CapabilitiesWriter;

    struct Capabilities : public RefBase {
        enum {
            // decoder flags
            kFlagSupportsAdaptivePlayback = 1 << 0,
            kFlagSupportsSecurePlayback = 1 << 1,
            kFlagSupportsTunneledPlayback = 1 << 2,

            // encoder flags
            kFlagSupportsIntraRefresh = 1 << 0,

    enum Attributes : int32_t {
        // attribute flags
        kFlagIsEncoder = 1 << 0,
        kFlagIsVendor = 1 << 1,
        kFlagIsSoftwareOnly = 1 << 2,
        kFlagIsHardwareAccelerated = 1 << 3,
    };

    struct Capabilities : public RefBase {
        constexpr static char FEATURE_ADAPTIVE_PLAYBACK[] = "feature-adaptive-playback";
        constexpr static char FEATURE_DYNAMIC_TIMESTAMP[] = "feature-dynamic-timestamp";
        constexpr static char FEATURE_FRAME_PARSING[] = "feature-frame-parsing";
        constexpr static char FEATURE_INTRA_REFRESH[] = "feature-frame-parsing";
        constexpr static char FEATURE_MULTIPLE_FRAMES[] = "feature-multiple-frames";
        constexpr static char FEATURE_SECURE_PLAYBACK[] = "feature-secure-playback";
        constexpr static char FEATURE_TUNNELED_PLAYBACK[] = "feature-tunneled-playback";

        /**
         * Returns the supported levels for each supported profile in a target array.
         *
         * @param profileLevels target array for the profile levels.
         */
        void getSupportedProfileLevels(Vector<ProfileLevel> *profileLevels) const;

        /**
         * Returns the supported color formats in a target array. Only used for video/image
         * components.
         *
         * @param colorFormats target array for the color formats.
         */
        void getSupportedColorFormats(Vector<uint32_t> *colorFormats) const;
        uint32_t getFlags() const;

        /**
         * Returns metadata associated with this codec capability.
         *
         * This contains:
         * - features,
         * - performance data.
         *
         * TODO: expose this as separate API-s and wrap here.
         */
        const sp<AMessage> getDetails() const;

    protected:
@@ -73,7 +101,6 @@ struct MediaCodecInfo : public RefBase {
        SortedVector<ProfileLevel> mProfileLevelsSorted;
        Vector<uint32_t> mColorFormats;
        SortedVector<uint32_t> mColorFormatsSorted;
        uint32_t mFlags;
        sp<AMessage> mDetails;

        Capabilities();
@@ -93,8 +120,7 @@ struct MediaCodecInfo : public RefBase {
    /**
     * This class is used for modifying information inside a `Capabilities`
     * object. An object of type `CapabilitiesWriter` can be obtained by calling
     * `MediaCodecInfoWriter::addMime()` or
     * `MediaCodecInfoWriter::updateMime()`.
     * `MediaCodecInfoWriter::addMediaType()`.
     */
    struct CapabilitiesWriter {
        /**
@@ -121,6 +147,13 @@ struct MediaCodecInfo : public RefBase {
         * @param value The `int32_t` value.
         */
        void addDetail(const char* key, int32_t value);
        /**
         * Removes a key-value pair from the list of details. If the key is not
         * present, this call does nothing.
         *
         * @param key The key.
         */
        void removeDetail(const char* key);
        /**
         * Add a profile-level pair. If this profile-level pair already exists,
         * it will be ignored.
@@ -136,13 +169,7 @@ struct MediaCodecInfo : public RefBase {
         * @param format The color format.
         */
        void addColorFormat(uint32_t format);
        /**
         * Add flags. The underlying operation is bitwise-or. In other words,
         * bits that have already been set will be ignored.
         *
         * @param flags The additional flags.
         */
        void addFlags(uint32_t flags);

    private:
        /**
         * The associated `Capabilities` object.
@@ -158,11 +185,27 @@ struct MediaCodecInfo : public RefBase {
        friend MediaCodecInfoWriter;
    };

    bool isEncoder() const;
    void getSupportedMimes(Vector<AString> *mimes) const;
    const sp<Capabilities> getCapabilitiesFor(const char *mime) const;
    inline bool isEncoder() const {
        return getAttributes() & kFlagIsEncoder;
    }

    Attributes getAttributes() const;
    void getSupportedMediaTypes(Vector<AString> *mediaTypes) const;
    const sp<Capabilities> getCapabilitiesFor(const char *mediaType) const;
    const char *getCodecName() const;

    /**
     * Returns a vector containing alternate names for the codec.
     *
     * \param aliases the destination array for the aliases. This is cleared.
     *
     * Multiple codecs may share alternate names as long as their supported media types are
     * distinct; however, these will result in different aliases for the MediaCodec user as
     * the canonical codec has to be resolved without knowing the media type in
     * MediaCodec::CreateByComponentName.
     */
    void getAliases(Vector<AString> *aliases) const;

    /**
     * Return the name of the service that hosts the codec. This value is not
     * visible at the Java level.
@@ -170,7 +213,14 @@ struct MediaCodecInfo : public RefBase {
     * Currently, this is the "instance name" of the IOmx service.
     */
    const char *getOwnerName() const;
    uint32_t rank() const;

    /**
     * Returns the rank of the component.
     *
     * Technically this is defined to be per media type, but that makes ordering the MediaCodecList
     * impossible as MediaCodecList is ordered by codec name.
     */
    uint32_t getRank() const;

    /**
     * Serialization over Binder
@@ -181,11 +231,12 @@ struct MediaCodecInfo : public RefBase {
private:
    AString mName;
    AString mOwner;
    bool mIsEncoder;
    Attributes mAttributes;
    KeyedVector<AString, sp<Capabilities> > mCaps;
    Vector<AString> mAliases;
    uint32_t mRank;

    ssize_t getCapabilityIndex(const char *mime) const;
    ssize_t getCapabilityIndex(const char *mediaType) const;

    /**
     * Construct an `MediaCodecInfo` object. After the construction, its
@@ -218,6 +269,13 @@ struct MediaCodecInfoWriter {
     * @param name The new name.
     */
    void setName(const char* name);
    /**
     * Adds an alias (alternate name) for the codec. Multiple codecs can share an alternate name
     * as long as their supported media types are distinct.
     *
     * @param name an alternate name.
     */
    void addAlias(const char* name);
    /**
     * Set the owner name of the codec.
     *
@@ -228,32 +286,32 @@ struct MediaCodecInfoWriter {
     */
    void setOwner(const char* owner);
    /**
     * Set whether this codec is an encoder or a decoder.
     * Sets codec attributes.
     *
     * @param isEncoder Whether this codec is an encoder or a decoder.
     * @param attributes Codec attributes.
     */
    void setEncoder(bool isEncoder = true);
    void setAttributes(typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes);
    /**
     * Add a mime to an indexed list and return a `CapabilitiesWriter` object
     * Add a media type to an indexed list and return a `CapabilitiesWriter` object
     * that can be used for modifying the associated `Capabilities`.
     *
     * If the mime already exists, this function will return the
     * `CapabilitiesWriter` associated with the mime.
     * If the media type already exists, this function will return the
     * `CapabilitiesWriter` associated with the media type.
     *
     * @param[in] mime The name of a new mime to add.
     * @param[in] mediaType The name of a new media type to add.
     * @return writer The `CapabilitiesWriter` object for modifying the
     * `Capabilities` associated with the mime. `writer` will be valid
     * regardless of whether `mime` already exists or not.
     * `Capabilities` associated with the media type. `writer` will be valid
     * regardless of whether `mediaType` already exists or not.
     */
    std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMime(
            const char* mime);
    std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMediaType(
            const char* mediaType);
    /**
     * Remove a mime.
     * Remove a media type.
     *
     * @param mime The name of the mime to remove.
     * @return `true` if `mime` is removed; `false` if `mime` is not found.
     * @param mediaType The name of the media type to remove.
     * @return `true` if `mediaType` is removed; `false` if `mediaType` is not found.
     */
    bool removeMime(const char* mime);
    bool removeMediaType(const char* mediaType);
    /**
     * Set rank of the codec. MediaCodecList will stable-sort the list according
     * to rank in non-descending order.
Loading