diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp index 18a36a4dea..86ba144795 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvh264enc.cpp @@ -246,6 +246,61 @@ gst_qsv_h264_enc_rc_lookahead_ds_get_type (void) return rc_lookahead_ds_type; } +/** + * GstQsvH264Trellis: + * + * Since: 1.24 + */ +#define GST_TYPE_QSV_H264_ENC_TRELLIS (gst_qsv_h264_enc_trellis_get_type ()) +static GType +gst_qsv_h264_enc_trellis_get_type (void) +{ + static GType trellis_type = 0; + static const GFlagsValue trellis[] = { + /** + * GstQsvH264Trellis::unknown + * + * Since: 1.22 + */ + {MFX_TRELLIS_UNKNOWN, "Unknown", "unknown"}, + + /** + * GstQsvH264Trellis::off + * + * Since: 1.24 + */ + {MFX_TRELLIS_OFF, "Disable for all frame types", "off"}, + + /** + * GstQsvH264Trellis::i + * + * Since: 1.24 + */ + {MFX_TRELLIS_I, "Enable for I frames", "i"}, + + /** + * GstQsvH264Trellis::p + * + * Since: 1.24 + */ + {MFX_TRELLIS_P, "Enable for P frames", "p"}, + + /** + * GstQsvH264Trellis::b + * + * Since: 1.24 + */ + {MFX_TRELLIS_B, "Enable for B frames", "b"}, + {0, nullptr, nullptr} + }; + + GST_QSV_CALL_ONCE_BEGIN { + trellis_type = g_flags_register_static ("GstQsvH264Trellis", trellis); + } GST_QSV_CALL_ONCE_END; + + return trellis_type; +} + enum { PROP_0, @@ -274,6 +329,15 @@ enum PROP_QVBR_QUALITY, PROP_DISABLE_HRD_CONFORMANCE, PROP_CC_INSERT, + PROP_TRELLIS, + PROP_MAX_FRAME_SIZE, + PROP_MAX_FRAME_SIZE_I, + PROP_MAX_FRAME_SIZE_P, + PROP_MAX_SLICE_SIZE, + PROP_NUM_SLICE, + PROP_NUM_SLICE_I, + PROP_NUM_SLICE_P, + PROP_NUM_SLICE_B, }; #define DEFAULT_CABAC MFX_CODINGOPTION_UNKNOWN @@ -293,6 +357,10 @@ enum #define DEFAULT_QVBR_QUALITY 0 #define DEFAULT_DISABLE_HRD_CONFORMANCE FALSE #define DEFAULT_CC_INSERT GST_QSV_H264_ENC_SEI_INSERT +#define DEFAULT_TRELLIS MFX_TRELLIS_UNKNOWN +#define DEFAULT_MAX_FRAME_SIZE 0 +#define DEFAULT_MAX_SLICE_SIZE 0 +#define DEFAULT_NUM_SLICE 0 #define DOC_SINK_CAPS_COMM \ "format = (string) NV12, " \ @@ -364,6 +432,15 @@ typedef struct _GstQsvH264Enc guint qvbr_quality; gboolean disable_hrd_conformance; GstQsvH264EncSeiInsertMode cc_insert; + mfxU16 trellis; + guint max_frame_size; + guint max_frame_size_i; + guint max_frame_size_p; + guint max_slice_size; + guint num_slice; + guint num_slice_i; + guint num_slice_p; + guint num_slice_b; } GstQsvH264Enc; typedef struct _GstQsvH264EncClass @@ -553,6 +630,110 @@ gst_qsv_h264_enc_class_init (GstQsvH264EncClass * klass, gpointer data) "Only CEA-708 RAW format is supported for now", GST_TYPE_QSV_H264_ENC_SEI_INSERT_MODE, DEFAULT_CC_INSERT, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + /** + * GstQsvH264Enc:trellis: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_TRELLIS, + g_param_spec_flags ("trellis", "Trellis", + "Trellis quantization mode", + GST_TYPE_QSV_H264_ENC_TRELLIS, DEFAULT_TRELLIS, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:max-frame-size: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_MAX_FRAME_SIZE, + g_param_spec_uint ("max-frame-size", "Max Frame Size", + "Maximum encoded frame size in bytes, " + "used for VBR based bitrate control modes", + 0, G_MAXUINT32, DEFAULT_MAX_FRAME_SIZE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:max-frame-size-i: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_MAX_FRAME_SIZE_I, + g_param_spec_uint ("max-frame-size-i", "Max Frame Size I", + "Maximum encoded I frame size in bytes, " + "used for VBR based bitrate control modes", + 0, G_MAXUINT32, DEFAULT_MAX_FRAME_SIZE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:max-frame-size-p: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_MAX_FRAME_SIZE_P, + g_param_spec_uint ("max-frame-size-p", "Max Frame Size P", + "Maximum encoded P and B frame size in bytes, " + "used for VBR based bitrate control modes. " + "\"max-frame-size-i\" must be non-zero, " + "otherwise this propert will be ignored", + 0, G_MAXUINT32, DEFAULT_MAX_FRAME_SIZE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:max-slice-size: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_MAX_SLICE_SIZE, + g_param_spec_uint ("max-slice-size", "Max Slice Size", + "Maximum slice size in bytes. If this parameter is specified other " + "controls over number of slices are ignored", + 0, G_MAXUINT32, DEFAULT_MAX_SLICE_SIZE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:num-slice: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_NUM_SLICE, + g_param_spec_uint ("num-slice", "Num Slice", + "Number of slices in each video frame", + 0, G_MAXUINT16, DEFAULT_NUM_SLICE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:num-slice-i: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_NUM_SLICE_I, + g_param_spec_uint ("num-slice-i", "Num Slice I", + "Number of slices for I frame", + 0, G_MAXUINT16, DEFAULT_NUM_SLICE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:num-slice-p: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_NUM_SLICE_P, + g_param_spec_uint ("num-slice-p", "Num Slice P", + "Number of slices for P frame", + 0, G_MAXUINT16, DEFAULT_NUM_SLICE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + /** + * GstQsvH264Enc:num-slice-b: + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_NUM_SLICE_B, + g_param_spec_uint ("num-slice-b", "Num Slice B", + "Number of slices for B frame", + 0, G_MAXUINT16, DEFAULT_NUM_SLICE, (GParamFlags) + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); parent_class = (GstElementClass *) g_type_class_peek_parent (klass); @@ -607,6 +788,8 @@ gst_qsv_h264_enc_class_init (GstQsvH264EncClass * klass, gpointer data) (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_QSV_H264_ENC_RC_LOOKAHEAD_DS, (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_QSV_H264_ENC_TRELLIS, + (GstPluginAPIFlags) 0); gst_caps_unref (cdata->sink_caps); gst_caps_unref (cdata->src_caps); @@ -642,6 +825,15 @@ gst_qsv_h264_enc_init (GstQsvH264Enc * self) self->qvbr_quality = DEFAULT_QVBR_QUALITY; self->disable_hrd_conformance = DEFAULT_DISABLE_HRD_CONFORMANCE; self->cc_insert = DEFAULT_CC_INSERT; + self->trellis = DEFAULT_TRELLIS; + self->max_frame_size = DEFAULT_MAX_FRAME_SIZE; + self->max_frame_size_i = DEFAULT_MAX_FRAME_SIZE; + self->max_frame_size_p = DEFAULT_MAX_FRAME_SIZE; + self->max_slice_size = DEFAULT_MAX_SLICE_SIZE; + self->num_slice = DEFAULT_NUM_SLICE; + self->num_slice_i = DEFAULT_NUM_SLICE; + self->num_slice_p = DEFAULT_NUM_SLICE; + self->num_slice_b = DEFAULT_NUM_SLICE; g_mutex_init (&self->prop_lock); @@ -809,6 +1001,42 @@ gst_qsv_h264_enc_set_property (GObject * object, guint prop_id, /* This property is unrelated to encoder-reset */ self->cc_insert = (GstQsvH264EncSeiInsertMode) g_value_get_enum (value); break; + case PROP_TRELLIS: + gst_qsv_h264_enc_check_update_enum (self, &self->trellis, + g_value_get_flags (value)); + break; + case PROP_MAX_FRAME_SIZE: + gst_qsv_h264_enc_check_update_uint (self, &self->max_frame_size, + g_value_get_uint (value), FALSE); + break; + case PROP_MAX_FRAME_SIZE_I: + gst_qsv_h264_enc_check_update_uint (self, &self->max_frame_size_i, + g_value_get_uint (value), FALSE); + break; + case PROP_MAX_FRAME_SIZE_P: + gst_qsv_h264_enc_check_update_uint (self, &self->max_frame_size_p, + g_value_get_uint (value), FALSE); + break; + case PROP_MAX_SLICE_SIZE: + gst_qsv_h264_enc_check_update_uint (self, &self->max_slice_size, + g_value_get_uint (value), FALSE); + break; + case PROP_NUM_SLICE: + gst_qsv_h264_enc_check_update_uint (self, &self->num_slice, + g_value_get_uint (value), FALSE); + break; + case PROP_NUM_SLICE_I: + gst_qsv_h264_enc_check_update_uint (self, &self->num_slice, + g_value_get_uint (value), FALSE); + break; + case PROP_NUM_SLICE_P: + gst_qsv_h264_enc_check_update_uint (self, &self->num_slice_p, + g_value_get_uint (value), FALSE); + break; + case PROP_NUM_SLICE_B: + gst_qsv_h264_enc_check_update_uint (self, &self->num_slice_b, + g_value_get_uint (value), FALSE); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -897,6 +1125,33 @@ gst_qsv_h264_enc_get_property (GObject * object, guint prop_id, GValue * value, case PROP_DISABLE_HRD_CONFORMANCE: g_value_set_boolean (value, self->disable_hrd_conformance); break; + case PROP_TRELLIS: + g_value_set_flags (value, self->trellis); + break; + case PROP_MAX_FRAME_SIZE: + g_value_set_uint (value, self->max_frame_size); + break; + case PROP_MAX_FRAME_SIZE_I: + g_value_set_uint (value, self->max_frame_size_i); + break; + case PROP_MAX_FRAME_SIZE_P: + g_value_set_uint (value, self->max_frame_size_p); + break; + case PROP_MAX_SLICE_SIZE: + g_value_set_uint (value, self->max_slice_size); + break; + case PROP_NUM_SLICE: + g_value_set_uint (value, self->num_slice); + break; + case PROP_NUM_SLICE_I: + g_value_set_uint (value, self->num_slice_i); + break; + case PROP_NUM_SLICE_P: + g_value_set_uint (value, self->num_slice_p); + break; + case PROP_NUM_SLICE_B: + g_value_set_uint (value, self->num_slice_b); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1375,6 +1630,7 @@ gst_qsv_h264_enc_set_format (GstQsvEncoder * encoder, param->mfx.GopPicSize = self->gop_size; param->mfx.IdrInterval = self->idr_interval; param->mfx.RateControlMethod = self->rate_control; + param->mfx.NumSlice = self->num_slice; param->mfx.NumRefFrame = self->ref_frames; gst_qsv_h264_enc_set_bitrate (self, param); @@ -1456,6 +1712,17 @@ gst_qsv_h264_enc_set_format (GstQsvEncoder * encoder, if (param->mfx.RateControlMethod == MFX_RATECONTROL_QVBR) option3->QVBRQuality = self->qvbr_quality; + option2->Trellis = self->trellis; + + option2->MaxFrameSize = self->max_frame_size; + option3->MaxFrameSizeI = self->max_frame_size_i; + if (self->max_frame_size_p && self->max_frame_size_i) + option3->MaxFrameSizeP = self->max_frame_size_p; + + option3->NumSliceI = self->num_slice_i; + option3->NumSliceP = self->num_slice_p; + option3->NumSliceB = self->num_slice_b; + if (signal_info) g_ptr_array_add (extra_params, signal_info); g_ptr_array_add (extra_params, option);