@@ -60,6 +60,7 @@ class AMFEncoder {
6060 DataFormat dataFormat_;
6161 amf::AMFComponentPtr AMFEncoder_ = NULL ;
6262 amf::AMFContextPtr AMFContext_ = NULL ;
63+ int32_t rc_;
6364
6465private:
6566 // system
@@ -76,6 +77,9 @@ class AMFEncoder {
7677 int32_t bitRateIn_;
7778 int32_t frameRate_;
7879 int32_t gop_;
80+ int32_t qp_;
81+ int32_t qp_min_;
82+ int32_t qp_max_;
7983 bool enable4K_ = false ;
8084 bool full_range_ = false ;
8185 bool bt709_ = false ;
@@ -86,15 +90,20 @@ class AMFEncoder {
8690public:
8791 AMFEncoder (void *handle, amf::AMF_MEMORY_TYPE memoryType, amf_wstring codec,
8892 DataFormat dataFormat, int32_t width, int32_t height,
89- int32_t bitrate, int32_t framerate, int32_t gop) {
93+ int32_t bitrate, int32_t framerate, int32_t gop,
94+ int32_t rc, int32_t qp, int32_t qp_min, int32_t qp_max) {
9095 handle_ = handle;
9196 dataFormat_ = dataFormat;
9297 AMFMemoryType_ = memoryType;
9398 resolution_ = std::make_pair (width, height);
9499 codec_ = codec;
95- bitRateIn_ = bitrate;
100+ bitRateIn_ = bitrate > 0 ? bitrate : DEFAULT_KBS * 1000 ;
96101 frameRate_ = framerate;
97102 gop_ = (gop > 0 && gop < MAX_GOP) ? gop : MAX_GOP;
103+ rc_ = rc;
104+ qp_ = qp;
105+ qp_min_ = qp_min;
106+ qp_max_ = qp_max;
98107 enable4K_ = width > 1920 && height > 1080 ;
99108 }
100109
@@ -259,10 +268,29 @@ class AMFEncoder {
259268 AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH, eDepth_);
260269 AMF_CHECK_RETURN (res,
261270 " SetProperty(AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH failed" );
262- res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
263- AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR);
264- AMF_CHECK_RETURN (res,
265- " SetProperty AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD" );
271+ if (rc_ == RC_CQP) {
272+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
273+ AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP);
274+ AMF_CHECK_RETURN (res,
275+ " SetProperty AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD" );
276+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_QP_I, (amf_int64)qp_);
277+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_QP_I" );
278+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_QP_P, (amf_int64)qp_);
279+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_QP_P" );
280+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_QP_B, (amf_int64)qp_);
281+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_QP_B" );
282+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_MIN_QP, (amf_int64)qp_min_);
283+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_MIN_QP" );
284+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_MAX_QP, (amf_int64)qp_max_);
285+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_MAX_QP" );
286+ } else {
287+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
288+ (rc_ == RC_VBR)
289+ ? AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR
290+ : AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR);
291+ AMF_CHECK_RETURN (res,
292+ " SetProperty AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD" );
293+ }
266294 if (enable4K_) {
267295 res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_PROFILE,
268296 AMF_VIDEO_ENCODER_PROFILE_HIGH);
@@ -311,6 +339,12 @@ class AMFEncoder {
311339 bitRateIn_);
312340 AMF_CHECK_RETURN (res,
313341 " SetProperty AMF_VIDEO_ENCODER_TARGET_BITRATE failed" );
342+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_PEAK_BITRATE,
343+ (rc_ == RC_VBR)
344+ ? util_encode::calc_vbr_max_rate (bitRateIn_)
345+ : (int64_t )bitRateIn_);
346+ AMF_CHECK_RETURN (res,
347+ " SetProperty AMF_VIDEO_ENCODER_PEAK_BITRATE failed" );
314348 res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_FRAMERATE,
315349 ::AMFConstructRate (frameRate_, 1 ));
316350 AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_FRAMERATE failed" );
@@ -348,11 +382,33 @@ class AMFEncoder {
348382 AMF_CHECK_RETURN (
349383 res, " SetProperty AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH failed" );
350384
351- res = AMFEncoder_->SetProperty (
352- AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD,
353- AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR);
354- AMF_CHECK_RETURN (
355- res, " SetProperty AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD failed" );
385+ if (rc_ == RC_CQP) {
386+ res = AMFEncoder_->SetProperty (
387+ AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD,
388+ AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP);
389+ AMF_CHECK_RETURN (
390+ res, " SetProperty AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD failed" );
391+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_QP_I, (amf_int64)qp_);
392+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_QP_I" );
393+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_QP_P, (amf_int64)qp_);
394+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_QP_P" );
395+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, (amf_int64)qp_min_);
396+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_MIN_QP_I" );
397+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, (amf_int64)qp_min_);
398+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_MIN_QP_P" );
399+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, (amf_int64)qp_max_);
400+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_MAX_QP_I" );
401+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, (amf_int64)qp_max_);
402+ AMF_CHECK_RETURN (res, " SetProperty AMF_VIDEO_ENCODER_HEVC_MAX_QP_P" );
403+ } else {
404+ res = AMFEncoder_->SetProperty (
405+ AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD,
406+ (rc_ == RC_VBR)
407+ ? AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR
408+ : AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR);
409+ AMF_CHECK_RETURN (
410+ res, " SetProperty AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD failed" );
411+ }
356412
357413 if (enable4K_) {
358414 res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_TIER,
@@ -404,6 +460,12 @@ class AMFEncoder {
404460 bitRateIn_);
405461 AMF_CHECK_RETURN (
406462 res, " SetProperty AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE failed" );
463+ res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE,
464+ (rc_ == RC_VBR)
465+ ? util_encode::calc_vbr_max_rate (bitRateIn_)
466+ : (int64_t )bitRateIn_);
467+ AMF_CHECK_RETURN (
468+ res, " SetProperty AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE failed" );
407469
408470 res = AMFEncoder_->SetProperty (AMF_VIDEO_ENCODER_HEVC_FRAMERATE,
409471 ::AMFConstructRate (frameRate_, 1 ));
@@ -471,9 +533,11 @@ int amf_destroy_encoder(void *encoder) {
471533
472534void *amf_new_encoder (void *handle, int64_t luid,
473535 DataFormat dataFormat, int32_t width, int32_t height,
474- int32_t kbs, int32_t framerate, int32_t gop) {
536+ int32_t kbs, int32_t framerate, int32_t gop,
537+ int32_t rc, int32_t qp, int32_t qp_min, int32_t qp_max) {
475538 AMFEncoder *enc = NULL ;
476539 try {
540+ util_encode::sanitize_qp (qp, qp_min, qp_max);
477541 amf_wstring codecStr;
478542 if (!convert_codec (dataFormat, codecStr)) {
479543 return NULL ;
@@ -483,7 +547,7 @@ void *amf_new_encoder(void *handle, int64_t luid,
483547 return NULL ;
484548 }
485549 enc = new AMFEncoder (handle, memoryType, codecStr, dataFormat, width,
486- height, kbs * 1000 , framerate, gop);
550+ height, kbs * 1000 , framerate, gop, rc, qp, qp_min, qp_max );
487551 if (enc) {
488552 if (AMF_OK == enc->initialize ()) {
489553 return enc;
@@ -527,7 +591,8 @@ int amf_driver_support() {
527591int amf_test_encode (int64_t *outLuids, int32_t *outVendors, int32_t maxDescNum, int32_t *outDescNum,
528592 DataFormat dataFormat, int32_t width,
529593 int32_t height, int32_t kbs, int32_t framerate,
530- int32_t gop, const int64_t *excludedLuids, const int32_t *excludeFormats, int32_t excludeCount) {
594+ int32_t gop, int32_t rc, int32_t qp, int32_t qp_min, int32_t qp_max,
595+ const int64_t *excludedLuids, const int32_t *excludeFormats, int32_t excludeCount) {
531596 try {
532597 Adapters adapters;
533598 if (!adapters.Init (ADAPTER_VENDOR_AMD))
@@ -541,7 +606,7 @@ int amf_test_encode(int64_t *outLuids, int32_t *outVendors, int32_t maxDescNum,
541606
542607 AMFEncoder *e = (AMFEncoder *)amf_new_encoder (
543608 (void *)adapter.get ()->device_ .Get (), currentLuid,
544- dataFormat, width, height, kbs, framerate, gop);
609+ dataFormat, width, height, kbs, framerate, gop, rc, qp, qp_min, qp_max );
545610 if (!e)
546611 continue ;
547612 if (e->test () == AMF_OK) {
@@ -568,14 +633,21 @@ int amf_set_bitrate(void *encoder, int32_t kbs) {
568633 try {
569634 AMFEncoder *enc = (AMFEncoder *)encoder;
570635 AMF_RESULT res = AMF_FAIL;
636+ int64_t peakBitrate = (enc->rc_ == RC_VBR)
637+ ? util_encode::calc_vbr_max_rate (kbs * 1000 )
638+ : (int64_t )(kbs * 1000 );
571639 switch (enc->dataFormat_ ) {
572640 case H264:
573641 res = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_TARGET_BITRATE,
574642 kbs * 1000 );
643+ enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_PEAK_BITRATE,
644+ peakBitrate);
575645 break ;
576646 case H265:
577647 res = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE,
578648 kbs * 1000 );
649+ enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE,
650+ peakBitrate);
579651 break ;
580652 }
581653 return res == AMF_OK ? 0 : -1 ;
@@ -586,6 +658,75 @@ int amf_set_bitrate(void *encoder, int32_t kbs) {
586658 return -1 ;
587659}
588660
661+ int amf_set_qp (void *encoder, int32_t qp, int32_t qp_min, int32_t qp_max) {
662+ try {
663+ util_encode::sanitize_qp (qp, qp_min, qp_max);
664+ AMFEncoder *enc = (AMFEncoder *)encoder;
665+ AMF_RESULT res = AMF_OK;
666+ auto set_prop_checked = [&](const char *name, AMF_RESULT r) {
667+ if (r != AMF_OK) {
668+ LOG_ERROR (std::string (" set qp property failed: " ) +
669+ name + " , result code: " + std::to_string ((int )r));
670+ res = r;
671+ }
672+ };
673+ switch (enc->dataFormat_ ) {
674+ case H264: {
675+ AMF_RESULT r = AMF_FAIL;
676+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_QP_I, (amf_int64)qp);
677+ set_prop_checked (" AMF_VIDEO_ENCODER_QP_I" , r);
678+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_QP_P, (amf_int64)qp);
679+ set_prop_checked (" AMF_VIDEO_ENCODER_QP_P" , r);
680+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_QP_B, (amf_int64)qp);
681+ set_prop_checked (" AMF_VIDEO_ENCODER_QP_B" , r);
682+ if (qp_min > 0 ) {
683+ r = enc->AMFEncoder_ ->SetProperty (
684+ AMF_VIDEO_ENCODER_MIN_QP, (amf_int64)(qp_min > 51 ? 51 : qp_min));
685+ set_prop_checked (" AMF_VIDEO_ENCODER_MIN_QP" , r);
686+ }
687+ if (qp_max > 0 ) {
688+ r = enc->AMFEncoder_ ->SetProperty (
689+ AMF_VIDEO_ENCODER_MAX_QP, (amf_int64)(qp_max > 51 ? 51 : qp_max));
690+ set_prop_checked (" AMF_VIDEO_ENCODER_MAX_QP" , r);
691+ }
692+ break ;
693+ }
694+ case H265: {
695+ AMF_RESULT r = AMF_FAIL;
696+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_QP_I, (amf_int64)qp);
697+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_QP_I" , r);
698+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_QP_P, (amf_int64)qp);
699+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_QP_P" , r);
700+ if (qp_min > 0 ) {
701+ amf_int64 v = qp_min > 51 ? 51 : qp_min;
702+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, v);
703+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_MIN_QP_I" , r);
704+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, v);
705+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_MIN_QP_P" , r);
706+ }
707+ if (qp_max > 0 ) {
708+ amf_int64 v = qp_max > 51 ? 51 : qp_max;
709+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, v);
710+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_MAX_QP_I" , r);
711+ r = enc->AMFEncoder_ ->SetProperty (AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, v);
712+ set_prop_checked (" AMF_VIDEO_ENCODER_HEVC_MAX_QP_P" , r);
713+ }
714+ break ;
715+ }
716+ default :
717+ res = AMF_FAIL;
718+ LOG_ERROR (std::string (" set qp failed: unsupported data format " ) +
719+ std::to_string ((int )enc->dataFormat_ ));
720+ break ;
721+ }
722+ return res == AMF_OK ? 0 : -1 ;
723+ } catch (const std::exception &e) {
724+ LOG_ERROR (std::string (" set qp to " ) + std::to_string (qp) +
725+ " failed: " + e.what ());
726+ }
727+ return -1 ;
728+ }
729+
589730int amf_set_framerate (void *encoder, int32_t framerate) {
590731 try {
591732 AMFEncoder *enc = (AMFEncoder *)encoder;
@@ -608,4 +749,4 @@ int amf_set_framerate(void *encoder, int32_t framerate) {
608749 return -1 ;
609750}
610751
611- } // extern "C"
752+ } // extern "C"
0 commit comments