nvdec: Use interlace info in input caps

... instead of relying on only parsed values from bitstream.
Also parses HEVC specific interlace information

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9170>
This commit is contained in:
Seungha Yang 2025-06-04 03:49:19 +09:00 committed by GStreamer Marge Bot
parent 3b896cd4ea
commit 712203163e
2 changed files with 56 additions and 4 deletions

View File

@ -1988,11 +1988,22 @@ gst_nv_decoder_negotiate (GstNvDecoder * decoder,
}
#endif
state = gst_video_decoder_set_interlaced_output_state (videodec,
state = gst_video_decoder_set_output_state (videodec,
GST_VIDEO_INFO_FORMAT (&decoder->output_info),
GST_VIDEO_INFO_INTERLACE_MODE (&decoder->output_info),
GST_VIDEO_INFO_WIDTH (&decoder->output_info),
GST_VIDEO_INFO_HEIGHT (&decoder->output_info), input_state);
if (GST_VIDEO_INFO_IS_INTERLACED (&decoder->info)) {
auto in_s = gst_caps_get_structure (input_state->caps, 0);
if (!gst_structure_has_field (in_s, "interlace-mode")) {
/* Use our parsed info if missed in upstream */
GST_VIDEO_INFO_INTERLACE_MODE (&state->info) =
GST_VIDEO_INFO_INTERLACE_MODE (&decoder->info);
GST_VIDEO_INFO_FIELD_ORDER (&state->info) =
GST_VIDEO_INFO_FIELD_ORDER (&decoder->info);
}
}
state->caps = gst_video_info_to_caps (&state->info);
switch (decoder->output_type) {

View File

@ -153,6 +153,7 @@ typedef struct _GstNvH265Dec
gint max_display_delay;
GstVideoFormat out_format;
GstVideoInterlaceMode interlace_mode;
} GstNvH265Dec;
typedef struct _GstNvH265DecClass
@ -193,6 +194,7 @@ static void gst_nv_h265_dec_set_context (GstElement * element,
GstContext * context);
static gboolean gst_nv_h265_dec_open (GstVideoDecoder * decoder);
static gboolean gst_nv_h265_dec_close (GstVideoDecoder * decoder);
static gboolean gst_nv_h265_dec_start (GstVideoDecoder * decoder);
static gboolean gst_nv_h265_dec_stop (GstVideoDecoder * decoder);
static gboolean gst_nv_h265_dec_negotiate (GstVideoDecoder * decoder);
static gboolean gst_nv_h265_dec_decide_allocation (GstVideoDecoder *
@ -334,6 +336,7 @@ gst_nv_h265_dec_class_init (GstNvH265DecClass * klass,
decoder_class->open = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_open);
decoder_class->close = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_close);
decoder_class->start = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_start);
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_stop);
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_negotiate);
decoder_class->decide_allocation =
@ -489,6 +492,23 @@ gst_nv_h265_dec_close (GstVideoDecoder * decoder)
return gst_nv_decoder_close (self->decoder);
}
static gboolean
gst_nv_h265_dec_start (GstVideoDecoder * decoder)
{
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
self->width = 0;
self->height = 0;
self->coded_width = 0;
self->coded_height = 0;
self->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
self->chroma_format_idc = 0;
self->bitdepth = 0;
self->max_dpb_size = 0;
return GST_VIDEO_DECODER_CLASS (parent_class)->start (decoder);
}
static gboolean
gst_nv_h265_dec_stop (GstVideoDecoder * decoder)
{
@ -581,6 +601,7 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
gboolean modified = FALSE;
guint max_width, max_height;
GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
GstVideoInterlaceMode interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
gboolean is_gbr = FALSE;
const GstH265VUIParams *vui = &sps->vui_params;
@ -630,6 +651,26 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
is_gbr = TRUE;
}
if (sps->vui_parameters_present_flag && sps->vui_params.field_seq_flag) {
GST_ELEMENT_WARNING (self, STREAM, NOT_IMPLEMENTED, (nullptr),
("alternate interlace mode is not properly supported. Output might have wrong aspect ratio"));
} else {
/* 7.4.4 Profile, tier and level sementics */
if (sps->profile_tier_level.progressive_source_flag &&
!sps->profile_tier_level.interlaced_source_flag) {
interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
} else {
interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
}
}
if (self->interlace_mode != interlace_mode) {
GST_INFO_OBJECT (self, "Interlace mode change %d -> %d",
self->interlace_mode, interlace_mode);
self->interlace_mode = interlace_mode;
modified = TRUE;
}
switch (self->bitdepth) {
case 8:
if (self->chroma_format_idc == 1)
@ -677,8 +718,8 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
if (modified || !gst_nv_decoder_is_configured (self->decoder)) {
GstVideoInfo info;
gst_video_info_set_format (&info,
self->out_format, self->width, self->height);
gst_video_info_set_interlaced_format (&info,
self->out_format, self->interlace_mode, self->width, self->height);
self->max_dpb_size = max_dpb_size;
max_width = gst_nv_decoder_get_max_output_size (self->coded_width,