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

Commit 0d658993 authored by Ray Essick's avatar Ray Essick Committed by Gerrit Code Review
Browse files

Merge "C2SoftHevcEnc: process QP bounding parameters"

parents c7ff9294 21b9f84d
Loading
Loading
Loading
Loading
+106 −2
Original line number Diff line number Diff line
@@ -245,6 +245,19 @@ class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
                })
                .withSetter(CodedColorAspectsSetter, mColorAspects)
                .build());

        addParameter(
                DefineParam(mPictureQuantization, C2_PARAMKEY_PICTURE_QUANTIZATION)
                .withDefault(C2StreamPictureQuantizationTuning::output::AllocShared(
                        0 /* flexCount */, 0u /* stream */))
                .withFields({C2F(mPictureQuantization, m.values[0].type_).oneOf(
                                {C2Config::picture_type_t(I_FRAME),
                                  C2Config::picture_type_t(P_FRAME),
                                  C2Config::picture_type_t(B_FRAME)}),
                             C2F(mPictureQuantization, m.values[0].min).any(),
                             C2F(mPictureQuantization, m.values[0].max).any()})
                .withSetter(PictureQuantizationSetter)
                .build());
    }

    static C2R InputDelaySetter(
@@ -464,9 +477,69 @@ class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
        me.set().matrix = coded.v.matrix;
        return C2R::Ok();
    }
    static C2R PictureQuantizationSetter(bool mayBlock,
                                         C2P<C2StreamPictureQuantizationTuning::output> &me) {
        (void)mayBlock;

        // these are the ones we're going to set, so want them to default
        // to the DEFAULT values for the codec
        int32_t iMin = HEVC_QP_MIN, pMin = HEVC_QP_MIN, bMin = HEVC_QP_MIN;
        int32_t iMax = HEVC_QP_MAX, pMax = HEVC_QP_MAX, bMax = HEVC_QP_MAX;

        for (size_t i = 0; i < me.v.flexCount(); ++i) {
            const C2PictureQuantizationStruct &layer = me.v.m.values[i];

            // layerMin is clamped to [HEVC_QP_MIN, layerMax] to avoid error
            // cases where layer.min > layer.max
            int32_t layerMax = std::clamp(layer.max, HEVC_QP_MIN, HEVC_QP_MAX);
            int32_t layerMin = std::clamp(layer.min, HEVC_QP_MIN, layerMax);
            if (layer.type_ == C2Config::picture_type_t(I_FRAME)) {
                iMax = layerMax;
                iMin = layerMin;
                ALOGV("iMin %d iMax %d", iMin, iMax);
            } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) {
                pMax = layerMax;
                pMin = layerMin;
                ALOGV("pMin %d pMax %d", pMin, pMax);
            } else if (layer.type_ == C2Config::picture_type_t(B_FRAME)) {
                bMax = layerMax;
                bMin = layerMin;
                ALOGV("bMin %d bMax %d", bMin, bMax);
            }
        }

        ALOGV("PictureQuantizationSetter(entry): i %d-%d p %d-%d b %d-%d",
              iMin, iMax, pMin, pMax, bMin, bMax);

        int32_t maxFrameQP = std::min(std::min(iMax, pMax), bMax);
        int32_t minFrameQP = std::max(std::max(iMin, pMin), bMin);
        if (minFrameQP > maxFrameQP) {
            minFrameQP = maxFrameQP;
        }

        // put them back into the structure
        for (size_t i = 0; i < me.v.flexCount(); ++i) {
            const C2PictureQuantizationStruct &layer = me.v.m.values[i];

            if (layer.type_ == C2Config::picture_type_t(I_FRAME) ||
                layer.type_ == C2Config::picture_type_t(P_FRAME) ||
                layer.type_ == C2Config::picture_type_t(B_FRAME)) {
                me.set().m.values[i].max = maxFrameQP;
                me.set().m.values[i].min = minFrameQP;
            }
        }

        ALOGV("PictureQuantizationSetter(exit): i = p = b = %d-%d",
              minFrameQP, maxFrameQP);

        return C2R::Ok();
    }
    std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() {
        return mCodedColorAspects;
    }
    std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const {
        return mPictureQuantization;
    }

   private:
    std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -482,6 +555,7 @@ class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
    std::shared_ptr<C2StreamGopTuning::output> mGop;
    std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
    std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
    std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization;
};

static size_t GetCPUCoreCount() {
@@ -654,12 +728,41 @@ c2_status_t C2SoftHevcEnc::initEncParams() {
        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 3;
    }

    // we resolved out-of-bound and unspecified values in PictureQuantizationSetter()
    // so we can start with defaults that are overridden as needed.
    int32_t maxFrameQP = mEncParams.s_config_prms.i4_max_frame_qp;
    int32_t minFrameQP = mEncParams.s_config_prms.i4_min_frame_qp;

    for (size_t i = 0; i < mQpBounds->flexCount(); ++i) {
        const C2PictureQuantizationStruct &layer = mQpBounds->m.values[i];

        // no need to loop, hevc library takes same range for I/P/B picture type
        if (layer.type_ == C2Config::picture_type_t(I_FRAME) ||
            layer.type_ == C2Config::picture_type_t(P_FRAME) ||
            layer.type_ == C2Config::picture_type_t(B_FRAME)) {

            maxFrameQP = layer.max;
            minFrameQP = layer.min;
            break;
        }
    }
    mEncParams.s_config_prms.i4_max_frame_qp = maxFrameQP;
    mEncParams.s_config_prms.i4_min_frame_qp = minFrameQP;

    ALOGV("MaxFrameQp: %d MinFrameQp: %d", maxFrameQP, minFrameQP);

    mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_frame_qp[0] =
        std::clamp(kDefaultInitQP, minFrameQP, maxFrameQP);

    switch (mBitrateMode->value) {
        case C2Config::BITRATE_IGNORE:
        case C2Config::BITRATE_IGNORE: {
            mEncParams.s_config_prms.i4_rate_control_mode = 3;
            // ensure initial qp values are within our newly configured bounds
            int32_t frameQp = getQpFromQuality(mQuality->value);
            mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_frame_qp[0] =
                getQpFromQuality(mQuality->value);
                std::clamp(frameQp, minFrameQP, maxFrameQP);
            break;
        }
        case C2Config::BITRATE_CONST:
            mEncParams.s_config_prms.i4_rate_control_mode = 5;
            break;
@@ -723,6 +826,7 @@ c2_status_t C2SoftHevcEnc::initEncoder() {
        mGop = mIntf->getGop_l();
        mRequestSync = mIntf->getRequestSync_l();
        mColorAspects = mIntf->getCodedColorAspects_l();
        mQpBounds = mIntf->getPictureQuantization_l();;
    }

    c2_status_t status = initEncParams();
+6 −0
Original line number Diff line number Diff line
@@ -42,6 +42,11 @@ namespace android {
#define DEFAULT_B_FRAMES     0
#define DEFAULT_RC_LOOKAHEAD 0

#define HEVC_QP_MIN 1
#define HEVC_QP_MAX 51

constexpr int32_t kDefaultInitQP = 32;

struct C2SoftHevcEnc : public SimpleC2Component {
    class IntfImpl;

@@ -90,6 +95,7 @@ struct C2SoftHevcEnc : public SimpleC2Component {
    std::shared_ptr<C2StreamGopTuning::output> mGop;
    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
    std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
    std::shared_ptr<C2StreamPictureQuantizationTuning::output> mQpBounds;
#ifdef FILE_DUMP_ENABLE
    char mInFile[200];
    char mOutFile[200];