mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
vkencoder-private: implement callback to chain control rate structures
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8007>
This commit is contained in:
parent
b99276a7f9
commit
e03b124c10
4 changed files with 176 additions and 9 deletions
|
@ -55,6 +55,7 @@ struct _GstVulkanEncoderPrivate
|
||||||
GstVulkanEncoderPicture *slots[32];
|
GstVulkanEncoderPicture *slots[32];
|
||||||
|
|
||||||
guint32 quality;
|
guint32 quality;
|
||||||
|
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode;
|
||||||
|
|
||||||
gboolean started;
|
gboolean started;
|
||||||
gboolean session_reset;
|
gboolean session_reset;
|
||||||
|
@ -127,6 +128,11 @@ gst_vulkan_encoder_finalize (GObject * object)
|
||||||
static void
|
static void
|
||||||
gst_vulkan_encoder_init (GstVulkanEncoder * self)
|
gst_vulkan_encoder_init (GstVulkanEncoder * self)
|
||||||
{
|
{
|
||||||
|
GstVulkanEncoderPrivate *priv;
|
||||||
|
|
||||||
|
priv = gst_vulkan_encoder_get_instance_private (self);
|
||||||
|
|
||||||
|
priv->rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -488,6 +494,53 @@ gst_vulkan_encoder_stop (GstVulkanEncoder * self)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
|
static const char *
|
||||||
|
_rate_control_mode_to_str (VkVideoEncodeRateControlModeFlagBitsKHR rc_mode)
|
||||||
|
{
|
||||||
|
const struct
|
||||||
|
{
|
||||||
|
VkVideoEncodeRateControlModeFlagBitsKHR mode;
|
||||||
|
const char *str;
|
||||||
|
} _RateControlMap[] = {
|
||||||
|
{VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR, "DEFAULT"},
|
||||||
|
#define F(mode) { G_PASTE(G_PASTE(VK_VIDEO_ENCODE_RATE_CONTROL_MODE_, mode), _BIT_KHR), G_STRINGIFY(mode) }
|
||||||
|
F (DISABLED),
|
||||||
|
F (CBR),
|
||||||
|
F (VBR),
|
||||||
|
#undef F
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i <= G_N_ELEMENTS (_RateControlMap); i++) {
|
||||||
|
if (rc_mode == _RateControlMap[i].mode)
|
||||||
|
return _RateControlMap[i].str;
|
||||||
|
}
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
_rate_control_mode_validate (GstVulkanEncoder * self,
|
||||||
|
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode)
|
||||||
|
{
|
||||||
|
GstVulkanEncoderPrivate *priv =
|
||||||
|
gst_vulkan_encoder_get_instance_private (self);
|
||||||
|
|
||||||
|
if (rc_mode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR
|
||||||
|
&& !(priv->caps.encoder.caps.rateControlModes & rc_mode)) {
|
||||||
|
rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR;
|
||||||
|
for (int i = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
|
||||||
|
i <= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; i++) {
|
||||||
|
if ((priv->caps.encoder.caps.rateControlModes) & i) {
|
||||||
|
GST_DEBUG_OBJECT (self, "rate control mode is forced to: %s",
|
||||||
|
_rate_control_mode_to_str (i));
|
||||||
|
rc_mode = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_vulkan_encoder_start:
|
* gst_vulkan_encoder_start:
|
||||||
* @self: a #GstVulkanEncoder
|
* @self: a #GstVulkanEncoder
|
||||||
|
@ -745,6 +798,9 @@ gst_vulkan_encoder_start (GstVulkanEncoder * self,
|
||||||
&priv->vk, &session_create, error))
|
&priv->vk, &session_create, error))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
/* check rate control mode if it was set before start */
|
||||||
|
_rate_control_mode_validate (self, priv->rc_mode);
|
||||||
|
|
||||||
priv->session_reset = TRUE;
|
priv->session_reset = TRUE;
|
||||||
priv->started = TRUE;
|
priv->started = TRUE;
|
||||||
|
|
||||||
|
@ -986,6 +1042,43 @@ bail:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_setup_rate_control (GstVulkanEncoder * self, GstVulkanEncoderPicture * pic,
|
||||||
|
GstVideoInfo * info, VkVideoEncodeRateControlInfoKHR * rc_info,
|
||||||
|
VkVideoEncodeRateControlLayerInfoKHR * rc_layer)
|
||||||
|
{
|
||||||
|
GstVulkanEncoderPrivate *priv;
|
||||||
|
|
||||||
|
priv = gst_vulkan_encoder_get_instance_private (self);
|
||||||
|
|
||||||
|
g_assert (priv->callbacks.setup_rc_pic);
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
*rc_info = (VkVideoEncodeRateControlInfoKHR) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR,
|
||||||
|
.rateControlMode = priv->rc_mode,
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
if (priv->rc_mode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
*rc_layer = (VkVideoEncodeRateControlLayerInfoKHR) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR,
|
||||||
|
.averageBitrate = 0, /* to be filled in callback */
|
||||||
|
.maxBitrate = 0, /* to be filled in callback */
|
||||||
|
.frameRateNumerator = GST_VIDEO_INFO_FPS_N (info),
|
||||||
|
.frameRateDenominator = GST_VIDEO_INFO_FPS_D (info),
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
rc_info->layerCount++;
|
||||||
|
rc_info->pLayers = rc_layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->callbacks.setup_rc_pic (pic, rc_info, rc_layer,
|
||||||
|
priv->callbacks_user_data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_vulkan_encoder_encode:
|
* gst_vulkan_encoder_encode:
|
||||||
* @self: a #GstVulkanEncoder
|
* @self: a #GstVulkanEncoder
|
||||||
|
@ -1018,6 +1111,8 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
|
||||||
GstVulkanCommandBuffer *cmd_buf;
|
GstVulkanCommandBuffer *cmd_buf;
|
||||||
GArray *barriers;
|
GArray *barriers;
|
||||||
VkVideoEncodeQualityLevelInfoKHR quality_info;
|
VkVideoEncodeQualityLevelInfoKHR quality_info;
|
||||||
|
VkVideoEncodeRateControlLayerInfoKHR rc_layer;
|
||||||
|
VkVideoEncodeRateControlInfoKHR rc_info;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_VULKAN_ENCODER (self), FALSE);
|
g_return_val_if_fail (GST_IS_VULKAN_ENCODER (self), FALSE);
|
||||||
g_return_val_if_fail (info != NULL && pic != NULL, FALSE);
|
g_return_val_if_fail (info != NULL && pic != NULL, FALSE);
|
||||||
|
@ -1028,25 +1123,23 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
|
||||||
if (!gst_vulkan_operation_begin (priv->exec, &err))
|
if (!gst_vulkan_operation_begin (priv->exec, &err))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
|
_setup_rate_control (self, pic, info, &rc_info, &rc_layer);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
quality_info = (VkVideoEncodeQualityLevelInfoKHR) {
|
quality_info = (VkVideoEncodeQualityLevelInfoKHR) {
|
||||||
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
|
||||||
.pNext = NULL,
|
.pNext = &rc_info,
|
||||||
.qualityLevel = priv->quality,
|
.qualityLevel = priv->quality,
|
||||||
};
|
};
|
||||||
coding_ctrl = (VkVideoCodingControlInfoKHR) {
|
coding_ctrl = (VkVideoCodingControlInfoKHR) {
|
||||||
.sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
|
||||||
.pNext = &quality_info,
|
.pNext = &quality_info,
|
||||||
.flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR
|
.flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR
|
||||||
|
| VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR
|
||||||
| VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
|
| VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
/* some information such as rate_control must be initialized. */
|
|
||||||
if (!priv->session_reset) {
|
|
||||||
/* begin_coding.pNext = &rate_control_info; */
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (pic->dpb_buffer && pic->dpb_view);
|
g_assert (pic->dpb_buffer && pic->dpb_view);
|
||||||
g_assert (pic->in_buffer && pic->img_view);
|
g_assert (pic->in_buffer && pic->img_view);
|
||||||
g_assert (pic->out_buffer);
|
g_assert (pic->out_buffer);
|
||||||
|
@ -1094,7 +1187,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
begin_coding = (VkVideoBeginCodingInfoKHR) {
|
begin_coding = (VkVideoBeginCodingInfoKHR) {
|
||||||
.sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
|
||||||
.pNext = NULL,
|
.pNext = !priv->session_reset ? &rc_info : NULL,
|
||||||
.videoSession = priv->session.session->handle,
|
.videoSession = priv->session.session->handle,
|
||||||
.videoSessionParameters = priv->session_params->handle,
|
.videoSessionParameters = priv->session_params->handle,
|
||||||
.referenceSlotCount = nb_refs + 1,
|
.referenceSlotCount = nb_refs + 1,
|
||||||
|
@ -1311,3 +1404,23 @@ gst_vulkan_encoder_set_callbacks (GstVulkanEncoder * self,
|
||||||
priv->callbacks_user_data = user_data;
|
priv->callbacks_user_data = user_data;
|
||||||
priv->callbacks_notify = notify;
|
priv->callbacks_notify = notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_vulkan_encoder_set_rc_mode (GstVulkanEncoder * self,
|
||||||
|
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode)
|
||||||
|
{
|
||||||
|
GstVulkanEncoderPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GST_IS_VULKAN_ENCODER (self));
|
||||||
|
|
||||||
|
priv = gst_vulkan_encoder_get_instance_private (self);
|
||||||
|
|
||||||
|
if (priv->rc_mode == rc_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->started)
|
||||||
|
_rate_control_mode_validate (self, rc_mode);
|
||||||
|
|
||||||
|
priv->session_reset = TRUE;
|
||||||
|
priv->rc_mode = rc_mode;
|
||||||
|
}
|
||||||
|
|
|
@ -45,6 +45,10 @@ typedef struct _GstVulkaneEncoderCallbacks GstVulkanEncoderCallbacks;
|
||||||
* @setup_codec_pic: Called after VkVideoEncodeInfoKHR and
|
* @setup_codec_pic: Called after VkVideoEncodeInfoKHR and
|
||||||
* VkVideoReferenceSlotInfoKHR are filled so they can be chained with the
|
* VkVideoReferenceSlotInfoKHR are filled so they can be chained with the
|
||||||
* specific codec structures. Called in gst_vulkan_encoder_encode().
|
* specific codec structures. Called in gst_vulkan_encoder_encode().
|
||||||
|
* @setup_rc_pic: Called after VkVideoEncodeRateControlInfoKHR and
|
||||||
|
* VkVideoEncodeRateControlLayerInfoKHR are filled so they can be chained
|
||||||
|
* with the specific codec structures. Called in
|
||||||
|
* gst_vulkan_encoder_encode().
|
||||||
*
|
*
|
||||||
* See gst_vulkan_encoder_set_callbacks()
|
* See gst_vulkan_encoder_set_callbacks()
|
||||||
*/
|
*/
|
||||||
|
@ -52,6 +56,9 @@ struct _GstVulkaneEncoderCallbacks
|
||||||
{
|
{
|
||||||
void (*setup_codec_pic) (GstVulkanEncoderPicture * pic,
|
void (*setup_codec_pic) (GstVulkanEncoderPicture * pic,
|
||||||
VkVideoEncodeInfoKHR * info, gpointer data);
|
VkVideoEncodeInfoKHR * info, gpointer data);
|
||||||
|
void (*setup_rc_pic) (GstVulkanEncoderPicture * pic,
|
||||||
|
VkVideoEncodeRateControlInfoKHR * info,
|
||||||
|
VkVideoEncodeRateControlLayerInfoKHR * layer, gpointer data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,6 +163,9 @@ void gst_vulkan_encoder_set_callbacks (GstVulkanEncode
|
||||||
GstVulkanEncoderCallbacks * callbacks,
|
GstVulkanEncoderCallbacks * callbacks,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
|
GST_VULKAN_API
|
||||||
|
void gst_vulkan_encoder_set_rc_mode (GstVulkanEncoder * self,
|
||||||
|
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode);
|
||||||
|
|
||||||
GST_VULKAN_API
|
GST_VULKAN_API
|
||||||
gboolean gst_vulkan_encoder_start (GstVulkanEncoder * self,
|
gboolean gst_vulkan_encoder_start (GstVulkanEncoder * self,
|
||||||
|
|
|
@ -405,6 +405,29 @@ setup_codec_pic (GstVulkanEncoderPicture * pic, VkVideoEncodeInfoKHR * info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_rc_codec (GstVulkanEncoderPicture * pic,
|
||||||
|
VkVideoEncodeRateControlInfoKHR * rc_info,
|
||||||
|
VkVideoEncodeRateControlLayerInfoKHR * rc_layer, gpointer data)
|
||||||
|
{
|
||||||
|
GstVulkanH264EncodeFrame *frame = (GstVulkanH264EncodeFrame *) pic;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
frame->rc_info = (VkVideoEncodeH264RateControlInfoKHR) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR,
|
||||||
|
.flags = VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
|
||||||
|
VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
|
||||||
|
.pNext = NULL,
|
||||||
|
.gopFrameCount = 1,
|
||||||
|
.idrPeriod = 1,
|
||||||
|
.consecutiveBFrameCount = 0,
|
||||||
|
.temporalLayerCount = 0,
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
rc_info->pNext = &frame->rc_info;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
|
encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
|
||||||
StdVideoH264SliceType slice_type, guint frame_num,
|
StdVideoH264SliceType slice_type, guint frame_num,
|
||||||
|
@ -415,7 +438,7 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
|
||||||
int i, ref_pics_num = 0;
|
int i, ref_pics_num = 0;
|
||||||
GstVulkanEncoderPicture *ref_pics[16] = { NULL, };
|
GstVulkanEncoderPicture *ref_pics[16] = { NULL, };
|
||||||
GstVulkanEncoderPicture *picture = &frame->picture;
|
GstVulkanEncoderPicture *picture = &frame->picture;
|
||||||
GstVulkanEncoderCallbacks cb = { setup_codec_pic };
|
GstVulkanEncoderCallbacks cb = { setup_codec_pic, setup_rc_codec };
|
||||||
|
|
||||||
GST_DEBUG ("Encoding frame num:%d", frame_num);
|
GST_DEBUG ("Encoding frame num:%d", frame_num);
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,27 @@ setup_codec_pic (GstVulkanEncoderPicture * pic, VkVideoEncodeInfoKHR * info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_rc_codec (GstVulkanEncoderPicture * pic,
|
||||||
|
VkVideoEncodeRateControlInfoKHR * rc_info,
|
||||||
|
VkVideoEncodeRateControlLayerInfoKHR * rc_layer, gpointer data)
|
||||||
|
{
|
||||||
|
GstVulkanH265EncodeFrame *frame = (GstVulkanH265EncodeFrame *) pic;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
frame->rc_info = (VkVideoEncodeH265RateControlInfoKHR) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR,
|
||||||
|
.flags = VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
|
||||||
|
VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
|
||||||
|
.pNext = NULL,
|
||||||
|
.gopFrameCount = 1,
|
||||||
|
.idrPeriod = 1,
|
||||||
|
.consecutiveBFrameCount = 0,
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
rc_info->pNext = &frame->rc_info;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
|
encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
|
||||||
|
@ -423,7 +444,7 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
|
||||||
gint16 delta_poc_s0_minus1 = 0, delta_poc_s1_minus1 = 0;
|
gint16 delta_poc_s0_minus1 = 0, delta_poc_s1_minus1 = 0;
|
||||||
GstVulkanEncoderPicture *picture = &frame->picture;
|
GstVulkanEncoderPicture *picture = &frame->picture;
|
||||||
gint picture_type = PICTURE_TYPE (slice_type, frame->is_ref);
|
gint picture_type = PICTURE_TYPE (slice_type, frame->is_ref);
|
||||||
GstVulkanEncoderCallbacks cb = { setup_codec_pic };
|
GstVulkanEncoderCallbacks cb = { setup_codec_pic, setup_rc_codec };
|
||||||
|
|
||||||
GST_DEBUG ("Encoding frame num: %d", frame_num);
|
GST_DEBUG ("Encoding frame num: %d", frame_num);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue