vkencoder-private: enhance algorithm to get the slot index

The algorithm for generating the current slot index is a simple round robin,
nonetheless it's not assured that the next slot index it's not still used by a
still living encode picture.

This new way holds an array with the still living encode pictures and the next
slot index looks for a released index in the array.

Its downside is deallocating a picture need to be removed from the array, so the
helper has to be passed to the uninit() function

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8007>
This commit is contained in:
Víctor Manuel Jáquez Leal 2024-09-19 13:28:15 +02:00 committed by GStreamer Marge Bot
parent d4de932664
commit 8fc2af44c8
4 changed files with 47 additions and 34 deletions

View file

@ -61,7 +61,7 @@ struct _GstVulkanEncoderPrivate
gboolean vk_loaded;
GstVulkanVideoFunctions vk;
gint current_slot_index;
GstVulkanEncoderPicture *slots[32];
gboolean started;
gboolean first_encode_cmd;
@ -436,14 +436,26 @@ gst_vulkan_encoder_picture_init (GstVulkanEncoderPicture * pic,
/**
* gst_vulkan_encoder_picture_clear:
* @pic: the #GstVulkanEncoderPicture to free.
* @self: the #GstVulkanEncoder instance.
*
* Release data of @pic.
*/
void
gst_vulkan_encoder_picture_clear (GstVulkanEncoderPicture * pic)
gst_vulkan_encoder_picture_clear (GstVulkanEncoderPicture * pic,
GstVulkanEncoder * self)
{
GstVulkanEncoderPrivate *priv;
g_return_if_fail (GST_IS_VULKAN_ENCODER (self));
g_return_if_fail (pic != NULL);
priv = gst_vulkan_encoder_get_instance_private (self);
if (pic->dpb_slot.slotIndex > 0) {
priv->slots[pic->dpb_slot.slotIndex] = NULL;
pic->dpb_slot.slotIndex = -1;
}
gst_clear_buffer (&pic->in_buffer);
gst_clear_buffer (&pic->dpb_buffer);
gst_clear_buffer (&pic->out_buffer);
@ -1069,7 +1081,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
GError *err = NULL;
gboolean ret = TRUE;
GstMemory *mem;
int i;
int i, slot_index = -1;
GstVulkanEncodeQueryResult *encode_res;
VkVideoEncodeRateControlLayerInfoKHR rate_control_layer;
VkVideoEncodeQualityLevelInfoKHR quality_level_info;
@ -1077,7 +1089,6 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
VkVideoBeginCodingInfoKHR begin_coding;
VkVideoEncodeInfoKHR encode_info;
VkVideoEndCodingInfoKHR end_coding;
gint maxDpbSlots;
VkVideoReferenceSlotInfoKHR ref_slots[37];
GstVulkanCommandBuffer *cmd_buf;
GArray *barriers;
@ -1087,8 +1098,6 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
priv = gst_vulkan_encoder_get_instance_private (self);
maxDpbSlots = priv->layered_dpb ? 2 : priv->caps.caps.maxDpbSlots;
/* initialize the vulkan operation */
if (!gst_vulkan_operation_begin (priv->exec, &err))
goto bail;
@ -1108,7 +1117,6 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
/* First run, some information such as rate_control and slot index must be initialized. */
if (!priv->first_encode_cmd) {
priv->current_slot_index = 0;
GST_OBJECT_LOCK (self);
/* *INDENT-OFF* */
rate_control_layer = (VkVideoEncodeRateControlLayerInfoKHR) {
@ -1150,6 +1158,16 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
g_assert (pic->in_buffer && pic->img_view);
g_assert (pic->out_buffer);
/* Attribute a free slot index to the picture to be used later as a reference.
* The picture is kept until it remains useful to the encoding process.*/
for (i = 0; i < priv->caps.caps.maxDpbSlots; i++) {
if (!priv->slots[i]) {
priv->slots[i] = pic;
slot_index = i;
break;
}
}
/* Set the ref slots according to the pic refs to bound the video
session encoding. It should contain all the references + 1 to book
a new slotIndex (-1) for the current picture. */
@ -1168,7 +1186,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
pic->dpb_slot = (VkVideoReferenceSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
.pNext = pic->codec_dpb_slot_info,
.slotIndex = priv->current_slot_index,
.slotIndex = slot_index,
.pPictureResource = &pic->dpb,
};
/* *INDENT-ON* */
@ -1229,12 +1247,6 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
/* Peek the output memory to be used by VkVideoEncodeInfoKHR.dstBuffer */
mem = gst_buffer_peek_memory (pic->out_buffer, 0);
/* Attribute a free slot index to the picture to be used later as a reference.
* The picture is kept until it remains useful to the encoding process.*/
priv->current_slot_index++;
if (priv->current_slot_index >= maxDpbSlots)
priv->current_slot_index = 0;
/* Setup the encode info */
/* *INDENT-OFF* */
encode_info = (VkVideoEncodeInfoKHR) {
@ -1244,7 +1256,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
.dstBuffer = ((GstVulkanBufferMemory *) mem)->buffer,
.dstBufferOffset = pic->offset,
.dstBufferRange = gst_memory_get_sizes (mem, NULL, NULL),
.srcPictureResource = (VkVideoPictureResourceInfoKHR) { // SPEC: this should be separate
.srcPictureResource = (VkVideoPictureResourceInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
.pNext = NULL,
.codedOffset = { 0, 0 },

View file

@ -168,4 +168,5 @@ gboolean gst_vulkan_encoder_picture_init (GstVulkanEncode
GstBuffer * in_buffer,
gsize size);
GST_VULKAN_API
void gst_vulkan_encoder_picture_clear (GstVulkanEncoderPicture * pic);
void gst_vulkan_encoder_picture_clear (GstVulkanEncoderPicture * pic,
GstVulkanEncoder * self);

View file

@ -79,11 +79,11 @@ _h264_encode_frame_new (GstVulkanEncoder * enc, GstBuffer * img_buffer,
}
static void
_h264_encode_frame_free (gpointer pframe)
_h264_encode_frame_free (GstVulkanEncoder * enc, gpointer pframe)
{
GstVulkanH264EncodeFrame *frame = pframe;
gst_vulkan_encoder_picture_clear (&frame->picture);
gst_vulkan_encoder_picture_clear (&frame->picture, enc);
g_free (frame);
}
@ -803,7 +803,7 @@ GST_START_TEST (test_encoder_h264_i)
check_encoded_frame (frame, GST_H264_NAL_SLICE_IDR);
frame_num++;
_h264_encode_frame_free (frame);
_h264_encode_frame_free (enc, frame);
}
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
@ -855,12 +855,12 @@ GST_START_TEST (test_encoder_h264_i_p)
encode_frame (enc, frame, STD_VIDEO_H264_SLICE_TYPE_P,
frame_num, list0, list0_num, NULL, 0, sps_id, pps_id);
check_encoded_frame (frame, GST_H264_NAL_SLICE);
_h264_encode_frame_free (list0[0]);
_h264_encode_frame_free (enc, list0[0]);
list0[0] = frame;
frame_num++;
}
_h264_encode_frame_free (list0[0]);
_h264_encode_frame_free (enc, list0[0]);
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
gst_object_unref (buffer_pool);
@ -931,7 +931,7 @@ GST_START_TEST (test_encoder_h264_i_p_b)
frame_num, list0, list0_num, list1, list1_num, sps_id, pps_id);
check_encoded_frame (frame, GST_H264_NAL_SLICE);
frame_num++;
_h264_encode_frame_free (frame);
_h264_encode_frame_free (enc, frame);
/* Encode third picture as a B-Frame */
frame = allocate_frame (enc, width, height, FALSE);
@ -942,10 +942,10 @@ GST_START_TEST (test_encoder_h264_i_p_b)
frame_num, list0, list0_num, list1, list1_num, sps_id, pps_id);
check_encoded_frame (frame, GST_H264_NAL_SLICE);
frame_num++;
_h264_encode_frame_free (frame);
_h264_encode_frame_free (enc, frame);
_h264_encode_frame_free (list0[0]);
_h264_encode_frame_free (list1[0]);
_h264_encode_frame_free (enc, list0[0]);
_h264_encode_frame_free (enc, list1[0]);
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
gst_object_unref (buffer_pool);

View file

@ -84,11 +84,11 @@ _h265_encode_frame_new (GstVulkanEncoder * enc, GstBuffer * img_buffer,
}
static void
_h265_encode_frame_free (gpointer pframe)
_h265_encode_frame_free (GstVulkanEncoder * enc, gpointer pframe)
{
GstVulkanH265EncodeFrame *frame = pframe;
gst_vulkan_encoder_picture_clear (&frame->picture);
gst_vulkan_encoder_picture_clear (&frame->picture, enc);
g_free (frame);
}
@ -975,7 +975,7 @@ GST_START_TEST (test_encoder_h265_i)
check_encoded_frame (frame, GST_H265_NAL_SLICE_IDR_W_RADL);
frame_num++;
_h265_encode_frame_free (frame);
_h265_encode_frame_free (enc, frame);
}
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
@ -1026,11 +1026,11 @@ GST_START_TEST (test_encoder_h265_i_p)
encode_frame (enc, frame, STD_VIDEO_H265_SLICE_TYPE_P,
frame_num, list0, list0_num, NULL, 0, vps_id, sps_id, pps_id);
check_encoded_frame (frame, GST_H265_NAL_SLICE_TRAIL_R);
_h265_encode_frame_free (list0[0]);
_h265_encode_frame_free (enc, list0[0]);
list0[0] = frame;
frame_num++;
}
_h265_encode_frame_free (list0[0]);
_h265_encode_frame_free (enc, list0[0]);
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
gst_object_unref (buffer_pool);
fail_unless (gst_buffer_pool_set_active (img_pool, FALSE));
@ -1098,7 +1098,7 @@ GST_START_TEST (test_encoder_h265_i_p_b)
frame_num, list0, list0_num, list1, list1_num, vps_id, sps_id, pps_id);
check_encoded_frame (frame, GST_H265_NAL_SLICE_TRAIL_N);
frame_num++;
_h265_encode_frame_free (frame);
_h265_encode_frame_free (enc, frame);
/* Encode 3rd picture as a B-Frame */
frame = allocate_frame (enc, width, height, FALSE);
@ -1107,10 +1107,10 @@ GST_START_TEST (test_encoder_h265_i_p_b)
frame_num, list0, list0_num, list1, list1_num, vps_id, sps_id, pps_id);
check_encoded_frame (frame, GST_H265_NAL_SLICE_TRAIL_N);
frame_num++;
_h265_encode_frame_free (frame);
_h265_encode_frame_free (enc, frame);
_h265_encode_frame_free (list0[0]);
_h265_encode_frame_free (list1[0]);
_h265_encode_frame_free (enc, list0[0]);
_h265_encode_frame_free (enc, list1[0]);
fail_unless (gst_buffer_pool_set_active (buffer_pool, FALSE));
gst_object_unref (buffer_pool);