You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
9.1 KiB
292 lines
9.1 KiB
/*
|
|
* 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
|