/* * Copyright 2014, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaCodecInfo" #include <utils/Log.h> #include <media/IOMX.h> #include <media/MediaCodecInfo.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <binder/Parcel.h> 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(); profileLevels->appendVector(mProfileLevels); } void MediaCodecInfo::Capabilities::getSupportedColorFormats( Vector<uint32_t> *colorFormats) const { colorFormats->clear(); colorFormats->appendVector(mColorFormats); } const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const { return mDetails; } MediaCodecInfo::Capabilities::Capabilities() { mDetails = new AMessage; } // static sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel( const Parcel &parcel) { sp<MediaCodecInfo::Capabilities> caps = new Capabilities(); size_t size = static_cast<size_t>(parcel.readInt32()); for (size_t i = 0; i < size; i++) { ProfileLevel profileLevel; profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32()); profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32()); if (caps != NULL) { caps->mProfileLevels.push_back(profileLevel); } } size = static_cast<size_t>(parcel.readInt32()); for (size_t i = 0; i < size; i++) { uint32_t color = static_cast<uint32_t>(parcel.readInt32()); if (caps != NULL) { caps->mColorFormats.push_back(color); } } sp<AMessage> details = AMessage::FromParcel(parcel); if (details == NULL) return NULL; if (caps != NULL) { caps->mDetails = details; } return caps; } status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { CHECK_LE(mProfileLevels.size(), static_cast<size_t>(INT32_MAX)); parcel->writeInt32(mProfileLevels.size()); for (size_t i = 0; i < mProfileLevels.size(); i++) { parcel->writeInt32(mProfileLevels.itemAt(i).mProfile); parcel->writeInt32(mProfileLevels.itemAt(i).mLevel); } CHECK_LE(mColorFormats.size(), static_cast<size_t>(INT32_MAX)); parcel->writeInt32(mColorFormats.size()); for (size_t i = 0; i < mColorFormats.size(); i++) { parcel->writeInt32(mColorFormats.itemAt(i)); } mDetails->writeToParcel(parcel); return OK; } void MediaCodecInfo::CapabilitiesWriter::addDetail( const char* key, const char* value) { mCap->mDetails->setString(key, value); } void MediaCodecInfo::CapabilitiesWriter::addDetail( const char* key, int32_t value) { 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; profileLevel.mProfile = profile; profileLevel.mLevel = level; if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) { mCap->mProfileLevels.push_back(profileLevel); mCap->mProfileLevelsSorted.add(profileLevel); } } void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) { if (mCap->mColorFormatsSorted.indexOf(format) < 0) { mCap->mColorFormats.push(format); mCap->mColorFormatsSorted.add(format); } } MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter( MediaCodecInfo::Capabilities* cap) : mCap(cap) { } MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const { return mAttributes; } uint32_t MediaCodecInfo::getRank() const { return mRank; } 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++) { mediaTypes->push_back(mCaps.keyAt(ix)); } } const sp<MediaCodecInfo::Capabilities> MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const { ssize_t ix = getCapabilityIndex(mediaType); if (ix >= 0) { return mCaps.valueAt(ix); } return NULL; } const char *MediaCodecInfo::getCodecName() const { return mName.c_str(); } const char *MediaCodecInfo::getOwnerName() const { return mOwner.c_str(); } // static sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) { AString name = AString::FromParcel(parcel); AString owner = AString::FromParcel(parcel); Attributes attributes = static_cast<Attributes>(parcel.readInt32()); uint32_t rank = parcel.readUint32(); sp<MediaCodecInfo> info = new MediaCodecInfo; info->mName = name; info->mOwner = owner; 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 mediaType = AString::FromParcel(parcel); sp<Capabilities> caps = Capabilities::FromParcel(parcel); if (caps == NULL) return NULL; if (info != NULL) { info->mCaps.add(mediaType, caps); } } return info; } status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const { mName.writeToParcel(parcel); mOwner.writeToParcel(parcel); 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); mCaps.valueAt(i)->writeToParcel(parcel); } return OK; } ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const { if (mediaType) { for (size_t ix = 0; ix < mCaps.size(); ix++) { if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) { return ix; } } } return -1; } 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::setAttributes( typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) { mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes; } void MediaCodecInfoWriter::setRank(uint32_t rank) { mInfo->mRank = rank; } std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> 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(mediaType), caps); return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>( new MediaCodecInfo::CapabilitiesWriter(caps.get())); } bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) { ssize_t ix = mInfo->getCapabilityIndex(mediaType); if (ix >= 0) { mInfo->mCaps.removeItemsAt(ix); return true; } return false; } MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) : mInfo(info) { } } // namespace android