Merge changes from topic "revert-3368981-revert-3341640-fix-b-364310317-fix-ANAPIC-comments-3-SRPURNABEL-ZMHYKOWFUK" into main
* changes:
Revert^2 "Audio CAP: Address ANAPIC comments, Part 3 (example & tools)."
Revert^2 "Audio CAP: Address ANAPIC comments, Part 3."
Revert^2 "Audio CAP: Address ANAPIC comments, Part 3 (Split back AudioPolicyForceUse)"
diff --git a/media/codec2/components/apv/C2SoftApvEnc.cpp b/media/codec2/components/apv/C2SoftApvEnc.cpp
index d6a9597..9c5e0b2 100644
--- a/media/codec2/components/apv/C2SoftApvEnc.cpp
+++ b/media/codec2/components/apv/C2SoftApvEnc.cpp
@@ -958,108 +958,98 @@
finish(workIndex, fillWork);
}
}
-void C2SoftApvEnc::createCsdData(const std::unique_ptr<C2Work>& work, oapv_bitb_t* bitb,
- uint32_t encodedSize) {
- uint32_t csdStart = 0, csdEnd = 0;
- uint32_t bitOffset = 0;
- uint8_t* buf = (uint8_t*)bitb->addr + csdStart;
- if (encodedSize == 0) {
- ALOGE("the first frame size is zero, so no csd data will be created.");
+void C2SoftApvEnc::createCsdData(const std::unique_ptr<C2Work>& work,
+ oapv_bitb_t* bitb,
+ uint32_t encodedSize) {
+ if (encodedSize < 31) {
+ ALOGE("the first frame size is too small, so no csd data will be created.");
return;
}
- ABitReader reader(buf, encodedSize);
+ ABitReader reader((uint8_t*)bitb->addr, encodedSize);
+
+ uint8_t number_of_configuration_entry = 0;
+ uint8_t pbu_type = 0;
+ uint8_t number_of_frame_info = 0;
+ bool color_description_present_flag = false;
+ bool capture_time_distance_ignored = false;
+ uint8_t profile_idc = 0;
+ uint8_t level_idc = 0;
+ uint8_t band_idc = 0;
+ uint32_t frame_width_minus1 = 0;
+ uint32_t frame_height_minus1 = 0;
+ uint8_t chroma_format_idc = 0;
+ uint8_t bit_depth_minus8 = 0;
+ uint8_t capture_time_distance = 0;
+ uint8_t color_primaries = 0;
+ uint8_t transfer_characteristics = 0;
+ uint8_t matrix_coefficients = 0;
/* pbu_header() */
- reader.skipBits(32);
- bitOffset += 32; // pbu_size
- reader.skipBits(32);
- bitOffset += 32; // currReadSize
- csdStart = bitOffset / 8;
-
- int32_t pbu_type = reader.getBits(8);
- bitOffset += 8; // pbu_type
- reader.skipBits(16);
- bitOffset += 16; // group_id
- reader.skipBits(8);
- bitOffset += 8; // reserved_zero_8bits
+ reader.skipBits(32); // pbu_size
+ reader.skipBits(32); // currReadSize
+ pbu_type = reader.getBits(8); // pbu_type
+ reader.skipBits(16); // group_id
+ reader.skipBits(8); // reserved_zero_8bits
/* frame info() */
- int32_t profile_idc = reader.getBits(8);
- bitOffset += 8; // profile_idc
- int32_t level_idc = reader.getBits(8);
- bitOffset += 8; // level_idc
- int32_t band_idc = reader.getBits(3);
- bitOffset += 3; // band_idc
- reader.skipBits(5);
- bitOffset += 5; // reserved_zero_5bits
- int32_t width = reader.getBits(32);
- bitOffset += 32; // width
- int32_t height = reader.getBits(32);
- bitOffset += 32; // height
- int32_t chroma_idc = reader.getBits(4);
- bitOffset += 4; // chroma_format_idc
- reader.skipBits(4);
- bitOffset += 4; // bit_depth
- reader.skipBits(8);
- bitOffset += 8; // capture_time_distance
- reader.skipBits(8);
- bitOffset += 8; // reserved_zero_8bits
+ profile_idc = reader.getBits(8); // profile_idc
+ level_idc = reader.getBits(8); // level_idc
+ band_idc = reader.getBits(3); // band_idc
+ reader.skipBits(5); // reserved_zero_5bits
+ frame_width_minus1 = reader.getBits(32); // width
+ frame_height_minus1 = reader.getBits(32); // height
+ chroma_format_idc = reader.getBits(4); // chroma_format_idc
+ bit_depth_minus8 = reader.getBits(4); // bit_depth
+ capture_time_distance = reader.getBits(8); // capture_time_distance
+ reader.skipBits(8); // reserved_zero_8bits
/* frame header() */
- reader.skipBits(8);
- bitOffset += 8; // reserved_zero_8bit
- bool color_description_present_flag = reader.getBits(1);
- bitOffset += 1; // color_description_present_flag
+ reader.skipBits(8); // reserved_zero_8bit
+ color_description_present_flag = reader.getBits(1); // color_description_present_flag
if (color_description_present_flag) {
- reader.skipBits(8);
- bitOffset += 8; // color_primaries
- reader.skipBits(8);
- bitOffset += 8; // transfer_characteristics
- reader.skipBits(8);
- bitOffset += 8; // matrix_coefficients
- }
- bool use_q_matrix = reader.getBits(1);
- bitOffset += 1; // use_q_matrix
- if (use_q_matrix) {
- /* quantization_matrix() */
- int32_t numComp = chroma_idc == 0 ? 1
- : chroma_idc == 2 ? 3
- : chroma_idc == 3 ? 3
- : chroma_idc == 4 ? 4
- : -1;
- int32_t needBitsForQ = 64 * 8 * numComp;
- reader.skipBits(needBitsForQ);
- bitOffset += needBitsForQ;
+ color_primaries = reader.getBits(8); // color_primaries
+ transfer_characteristics = reader.getBits(8); // transfer_characteristics
+ matrix_coefficients = reader.getBits(8); // matrix_coefficients
}
- /* tile_info() */
- int32_t tile_width_in_mbs_minus1 = reader.getBits(28);
- bitOffset += 28;
- int32_t tile_height_in_mbs_minus1 = reader.getBits(28);
- bitOffset += 28;
- bool tile_size_present_in_fh_flag = reader.getBits(1);
- bitOffset += 1;
- if (tile_size_present_in_fh_flag) {
- int32_t numTiles = ceil((double)width / (double)tile_width_in_mbs_minus1) *
- ceil((double)height / (double)tile_height_in_mbs_minus1);
- reader.skipBits(32 * numTiles);
- bitOffset += (32 * numTiles);
- }
+ number_of_configuration_entry = 1; // The real-time encoding on the device is assumed to be 1.
+ number_of_frame_info = 1; // The real-time encoding on the device is assumed to be 1.
- reader.skipBits(8);
- bitOffset += 8; // reserved_zero_8bits
+ std::vector<uint8_t> csdData;
+ csdData.push_back((uint8_t)0x1);
+ csdData.push_back(number_of_configuration_entry);
- /* byte_alignmenet() */
- while (bitOffset % 8) {
- reader.skipBits(1);
- bitOffset += 1;
+ for (uint8_t i = 0; i < number_of_configuration_entry; i++) {
+ csdData.push_back(pbu_type);
+ csdData.push_back(number_of_frame_info);
+ for (uint8_t j = 0; j < number_of_frame_info; j++) {
+ csdData.push_back((uint8_t)((color_description_present_flag << 1) |
+ capture_time_distance_ignored));
+ csdData.push_back(profile_idc);
+ csdData.push_back(level_idc);
+ csdData.push_back(band_idc);
+ csdData.push_back((uint8_t)((frame_width_minus1 >> 24) & 0xff));
+ csdData.push_back((uint8_t)((frame_width_minus1 >> 16) & 0xff));
+ csdData.push_back((uint8_t)((frame_width_minus1 >> 8) & 0xff));
+ csdData.push_back((uint8_t)(frame_width_minus1 & 0xff));
+ csdData.push_back((uint8_t)((frame_height_minus1 >> 24) & 0xff));
+ csdData.push_back((uint8_t)((frame_height_minus1 >> 16) & 0xff));
+ csdData.push_back((uint8_t)((frame_height_minus1 >> 8) & 0xff));
+ csdData.push_back((uint8_t)(frame_height_minus1 & 0xff));
+ csdData.push_back((uint8_t)(((chroma_format_idc << 4) & 0xf0) |
+ (bit_depth_minus8 & 0xf)));
+ csdData.push_back((uint8_t)(capture_time_distance));
+ if (color_description_present_flag) {
+ csdData.push_back(color_primaries);
+ csdData.push_back(transfer_characteristics);
+ csdData.push_back(matrix_coefficients);
+ }
+ }
}
- csdEnd = bitOffset / 8;
- int32_t csdSize = csdEnd - csdStart + 1;
std::unique_ptr<C2StreamInitDataInfo::output> csd =
- C2StreamInitDataInfo::output::AllocUnique(csdSize, 0u);
+ C2StreamInitDataInfo::output::AllocUnique(csdData.size(), 0u);
if (!csd) {
ALOGE("CSD allocation failed");
mSignalledError = true;
@@ -1068,10 +1058,10 @@
return;
}
- buf = buf + csdStart;
- memcpy(csd->m.value, buf, csdSize);
+ memcpy(csd->m.value, csdData.data(), csdData.size());
work->worklets.front()->output.configUpdate.push_back(std::move(csd));
}
+
c2_status_t C2SoftApvEnc::drainInternal(uint32_t drainMode,
const std::shared_ptr<C2BlockPool>& pool,
const std::unique_ptr<C2Work>& work) {
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 069d6ad..fa5ce77 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -70,6 +70,7 @@
enum platform_level_t : uint32_t; ///< platform level
enum prepend_header_mode_t : uint32_t; ///< prepend header operational modes
enum profile_t : uint32_t; ///< coding profile
+ enum resource_kind_t : uint32_t; ///< resource kinds
enum scaling_method_t : uint32_t; ///< scaling methods
enum scan_order_t : uint32_t; ///< scan orders
enum secure_mode_t : uint32_t; ///< secure/protected modes
@@ -101,6 +102,7 @@
kParamIndexMasteringDisplayColorVolume,
kParamIndexChromaOffset,
kParamIndexGopLayer,
+ kParamIndexSystemResource,
/* =================================== parameter indices =================================== */
@@ -167,6 +169,10 @@
/* Region of Interest Encoding parameters */
kParamIndexQpOffsetMapBuffer, // info-buffer, used to signal qp-offset map for a frame
+ /* resource capacity and resources excluded */
+ kParamIndexResourcesCapacity,
+ kParamIndexResourcesExcluded,
+
// deprecated
kParamIndexDelayRequest = kParamIndexDelay | C2Param::CoreIndex::IS_REQUEST_FLAG,
@@ -1257,21 +1263,114 @@
/* ----------------------------------------- resources ----------------------------------------- */
/**
- * Resources needed and resources reserved for current configuration.
- *
- * Resources are tracked as a vector of positive numbers. Available resources are defined by
- * the vendor.
- *
- * By default, no resources are reserved for a component. If resource reservation is successful,
- * the component shall be able to use those resources exclusively. If however, the component is
- * not using all of the reserved resources, those may be shared with other components.
- *
- * TODO: define some of the resources.
+ * Resource kind.
*/
-typedef C2GlobalParam<C2Tuning, C2Uint64Array, kParamIndexResourcesNeeded> C2ResourcesNeededTuning;
-typedef C2GlobalParam<C2Tuning, C2Uint64Array, kParamIndexResourcesReserved>
- C2ResourcesReservedTuning;
+C2ENUM(C2Config::resource_kind_t, uint32_t,
+ CONST,
+ PER_FRAME,
+ PER_INPUT_BLOCK,
+ PER_OUTPUT_BLOCK
+)
+
+/**
+ * Definition of a system resource use.
+ *
+ * [PROPOSED]
+ *
+ * System resources are defined by the default component store.
+ * They represent any physical or abstract entities of limited availability
+ * that is required for a component instance to execute and process work.
+ *
+ * Each defined resource has an id.
+ * The use of a resource is specified by the amount and the kind (e.g. whether the amount
+ * of resources is required for each frame processed, or whether they are required
+ * regardless of the processing rate (const amount)).
+ *
+ * Note: implementations can shadow this structure with their own custom resource
+ * structure where a uint32_t based enum is used for id.
+ * This can be used to provide a name for each resource, via parameter descriptors.
+ */
+
+struct C2SystemResourceStruct {
+ C2SystemResourceStruct(uint32_t id_,
+ C2Config::resource_kind_t kind_,
+ uint64_t amount_)
+ : id(id_), kind(kind_), amount(amount_) { }
+ uint32_t id;
+ C2Config::resource_kind_t kind;
+ uint64_t amount;
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(SystemResource)
+ C2FIELD(id, "id")
+ C2FIELD(kind, "kind")
+ C2FIELD(amount, "amount")
+};
+
+/**
+ * Total system resource capacity.
+ *
+ * [PROPOSED]
+ *
+ * This setting is implemented by the default component store.
+ * The total resource capacity is specified as the maximum amount for each resource ID
+ * that is supported by the device hardware or firmware.
+ * As such, the kind must be CONST for each element.
+ */
+typedef C2GlobalParam<C2Tuning,
+ C2SimpleArrayStruct<C2SystemResourceStruct>,
+ kParamIndexResourcesCapacity> C2ResourcesCapacityTuning;
+constexpr char C2_PARAMKEY_RESOURCES_CAPACITY[] = "resources.capacity";
+
+/**
+ * Excluded system resources.
+ *
+ * [PROPOSED]
+ *
+ * This setting is implemented by the default component store.
+ * Some system resources may be used by components and not tracked by the Codec 2.0 API.
+ * This is communicated by this tuning.
+ * Excluded resources are the total resources that are used by non-Codec 2.0 components.
+ * It is specified as the excluded amount for each resource ID that is used by
+ * a non-Codec 2.0 component. As such, the kind must be CONST for each element.
+ *
+ * The platform can calculate the available resources as total capacity minus
+ * excluded resource minus sum of needed resources for each component.
+ */
+typedef C2GlobalParam<C2Tuning,
+ C2SimpleArrayStruct<C2SystemResourceStruct>,
+ kParamIndexResourcesExcluded> C2ResourcesExcludedTuning;
+constexpr char C2_PARAMKEY_RESOURCES_EXCLUDED[] = "resources.excluded";
+
+/**
+ * System resources needed for the current configuration.
+ *
+ * [PROPOSED]
+ *
+ * Resources are tracked as a list of individual resource use specifications.
+ * The resource kind can be CONST, PER_FRAME, PER_INPUT_BLODCK or PER_OUTPUT_BLOCK.
+ */
+typedef C2GlobalParam<C2Tuning,
+ C2SimpleArrayStruct<C2SystemResourceStruct>,
+ kParamIndexResourcesNeeded> C2ResourcesNeededTuning;
constexpr char C2_PARAMKEY_RESOURCES_NEEDED[] = "resources.needed";
+
+/**
+ * System resources reserved for this component
+ *
+ * [FUTURE]
+ *
+ * This allows the platform to set aside system resources for the component.
+ * Since this is a static resource reservation, kind must be CONST for each element.
+ * This resource reservation only considers CONST and PER_FRAME use.
+ *
+ * By default, no resources are reserved for a component.
+ * If resource reservation is successful, the component shall be able to use those
+ * resources exclusively. If however, the component is not using all of the
+ * reserved resources, those may be shared with other components.
+ */
+typedef C2GlobalParam<C2Tuning,
+ C2SimpleArrayStruct<C2SystemResourceStruct>,
+ kParamIndexResourcesReserved> C2ResourcesReservedTuning;
constexpr char C2_PARAMKEY_RESOURCES_RESERVED[] = "resources.reserved";
/**
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index fd242a1..0f5cdd6 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -16,6 +16,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2InfoBuilder"
+
+#include <cstdlib>
+
#include <log/log.h>
#include <strings.h>
@@ -508,6 +511,10 @@
&& !hasPrefix(v.first, "domain-")
&& !hasPrefix(v.first, "variant-")) {
writer->addGlobalSetting(v.first.c_str(), v.second.c_str());
+ if (v.first == "max-concurrent-instances") {
+ MediaCodecInfoWriter::SetMaxSupportedInstances(
+ (int32_t)strtol(v.second.c_str(), NULL, 10));
+ }
}
}
@@ -797,6 +804,7 @@
}
}
}
+ codecInfo->createCodecCaps();
}
}
return OK;
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index d5d1a09..3834278 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -26,6 +26,9 @@
namespace android {
+// initialize max supported instances with default value.
+int32_t MediaCodecInfo::sMaxSupportedInstances = 0;
+
/** This redundant redeclaration is needed for C++ pre 14 */
constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
@@ -169,6 +172,15 @@
return NULL;
}
+const std::shared_ptr<CodecCapabilities> MediaCodecInfo::getCodecCapsFor(
+ const char *mediaType) const {
+ ssize_t ix = getCodecCapIndex(mediaType);
+ if (ix >= 0) {
+ return mCodecCaps.valueAt(ix);
+ }
+ return nullptr;
+}
+
const char *MediaCodecInfo::getCodecName() const {
return mName.c_str();
}
@@ -179,6 +191,7 @@
// static
sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
+ sMaxSupportedInstances = parcel.readInt32();
AString name = AString::FromParcel(parcel);
AString owner = AString::FromParcel(parcel);
Attributes attributes = static_cast<Attributes>(parcel.readInt32());
@@ -201,12 +214,17 @@
return NULL;
if (info != NULL) {
info->mCaps.add(mediaType, caps);
+ std::shared_ptr<CodecCapabilities> codecCaps
+ = MediaCodecInfoWriter::BuildCodecCapabilities(
+ mediaType.c_str(), caps, info->isEncoder());
+ info->mCodecCaps.add(mediaType, codecCaps);
}
}
return info;
}
status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(sMaxSupportedInstances);
mName.writeToParcel(parcel);
mOwner.writeToParcel(parcel);
parcel->writeInt32(mAttributes);
@@ -234,6 +252,25 @@
return -1;
}
+ssize_t MediaCodecInfo::getCodecCapIndex(const char *mediaType) const {
+ if (mediaType == nullptr) {
+ return -1;
+ }
+
+ if (mCodecCaps.size() != mCaps.size()) {
+ ALOGE("Size of mCodecCaps and mCaps do not match, which are %zu and %zu",
+ mCodecCaps.size(), mCaps.size());
+ }
+
+ for (size_t ix = 0; ix < mCodecCaps.size(); ix++) {
+ if (mCodecCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
+ return ix;
+ }
+ }
+
+ return -1;
+}
+
MediaCodecInfo::MediaCodecInfo()
: mAttributes((MediaCodecInfo::Attributes)0),
mRank(0x100) {
@@ -283,6 +320,52 @@
return false;
}
+void MediaCodecInfoWriter::createCodecCaps() {
+ mInfo->mCodecCaps.clear();
+ for (size_t ix = 0; ix < mInfo->mCaps.size(); ix++) {
+ AString mediaType = mInfo->mCaps.keyAt(ix);
+ sp<MediaCodecInfo::Capabilities> caps = mInfo->mCaps.valueAt(ix);
+ mInfo->mCodecCaps.add(mediaType,
+ BuildCodecCapabilities(mediaType.c_str(), caps, mInfo->isEncoder(),
+ MediaCodecInfo::sMaxSupportedInstances));
+ }
+}
+
+// static
+std::shared_ptr<CodecCapabilities> MediaCodecInfoWriter::BuildCodecCapabilities(
+ const char *mediaType, sp<MediaCodecInfo::Capabilities> caps, bool isEncoder,
+ int32_t maxSupportedInstances) {
+ Vector<ProfileLevel> profileLevels_;
+ Vector<uint32_t> colorFormats_;
+ caps->getSupportedProfileLevels(&profileLevels_);
+ caps->getSupportedColorFormats(&colorFormats_);
+
+ std::vector<ProfileLevel> profileLevels;
+ std::vector<uint32_t> colorFormats;
+ for (ProfileLevel pl : profileLevels_) {
+ profileLevels.push_back(pl);
+ }
+ for (uint32_t cf : colorFormats_) {
+ colorFormats.push_back(cf);
+ }
+
+ sp<AMessage> defaultFormat = new AMessage();
+ defaultFormat->setString("mime", mediaType);
+
+ sp<AMessage> capabilitiesInfo = caps->getDetails();
+
+ std::shared_ptr<CodecCapabilities> codecCaps = std::make_shared<CodecCapabilities>();
+ codecCaps->init(profileLevels, colorFormats, isEncoder, defaultFormat,
+ capabilitiesInfo, maxSupportedInstances);
+
+ return codecCaps;
+}
+
+// static
+void MediaCodecInfoWriter::SetMaxSupportedInstances(int32_t maxSupportedInstances) {
+ MediaCodecInfo::sMaxSupportedInstances = maxSupportedInstances;
+}
+
MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
mInfo(info) {
}
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index 72aca98..60e383a 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -192,6 +192,7 @@
Attributes getAttributes() const;
void getSupportedMediaTypes(Vector<AString> *mediaTypes) const;
const sp<Capabilities> getCapabilitiesFor(const char *mediaType) const;
+ const std::shared_ptr<CodecCapabilities> getCodecCapsFor(const char *mediaType) const;
const char *getCodecName() const;
/**
@@ -229,14 +230,21 @@
status_t writeToParcel(Parcel *parcel) const;
private:
+ /**
+ * Max supported instances setting from MediaCodecList global setting.
+ */
+ static int32_t sMaxSupportedInstances;
+
AString mName;
AString mOwner;
Attributes mAttributes;
KeyedVector<AString, sp<Capabilities> > mCaps;
+ KeyedVector<AString, std::shared_ptr<CodecCapabilities>> mCodecCaps;
Vector<AString> mAliases;
uint32_t mRank;
ssize_t getCapabilityIndex(const char *mediaType) const;
+ ssize_t getCodecCapIndex(const char *mediaType) const;
/**
* Construct an `MediaCodecInfo` object. After the construction, its
@@ -264,6 +272,15 @@
*/
struct MediaCodecInfoWriter {
/**
+ * Get CodecCapabilities from Capabilities.
+ */
+ static std::shared_ptr<CodecCapabilities> BuildCodecCapabilities(const char *mediaType,
+ sp<MediaCodecInfo::Capabilities> caps, bool isEncoder, int maxSupportedInstances = 0);
+ /**
+ * Set the max supported instances global setting from MediaCodecList.
+ */
+ static void SetMaxSupportedInstances(int32_t maxSupportedInstances);
+ /**
* Set the name of the codec.
*
* @param name The new name.
@@ -319,6 +336,10 @@
* @param rank The rank of the component.
*/
void setRank(uint32_t rank);
+ /**
+ * Create CodecCapabilities map from Capabilities.
+ */
+ void createCodecCaps();
private:
/**
* The associated `MediaCodecInfo`.
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 79ffdeb..1cb8f14 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -21,6 +21,8 @@
#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
#endif
+#include <cstdlib>
+
#include <android-base/properties.h>
#include <utils/Log.h>
@@ -131,6 +133,10 @@
for (const auto& p : serviceAttributes) {
writer->addGlobalSetting(
p.key.c_str(), p.value.c_str());
+ if (p.key == "max-concurrent-instances") {
+ MediaCodecInfoWriter::SetMaxSupportedInstances(
+ (int32_t)strtol(p.value.c_str(), NULL, 10));
+ }
}
// Convert roles to lists of codecs
@@ -217,6 +223,8 @@
ALOGW("Fail to add media type %s to codec %s",
typeName.c_str(), nodeName.c_str());
info->removeMediaType(typeName.c_str());
+ } else {
+ info->createCodecCaps();
}
}
}