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

Commit fd21270f authored by Arun Johnson's avatar Arun Johnson
Browse files

MultiAccessUnitHelper to handle dynamic config

MultiAccessUnitHelper can accept changes to its config
on the fly
Bug: 335714093
Flag: com.android.media.codec.flags.large_audio_frame

Change-Id: I18ad7b238f0689be8a313cdab0021cfe7a18e0db
parent e5d2d6f8
Loading
Loading
Loading
Loading
+117 −25
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <C2Debug.h>
#include <C2PlatformSupport.h>

static inline constexpr  uint32_t MAX_SUPPORTED_SIZE = ( 10 * 512000 * 8 * 2u);
namespace android {

static C2R MultiAccessUnitParamsSetter(
@@ -39,8 +40,6 @@ static C2R MultiAccessUnitParamsSetter(
        res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.thresholdSize)));
    } else if (me.v.maxSize < me.v.thresholdSize) {
        me.set().maxSize = me.v.thresholdSize;
    } else if (me.v.thresholdSize == 0 && me.v.maxSize > 0) {
        me.set().thresholdSize = me.v.maxSize;
    }
    std::vector<std::unique_ptr<C2SettingResult>> failures;
    res.retrieveFailures(&failures);
@@ -61,9 +60,9 @@ MultiAccessUnitInterface::MultiAccessUnitInterface(
            .withDefault(new C2LargeFrame::output(0u, 0, 0))
            .withFields({
                C2F(mLargeFrameParams, maxSize).inRange(
                        0, c2_min(UINT_MAX, 10 * 512000 * 8 * 2u)),
                        0, c2_min(UINT_MAX, MAX_SUPPORTED_SIZE)),
                C2F(mLargeFrameParams, thresholdSize).inRange(
                        0, c2_min(UINT_MAX, 10 * 512000 * 8 * 2u))
                        0, c2_min(UINT_MAX, MAX_SUPPORTED_SIZE))
            })
            .withSetter(MultiAccessUnitParamsSetter)
            .build());
@@ -115,6 +114,18 @@ bool MultiAccessUnitInterface::getDecoderSampleRateAndChannelCount(
    return false;
}

bool MultiAccessUnitInterface::getMaxInputSize(
        C2StreamMaxBufferSizeInfo::input* const maxInputSize) const {
    if (maxInputSize == nullptr || mC2ComponentIntf == nullptr) {
        return false;
    }
    c2_status_t err = mC2ComponentIntf->query_vb({maxInputSize}, {}, C2_MAY_BLOCK, nullptr);
    if (err != OK) {
        return false;
    }
    return true;
}

