vkh265dec: update only vps/sps on demand and pass pps always

As PPS can change over the stream, the pps should be always
updated to avoid missing picture parameters sets.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8124>
This commit is contained in:
Stéphane Cerveau 2024-12-10 15:09:24 +01:00 committed by GStreamer Marge Bot
parent 73c4eb3001
commit 570c086254

View File

@ -31,7 +31,46 @@
typedef struct _GstVulkanH265Decoder GstVulkanH265Decoder;
typedef struct _GstVulkanH265Picture GstVulkanH265Picture;
typedef struct _VPS VPS;
typedef struct _SPS SPS;
typedef struct _PPS PPS;
struct _SPS
{
StdVideoH265SequenceParameterSet sps;
StdVideoH265ScalingLists scaling;
StdVideoH265HrdParameters vui_header;
StdVideoH265SequenceParameterSetVui vui;
StdVideoH265ProfileTierLevel ptl;
StdVideoH265DecPicBufMgr dpbm;
StdVideoH265PredictorPaletteEntries pal;
StdVideoH265SubLayerHrdParameters nal_hrd[GST_H265_MAX_SUB_LAYERS];
StdVideoH265SubLayerHrdParameters vcl_hrd[GST_H265_MAX_SUB_LAYERS];
/* 7.4.3.2.1: num_short_term_ref_pic_sets is in [0, 64]. */
StdVideoH265ShortTermRefPicSet str[64];
StdVideoH265LongTermRefPicsSps ltr;
};
struct _PPS
{
StdVideoH265PictureParameterSet pps;
StdVideoH265ScalingLists scaling;
StdVideoH265PredictorPaletteEntries pal;
};
struct _VPS
{
StdVideoH265VideoParameterSet vps;
StdVideoH265ProfileTierLevel ptl;
StdVideoH265DecPicBufMgr dpbm;
/* FIXME: a VPS can have multiple header params, each with its own nal and vlc
headers sets. Sadly, that's not currently supported by the GStreamer H265
parser, which only supports one header params per VPS. */
StdVideoH265HrdParameters hrd;
StdVideoH265SubLayerHrdParameters nal_hdr[GST_H265_MAX_SUB_LAYERS];
StdVideoH265SubLayerHrdParameters vcl_hdr[GST_H265_MAX_SUB_LAYERS];
};
struct _GstVulkanH265Picture
{
GstVulkanDecoderPicture base;
@ -73,6 +112,9 @@ struct _GstVulkanH265Decoder
VkChromaLocation xloc, yloc;
GstVideoCodecState *output_state;
VPS std_vps;
SPS std_sps;
PPS std_pps;
};
static GstStaticPadTemplate gst_vulkan_h265dec_sink_template =
@ -614,41 +656,7 @@ allocation_failed:
}
}
struct SPS
{
StdVideoH265SequenceParameterSet sps;
StdVideoH265ScalingLists scaling;
StdVideoH265HrdParameters vui_header;
StdVideoH265SequenceParameterSetVui vui;
StdVideoH265ProfileTierLevel ptl;
StdVideoH265DecPicBufMgr dpbm;
StdVideoH265PredictorPaletteEntries pal;
StdVideoH265SubLayerHrdParameters nal_hrd[GST_H265_MAX_SUB_LAYERS];
StdVideoH265SubLayerHrdParameters vcl_hrd[GST_H265_MAX_SUB_LAYERS];
/* 7.4.3.2.1: num_short_term_ref_pic_sets is in [0, 64]. */
StdVideoH265ShortTermRefPicSet str[64];
StdVideoH265LongTermRefPicsSps ltr;
};
struct PPS
{
StdVideoH265PictureParameterSet pps;
StdVideoH265ScalingLists scaling;
StdVideoH265PredictorPaletteEntries pal;
};
struct VPS
{
StdVideoH265VideoParameterSet vps;
StdVideoH265ProfileTierLevel ptl;
StdVideoH265DecPicBufMgr dpbm;
/* FIXME: a VPS can have multiple header params, each with its own nal and vlc
headers sets. Sadly, that's not currently supported by the GStreamer H265
parser, which only supports one header params per VPS. */
StdVideoH265HrdParameters hrd;
StdVideoH265SubLayerHrdParameters nal_hdr[GST_H265_MAX_SUB_LAYERS];
StdVideoH265SubLayerHrdParameters vcl_hdr[GST_H265_MAX_SUB_LAYERS];
};
static void
_copy_scaling_list (const GstH265ScalingList * scaling_list,
@ -781,7 +789,7 @@ _copy_profile_tier_level (const GstH265ProfileTierLevel * ptl,
}
static void
_fill_sps (const GstH265SPS * sps, struct SPS *std_sps)
_fill_sps (const GstH265SPS * sps, SPS * std_sps)
{
int i;
const GstH265VUIParams *vui_params = &sps->vui_params;
@ -1055,7 +1063,7 @@ _fill_sps (const GstH265SPS * sps, struct SPS *std_sps)
}
static void
_fill_pps (const GstH265PPS * pps, const GstH265SPS * sps, struct PPS *std_pps)
_fill_pps (const GstH265PPS * pps, PPS * std_pps)
{
int i, j;
@ -1113,7 +1121,7 @@ _fill_pps (const GstH265PPS * pps, const GstH265SPS * sps, struct PPS *std_pps)
},
.pps_pic_parameter_set_id = pps->id,
.pps_seq_parameter_set_id = pps->sps_id,
.sps_video_parameter_set_id = sps->vps_id,
.sps_video_parameter_set_id = pps->sps->vps_id,
.num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
.num_ref_idx_l0_default_active_minus1 =
pps->num_ref_idx_l0_default_active_minus1,
@ -1177,7 +1185,7 @@ _fill_pps (const GstH265PPS * pps, const GstH265SPS * sps, struct PPS *std_pps)
}
static void
_fill_vps (const GstH265VPS * vps, struct VPS * std_vps)
_fill_vps (const GstH265VPS * vps, VPS * std_vps)
{
const GstH265HRDParams *hrd = &vps->hrd_params;
@ -1261,22 +1269,20 @@ _fill_vps (const GstH265VPS * vps, struct VPS * std_vps)
}
static GstFlowReturn
_update_parameters (GstVulkanH265Decoder * self, const GstH265PPS * pps)
_update_parameters (GstVulkanH265Decoder * self, const GstH265VPS * vps,
const GstH265SPS * sps, const GstH265PPS * pps)
{
GstH265SPS *sps = pps->sps;
GstH265VPS *vps = sps->vps;
struct SPS std_sps;
struct PPS std_pps;
struct VPS std_vps;
gboolean update = FALSE;
VkVideoDecodeH265SessionParametersAddInfoKHR params = {
.sType =
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
.stdSPSCount = 1,
.pStdSPSs = &std_sps.sps,
.pStdSPSs = &self->std_sps.sps,
.stdPPSCount = 1,
.pStdPPSs = &std_pps.pps,
.pStdPPSs = &self->std_pps.pps,
.stdVPSCount = 1,
.pStdVPSs = &std_vps.vps,
.pStdVPSs = &self->std_vps.vps,
};
/* *INDENT-OFF* */
GstVulkanDecoderParameters dec_params = {
@ -1291,10 +1297,21 @@ _update_parameters (GstVulkanH265Decoder * self, const GstH265PPS * pps)
};
/* *INDENT-ON* */
GError *error = NULL;
if (vps) {
_fill_vps (vps, &self->std_vps);
update = TRUE;
}
if (sps) {
_fill_sps (sps, &self->std_sps);
update = TRUE;
}
if (pps) {
_fill_pps (pps, &self->std_pps);
update = TRUE;
}
_fill_sps (sps, &std_sps);
_fill_pps (pps, sps, &std_pps);
_fill_vps (vps, &std_vps);
if (!update)
return GST_FLOW_OK;
if (!gst_vulkan_decoder_update_video_session_parameters (self->decoder,
&dec_params, &error)) {
@ -1393,6 +1410,8 @@ gst_vulkan_h265_decoder_start_picture (GstH265Decoder * decoder,
{
GstVulkanH265Decoder *self = GST_VULKAN_H265_DECODER (decoder);
GstH265PPS *pps = slice->header.pps;
GstH265SPS *sps = pps->sps;
GstH265VPS *vps = sps->vps;
GstFlowReturn ret;
GstVulkanH265Picture *pic;
GArray *refs;
@ -1400,10 +1419,14 @@ gst_vulkan_h265_decoder_start_picture (GstH265Decoder * decoder,
GST_TRACE_OBJECT (self, "Start picture");
if (self->need_params_update) {
ret = _update_parameters (self, pps);
ret =
_update_parameters (self, self->need_params_update ? vps : NULL,
self->need_params_update ? sps : NULL, pps);
if (ret != GST_FLOW_OK)
return ret;
if (self->need_params_update) {
self->need_params_update = FALSE;
}