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
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 5308e1c..86ad997 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
}
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;
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index b3777d3..54f565a 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -30,6 +30,8 @@
#include <utils/Vector.h>
#include <utils/StrongPointer.h>
+#include <type_traits>
+
namespace android {
struct AMessage;
@@ -51,21 +53,47 @@
struct CapabilitiesWriter;
+ enum Attributes : int32_t {
+ // attribute flags
+ kFlagIsEncoder = 1 << 0,
+ kFlagIsVendor = 1 << 1,
+ kFlagIsSoftwareOnly = 1 << 2,
+ kFlagIsHardwareAccelerated = 1 << 3,
+ };
+
struct Capabilities : public RefBase {
- enum {
- // decoder flags
- kFlagSupportsAdaptivePlayback = 1 << 0,
- kFlagSupportsSecurePlayback = 1 << 1,
- kFlagSupportsTunneledPlayback = 1 << 2,
+ 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";
- // encoder flags
- kFlagSupportsIntraRefresh = 1 << 0,
-
- };
-
+ /**
+ * 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 @@
SortedVector<ProfileLevel> mProfileLevelsSorted;
Vector<uint32_t> mColorFormats;
SortedVector<uint32_t> mColorFormatsSorted;
- uint32_t mFlags;
sp<AMessage> mDetails;
Capabilities();
@@ -93,8 +120,7 @@
/**
* 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 {
/**
@@ -122,6 +148,13 @@
*/
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 @@
* @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,19 +185,42 @@
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.
*
* 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 @@
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
@@ -219,6 +270,13 @@
*/
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.
*
* This "owner name" is the name of the `IOmx` instance that supports this
@@ -228,32 +286,32 @@
*/
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.