Loading apex/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,10 @@ apex_defaults { }, }, // JNI native_shared_libs: ["libmediaparser-jni"], native_shared_libs: [ "libmediaparser-jni", "libmediaformatshaper", ], compile_multilib: "both", prebuilts: [ "code_coverage.policy", Loading media/codec2/components/avc/C2SoftAvcEnc.cpp +78 −106 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <log/log.h> #include <utils/misc.h> #include <algorithm> #include <media/hardware/VideoAPI.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> Loading Loading @@ -120,6 +122,19 @@ public: .withSetter(GopSetter) .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()); addParameter( DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY) .withDefault(new C2PortActualDelayTuning::input(DEFAULT_B_FRAMES)) Loading Loading @@ -185,23 +200,6 @@ public: .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate) .build()); addParameter( DefineParam(mQuantization, C2_PARAMKEY_QUANTIZATION) .withDefault(new C2StreamQuantizationInfo::output(0u, DEFAULT_QP_MAX, DEFAULT_QP_MIN, DEFAULT_QP_MAX, DEFAULT_QP_MIN, DEFAULT_QP_MAX, DEFAULT_QP_MIN)) .withFields({ C2F(mQuantization, iMax).inRange(1, 51), C2F(mQuantization, iMin).inRange(1, 51), C2F(mQuantization, pMax).inRange(1, 51), C2F(mQuantization, pMin).inRange(1, 51), C2F(mQuantization, bMax).inRange(1, 51), C2F(mQuantization, bMin).inRange(1, 51), }) .withSetter(QuantizationSetter) .build()); addParameter( DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME) .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE)) Loading Loading @@ -237,70 +235,6 @@ public: return res; } static C2R QuantizationSetter(bool mayBlock, C2P<C2StreamQuantizationInfo::output> &me) { (void)mayBlock; (void)me; C2R res = C2R::Ok(); ALOGV("QuantizationSetter enters max/min i %d/%d p %d/%d b %d/%d", me.v.iMax, me.v.iMin, me.v.pMax, me.v.pMin, me.v.bMax, me.v.bMin); // bounds checking constexpr int qp_lowest = 1; constexpr int qp_highest = 51; if (me.v.iMax < qp_lowest) { me.set().iMax = qp_lowest; } else if (me.v.iMax > qp_highest) { me.set().iMax = qp_highest; } if (me.v.iMin < qp_lowest) { me.set().iMin = qp_lowest; } else if (me.v.iMin > qp_highest) { me.set().iMin = qp_highest; } if (me.v.pMax < qp_lowest) { me.set().pMax = qp_lowest; } else if (me.v.pMax > qp_highest) { me.set().pMax = qp_highest; } if (me.v.pMin < qp_lowest) { me.set().pMin = qp_lowest; } else if (me.v.pMin > qp_highest) { me.set().pMin = qp_highest; } if (me.v.bMax < qp_lowest) { me.set().bMax = qp_lowest; } else if (me.v.bMax > qp_highest) { me.set().bMax = qp_highest; } if (me.v.bMin < qp_lowest) { me.set().bMin = qp_lowest; } else if (me.v.bMin > qp_highest) { me.set().bMin = qp_highest; } // consistency checking, e.g. min<max // if (me.v.iMax < me.v.iMin) { me.set().iMax = me.v.iMin; } if (me.v.pMax < me.v.pMin) { me.set().pMax = me.v.pMin; } if (me.v.bMax < me.v.bMin) { me.set().bMax = me.v.bMin; } // TODO: enforce any sort of i_max < p_max < b_max? return res; } static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe, C2P<C2StreamPictureSizeInfo::input> &me) { Loading Loading @@ -418,6 +352,13 @@ public: return C2R::Ok(); } static C2R PictureQuantizationSetter(bool mayBlock, C2P<C2StreamPictureQuantizationTuning::output> &me) { (void)mayBlock; (void)me; return C2R::Ok(); } IV_PROFILE_T getProfile_l() const { switch (mProfileLevel->profile) { case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]]; Loading Loading @@ -475,7 +416,8 @@ public: std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; } std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; } std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; } std::shared_ptr<C2StreamQuantizationInfo::output> getQuantization_l() const { return mQuantization; } std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const { return mPictureQuantization; } private: std::shared_ptr<C2StreamUsageTuning::input> mUsage; Loading @@ -487,7 +429,7 @@ private: std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod; std::shared_ptr<C2StreamGopTuning::output> mGop; std::shared_ptr<C2StreamQuantizationInfo::output> mQuantization; std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization; }; #define ive_api_function ih264e_api_function Loading Loading @@ -748,36 +690,67 @@ c2_status_t C2SoftAvcEnc::setQp() { ive_ctl_set_qp_op_t s_qp_op; IV_STATUS_T status; ALOGV("in setQp()"); // set the defaults s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL; s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP; s_qp_ip.u4_i_qp = DEFAULT_I_QP; s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN; s_qp_ip.u4_p_qp = DEFAULT_P_QP; s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN; s_qp_ip.u4_b_qp = DEFAULT_P_QP; s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN; // these are the ones we're going to set, so want them to default .... // to the DEFAULT values for the codec instea dof CODEC_ bounding int32_t iMin = INT32_MIN, pMin = INT32_MIN, bMin = INT32_MIN; int32_t iMax = INT32_MAX, pMax = INT32_MAX, bMax = INT32_MAX; std::shared_ptr<C2StreamPictureQuantizationTuning::output> qp = mIntf->getPictureQuantization_l(); for (size_t i = 0; i < qp->flexCount(); ++i) { const C2PictureQuantizationStruct &layer = qp->m.values[i]; if (layer.type_ == C2Config::picture_type_t(I_FRAME)) { iMax = layer.max; iMin = layer.min; ALOGV("iMin %d iMax %d", iMin, iMax); } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) { pMax = layer.max; pMin = layer.min; ALOGV("pMin %d pMax %d", pMin, pMax); } else if (layer.type_ == C2Config::picture_type_t(B_FRAME)) { bMax = layer.max; bMin = layer.min; ALOGV("bMin %d bMax %d", bMin, bMax); } } // INT32_{MIN,MAX} means unspecified, so use the codec's default if (iMax == INT32_MAX) iMax = DEFAULT_I_QP_MAX; if (iMin == INT32_MIN) iMin = DEFAULT_I_QP_MIN; if (pMax == INT32_MAX) pMax = DEFAULT_P_QP_MAX; if (pMin == INT32_MIN) pMin = DEFAULT_P_QP_MIN; if (bMax == INT32_MAX) bMax = DEFAULT_B_QP_MAX; if (bMin == INT32_MIN) bMin = DEFAULT_B_QP_MIN; // ensure we have legal values iMax = std::clamp(iMax, CODEC_QP_MIN, CODEC_QP_MAX); iMin = std::clamp(iMin, CODEC_QP_MIN, CODEC_QP_MAX); pMax = std::clamp(pMax, CODEC_QP_MIN, CODEC_QP_MAX); pMin = std::clamp(pMin, CODEC_QP_MIN, CODEC_QP_MAX); bMax = std::clamp(bMax, CODEC_QP_MIN, CODEC_QP_MAX); bMin = std::clamp(bMin, CODEC_QP_MIN, CODEC_QP_MAX); s_qp_ip.u4_i_qp_max = iMax; s_qp_ip.u4_i_qp_min = iMin; s_qp_ip.u4_p_qp_max = pMax; s_qp_ip.u4_p_qp_min = pMin; s_qp_ip.u4_b_qp_max = bMax; s_qp_ip.u4_b_qp_min = bMin; // ensure initial qp values are within our newly configured bounds... s_qp_ip.u4_i_qp = std::clamp(DEFAULT_I_QP, iMin, iMax); s_qp_ip.u4_p_qp = std::clamp(DEFAULT_P_QP, pMin, pMax); s_qp_ip.u4_b_qp = std::clamp(DEFAULT_B_QP, bMin, bMax); ALOGV("setting QP: i %d-%d p %d-%d b %d-%d", iMin, iMax, pMin, pMax, bMin, bMax); // parameter parsing ensured proper range 1..51, so only worry about ordering bool valid = true; if (mQuantization->iMax < mQuantization->iMin) valid = false; if (mQuantization->pMax < mQuantization->pMin) valid = false; if (mQuantization->bMax < mQuantization->bMin) valid = false; if (valid) { s_qp_ip.u4_i_qp_max = mQuantization->iMax; s_qp_ip.u4_i_qp_min = mQuantization->iMin; s_qp_ip.u4_p_qp_max = mQuantization->pMax; s_qp_ip.u4_p_qp_min = mQuantization->pMin; s_qp_ip.u4_b_qp_max = mQuantization->bMax; s_qp_ip.u4_b_qp_min = mQuantization->bMin; } s_qp_ip.u4_timestamp_high = -1; s_qp_ip.u4_timestamp_low = -1; Loading Loading @@ -1026,7 +999,6 @@ c2_status_t C2SoftAvcEnc::initEncoder() { mIInterval = mIntf->getSyncFramePeriod_l(); mIDRInterval = mIntf->getSyncFramePeriod_l(); gop = mIntf->getGop_l(); mQuantization = mIntf->getQuantization_l(); } if (gop && gop->flexCount() > 0) { uint32_t syncInterval = 1; Loading media/codec2/components/avc/C2SoftAvcEnc.h +5 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,11 @@ namespace android { #define STRLENGTH 500 #define DEFAULT_CONSTRAINED_INTRA 0 /** limits as specified by h264 */ #define CODEC_QP_MIN 0 #define CODEC_QP_MAX 51 #define MIN(a, b) ((a) < (b))? (a) : (b) #define MAX(a, b) ((a) > (b))? (a) : (b) #define ALIGN16(x) ((((x) + 15) >> 4) << 4) Loading Loading @@ -192,7 +197,6 @@ private: std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; std::shared_ptr<C2StreamBitrateInfo::output> mBitrate; std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; std::shared_ptr<C2StreamQuantizationInfo::output> mQuantization; uint32_t mOutBufferSize; UWORD32 mHeaderGenerated; Loading media/codec2/core/include/C2Config.h +26 −33 Original line number Diff line number Diff line Loading @@ -187,7 +187,7 @@ enum C2ParamIndexKind : C2Param::type_index_t { kParamIndexPictureType, kParamIndexHdr10PlusMetadata, kParamIndexQuantization, kParamIndexPictureQuantization, /* ------------------------------------ video components ------------------------------------ */ Loading Loading @@ -710,38 +710,6 @@ typedef C2StreamParam<C2Info, C2ProfileLevelStruct, kParamIndexProfileLevel> C2StreamProfileLevelInfo; constexpr char C2_PARAMKEY_PROFILE_LEVEL[] = "coded.pl"; struct C2QuantizationStruct { int32_t iMax; ///< max/min for I frames int32_t iMin; int32_t pMax; ///< max/min for P frames int32_t pMin; int32_t bMax; ///< max/min for B frames int32_t bMin; C2QuantizationStruct( int32_t iMax_ = INT32_MAX, int32_t iMin_ = INT32_MIN, int32_t pMax_ = INT32_MAX, int32_t pMin_ = INT32_MIN, int32_t bMax_ = INT32_MAX, int32_t bMin_ = INT32_MIN) : iMax(iMax_), iMin(iMin_), pMax(pMax_), pMin(pMin_), bMax(bMax_), bMin(bMin_) { } DEFINE_AND_DESCRIBE_C2STRUCT(Quantization) // reference? C2FIELD(iMax, "i-max") C2FIELD(iMin, "i-min") C2FIELD(pMax, "p-max") C2FIELD(pMin, "p-min") C2FIELD(bMax, "b-max") C2FIELD(bMin, "b-min") }; typedef C2StreamParam<C2Info, C2QuantizationStruct, kParamIndexQuantization> C2StreamQuantizationInfo; constexpr char C2_PARAMKEY_QUANTIZATION[] = "coded.qp"; /** * Codec-specific initialization data. * Loading Loading @@ -1732,6 +1700,31 @@ typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2GopLayerStruct>, kParamInd C2StreamGopTuning; constexpr char C2_PARAMKEY_GOP[] = "coding.gop"; /** * Quantization * min/max for each picture type * */ struct C2PictureQuantizationStruct { C2PictureQuantizationStruct() : type_((C2Config::picture_type_t)0), min(INT32_MIN), max(INT32_MAX) {} C2PictureQuantizationStruct(C2Config::picture_type_t type, int32_t min_, int32_t max_) : type_(type), min(min_), max(max_) { } C2Config::picture_type_t type_; int32_t min; // INT32_MIN == 'no lower bound specified' int32_t max; // INT32_MAX == 'no upper bound specified' DEFINE_AND_DESCRIBE_C2STRUCT(PictureQuantization) C2FIELD(type_, "type") C2FIELD(min, "min") C2FIELD(max, "max") }; typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2PictureQuantizationStruct>, kParamIndexPictureQuantization> C2StreamPictureQuantizationTuning; constexpr char C2_PARAMKEY_PICTURE_QUANTIZATION[] = "coding.qp"; /** * Sync frame can be requested on demand by the client. * Loading media/codec2/sfplugin/CCodec.cpp +39 −0 Original line number Diff line number Diff line Loading @@ -1086,6 +1086,45 @@ void CCodec::configure(const sp<AMessage> &msg) { configUpdate.push_back(std::move(gop)); } if ((config->mDomain & Config::IS_ENCODER) && (config->mDomain & Config::IS_VIDEO)) { // we may not use all 3 of these entries std::unique_ptr<C2StreamPictureQuantizationTuning::output> qp = C2StreamPictureQuantizationTuning::output::AllocUnique(3 /* flexCount */, 0u /* stream */); int ix = 0; int32_t iMax = INT32_MAX; int32_t iMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MAX, &iMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MIN, &iMin); if (iMax != INT32_MAX || iMin != INT32_MIN) { qp->m.values[ix++] = {I_FRAME, iMin, iMax}; } int32_t pMax = INT32_MAX; int32_t pMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MAX, &pMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MIN, &pMin); if (pMax != INT32_MAX || pMin != INT32_MIN) { qp->m.values[ix++] = {P_FRAME, pMin, pMax}; } int32_t bMax = INT32_MAX; int32_t bMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MAX, &bMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MIN, &bMin); if (bMax != INT32_MAX || bMin != INT32_MIN) { qp->m.values[ix++] = {B_FRAME, bMin, bMax}; } // adjust to reflect actual use. qp->setFlexCount(ix); configUpdate.push_back(std::move(qp)); } err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK); if (err != OK) { ALOGW("failed to configure c2 params"); Loading Loading
apex/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,10 @@ apex_defaults { }, }, // JNI native_shared_libs: ["libmediaparser-jni"], native_shared_libs: [ "libmediaparser-jni", "libmediaformatshaper", ], compile_multilib: "both", prebuilts: [ "code_coverage.policy", Loading
media/codec2/components/avc/C2SoftAvcEnc.cpp +78 −106 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <log/log.h> #include <utils/misc.h> #include <algorithm> #include <media/hardware/VideoAPI.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> Loading Loading @@ -120,6 +122,19 @@ public: .withSetter(GopSetter) .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()); addParameter( DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY) .withDefault(new C2PortActualDelayTuning::input(DEFAULT_B_FRAMES)) Loading Loading @@ -185,23 +200,6 @@ public: .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate) .build()); addParameter( DefineParam(mQuantization, C2_PARAMKEY_QUANTIZATION) .withDefault(new C2StreamQuantizationInfo::output(0u, DEFAULT_QP_MAX, DEFAULT_QP_MIN, DEFAULT_QP_MAX, DEFAULT_QP_MIN, DEFAULT_QP_MAX, DEFAULT_QP_MIN)) .withFields({ C2F(mQuantization, iMax).inRange(1, 51), C2F(mQuantization, iMin).inRange(1, 51), C2F(mQuantization, pMax).inRange(1, 51), C2F(mQuantization, pMin).inRange(1, 51), C2F(mQuantization, bMax).inRange(1, 51), C2F(mQuantization, bMin).inRange(1, 51), }) .withSetter(QuantizationSetter) .build()); addParameter( DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME) .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE)) Loading Loading @@ -237,70 +235,6 @@ public: return res; } static C2R QuantizationSetter(bool mayBlock, C2P<C2StreamQuantizationInfo::output> &me) { (void)mayBlock; (void)me; C2R res = C2R::Ok(); ALOGV("QuantizationSetter enters max/min i %d/%d p %d/%d b %d/%d", me.v.iMax, me.v.iMin, me.v.pMax, me.v.pMin, me.v.bMax, me.v.bMin); // bounds checking constexpr int qp_lowest = 1; constexpr int qp_highest = 51; if (me.v.iMax < qp_lowest) { me.set().iMax = qp_lowest; } else if (me.v.iMax > qp_highest) { me.set().iMax = qp_highest; } if (me.v.iMin < qp_lowest) { me.set().iMin = qp_lowest; } else if (me.v.iMin > qp_highest) { me.set().iMin = qp_highest; } if (me.v.pMax < qp_lowest) { me.set().pMax = qp_lowest; } else if (me.v.pMax > qp_highest) { me.set().pMax = qp_highest; } if (me.v.pMin < qp_lowest) { me.set().pMin = qp_lowest; } else if (me.v.pMin > qp_highest) { me.set().pMin = qp_highest; } if (me.v.bMax < qp_lowest) { me.set().bMax = qp_lowest; } else if (me.v.bMax > qp_highest) { me.set().bMax = qp_highest; } if (me.v.bMin < qp_lowest) { me.set().bMin = qp_lowest; } else if (me.v.bMin > qp_highest) { me.set().bMin = qp_highest; } // consistency checking, e.g. min<max // if (me.v.iMax < me.v.iMin) { me.set().iMax = me.v.iMin; } if (me.v.pMax < me.v.pMin) { me.set().pMax = me.v.pMin; } if (me.v.bMax < me.v.bMin) { me.set().bMax = me.v.bMin; } // TODO: enforce any sort of i_max < p_max < b_max? return res; } static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe, C2P<C2StreamPictureSizeInfo::input> &me) { Loading Loading @@ -418,6 +352,13 @@ public: return C2R::Ok(); } static C2R PictureQuantizationSetter(bool mayBlock, C2P<C2StreamPictureQuantizationTuning::output> &me) { (void)mayBlock; (void)me; return C2R::Ok(); } IV_PROFILE_T getProfile_l() const { switch (mProfileLevel->profile) { case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]]; Loading Loading @@ -475,7 +416,8 @@ public: std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; } std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; } std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; } std::shared_ptr<C2StreamQuantizationInfo::output> getQuantization_l() const { return mQuantization; } std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const { return mPictureQuantization; } private: std::shared_ptr<C2StreamUsageTuning::input> mUsage; Loading @@ -487,7 +429,7 @@ private: std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod; std::shared_ptr<C2StreamGopTuning::output> mGop; std::shared_ptr<C2StreamQuantizationInfo::output> mQuantization; std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization; }; #define ive_api_function ih264e_api_function Loading Loading @@ -748,36 +690,67 @@ c2_status_t C2SoftAvcEnc::setQp() { ive_ctl_set_qp_op_t s_qp_op; IV_STATUS_T status; ALOGV("in setQp()"); // set the defaults s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL; s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP; s_qp_ip.u4_i_qp = DEFAULT_I_QP; s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN; s_qp_ip.u4_p_qp = DEFAULT_P_QP; s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN; s_qp_ip.u4_b_qp = DEFAULT_P_QP; s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX; s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN; // these are the ones we're going to set, so want them to default .... // to the DEFAULT values for the codec instea dof CODEC_ bounding int32_t iMin = INT32_MIN, pMin = INT32_MIN, bMin = INT32_MIN; int32_t iMax = INT32_MAX, pMax = INT32_MAX, bMax = INT32_MAX; std::shared_ptr<C2StreamPictureQuantizationTuning::output> qp = mIntf->getPictureQuantization_l(); for (size_t i = 0; i < qp->flexCount(); ++i) { const C2PictureQuantizationStruct &layer = qp->m.values[i]; if (layer.type_ == C2Config::picture_type_t(I_FRAME)) { iMax = layer.max; iMin = layer.min; ALOGV("iMin %d iMax %d", iMin, iMax); } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) { pMax = layer.max; pMin = layer.min; ALOGV("pMin %d pMax %d", pMin, pMax); } else if (layer.type_ == C2Config::picture_type_t(B_FRAME)) { bMax = layer.max; bMin = layer.min; ALOGV("bMin %d bMax %d", bMin, bMax); } } // INT32_{MIN,MAX} means unspecified, so use the codec's default if (iMax == INT32_MAX) iMax = DEFAULT_I_QP_MAX; if (iMin == INT32_MIN) iMin = DEFAULT_I_QP_MIN; if (pMax == INT32_MAX) pMax = DEFAULT_P_QP_MAX; if (pMin == INT32_MIN) pMin = DEFAULT_P_QP_MIN; if (bMax == INT32_MAX) bMax = DEFAULT_B_QP_MAX; if (bMin == INT32_MIN) bMin = DEFAULT_B_QP_MIN; // ensure we have legal values iMax = std::clamp(iMax, CODEC_QP_MIN, CODEC_QP_MAX); iMin = std::clamp(iMin, CODEC_QP_MIN, CODEC_QP_MAX); pMax = std::clamp(pMax, CODEC_QP_MIN, CODEC_QP_MAX); pMin = std::clamp(pMin, CODEC_QP_MIN, CODEC_QP_MAX); bMax = std::clamp(bMax, CODEC_QP_MIN, CODEC_QP_MAX); bMin = std::clamp(bMin, CODEC_QP_MIN, CODEC_QP_MAX); s_qp_ip.u4_i_qp_max = iMax; s_qp_ip.u4_i_qp_min = iMin; s_qp_ip.u4_p_qp_max = pMax; s_qp_ip.u4_p_qp_min = pMin; s_qp_ip.u4_b_qp_max = bMax; s_qp_ip.u4_b_qp_min = bMin; // ensure initial qp values are within our newly configured bounds... s_qp_ip.u4_i_qp = std::clamp(DEFAULT_I_QP, iMin, iMax); s_qp_ip.u4_p_qp = std::clamp(DEFAULT_P_QP, pMin, pMax); s_qp_ip.u4_b_qp = std::clamp(DEFAULT_B_QP, bMin, bMax); ALOGV("setting QP: i %d-%d p %d-%d b %d-%d", iMin, iMax, pMin, pMax, bMin, bMax); // parameter parsing ensured proper range 1..51, so only worry about ordering bool valid = true; if (mQuantization->iMax < mQuantization->iMin) valid = false; if (mQuantization->pMax < mQuantization->pMin) valid = false; if (mQuantization->bMax < mQuantization->bMin) valid = false; if (valid) { s_qp_ip.u4_i_qp_max = mQuantization->iMax; s_qp_ip.u4_i_qp_min = mQuantization->iMin; s_qp_ip.u4_p_qp_max = mQuantization->pMax; s_qp_ip.u4_p_qp_min = mQuantization->pMin; s_qp_ip.u4_b_qp_max = mQuantization->bMax; s_qp_ip.u4_b_qp_min = mQuantization->bMin; } s_qp_ip.u4_timestamp_high = -1; s_qp_ip.u4_timestamp_low = -1; Loading Loading @@ -1026,7 +999,6 @@ c2_status_t C2SoftAvcEnc::initEncoder() { mIInterval = mIntf->getSyncFramePeriod_l(); mIDRInterval = mIntf->getSyncFramePeriod_l(); gop = mIntf->getGop_l(); mQuantization = mIntf->getQuantization_l(); } if (gop && gop->flexCount() > 0) { uint32_t syncInterval = 1; Loading
media/codec2/components/avc/C2SoftAvcEnc.h +5 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,11 @@ namespace android { #define STRLENGTH 500 #define DEFAULT_CONSTRAINED_INTRA 0 /** limits as specified by h264 */ #define CODEC_QP_MIN 0 #define CODEC_QP_MAX 51 #define MIN(a, b) ((a) < (b))? (a) : (b) #define MAX(a, b) ((a) > (b))? (a) : (b) #define ALIGN16(x) ((((x) + 15) >> 4) << 4) Loading Loading @@ -192,7 +197,6 @@ private: std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; std::shared_ptr<C2StreamBitrateInfo::output> mBitrate; std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; std::shared_ptr<C2StreamQuantizationInfo::output> mQuantization; uint32_t mOutBufferSize; UWORD32 mHeaderGenerated; Loading
media/codec2/core/include/C2Config.h +26 −33 Original line number Diff line number Diff line Loading @@ -187,7 +187,7 @@ enum C2ParamIndexKind : C2Param::type_index_t { kParamIndexPictureType, kParamIndexHdr10PlusMetadata, kParamIndexQuantization, kParamIndexPictureQuantization, /* ------------------------------------ video components ------------------------------------ */ Loading Loading @@ -710,38 +710,6 @@ typedef C2StreamParam<C2Info, C2ProfileLevelStruct, kParamIndexProfileLevel> C2StreamProfileLevelInfo; constexpr char C2_PARAMKEY_PROFILE_LEVEL[] = "coded.pl"; struct C2QuantizationStruct { int32_t iMax; ///< max/min for I frames int32_t iMin; int32_t pMax; ///< max/min for P frames int32_t pMin; int32_t bMax; ///< max/min for B frames int32_t bMin; C2QuantizationStruct( int32_t iMax_ = INT32_MAX, int32_t iMin_ = INT32_MIN, int32_t pMax_ = INT32_MAX, int32_t pMin_ = INT32_MIN, int32_t bMax_ = INT32_MAX, int32_t bMin_ = INT32_MIN) : iMax(iMax_), iMin(iMin_), pMax(pMax_), pMin(pMin_), bMax(bMax_), bMin(bMin_) { } DEFINE_AND_DESCRIBE_C2STRUCT(Quantization) // reference? C2FIELD(iMax, "i-max") C2FIELD(iMin, "i-min") C2FIELD(pMax, "p-max") C2FIELD(pMin, "p-min") C2FIELD(bMax, "b-max") C2FIELD(bMin, "b-min") }; typedef C2StreamParam<C2Info, C2QuantizationStruct, kParamIndexQuantization> C2StreamQuantizationInfo; constexpr char C2_PARAMKEY_QUANTIZATION[] = "coded.qp"; /** * Codec-specific initialization data. * Loading Loading @@ -1732,6 +1700,31 @@ typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2GopLayerStruct>, kParamInd C2StreamGopTuning; constexpr char C2_PARAMKEY_GOP[] = "coding.gop"; /** * Quantization * min/max for each picture type * */ struct C2PictureQuantizationStruct { C2PictureQuantizationStruct() : type_((C2Config::picture_type_t)0), min(INT32_MIN), max(INT32_MAX) {} C2PictureQuantizationStruct(C2Config::picture_type_t type, int32_t min_, int32_t max_) : type_(type), min(min_), max(max_) { } C2Config::picture_type_t type_; int32_t min; // INT32_MIN == 'no lower bound specified' int32_t max; // INT32_MAX == 'no upper bound specified' DEFINE_AND_DESCRIBE_C2STRUCT(PictureQuantization) C2FIELD(type_, "type") C2FIELD(min, "min") C2FIELD(max, "max") }; typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2PictureQuantizationStruct>, kParamIndexPictureQuantization> C2StreamPictureQuantizationTuning; constexpr char C2_PARAMKEY_PICTURE_QUANTIZATION[] = "coding.qp"; /** * Sync frame can be requested on demand by the client. * Loading
media/codec2/sfplugin/CCodec.cpp +39 −0 Original line number Diff line number Diff line Loading @@ -1086,6 +1086,45 @@ void CCodec::configure(const sp<AMessage> &msg) { configUpdate.push_back(std::move(gop)); } if ((config->mDomain & Config::IS_ENCODER) && (config->mDomain & Config::IS_VIDEO)) { // we may not use all 3 of these entries std::unique_ptr<C2StreamPictureQuantizationTuning::output> qp = C2StreamPictureQuantizationTuning::output::AllocUnique(3 /* flexCount */, 0u /* stream */); int ix = 0; int32_t iMax = INT32_MAX; int32_t iMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MAX, &iMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_I_MIN, &iMin); if (iMax != INT32_MAX || iMin != INT32_MIN) { qp->m.values[ix++] = {I_FRAME, iMin, iMax}; } int32_t pMax = INT32_MAX; int32_t pMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MAX, &pMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_P_MIN, &pMin); if (pMax != INT32_MAX || pMin != INT32_MIN) { qp->m.values[ix++] = {P_FRAME, pMin, pMax}; } int32_t bMax = INT32_MAX; int32_t bMin = INT32_MIN; (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MAX, &bMax); (void) sdkParams->findInt32(KEY_VIDEO_QP_B_MIN, &bMin); if (bMax != INT32_MAX || bMin != INT32_MIN) { qp->m.values[ix++] = {B_FRAME, bMin, bMax}; } // adjust to reflect actual use. qp->setFlexCount(ix); configUpdate.push_back(std::move(qp)); } err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK); if (err != OK) { ALOGW("failed to configure c2 params"); Loading