vkencoder-private: implement callback to chain codec specific structures

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8007>
This commit is contained in:
Víctor Manuel Jáquez Leal 2024-11-08 11:44:40 +01:00 committed by GStreamer Marge Bot
parent ab6aafb076
commit b99276a7f9
4 changed files with 127 additions and 42 deletions

View file

@ -37,6 +37,10 @@ struct _GstVulkanEncoderPrivate
GstCaps *profile_caps; GstCaps *profile_caps;
GstVulkanEncoderCallbacks callbacks;
gpointer callbacks_user_data;
GDestroyNotify callbacks_notify;
GstVulkanOperation *exec; GstVulkanOperation *exec;
GstVulkanVideoSession session; GstVulkanVideoSession session;
@ -106,6 +110,14 @@ static void
gst_vulkan_encoder_finalize (GObject * object) gst_vulkan_encoder_finalize (GObject * object)
{ {
GstVulkanEncoder *self = GST_VULKAN_ENCODER (object); GstVulkanEncoder *self = GST_VULKAN_ENCODER (object);
GstVulkanEncoderPrivate *priv =
gst_vulkan_encoder_get_instance_private (self);
if (priv->callbacks_user_data && priv->callbacks_notify) {
priv->callbacks_notify (priv->callbacks_user_data);
priv->callbacks_user_data = NULL;
priv->callbacks_notify = NULL;
}
gst_clear_object (&self->queue); gst_clear_object (&self->queue);
@ -1066,7 +1078,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
}; };
pic->dpb_slot = (VkVideoReferenceSlotInfoKHR) { pic->dpb_slot = (VkVideoReferenceSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
.pNext = pic->codec_dpb_slot_info, .pNext = NULL, /* to fill in callback */
.slotIndex = slot_index, .slotIndex = slot_index,
.pPictureResource = &pic->dpb, .pPictureResource = &pic->dpb,
}; };
@ -1110,7 +1122,7 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
/* *INDENT-OFF* */ /* *INDENT-OFF* */
encode_info = (VkVideoEncodeInfoKHR) { encode_info = (VkVideoEncodeInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR, .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR,
.pNext = pic->codec_pic_info, .pNext = NULL, /* to fill in callback */
.flags = 0x0, .flags = 0x0,
.dstBuffer = ((GstVulkanBufferMemory *) mem)->buffer, .dstBuffer = ((GstVulkanBufferMemory *) mem)->buffer,
.dstBufferOffset = pic->offset, .dstBufferOffset = pic->offset,
@ -1137,6 +1149,10 @@ gst_vulkan_encoder_encode (GstVulkanEncoder * self, GstVideoInfo * info,
encode_info.dstBufferRange = GST_ROUND_DOWN_N (encode_info.dstBufferRange, encode_info.dstBufferRange = GST_ROUND_DOWN_N (encode_info.dstBufferRange,
priv->caps.caps.minBitstreamBufferSizeAlignment); priv->caps.caps.minBitstreamBufferSizeAlignment);
g_assert (priv->callbacks.setup_codec_pic);
priv->callbacks.setup_codec_pic (pic, &encode_info,
priv->callbacks_user_data);
gst_vulkan_operation_add_dependency_frame (priv->exec, pic->in_buffer, gst_vulkan_operation_add_dependency_frame (priv->exec, pic->in_buffer,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR); VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
@ -1277,3 +1293,21 @@ gst_vulkan_encoder_create_from_queue (GstVulkanQueue * queue, guint codec)
return encoder; return encoder;
} }
void
gst_vulkan_encoder_set_callbacks (GstVulkanEncoder * self,
GstVulkanEncoderCallbacks * callbacks, gpointer user_data,
GDestroyNotify notify)
{
GstVulkanEncoderPrivate *priv;
g_return_if_fail (GST_IS_VULKAN_ENCODER (self) && callbacks);
priv = gst_vulkan_encoder_get_instance_private (self);
priv->callbacks = *callbacks;
if (priv->callbacks_user_data && priv->callbacks_notify)
priv->callbacks_notify (priv->callbacks_user_data);
priv->callbacks_user_data = user_data;
priv->callbacks_notify = notify;
}

View file

@ -38,6 +38,21 @@ typedef union _GstVulkanEncoderParameters GstVulkanEncoderParameters;
typedef union _GstVulkanEncoderParametersOverrides GstVulkanEncoderParametersOverrides; typedef union _GstVulkanEncoderParametersOverrides GstVulkanEncoderParametersOverrides;
typedef union _GstVulkanEncoderParametersFeedback GstVulkanEncoderParametersFeedback; typedef union _GstVulkanEncoderParametersFeedback GstVulkanEncoderParametersFeedback;
typedef struct _GstVulkanEncoderPicture GstVulkanEncoderPicture; typedef struct _GstVulkanEncoderPicture GstVulkanEncoderPicture;
typedef struct _GstVulkaneEncoderCallbacks GstVulkanEncoderCallbacks;
/**
* GstVulkaneEncoderCallbacks:
* @setup_codec_pic: Called after VkVideoEncodeInfoKHR and
* VkVideoReferenceSlotInfoKHR are filled so they can be chained with the
* specific codec structures. Called in gst_vulkan_encoder_encode().
*
* See gst_vulkan_encoder_set_callbacks()
*/
struct _GstVulkaneEncoderCallbacks
{
void (*setup_codec_pic) (GstVulkanEncoderPicture * pic,
VkVideoEncodeInfoKHR * info, gpointer data);
};
/** /**
* GstVulkanEncoderPicture: * GstVulkanEncoderPicture:
@ -66,8 +81,6 @@ struct _GstVulkanEncoderPicture
VkVideoReferenceSlotInfoKHR dpb_slot; VkVideoReferenceSlotInfoKHR dpb_slot;
gpointer codec_rc_info; gpointer codec_rc_info;
gpointer codec_pic_info;
gpointer codec_dpb_slot_info;
}; };
/** /**
@ -138,6 +151,12 @@ GST_VULKAN_API
GstVulkanEncoder * gst_vulkan_encoder_create_from_queue (GstVulkanQueue * queue, GstVulkanEncoder * gst_vulkan_encoder_create_from_queue (GstVulkanQueue * queue,
guint codec); guint codec);
GST_VULKAN_API
void gst_vulkan_encoder_set_callbacks (GstVulkanEncoder * self,
GstVulkanEncoderCallbacks * callbacks,
gpointer user_data,
GDestroyNotify notify);
GST_VULKAN_API GST_VULKAN_API
gboolean gst_vulkan_encoder_start (GstVulkanEncoder * self, gboolean gst_vulkan_encoder_start (GstVulkanEncoder * self,
GstVulkanVideoProfile * profile, GstVulkanVideoProfile * profile,

View file

@ -370,8 +370,40 @@ allocate_frame (GstVulkanEncoder * enc, int width,
} }
#define PICTURE_TYPE(slice_type, is_ref) \ #define PICTURE_TYPE(slice_type, is_ref) \
(slice_type == STD_VIDEO_H264_SLICE_TYPE_I && is_ref) ? \ (slice_type == STD_VIDEO_H264_SLICE_TYPE_I && is_ref) \
STD_VIDEO_H264_PICTURE_TYPE_IDR : (StdVideoH264PictureType) slice_type ? STD_VIDEO_H264_PICTURE_TYPE_IDR \
: (StdVideoH264PictureType)slice_type
static void
setup_codec_pic (GstVulkanEncoderPicture * pic, VkVideoEncodeInfoKHR * info,
gpointer data)
{
GstVulkanH264EncodeFrame *frame = (GstVulkanH264EncodeFrame *) pic;
GstVulkanVideoCapabilities *enc_caps = data;
info->pNext = &frame->enc_pic_info;
pic->dpb_slot.pNext = &frame->dpb_slot_info;
{
/* *INDENT-OFF* */
frame->enc_pic_info = (VkVideoEncodeH264PictureInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_KHR,
.pNext = NULL,
.naluSliceEntryCount = 1,
.pNaluSliceEntries = &frame->slice_info,
.pStdPictureInfo = &frame->pic_info,
.generatePrefixNalu =
(enc_caps->encoder.codec.h264.flags
& VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR),
};
frame->dpb_slot_info = (VkVideoEncodeH264DpbSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR,
.pNext = NULL,
.pStdReferenceInfo = &frame->ref_info,
};
/* *INDENT-ON* */
}
}
static void static void
encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame, encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
@ -383,11 +415,14 @@ 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 };
GST_DEBUG ("Encoding frame num:%d", frame_num); GST_DEBUG ("Encoding frame num:%d", frame_num);
fail_unless (gst_vulkan_encoder_caps (enc, &enc_caps)); fail_unless (gst_vulkan_encoder_caps (enc, &enc_caps));
gst_vulkan_encoder_set_callbacks (enc, &cb, &enc_caps, NULL);
frame->slice_hdr = (StdVideoEncodeH264SliceHeader) { frame->slice_hdr = (StdVideoEncodeH264SliceHeader) {
/* *INDENT-OFF* */ /* *INDENT-OFF* */
.flags = (StdVideoEncodeH264SliceHeaderFlags) { .flags = (StdVideoEncodeH264SliceHeaderFlags) {
@ -462,16 +497,6 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR, .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR,
}; };
frame->enc_pic_info = (VkVideoEncodeH264PictureInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_KHR,
.pNext = NULL,
.naluSliceEntryCount = 1,
.pNaluSliceEntries = &frame->slice_info,
.pStdPictureInfo = &frame->pic_info,
.generatePrefixNalu = (enc_caps.encoder.codec.h264.flags
& VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR),
};
frame->ref_info = (StdVideoEncodeH264ReferenceInfo) { frame->ref_info = (StdVideoEncodeH264ReferenceInfo) {
.flags = { .flags = {
.used_for_long_term_reference = 0, .used_for_long_term_reference = 0,
@ -483,17 +508,9 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH264EncodeFrame * frame,
.long_term_frame_idx = 0, .long_term_frame_idx = 0,
.temporal_id = 0, .temporal_id = 0,
}; };
frame->dpb_slot_info = (VkVideoEncodeH264DpbSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR,
.pNext = NULL,
.pStdReferenceInfo = &frame->ref_info,
};
/* *INDENT-ON* */ /* *INDENT-ON* */
picture->codec_pic_info = &frame->enc_pic_info;
picture->codec_rc_info = &frame->rc_info; picture->codec_rc_info = &frame->rc_info;
picture->codec_dpb_slot_info = &frame->dpb_slot_info;
for (i = 0; i < list0_num; i++) { for (i = 0; i < list0_num; i++) {
ref_pics[i] = &list0[i]->picture; ref_pics[i] = &list0[i]->picture;

View file

@ -383,6 +383,34 @@ allocate_frame (GstVulkanEncoder * enc, int width,
slice_type == STD_VIDEO_H265_SLICE_TYPE_B ? STD_VIDEO_H265_PICTURE_TYPE_B: \ slice_type == STD_VIDEO_H265_SLICE_TYPE_B ? STD_VIDEO_H265_PICTURE_TYPE_B: \
(StdVideoH265PictureType) slice_type (StdVideoH265PictureType) slice_type
static void
setup_codec_pic (GstVulkanEncoderPicture * pic, VkVideoEncodeInfoKHR * info,
gpointer data)
{
GstVulkanH265EncodeFrame *frame = (GstVulkanH265EncodeFrame *) pic;
info->pNext = &frame->enc_pic_info;
pic->dpb_slot.pNext = &frame->dpb_slot_info;
{
/* *INDENT-OFF* */
frame->enc_pic_info = (VkVideoEncodeH265PictureInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR,
.pNext = NULL,
.naluSliceSegmentEntryCount = 1,
.pNaluSliceSegmentEntries = &frame->slice_info,
.pStdPictureInfo = &frame->pic_info,
};
frame->dpb_slot_info = (VkVideoEncodeH265DpbSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR,
.pNext = NULL,
.pStdReferenceInfo = &frame->ref_info,
};
/* *INDENT-ON* */
}
}
static void static void
encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame, encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
StdVideoH265SliceType slice_type, guint frame_num, StdVideoH265SliceType slice_type, guint frame_num,
@ -394,10 +422,13 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
GstVulkanEncoderPicture *ref_pics[16] = { NULL, }; GstVulkanEncoderPicture *ref_pics[16] = { NULL, };
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 };
GST_DEBUG ("Encoding frame num: %d", frame_num); GST_DEBUG ("Encoding frame num: %d", frame_num);
gst_vulkan_encoder_set_callbacks (enc, &cb, NULL, NULL);
ref_pics_num = list0_num + list1_num; ref_pics_num = list0_num + list1_num;
frame->slice_wt = (StdVideoEncodeH265WeightTable) { frame->slice_wt = (StdVideoEncodeH265WeightTable) {
@ -534,14 +565,6 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR, .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR,
}; };
frame->enc_pic_info = (VkVideoEncodeH265PictureInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR,
.pNext = NULL,
.naluSliceSegmentEntryCount = 1,
.pNaluSliceSegmentEntries = &frame->slice_info,
.pStdPictureInfo = &frame->pic_info,
};
frame->ref_info = (StdVideoEncodeH265ReferenceInfo) { frame->ref_info = (StdVideoEncodeH265ReferenceInfo) {
.flags = (StdVideoEncodeH265ReferenceInfoFlags) { .flags = (StdVideoEncodeH265ReferenceInfoFlags) {
.used_for_long_term_reference = 0, .used_for_long_term_reference = 0,
@ -551,17 +574,9 @@ encode_frame (GstVulkanEncoder * enc, GstVulkanH265EncodeFrame * frame,
.PicOrderCntVal = frame->pic_order_cnt, .PicOrderCntVal = frame->pic_order_cnt,
.TemporalId = 0, .TemporalId = 0,
}; };
frame->dpb_slot_info = (VkVideoEncodeH265DpbSlotInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR,
.pNext = NULL,
.pStdReferenceInfo = &frame->ref_info,
};
/* *INDENT-ON* */ /* *INDENT-ON* */
picture->codec_pic_info = &frame->enc_pic_info;
picture->codec_rc_info = &frame->rc_info; picture->codec_rc_info = &frame->rc_info;
picture->codec_dpb_slot_info = &frame->dpb_slot_info;
for (i = 0; i < list0_num; i++) { for (i = 0; i < list0_num; i++) {
ref_pics[i] = &list0[i]->picture; ref_pics[i] = &list0[i]->picture;