Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d946e718 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "CCodec: query api feature for block model" into rvc-dev am: 752adf7f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/11626653

Change-Id: I9c88c4cd4364e0d40421a234419bc70641ace2d3
parents 63d20b77 752adf7f
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -38,6 +38,16 @@ SimpleInterface<void>::BaseParams::BaseParams(
    : C2InterfaceHelper(reflector) {
    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()))
@@ -305,7 +315,6 @@ void SimpleInterface<void>::BaseParams::noTimeStretch() {
    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;
+127 −48
Original line number Diff line number Diff line
@@ -1955,11 +1955,98 @@ PersistentSurface *CCodec::CreateInputSurface() {
            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,
                &params);
        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 @@ static status_t GetCommonAllocatorIds(
    }
    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, &params);
        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,15 +2082,12 @@ static status_t GetCommonAllocatorIds(
            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) {
        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) {
                for (size_t j = 0; j < allocators.flexCount(); ++j) {
                    if (allocators.m.values[j] == *it) {
                        found = true;
                        break;
                    }
@@ -2023,7 +2099,6 @@ static status_t GetCommonAllocatorIds(
                }
            }
        }
        }
        if (!filtered) {
            // The component does not advertise supported allocators. Use default.
            bool containsDefault = (ids->count(defaultAllocatorId) > 0u);
@@ -2052,23 +2127,16 @@ static status_t CalculateMinMaxUsage(
    *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 CalculateMinMaxUsage(
// 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;
+16 −3
Original line number Diff line number Diff line
@@ -916,6 +916,12 @@ status_t CCodecBufferChannel::start(

    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 @@ status_t CCodecBufferChannel::start(
            // 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,
                                    &params);
            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 @@ status_t CCodecBufferChannel::start(
                    }
                }
            }
            if (featuresSetting) {
                apiFeatures = featuresSetting.value;
            }

            // TODO: use C2Component wrapper to associate this pool with ourselves
            if ((poolMask >> pools->inputAllocatorId) & 1) {
@@ -982,7 +992,10 @@ status_t CCodecBufferChannel::start(
        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) {