//C2MultiAccessUnitBuffer
class C2MultiAccessUnitBuffer : public C2Buffer {
    public:
@@ -128,6 +139,7 @@ class C2MultiAccessUnitBuffer : public C2Buffer {
MultiAccessUnitHelper::MultiAccessUnitHelper(
        const std::shared_ptr<MultiAccessUnitInterface>& intf,
        std::shared_ptr<C2BlockPool>& linearPool):
        mMultiAccessOnOffAllowed(true),
        mInit(false),
        mInterface(intf),
        mLinearPool(linearPool) {
@@ -152,6 +164,63 @@ bool MultiAccessUnitHelper::isEnabledOnPlatform() {
    return result;
}

bool MultiAccessUnitHelper::tryReconfigure(const std::unique_ptr<C2Param> &param) {
    C2LargeFrame::output *lfp = C2LargeFrame::output::From(param.get());
    if (lfp == nullptr) {
        return false;
    }
    bool isDecoder = (mInterface->kind() == C2Component::KIND_DECODER) ? true : false;
    if (!isDecoder) {
        C2StreamMaxBufferSizeInfo::input maxInputSize(0);
        if (!mInterface->getMaxInputSize(&maxInputSize)) {
            LOG(ERROR) << "Error in reconfigure: "
                    << "Encoder failed to respond with a valid max input size";
            return false;
        }
        // This is assuming a worst case compression ratio of 1:1
        // In no case the encoder should give an output more than
        // what is being provided to the encoder in a single call.
        if (lfp->maxSize < maxInputSize.value) {
            lfp->maxSize = maxInputSize.value;
        }
    }
    lfp->maxSize =
            (lfp->maxSize > MAX_SUPPORTED_SIZE) ? MAX_SUPPORTED_SIZE :
                    (lfp->maxSize < 0) ? 0 : lfp->maxSize;
    lfp->thresholdSize =
            (lfp->thresholdSize > MAX_SUPPORTED_SIZE) ? MAX_SUPPORTED_SIZE :
                    (lfp->thresholdSize < 0) ? 0 : lfp->thresholdSize;
    C2LargeFrame::output currentConfig = mInterface->getLargeFrameParam();
    if ((currentConfig.maxSize == lfp->maxSize)
            && (currentConfig.thresholdSize == lfp->thresholdSize)) {
        // no need to update
        return false;
    }
    if (isDecoder) {
        bool isOnOffTransition =
                (currentConfig.maxSize == 0 && lfp->maxSize != 0)
                || (currentConfig.maxSize != 0 && lfp->maxSize == 0);
            if (isOnOffTransition && !mMultiAccessOnOffAllowed) {
                LOG(ERROR) << "Setting new configs not allowed"
                        << " MaxSize: " << lfp->maxSize
                        << " ThresholdSize: " << lfp->thresholdSize;
                return false;
            }
    }
    std::vector<C2Param*> config{lfp};
    std::vector<std::unique_ptr<C2SettingResult>> failures;
    if (C2_OK != mInterface->config(config, C2_MAY_BLOCK, &failures)) {
        LOG(ERROR) << "Dynamic config not applied for"
                << " MaxSize: " << lfp->maxSize
                << " ThresholdSize: " << lfp->thresholdSize;
        return false;
    }
    LOG(DEBUG) << "Updated from param maxSize "
            << lfp->maxSize
            << " ThresholdSize " << lfp->thresholdSize;
    return true;
}

std::shared_ptr<MultiAccessUnitInterface> MultiAccessUnitHelper::getInterface() {
    return mInterface;
}
@@ -163,6 +232,7 @@ bool MultiAccessUnitHelper::getStatus() {
void MultiAccessUnitHelper::reset() {
    std::lock_guard<std::mutex> l(mLock);
    mFrameHolder.clear();
    mMultiAccessOnOffAllowed = true;
}

c2_status_t MultiAccessUnitHelper::error(
@@ -181,6 +251,7 @@ c2_status_t MultiAccessUnitHelper::error(
        }
    }
    mFrameHolder.clear();
    mMultiAccessOnOffAllowed = true;
    return C2_OK;
}

@@ -232,16 +303,23 @@ c2_status_t MultiAccessUnitHelper::scatter(
        uint64_t newFrameIdx = mFrameIndex++;
        // TODO: Do not split buffers if component inherantly supports MultipleFrames.
        // if thats case, only replace frameindex.
        auto cloneInputWork = [&newFrameIdx](std::unique_ptr<C2Work>& inWork, uint32_t flags) {
        auto cloneInputWork = [&frameInfo, &newFrameIdx, this]
                (std::unique_ptr<C2Work>& inWork, uint32_t flags) -> std::unique_ptr<C2Work> {
            std::unique_ptr<C2Work> newWork(new C2Work);
            newWork->input.flags = (C2FrameData::flags_t)flags;
            newWork->input.ordinal = inWork->input.ordinal;
            newWork->input.ordinal.frameIndex = newFrameIdx;
            if (!inWork->input.configUpdate.empty()) {
                for (std::unique_ptr<C2Param>& param : inWork->input.configUpdate) {
                    newWork->input.configUpdate.push_back(
                            std::move(C2Param::Copy(*(param.get()))));
                    if (param->index() == C2LargeFrame::output::PARAM_TYPE) {
                        if (tryReconfigure(param)) {
                            frameInfo.mConfigUpdate.push_back(std::move(param));
                        }
                    } else {
                        newWork->input.configUpdate.push_back(std::move(param));
                    }
                }
                inWork->input.configUpdate.clear();
            }
            newWork->input.infoBuffers = (inWork->input.infoBuffers);
            if (!inWork->worklets.empty() && inWork->worklets.front() != nullptr) {
@@ -331,6 +409,7 @@ c2_status_t MultiAccessUnitHelper::scatter(
            frameInfo.mLargeFrameTuning = multiAccessParams;
            std::lock_guard<std::mutex> l(mLock);
            mFrameHolder.push_back(std::move(frameInfo));
            mMultiAccessOnOffAllowed = false;
        }
    }
    return C2_OK;
@@ -369,8 +448,7 @@ c2_status_t MultiAccessUnitHelper::gather(
                    if (work->result != C2_OK
                            || work->worklets.empty()
                            || !work->worklets.front()
                            || (frame->mLargeFrameTuning.thresholdSize == 0
                            || frame->mLargeFrameTuning.maxSize == 0)) {
                            || frame->mLargeFrameTuning.maxSize == 0) {
                        if (removeEntry) {
                            frame->mComponentFrameIds.erase(it);
                            removeEntry = false;
@@ -683,10 +761,15 @@ c2_status_t MultiAccessUnitHelper::finalizeWork(
            frame.mWview->setOffset(0);
            std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateLinearBuffer(
                    frame.mBlock->share(0, size, ::C2Fence()));
            frame.mLargeWork->worklets.front()->output.buffers.push_back(std::move(c2Buffer));
        }
        if (frame.mLargeWork->worklets.front()->output.buffers.size() > 0) {
            std::shared_ptr<C2Buffer>& c2Buffer =
                frame.mLargeWork->worklets.front()->output.buffers.front();
            if (c2Buffer != nullptr) {
                if (frame.mAccessUnitInfos.size() > 0) {
                    if (finalFlags & C2FrameData::FLAG_END_OF_STREAM) {
                    frame.mAccessUnitInfos.back().flags |=
                            C2FrameData::FLAG_END_OF_STREAM;
                        frame.mAccessUnitInfos.back().flags |= C2FrameData::FLAG_END_OF_STREAM;
                    }
                    std::shared_ptr<C2AccessUnitInfos::output> largeFrame =
                            C2AccessUnitInfos::output::AllocShared(
@@ -697,12 +780,20 @@ c2_status_t MultiAccessUnitHelper::finalizeWork(
                for (auto &info : frame.mInfos) {
                    c2Buffer->setInfo(std::const_pointer_cast<C2Info>(info));
                }
            frame.mLargeWork->worklets.front()->output.buffers.push_back(std::move(c2Buffer));
            }
        }
        if (frame.mConfigUpdate.size() > 0) {
            outFrameData.configUpdate.insert(
                    outFrameData.configUpdate.end(),
                    make_move_iterator(frame.mConfigUpdate.begin()),
                    make_move_iterator(frame.mConfigUpdate.end()));
        }
    }
    frame.mConfigUpdate.clear();
    frame.mInfos.clear();
    frame.mBlock.reset();
    frame.mWview.reset();
        }
    }

    LOG(DEBUG) << "Multi access-unitflag setting as " << finalFlags;
    return C2_OK;
}
@@ -735,6 +826,7 @@ void MultiAccessUnitHelper::MultiAccessUnitInfo::reset() {
    mBlock.reset();
    mWview.reset();
    mInfos.clear();
    mConfigUpdate.clear();
    mAccessUnitInfos.clear();
    mLargeWork.reset();
}
+19 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct MultiAccessUnitInterface : public C2InterfaceHelper {
protected:
    bool getDecoderSampleRateAndChannelCount(
            uint32_t * const sampleRate_, uint32_t * const channelCount_) const;
    bool getMaxInputSize(C2StreamMaxBufferSizeInfo::input* const maxInputSize) const;
    const std::shared_ptr<C2ComponentInterface> mC2ComponentIntf;
    std::shared_ptr<C2LargeFrame::output> mLargeFrameParams;
    C2ComponentKindSetting mKind;
@@ -139,6 +140,11 @@ protected:
         */
        std::vector<std::shared_ptr<const C2Info>> mInfos;

        /*
         * Vector for holding config updates from the wrapper
         */
        std::vector<std::unique_ptr<C2Param>> mConfigUpdate;

        /*
         * C2AccessUnitInfos for the current buffer
         */
@@ -169,6 +175,11 @@ protected:
        void reset();
    };

    /*
     * Reconfigure helper
     */
    bool tryReconfigure(const std::unique_ptr<C2Param> &p);

    /*
     * Creates a linear block to be used with work
     */
@@ -195,6 +206,14 @@ protected:
            uint32_t size,
            int64_t timestamp);

    // Flag to allow dynamic on/off settings on this helper.
    // Once enabled and buffers in transit, it is not possible
    // to turn this module off by setting the max output value
    // to 0. This is because the skip cut buffer expects the
    // metadata to be always present along with a valid buffer.
    // This flag is used to monitor that state of this module.
    bool mMultiAccessOnOffAllowed;

    bool mInit;

    // Interface of this module