From 6fe35ad59d3fdca467a1b36fbe995c62d65a36d0 Mon Sep 17 00:00:00 2001 From: Fan F He Date: Fri, 29 Apr 2022 19:27:16 +0800 Subject: [PATCH] msdkenc: Enable LowDelayBrc and MaxFrameSize for I/P frame Enable these features for accurate bitrate control. Feature introduction of LowDelayBRC, MaxFrameSizeI and MaxFrameSizeP could be found here: https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md Signed-off-by: Fan F He Part-of: --- .../gst-plugins-bad/sys/msdk/gstmsdkenc.c | 50 +++++++++++++++++++ .../gst-plugins-bad/sys/msdk/gstmsdkenc.h | 6 +++ .../gst-plugins-bad/sys/msdk/gstmsdkh264enc.c | 4 ++ .../gst-plugins-bad/sys/msdk/gstmsdkh265enc.c | 7 +++ .../gst-plugins-bad/sys/msdk/gstmsdkh265enc.h | 2 + .../gst-plugins-bad/sys/msdk/msdk-enums.c | 18 +++++++ .../gst-plugins-bad/sys/msdk/msdk-enums.h | 3 ++ 7 files changed, 90 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c index b7bee4327a..80b5c59a3d 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c @@ -113,7 +113,10 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", #define PROP_RC_LOOKAHEAD_DEPTH_DEFAULT 10 #define PROP_MAX_VBV_BITRATE_DEFAULT 0 #define PROP_MAX_FRAME_SIZE_DEFAULT 0 +#define PROP_MAX_FRAME_SIZE_I_DEFAULT 0 +#define PROP_MAX_FRAME_SIZE_P_DEFAULT 0 #define PROP_MBBRC_DEFAULT MFX_CODINGOPTION_OFF +#define PROP_LOWDELAY_BRC_DEFAULT MFX_CODINGOPTION_OFF #define PROP_ADAPTIVE_I_DEFAULT MFX_CODINGOPTION_OFF #define PROP_ADAPTIVE_B_DEFAULT MFX_CODINGOPTION_OFF @@ -222,7 +225,15 @@ ensure_bitrate_control (GstMsdkEnc * thiz) break; case MFX_RATECONTROL_VBR: + thiz->enable_extopt3 = TRUE; option2->MaxFrameSize = thiz->max_frame_size * 1000; + if (thiz->max_frame_size_i > 0) + option3->MaxFrameSizeI = thiz->max_frame_size_i * 1000; + if (thiz->max_frame_size_p > 0) + option3->MaxFrameSizeP = thiz->max_frame_size_p * 1000; + if (thiz->lowdelay_brc != MFX_CODINGOPTION_UNKNOWN) { + option3->LowDelayBRC = thiz->lowdelay_brc; + } break; case MFX_RATECONTROL_VCM: @@ -2282,6 +2293,8 @@ gst_msdkenc_init (GstMsdkEnc * thiz) thiz->rate_control = PROP_RATE_CONTROL_DEFAULT; thiz->bitrate = PROP_BITRATE_DEFAULT; thiz->max_frame_size = PROP_MAX_FRAME_SIZE_DEFAULT; + thiz->max_frame_size_i = PROP_MAX_FRAME_SIZE_I_DEFAULT; + thiz->max_frame_size_p = PROP_MAX_FRAME_SIZE_P_DEFAULT; thiz->max_vbv_bitrate = PROP_MAX_VBV_BITRATE_DEFAULT; thiz->accuracy = PROP_AVBR_ACCURACY_DEFAULT; thiz->convergence = PROP_AVBR_ACCURACY_DEFAULT; @@ -2295,6 +2308,7 @@ gst_msdkenc_init (GstMsdkEnc * thiz) thiz->b_frames = PROP_B_FRAMES_DEFAULT; thiz->num_slices = PROP_NUM_SLICES_DEFAULT; thiz->mbbrc = PROP_MBBRC_DEFAULT; + thiz->lowdelay_brc = PROP_LOWDELAY_BRC_DEFAULT; thiz->adaptive_i = PROP_ADAPTIVE_I_DEFAULT; thiz->adaptive_b = PROP_ADAPTIVE_B_DEFAULT; @@ -2351,6 +2365,12 @@ gst_msdkenc_set_common_property (GObject * object, guint prop_id, case GST_MSDKENC_PROP_MAX_FRAME_SIZE: thiz->max_frame_size = g_value_get_uint (value); break; + case GST_MSDKENC_PROP_MAX_FRAME_SIZE_I: + thiz->max_frame_size_i = g_value_get_uint (value); + break; + case GST_MSDKENC_PROP_MAX_FRAME_SIZE_P: + thiz->max_frame_size_p = g_value_get_uint (value); + break; case GST_MSDKENC_PROP_MAX_VBV_BITRATE: thiz->max_vbv_bitrate = g_value_get_uint (value); break; @@ -2390,6 +2410,9 @@ gst_msdkenc_set_common_property (GObject * object, guint prop_id, case GST_MSDKENC_PROP_MBBRC: thiz->mbbrc = g_value_get_enum (value); break; + case GST_MSDKENC_PROP_LOWDELAY_BRC: + thiz->lowdelay_brc = g_value_get_enum (value); + break; case GST_MSDKENC_PROP_ADAPTIVE_I: thiz->adaptive_i = g_value_get_enum (value); break; @@ -2454,6 +2477,12 @@ gst_msdkenc_get_common_property (GObject * object, guint prop_id, case GST_MSDKENC_PROP_MAX_FRAME_SIZE: g_value_set_uint (value, thiz->max_frame_size); break; + case GST_MSDKENC_PROP_MAX_FRAME_SIZE_I: + g_value_set_uint (value, thiz->max_frame_size_i); + break; + case GST_MSDKENC_PROP_MAX_FRAME_SIZE_P: + g_value_set_uint (value, thiz->max_frame_size_p); + break; case GST_MSDKENC_PROP_MAX_VBV_BITRATE: g_value_set_uint (value, thiz->max_vbv_bitrate); break; @@ -2493,6 +2522,9 @@ gst_msdkenc_get_common_property (GObject * object, guint prop_id, case GST_MSDKENC_PROP_MBBRC: g_value_set_enum (value, thiz->mbbrc); break; + case GST_MSDKENC_PROP_LOWDELAY_BRC: + g_value_set_enum (value, thiz->lowdelay_brc); + break; case GST_MSDKENC_PROP_ADAPTIVE_I: g_value_set_enum (value, thiz->adaptive_i); break; @@ -2558,6 +2590,18 @@ gst_msdkenc_install_common_properties (GstMsdkEncClass * klass) 0, G_MAXUINT16, PROP_MAX_FRAME_SIZE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[GST_MSDKENC_PROP_MAX_FRAME_SIZE_I] = + g_param_spec_uint ("max-frame-size-i", "Max Frame Size for I frame", + "Maximum possible size (in kbyte) of I frames (0: auto-calculate)", + 0, G_MAXUINT16, PROP_MAX_FRAME_SIZE_I_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[GST_MSDKENC_PROP_MAX_FRAME_SIZE_P] = + g_param_spec_uint ("max-frame-size-p", "Max Frame Size for P frame", + "Maximum possible size (in kbyte) of P frames (0: auto-calculate)", + 0, G_MAXUINT16, PROP_MAX_FRAME_SIZE_P_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /* Set the same upper bound with bitrate */ obj_properties[GST_MSDKENC_PROP_MAX_VBV_BITRATE] = g_param_spec_uint ("max-vbv-bitrate", "Max VBV Bitrate", @@ -2637,6 +2681,12 @@ gst_msdkenc_install_common_properties (GstMsdkEncClass * klass) gst_msdkenc_mbbrc_get_type (), PROP_MBBRC_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[GST_MSDKENC_PROP_LOWDELAY_BRC] = + g_param_spec_enum ("lowdelay-brc", "Low delay bitrate control", + "Bitrate control for low-delay user scenarios", + gst_msdkenc_lowdelay_brc_get_type (), + PROP_LOWDELAY_BRC_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[GST_MSDKENC_PROP_ADAPTIVE_I] = g_param_spec_enum ("i-adapt", "Adaptive I-Frame Insertion", "Adaptive I-Frame Insertion control", diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.h b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.h index e16f4e0a78..705a6b0fb6 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.h @@ -84,6 +84,9 @@ enum GST_MSDKENC_PROP_ADAPTIVE_I, GST_MSDKENC_PROP_ADAPTIVE_B, GST_MSDKENC_PROP_EXT_CODING_PROPS, + GST_MSDKENC_PROP_LOWDELAY_BRC, + GST_MSDKENC_PROP_MAX_FRAME_SIZE_I, + GST_MSDKENC_PROP_MAX_FRAME_SIZE_P, GST_MSDKENC_PROP_MAX, }; @@ -159,6 +162,9 @@ struct _GstMsdkEnc gint16 mbbrc; gint16 adaptive_i; gint16 adaptive_b; + guint max_frame_size_i; + guint max_frame_size_p; + gint16 lowdelay_brc; GstStructure *ext_coding_props; diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh264enc.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh264enc.c index 713ca8faec..4dd30e6884 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh264enc.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh264enc.c @@ -404,6 +404,10 @@ gst_msdkh264enc_configure (GstMsdkEnc * encoder) (thiz->cabac ? MFX_CODINGOPTION_OFF : MFX_CODINGOPTION_ON); } + if (encoder->option3.LowDelayBRC == MFX_CODINGOPTION_ON) { + thiz->option.NalHrdConformance = MFX_CODINGOPTION_OFF; + } + gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & thiz->option); encoder->option2.Trellis = thiz->trellis ? thiz->trellis : MFX_TRELLIS_OFF; diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c index 5fca672aab..33dfcfe417 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c @@ -539,6 +539,13 @@ gst_msdkh265enc_configure (GstMsdkEnc * encoder) encoder->enable_extopt3 = TRUE; } + if (encoder->option3.LowDelayBRC == MFX_CODINGOPTION_ON) { + h265enc->option.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + h265enc->option.Header.BufferSz = sizeof (h265enc->option); + h265enc->option.NalHrdConformance = MFX_CODINGOPTION_OFF; + gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->option); + } + gst_msdkenc_ensure_extended_coding_options (encoder); if (h265enc->num_tile_rows > 1 || h265enc->num_tile_cols > 1) { diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h index 96ae345ccf..ef241a7cc2 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h @@ -75,6 +75,8 @@ struct _GstMsdkH265Enc mfxExtHEVCTiles ext_tiles; mfxExtHEVCParam ext_param; + + mfxExtCodingOption option; /* roi[0] for current ROI and roi[1] for previous ROI */ mfxExtEncoderROI roi[2]; diff --git a/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.c b/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.c index edd6f2eabe..cd0de2a4df 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.c +++ b/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.c @@ -140,6 +140,24 @@ gst_msdkenc_mbbrc_get_type (void) return type; } +GType +gst_msdkenc_lowdelay_brc_get_type (void) +{ + static GType type = 0; + + static const GEnumValue values[] = { + {MFX_CODINGOPTION_UNKNOWN, "SDK decides what to do", "auto"}, + {MFX_CODINGOPTION_OFF, "Disable LowDelay bit rate control", "off"}, + {MFX_CODINGOPTION_ON, "Enable LowDelay bit rate control ", "on"}, + {0, NULL, NULL} + }; + + if (!type) { + type = g_enum_register_static ("GstMsdkEncLowDelayBitrateControl", values); + } + return type; +} + GType gst_msdkenc_adaptive_i_get_type (void) { diff --git a/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.h b/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.h index 56027a90ee..967ed5a5bf 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.h +++ b/subprojects/gst-plugins-bad/sys/msdk/msdk-enums.h @@ -63,6 +63,9 @@ gst_msdkenc_rc_lookahead_ds_get_type (void); GType gst_msdkenc_mbbrc_get_type (void); +GType +gst_msdkenc_lowdelay_brc_get_type (void); + GType gst_msdkenc_adaptive_i_get_type (void);