Make change and version bump to r_aml_300801400 for mainline module file: apex/manifest_codec.json
Change-Id: I1df760de5013795cb95a1e7b74a90276854d5100
diff --git a/apex/manifest.json b/apex/manifest.json
index 4a874d1..a3684cf 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media",
- "version": 300801300
+ "version": 300801400
}
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 1189cdb..faf529f 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media.swcodec",
- "version": 300801300
+ "version": 300801400
}
diff --git a/media/codec2/components/base/SimpleC2Interface.cpp b/media/codec2/components/base/SimpleC2Interface.cpp
index 5c019f3..29740d1 100644
--- a/media/codec2/components/base/SimpleC2Interface.cpp
+++ b/media/codec2/components/base/SimpleC2Interface.cpp
@@ -39,6 +39,16 @@
setDerivedInstance(this);
addParameter(
+ DefineParam(mApiFeatures, C2_PARAMKEY_API_FEATURES)
+ .withConstValue(new C2ApiFeaturesSetting(C2Config::api_feature_t(
+ API_REFLECTION |
+ API_VALUES |
+ API_CURRENT_VALUES |
+ API_DEPENDENCY |
+ API_SAME_INPUT_BUFFER)))
+ .build());
+
+ addParameter(
DefineParam(mName, C2_PARAMKEY_COMPONENT_NAME)
.withConstValue(AllocSharedString<C2ComponentNameSetting>(name.c_str()))
.build());
@@ -305,7 +315,6 @@
Clients need to handle the following base params due to custom dependency.
std::shared_ptr<C2ApiLevelSetting> mApiLevel;
- std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures;
std::shared_ptr<C2ComponentAttributesSetting> mAttrib;
std::shared_ptr<C2PortSuggestedBufferCountTuning::input> mSuggestedInputBufferCount;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 74e105e..7e9090f 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -460,8 +460,8 @@
const C2ConstGraphicBlock inBuffer =
inputBuffer->data().graphicBlocks().front();
- if (inBuffer.width() != mSize->width ||
- inBuffer.height() != mSize->height) {
+ if (inBuffer.width() < mSize->width ||
+ inBuffer.height() < mSize->height) {
ALOGE("unexpected Input buffer attributes %d(%d) x %d(%d)",
inBuffer.width(), mSize->width, inBuffer.height(),
mSize->height);
@@ -472,8 +472,8 @@
bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
vpx_image_t raw_frame;
const C2PlanarLayout &layout = rView->layout();
- uint32_t width = rView->width();
- uint32_t height = rView->height();
+ uint32_t width = mSize->width;
+ uint32_t height = mSize->height;
if (width > 0x8000 || height > 0x8000) {
ALOGE("Image too big: %u x %u", width, height);
work->result = C2_BAD_VALUE;
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index a3fff35..6f8b1d4 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1955,11 +1955,98 @@
inputSurface->getHalInterface()));
}
-static void MaybeLogUnrecognizedName(const char *func, const std::string &name) {
- thread_local std::set<std::string> sLogged{};
- if (sLogged.insert(name).second) {
- ALOGW("%s: Unrecognized interface name: %s", func, name.c_str());
+class IntfCache {
+public:
+ IntfCache() = default;
+
+ status_t init(const std::string &name) {
+ std::shared_ptr<Codec2Client::Interface> intf{
+ Codec2Client::CreateInterfaceByName(name.c_str())};
+ if (!intf) {
+ ALOGW("IntfCache [%s]: Unrecognized interface name", name.c_str());
+ mInitStatus = NO_INIT;
+ return NO_INIT;
+ }
+ const static C2StreamUsageTuning::input sUsage{0u /* stream id */};
+ mFields.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField{&sUsage, &sUsage.value}));
+ c2_status_t err = intf->querySupportedValues(mFields, C2_MAY_BLOCK);
+ if (err != C2_OK) {
+ ALOGW("IntfCache [%s]: failed to query usage supported value (err=%d)",
+ name.c_str(), err);
+ mFields[0].status = err;
+ }
+ std::vector<std::unique_ptr<C2Param>> params;
+ err = intf->query(
+ {&mApiFeatures},
+ {C2PortAllocatorsTuning::input::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ ¶ms);
+ if (err != C2_OK && err != C2_BAD_INDEX) {
+ ALOGW("IntfCache [%s]: failed to query api features (err=%d)",
+ name.c_str(), err);
+ }
+ while (!params.empty()) {
+ C2Param *param = params.back().release();
+ params.pop_back();
+ if (!param) {
+ continue;
+ }
+ if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
+ mInputAllocators.reset(
+ C2PortAllocatorsTuning::input::From(params[0].get()));
+ }
+ }
+ mInitStatus = OK;
+ return OK;
}
+
+ status_t initCheck() const { return mInitStatus; }
+
+ const C2FieldSupportedValuesQuery &getUsageSupportedValues() const {
+ CHECK_EQ(1u, mFields.size());
+ return mFields[0];
+ }
+
+ const C2ApiFeaturesSetting &getApiFeatures() const {
+ return mApiFeatures;
+ }
+
+ const C2PortAllocatorsTuning::input &getInputAllocators() const {
+ static std::unique_ptr<C2PortAllocatorsTuning::input> sInvalidated = []{
+ std::unique_ptr<C2PortAllocatorsTuning::input> param =
+ C2PortAllocatorsTuning::input::AllocUnique(0);
+ param->invalidate();
+ return param;
+ }();
+ return mInputAllocators ? *mInputAllocators : *sInvalidated;
+ }
+
+private:
+ status_t mInitStatus{NO_INIT};
+
+ std::vector<C2FieldSupportedValuesQuery> mFields;
+ C2ApiFeaturesSetting mApiFeatures;
+ std::unique_ptr<C2PortAllocatorsTuning::input> mInputAllocators;
+};
+
+static const IntfCache &GetIntfCache(const std::string &name) {
+ static IntfCache sNullIntfCache;
+ static std::mutex sMutex;
+ static std::map<std::string, IntfCache> sCache;
+ std::unique_lock<std::mutex> lock{sMutex};
+ auto it = sCache.find(name);
+ if (it == sCache.end()) {
+ lock.unlock();
+ IntfCache intfCache;
+ status_t err = intfCache.init(name);
+ if (err != OK) {
+ return sNullIntfCache;
+ }
+ lock.lock();
+ it = sCache.insert({name, std::move(intfCache)}).first;
+ }
+ return it->second;
}
static status_t GetCommonAllocatorIds(
@@ -1977,24 +2064,16 @@
}
bool firstIteration = true;
for (const std::string &name : names) {
- std::shared_ptr<Codec2Client::Interface> intf{
- Codec2Client::CreateInterfaceByName(name.c_str())};
- if (!intf) {
- MaybeLogUnrecognizedName(__FUNCTION__, name);
+ const IntfCache &intfCache = GetIntfCache(name);
+ if (intfCache.initCheck() != OK) {
continue;
}
- std::vector<std::unique_ptr<C2Param>> params;
- c2_status_t err = intf->query(
- {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, ¶ms);
+ const C2PortAllocatorsTuning::input &allocators = intfCache.getInputAllocators();
if (firstIteration) {
firstIteration = false;
- if (err == C2_OK && params.size() == 1u) {
- C2PortAllocatorsTuning::input *allocators =
- C2PortAllocatorsTuning::input::From(params[0].get());
- if (allocators && allocators->flexCount() > 0) {
- ids->insert(allocators->m.values,
- allocators->m.values + allocators->flexCount());
- }
+ if (allocators && allocators.flexCount() > 0) {
+ ids->insert(allocators.m.values,
+ allocators.m.values + allocators.flexCount());
}
if (ids->empty()) {
// The component does not advertise allocators. Use default.
@@ -2003,24 +2082,20 @@
continue;
}
bool filtered = false;
- if (err == C2_OK && params.size() == 1u) {
- C2PortAllocatorsTuning::input *allocators =
- C2PortAllocatorsTuning::input::From(params[0].get());
- if (allocators && allocators->flexCount() > 0) {
- filtered = true;
- for (auto it = ids->begin(); it != ids->end(); ) {
- bool found = false;
- for (size_t j = 0; j < allocators->flexCount(); ++j) {
- if (allocators->m.values[j] == *it) {
- found = true;
- break;
- }
+ if (allocators && allocators.flexCount() > 0) {
+ filtered = true;
+ for (auto it = ids->begin(); it != ids->end(); ) {
+ bool found = false;
+ for (size_t j = 0; j < allocators.flexCount(); ++j) {
+ if (allocators.m.values[j] == *it) {
+ found = true;
+ break;
}
- if (found) {
- ++it;
- } else {
- it = ids->erase(it);
- }
+ }
+ if (found) {
+ ++it;
+ } else {
+ it = ids->erase(it);
}
}
}
@@ -2052,23 +2127,16 @@
*minUsage = 0;
*maxUsage = ~0ull;
for (const std::string &name : names) {
- std::shared_ptr<Codec2Client::Interface> intf{
- Codec2Client::CreateInterfaceByName(name.c_str())};
- if (!intf) {
- MaybeLogUnrecognizedName(__FUNCTION__, name);
+ const IntfCache &intfCache = GetIntfCache(name);
+ if (intfCache.initCheck() != OK) {
continue;
}
- std::vector<C2FieldSupportedValuesQuery> fields;
- fields.push_back(C2FieldSupportedValuesQuery::Possible(
- C2ParamField{&sUsage, &sUsage.value}));
- c2_status_t err = intf->querySupportedValues(fields, C2_MAY_BLOCK);
- if (err != C2_OK) {
+ const C2FieldSupportedValuesQuery &usageSupportedValues =
+ intfCache.getUsageSupportedValues();
+ if (usageSupportedValues.status != C2_OK) {
continue;
}
- if (fields[0].status != C2_OK) {
- continue;
- }
- const C2FieldSupportedValues &supported = fields[0].values;
+ const C2FieldSupportedValues &supported = usageSupportedValues.values;
if (supported.type != C2FieldSupportedValues::FLAGS) {
continue;
}
@@ -2089,6 +2157,17 @@
// static
status_t CCodec::CanFetchLinearBlock(
const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible) {
+ for (const std::string &name : names) {
+ const IntfCache &intfCache = GetIntfCache(name);
+ if (intfCache.initCheck() != OK) {
+ continue;
+ }
+ const C2ApiFeaturesSetting &features = intfCache.getApiFeatures();
+ if (features && !(features.value & API_SAME_INPUT_BUFFER)) {
+ *isCompatible = false;
+ return OK;
+ }
+ }
uint64_t minUsage = usage.expected;
uint64_t maxUsage = ~0ull;
std::set<C2Allocator::id_t> allocators;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 4345a9f..c07f3dc 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -916,6 +916,12 @@
if (inputFormat != nullptr) {
bool graphic = (iStreamFormat.value == C2BufferData::GRAPHIC);
+ C2Config::api_feature_t apiFeatures = C2Config::api_feature_t(
+ API_REFLECTION |
+ API_VALUES |
+ API_CURRENT_VALUES |
+ API_DEPENDENCY |
+ API_SAME_INPUT_BUFFER);
std::shared_ptr<C2BlockPool> pool;
{
Mutexed<BlockPools>::Locked pools(mBlockPools);
@@ -927,14 +933,15 @@
// query C2PortAllocatorsTuning::input from component. If an allocator ID is obtained
// from component, create the input block pool with given ID. Otherwise, use default IDs.
std::vector<std::unique_ptr<C2Param>> params;
- err = mComponent->query({ },
+ C2ApiFeaturesSetting featuresSetting{apiFeatures};
+ err = mComponent->query({ &featuresSetting },
{ C2PortAllocatorsTuning::input::PARAM_TYPE },
C2_DONT_BLOCK,
¶ms);
if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {
ALOGD("[%s] Query input allocators returned %zu params => %s (%u)",
mName, params.size(), asString(err), err);
- } else if (err == C2_OK && params.size() == 1) {
+ } else if (params.size() == 1) {
C2PortAllocatorsTuning::input *inputAllocators =
C2PortAllocatorsTuning::input::From(params[0].get());
if (inputAllocators && inputAllocators->flexCount() > 0) {
@@ -949,6 +956,9 @@
}
}
}
+ if (featuresSetting) {
+ apiFeatures = featuresSetting.value;
+ }
// TODO: use C2Component wrapper to associate this pool with ourselves
if ((poolMask >> pools->inputAllocatorId) & 1) {
@@ -982,7 +992,10 @@
input->numSlots = numInputSlots;
input->extraBuffers.flush();
input->numExtraSlots = 0u;
- if (!buffersBoundToCodec) {
+ bool conforming = (apiFeatures & API_SAME_INPUT_BUFFER);
+ // For encrypted content, framework decrypts source buffer (ashmem) into
+ // C2Buffers. Thus non-conforming codecs can process these.
+ if (!buffersBoundToCodec && (hasCryptoOrDescrambler() || conforming)) {
input->buffers.reset(new SlotInputBuffers(mName));
} else if (graphic) {
if (mInputSurface) {