diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h265.c b/gst-libs/gst/vaapi/gstvaapiencoder_h265.c index 82426d1a1c..603ab6c94e 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h265.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h265.c @@ -100,6 +100,8 @@ struct _GstVaapiEncoderH265 guint32 init_qp; guint32 min_qp; guint32 qp_i; + guint32 qp_ip; + guint32 qp_ib; guint32 num_slices; guint32 num_bframes; guint32 ctu_width; /* CTU == Coding Tree Unit */ @@ -1723,6 +1725,21 @@ add_slice_headers (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture, slice_param->max_num_merge_cand = 5; /* MaxNumMergeCand */ slice_param->slice_qp_delta = encoder->qp_i - encoder->init_qp; + if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP) { + if (picture->type == GST_VAAPI_PICTURE_TYPE_P) { + slice_param->slice_qp_delta += encoder->qp_ip; + } else if (picture->type == GST_VAAPI_PICTURE_TYPE_B) { + slice_param->slice_qp_delta += encoder->qp_ib; + } + if ((gint) encoder->init_qp + slice_param->slice_qp_delta < + (gint) encoder->min_qp) { + slice_param->slice_qp_delta = encoder->min_qp - encoder->init_qp; + } + /* TODO: max_qp could be provided as a property in the future */ + if ((gint) encoder->init_qp + slice_param->slice_qp_delta > 51) { + slice_param->slice_qp_delta = 51 - encoder->init_qp; + } + } slice_param->slice_fields.bits. slice_loop_filter_across_slices_enabled_flag = TRUE; @@ -2543,6 +2560,12 @@ gst_vaapi_encoder_h265_set_property (GstVaapiEncoder * base_encoder, case GST_VAAPI_ENCODER_H265_PROP_MIN_QP: encoder->min_qp = g_value_get_uint (value); break; + case GST_VAAPI_ENCODER_H265_PROP_QP_IP: + encoder->qp_ip = g_value_get_int (value); + break; + case GST_VAAPI_ENCODER_H265_PROP_QP_IB: + encoder->qp_ib = g_value_get_int (value); + break; case GST_VAAPI_ENCODER_H265_PROP_NUM_SLICES: encoder->num_slices = g_value_get_uint (value); break; @@ -2655,6 +2678,32 @@ gst_vaapi_encoder_h265_get_default_properties (void) "Minimum QP", "Minimum quantizer value", 1, 51, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiEncoderH265:qp-ip: + * + * The difference of QP between I and P Frame. + * This is available only on CQP mode. + */ + GST_VAAPI_ENCODER_PROPERTIES_APPEND (props, + GST_VAAPI_ENCODER_H265_PROP_QP_IP, + g_param_spec_int ("qp-ip", + "Difference of QP between I and P frame", + "Difference of QP between I and P frame (available only on CQP)", + -51, 51, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstVaapiEncoderH265:qp-ib: + * + * The difference of QP between I and B Frame. + * This is available only on CQP mode. + */ + GST_VAAPI_ENCODER_PROPERTIES_APPEND (props, + GST_VAAPI_ENCODER_H265_PROP_QP_IB, + g_param_spec_int ("qp-ib", + "Difference of QP between I and B frame", + "Difference of QP between I and B frame (available only on CQP)", + -51, 51, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* FIXME: there seems to be issues with multi-slice encoding */ /** * GstVaapiEncoderH265:num-slices: diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h265.h b/gst-libs/gst/vaapi/gstvaapiencoder_h265.h index f09081ee50..3496742a30 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h265.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h265.h @@ -43,6 +43,8 @@ typedef struct _GstVaapiEncoderH265 GstVaapiEncoderH265; * @GST_VAAPI_ENCODER_H265_PROP_NUM_REF_FRAMES: Maximum number of reference frames. * @GST_VAAPI_ENCODER_H265_PROP_CPB_LENGTH: Length of the CPB buffer * @GST_VAAPI_ENCODER_H265_PROP_MBBRC: Macroblock level Bitrate Control. + * @GST_VAAPI_ENCODER_H265_PROP_QP_IP: Difference of QP between I and P frame. + * @GST_VAAPI_ENCODER_H265_PROP_QP_IB: Difference of QP between I and B frame. * in milliseconds (uint). * * The set of H.265 encoder specific configurable properties. @@ -55,6 +57,8 @@ typedef enum { GST_VAAPI_ENCODER_H265_PROP_NUM_REF_FRAMES = -5, GST_VAAPI_ENCODER_H265_PROP_CPB_LENGTH = -7, GST_VAAPI_ENCODER_H265_PROP_MBBRC = -8, + GST_VAAPI_ENCODER_H265_PROP_QP_IP = -9, + GST_VAAPI_ENCODER_H265_PROP_QP_IB = -10, } GstVaapiEncoderH265Prop; GstVaapiEncoder *