diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.c b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.c index 3e3fc5fc76..540ded828f 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.c @@ -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 }, diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.h b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.h index 42f49c2259..4857145441 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkencoder-private.h @@ -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); diff --git a/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh264.c b/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh264.c index d7711a07df..30ac4daf97 100644 --- a/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh264.c +++ b/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh264.c @@ -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); diff --git a/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh265.c b/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh265.c index 669ab1f858..9eaa68524e 100644 --- a/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh265.c +++ b/subprojects/gst-plugins-bad/tests/check/libs/vkvideoencodeh265.c @@ -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);