va: Add and use common decode negotiate vmethod.

This vmethod can be used by decoders with the same VA decoder reopen logic:
same profile, chroma, width and height.

Also a new public method called gst_va_base_dec_set_output_state() with the
common GStreamer code for setting the output state, which is always called by
the negotiate vmethod.

In order to do this refactoring, new variables in vabasedec have to be populated
by the decoders:

* width and height define the resolution set in VA decoder. In the case of H264
  would be de coded_width and codec_height, or max_width and max_height in AV1.
* output_info is the downstream video info used for negotiation in
  gst_va_base_dec_set_output_state().
* input_state, from codec parent class shall be also held by vabasedec

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3480>
This commit is contained in:
Victor Manuel Jaquez Leal 2022-11-26 09:11:39 +01:00 committed by Víctor Manuel Jáquez Leal
parent 31c63a6e6c
commit b6538e0560
6 changed files with 115 additions and 246 deletions

View file

@ -101,9 +101,8 @@ gst_va_base_dec_stop (GstVideoDecoder * decoder)
if (!gst_va_decoder_close (base->decoder)) if (!gst_va_decoder_close (base->decoder))
return FALSE; return FALSE;
if (base->output_state) g_clear_pointer (&base->output_state, gst_video_codec_state_unref);
gst_video_codec_state_unref (base->output_state); g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
base->output_state = NULL;
if (base->other_pool) if (base->other_pool)
gst_buffer_pool_set_active (base->other_pool, FALSE); gst_buffer_pool_set_active (base->other_pool, FALSE);
@ -662,10 +661,41 @@ gst_va_base_dec_set_context (GstElement * element, GstContext * context)
(element))->set_context (element, context); (element))->set_context (element, context);
} }
static gboolean
gst_va_base_dec_negotiate (GstVideoDecoder * decoder)
{
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
/* Ignore downstream renegotiation request. */
if (!base->need_negotiation)
return TRUE;
base->need_negotiation = FALSE;
if (!gst_va_decoder_config_is_equal (base->decoder, base->profile,
base->rt_format, base->width, base->height)) {
if (gst_va_decoder_is_open (base->decoder) &&
!gst_va_decoder_close (base->decoder))
return FALSE;
if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
return FALSE;
if (!gst_va_decoder_set_frame_size (base->decoder, base->width,
base->height))
return FALSE;
}
if (!gst_va_base_dec_set_output_state (base))
return FALSE;
return GST_VIDEO_DECODER_CLASS (GST_VA_BASE_DEC_GET_PARENT_CLASS (decoder))
->negotiate (decoder);
}
void void
gst_va_base_dec_init (GstVaBaseDec * base, GstDebugCategory * cat) gst_va_base_dec_init (GstVaBaseDec * base, GstDebugCategory * cat)
{ {
base->debug_category = cat; base->debug_category = cat;
gst_video_info_init (&base->output_info);
} }
void void
@ -713,6 +743,7 @@ gst_va_base_dec_class_init (GstVaBaseDecClass * klass, GstVaCodecs codec,
decoder_class->sink_query = GST_DEBUG_FUNCPTR (gst_va_base_dec_sink_query); decoder_class->sink_query = GST_DEBUG_FUNCPTR (gst_va_base_dec_sink_query);
decoder_class->decide_allocation = decoder_class->decide_allocation =
GST_DEBUG_FUNCPTR (gst_va_base_dec_decide_allocation); GST_DEBUG_FUNCPTR (gst_va_base_dec_decide_allocation);
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_base_dec_negotiate);
g_object_class_install_property (object_class, GST_VA_DEC_PROP_DEVICE_PATH, g_object_class_install_property (object_class, GST_VA_DEC_PROP_DEVICE_PATH,
g_param_spec_string ("device-path", "Device Path", g_param_spec_string ("device-path", "Device Path",
@ -978,7 +1009,7 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
src_vinfo = &base->output_state->info; src_vinfo = &base->output_state->info;
gst_video_info_set_format (&dest_vinfo, GST_VIDEO_INFO_FORMAT (src_vinfo), gst_video_info_set_format (&dest_vinfo, GST_VIDEO_INFO_FORMAT (src_vinfo),
base->width, base->height); GST_VIDEO_INFO_WIDTH (src_vinfo), GST_VIDEO_INFO_HEIGHT (src_vinfo));
ret = gst_buffer_pool_acquire_buffer (base->other_pool, &buffer, NULL); ret = gst_buffer_pool_acquire_buffer (base->other_pool, &buffer, NULL);
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
@ -1003,8 +1034,8 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
} else { } else {
/* gst_video_frame_copy can crop this, but does not know, so let /* gst_video_frame_copy can crop this, but does not know, so let
* make it think it's all right */ * make it think it's all right */
GST_VIDEO_INFO_WIDTH (&src_frame.info) = base->width; GST_VIDEO_INFO_WIDTH (&src_frame.info) = GST_VIDEO_INFO_WIDTH (src_vinfo);
GST_VIDEO_INFO_HEIGHT (&src_frame.info) = base->height; GST_VIDEO_INFO_HEIGHT (&src_frame.info) = GST_VIDEO_INFO_HEIGHT (src_vinfo);
if (!gst_video_frame_copy (&dest_frame, &src_frame)) { if (!gst_video_frame_copy (&dest_frame, &src_frame)) {
gst_video_frame_unmap (&src_frame); gst_video_frame_unmap (&src_frame);
@ -1070,3 +1101,35 @@ gst_va_base_dec_prepare_output_frame (GstVaBaseDec * base,
return gst_video_decoder_allocate_output_frame (vdec, frame); return gst_video_decoder_allocate_output_frame (vdec, frame);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
gboolean
gst_va_base_dec_set_output_state (GstVaBaseDec * base)
{
GstVideoDecoder *decoder = GST_VIDEO_DECODER (base);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
GstCapsFeatures *capsfeatures = NULL;
GstVideoInfo *info = &base->output_info;
if (base->output_state)
gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures);
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE;
base->output_state =
gst_video_decoder_set_interlaced_output_state (decoder, format,
GST_VIDEO_INFO_INTERLACE_MODE (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), base->input_state);
/* set caps feature */
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
GST_INFO_OBJECT (base, "Negotiated caps %" GST_PTR_FORMAT,
base->output_state->caps);
return TRUE;
}

View file

@ -68,12 +68,15 @@ struct _GstVaBaseDec
VAProfile profile; VAProfile profile;
guint rt_format; guint rt_format;
/* coded or max resolution */
gint width; gint width;
gint height; gint height;
guint min_buffers; guint min_buffers;
GstVideoInfo output_info;
GstVideoCodecState *output_state; GstVideoCodecState *output_state;
GstVideoCodecState *input_state;
GstBufferPool *other_pool; GstBufferPool *other_pool;
gboolean need_valign; gboolean need_valign;
@ -137,5 +140,6 @@ gboolean gst_va_base_dec_process_output (GstVaBaseDec * base,
GstVideoBufferFlags buffer_flags); GstVideoBufferFlags buffer_flags);
GstFlowReturn gst_va_base_dec_prepare_output_frame (GstVaBaseDec * base, GstFlowReturn gst_va_base_dec_prepare_output_frame (GstVaBaseDec * base,
GstVideoCodecFrame * frame); GstVideoCodecFrame * frame);
gboolean gst_va_base_dec_set_output_state (GstVaBaseDec * base);
G_END_DECLS G_END_DECLS

View file

@ -75,8 +75,6 @@ struct _GstVaH264Dec
{ {
GstVaBaseDec parent; GstVaBaseDec parent;
gint coded_width;
gint coded_height;
gint dpb_size; gint dpb_size;
/* Used to fill VAPictureParameterBufferH264.ReferenceFrames */ /* Used to fill VAPictureParameterBufferH264.ReferenceFrames */
@ -643,6 +641,7 @@ gst_va_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
{ {
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaH264Dec *self = GST_VA_H264_DEC (decoder); GstVaH264Dec *self = GST_VA_H264_DEC (decoder);
GstVideoInfo *info = &base->output_info;
VAProfile profile; VAProfile profile;
gint display_width; gint display_width;
gint display_height; gint display_height;
@ -680,34 +679,35 @@ gst_va_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
rt_format, sps->width, sps->height)) { rt_format, sps->width, sps->height)) {
base->profile = profile; base->profile = profile;
base->rt_format = rt_format; base->rt_format = rt_format;
self->coded_width = sps->width; base->width = sps->width;
self->coded_height = sps->height; base->height = sps->height;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)", GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)",
gst_va_profile_name (profile), rt_format, self->coded_width, gst_va_profile_name (profile), rt_format, base->width, base->height);
self->coded_height);
} }
if (base->width != display_width || base->height != display_height) { if (GST_VIDEO_INFO_WIDTH (info) != display_width ||
base->width = display_width; GST_VIDEO_INFO_HEIGHT (info) != display_height) {
base->height = display_height; GST_VIDEO_INFO_WIDTH (info) = display_width;
GST_VIDEO_INFO_HEIGHT (info) = display_height;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Resolution changed to %dx%d", base->width, GST_INFO_OBJECT (self, "Resolution changed to %dx%d",
base->height); GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
} }
interlaced = !sps->frame_mbs_only_flag; interlaced = !sps->frame_mbs_only_flag;
if (self->interlaced != interlaced) { if (self->interlaced != interlaced) {
self->interlaced = interlaced; self->interlaced = interlaced;
GST_VIDEO_INFO_INTERLACE_MODE (info) = interlaced ?
GST_VIDEO_INTERLACE_MODE_MIXED : GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Interlaced mode changed to %d", interlaced); GST_INFO_OBJECT (self, "Interlaced mode changed to %d", interlaced);
} }
base->need_valign = base->width < self->coded_width base->need_valign = GST_VIDEO_INFO_WIDTH (info) < base->width ||
|| base->height < self->coded_height; GST_VIDEO_INFO_HEIGHT (info) < base->height;
if (base->need_valign) { if (base->need_valign) {
/* *INDENT-OFF* */ /* *INDENT-OFF* */
if (base->valign.padding_left != padding_left || if (base->valign.padding_left != padding_left ||
@ -728,8 +728,9 @@ gst_va_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
} }
base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */ base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */
base->need_negotiation = negotiation_needed; base->need_negotiation = negotiation_needed;
g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
base->input_state = gst_video_codec_state_ref (decoder->input_state);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -823,56 +824,6 @@ gst_va_h264_dec_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
return caps; return caps;
} }
static gboolean
gst_va_h264_dec_negotiate (GstVideoDecoder * decoder)
{
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaH264Dec *self = GST_VA_H264_DEC (decoder);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
GstCapsFeatures *capsfeatures = NULL;
GstH264Decoder *h264dec = GST_H264_DECODER (decoder);
/* Ignore downstream renegotiation request. */
if (!base->need_negotiation)
return TRUE;
base->need_negotiation = FALSE;
if (gst_va_decoder_is_open (base->decoder)
&& !gst_va_decoder_close (base->decoder))
return FALSE;
if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
return FALSE;
if (!gst_va_decoder_set_frame_size (base->decoder, self->coded_width,
self->coded_height))
return FALSE;
if (base->output_state)
gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures);
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE;
base->output_state =
gst_video_decoder_set_output_state (decoder, format,
base->width, base->height, h264dec->input_state);
if (self->interlaced)
base->output_state->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
base->output_state->caps);
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
static void static void
gst_va_h264_dec_dispose (GObject * object) gst_va_h264_dec_dispose (GObject * object)
{ {
@ -926,7 +877,6 @@ gst_va_h264_dec_class_init (gpointer g_class, gpointer class_data)
gobject_class->dispose = gst_va_h264_dec_dispose; gobject_class->dispose = gst_va_h264_dec_dispose;
decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h264_dec_getcaps); decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h264_dec_getcaps);
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_h264_dec_negotiate);
h264decoder_class->new_sequence = h264decoder_class->new_sequence =
GST_DEBUG_FUNCPTR (gst_va_h264_dec_new_sequence); GST_DEBUG_FUNCPTR (gst_va_h264_dec_new_sequence);

View file

@ -88,8 +88,6 @@ struct _GstVaH265Dec
{ {
GstVaBaseDec parent; GstVaBaseDec parent;
gint coded_width;
gint coded_height;
gint dpb_size; gint dpb_size;
VAPictureParameterBufferHEVCExtension pic_param; VAPictureParameterBufferHEVCExtension pic_param;
@ -1047,6 +1045,7 @@ gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
{ {
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaH265Dec *self = GST_VA_H265_DEC (decoder); GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
GstVideoInfo *info = &base->output_info;
VAProfile profile; VAProfile profile;
gint display_width; gint display_width;
gint display_height; gint display_height;
@ -1083,26 +1082,26 @@ gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
rt_format, sps->width, sps->height)) { rt_format, sps->width, sps->height)) {
base->profile = profile; base->profile = profile;
base->rt_format = rt_format; base->rt_format = rt_format;
self->coded_width = sps->width; base->width = sps->width;
self->coded_height = sps->height; base->height = sps->height;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)", GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)",
gst_va_profile_name (profile), rt_format, self->coded_width, gst_va_profile_name (profile), rt_format, base->width, base->height);
self->coded_height);
} }
if (base->width != display_width || base->height != display_height) { if (GST_VIDEO_INFO_WIDTH (info) != display_width ||
base->width = display_width; GST_VIDEO_INFO_HEIGHT (info) != display_height) {
base->height = display_height; GST_VIDEO_INFO_WIDTH (info) = display_width;
GST_VIDEO_INFO_HEIGHT (info) = display_height;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Resolution changed to %dx%d", base->width, GST_INFO_OBJECT (self, "Resolution changed to %dx%d",
base->height); GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
} }
base->need_valign = base->width < self->coded_width base->need_valign = GST_VIDEO_INFO_WIDTH (info) < base->width ||
|| base->height < self->coded_height; GST_VIDEO_INFO_HEIGHT (info) < base->height;
if (base->need_valign) { if (base->need_valign) {
/* *INDENT-OFF* */ /* *INDENT-OFF* */
if (base->valign.padding_left != padding_left || if (base->valign.padding_left != padding_left ||
@ -1123,8 +1122,9 @@ gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
} }
base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */ base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */
base->need_negotiation = negotiation_needed; base->need_negotiation = negotiation_needed;
g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
base->input_state = gst_video_codec_state_ref (decoder->input_state);
{ {
/* FIXME: We don't have parser API for sps_range_extension, so /* FIXME: We don't have parser API for sps_range_extension, so
@ -1196,54 +1196,6 @@ gst_va_h265_dec_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
return caps; return caps;
} }
static gboolean
gst_va_h265_dec_negotiate (GstVideoDecoder * decoder)
{
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
GstCapsFeatures *capsfeatures = NULL;
GstH265Decoder *h265dec = GST_H265_DECODER (decoder);
/* Ignore downstream renegotiation request. */
if (!base->need_negotiation)
return TRUE;
base->need_negotiation = FALSE;
if (gst_va_decoder_is_open (base->decoder)
&& !gst_va_decoder_close (base->decoder))
return FALSE;
if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
return FALSE;
if (!gst_va_decoder_set_frame_size (base->decoder, self->coded_width,
self->coded_height))
return FALSE;
if (base->output_state)
gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures);
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE;
base->output_state =
gst_video_decoder_set_output_state (decoder, format,
base->width, base->height, h265dec->input_state);
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
base->output_state->caps);
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
static void static void
gst_va_h265_dec_dispose (GObject * object) gst_va_h265_dec_dispose (GObject * object)
{ {
@ -1296,7 +1248,6 @@ gst_va_h265_dec_class_init (gpointer g_class, gpointer class_data)
gobject_class->dispose = gst_va_h265_dec_dispose; gobject_class->dispose = gst_va_h265_dec_dispose;
decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h265_dec_getcaps); decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h265_dec_getcaps);
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_h265_dec_negotiate);
h265decoder_class->new_sequence = h265decoder_class->new_sequence =
GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_sequence); GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_sequence);

View file

@ -85,56 +85,6 @@ static const gchar *src_caps_str =
static const gchar *sink_caps_str = "video/x-mpeg2"; static const gchar *sink_caps_str = "video/x-mpeg2";
static gboolean
gst_va_mpeg2_dec_negotiate (GstVideoDecoder * decoder)
{
GstCapsFeatures *capsfeatures = NULL;
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaMpeg2Dec *self = GST_VA_MPEG2_DEC (decoder);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
GstMpeg2Decoder *mpeg2dec = GST_MPEG2_DECODER (decoder);
/* Ignore downstream renegotiation request. */
if (!base->need_negotiation)
return TRUE;
base->need_negotiation = FALSE;
if (gst_va_decoder_is_open (base->decoder)
&& !gst_va_decoder_close (base->decoder))
return FALSE;
if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
return FALSE;
if (!gst_va_decoder_set_frame_size (base->decoder, base->width, base->height))
return FALSE;
if (base->output_state)
gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures);
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE;
base->output_state =
gst_video_decoder_set_output_state (decoder, format,
base->width, base->height, mpeg2dec->input_state);
if (!self->progressive)
base->output_state->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
base->output_state->caps);
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
static VAProfile static VAProfile
_map_profile (GstMpegVideoProfile profile) _map_profile (GstMpegVideoProfile profile)
{ {
@ -226,6 +176,7 @@ gst_va_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder,
{ {
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaMpeg2Dec *self = GST_VA_MPEG2_DEC (decoder); GstVaMpeg2Dec *self = GST_VA_MPEG2_DEC (decoder);
GstVideoInfo *info = &base->output_info;
VAProfile profile; VAProfile profile;
GstMpegVideoProfile mpeg_profile; GstMpegVideoProfile mpeg_profile;
gboolean negotiation_needed = FALSE; gboolean negotiation_needed = FALSE;
@ -259,8 +210,8 @@ gst_va_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder,
rt_format, width, height)) { rt_format, width, height)) {
base->profile = profile; base->profile = profile;
base->rt_format = rt_format; base->rt_format = rt_format;
base->width = width; GST_VIDEO_INFO_WIDTH (info) = base->width = width;
base->height = height; GST_VIDEO_INFO_HEIGHT (info) = base->height = height;
negotiation_needed = TRUE; negotiation_needed = TRUE;
@ -271,16 +222,17 @@ gst_va_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder,
progressive = seq_ext ? seq_ext->progressive : 1; progressive = seq_ext ? seq_ext->progressive : 1;
if (self->progressive != progressive) { if (self->progressive != progressive) {
self->progressive = progressive; self->progressive = progressive;
GST_VIDEO_INFO_INTERLACE_MODE (info) = progressive ?
GST_VIDEO_INTERLACE_MODE_PROGRESSIVE : GST_VIDEO_INTERLACE_MODE_MIXED;
negotiation_needed = TRUE; negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "Interlaced mode changed to %d", !progressive); GST_INFO_OBJECT (self, "Interlaced mode changed to %d", !progressive);
} }
base->need_valign = FALSE; base->need_valign = FALSE;
base->min_buffers = 2 + 4; /* max num pic references + scratch surfaces */ base->min_buffers = 2 + 4; /* max num pic references + scratch surfaces */
base->need_negotiation = negotiation_needed; base->need_negotiation = negotiation_needed;
g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
base->input_state = gst_video_codec_state_ref (decoder->input_state);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -594,7 +546,6 @@ gst_va_mpeg2_dec_class_init (gpointer g_class, gpointer class_data)
GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstMpeg2DecoderClass *mpeg2decoder_class = GST_MPEG2_DECODER_CLASS (g_class); GstMpeg2DecoderClass *mpeg2decoder_class = GST_MPEG2_DECODER_CLASS (g_class);
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_class);
struct CData *cdata = class_data; struct CData *cdata = class_data;
gchar *long_name; gchar *long_name;
@ -627,8 +578,6 @@ gst_va_mpeg2_dec_class_init (gpointer g_class, gpointer class_data)
gobject_class->dispose = gst_va_mpeg2_dec_dispose; gobject_class->dispose = gst_va_mpeg2_dec_dispose;
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_mpeg2_dec_negotiate);
mpeg2decoder_class->new_sequence = mpeg2decoder_class->new_sequence =
GST_DEBUG_FUNCPTR (gst_va_mpeg2_dec_new_sequence); GST_DEBUG_FUNCPTR (gst_va_mpeg2_dec_new_sequence);
mpeg2decoder_class->new_picture = mpeg2decoder_class->new_picture =

View file

@ -82,53 +82,6 @@ static const gchar *src_caps_str =
static const gchar *sink_caps_str = "video/x-vp8"; static const gchar *sink_caps_str = "video/x-vp8";
static gboolean
gst_va_vp8_dec_negotiate (GstVideoDecoder * decoder)
{
GstCapsFeatures *capsfeatures = NULL;
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaVp8Dec *self = GST_VA_VP8_DEC (decoder);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
GstVp8Decoder *vp8dec = GST_VP8_DECODER (decoder);
/* Ignore downstream renegotiation request. */
if (!base->need_negotiation)
return TRUE;
base->need_negotiation = FALSE;
if (gst_va_decoder_is_open (base->decoder)
&& !gst_va_decoder_close (base->decoder))
return FALSE;
if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
return FALSE;
if (!gst_va_decoder_set_frame_size (base->decoder, base->width, base->height))
return FALSE;
if (base->output_state)
gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures);
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE;
base->output_state =
gst_video_decoder_set_output_state (decoder, format,
base->width, base->height, vp8dec->input_state);
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
base->output_state->caps);
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
static VAProfile static VAProfile
_get_profile (GstVaVp8Dec * self, const GstVp8FrameHdr * frame_hdr) _get_profile (GstVaVp8Dec * self, const GstVp8FrameHdr * frame_hdr)
{ {
@ -147,6 +100,7 @@ gst_va_vp8_dec_new_sequence (GstVp8Decoder * decoder,
{ {
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaVp8Dec *self = GST_VA_VP8_DEC (decoder); GstVaVp8Dec *self = GST_VA_VP8_DEC (decoder);
GstVideoInfo *info = &base->output_info;
VAProfile profile; VAProfile profile;
guint rt_format; guint rt_format;
gboolean negotiation_needed = FALSE; gboolean negotiation_needed = FALSE;
@ -169,15 +123,16 @@ gst_va_vp8_dec_new_sequence (GstVp8Decoder * decoder,
if (!gst_va_decoder_config_is_equal (base->decoder, profile, if (!gst_va_decoder_config_is_equal (base->decoder, profile,
rt_format, frame_hdr->width, frame_hdr->height)) { rt_format, frame_hdr->width, frame_hdr->height)) {
base->profile = profile; base->profile = profile;
base->width = frame_hdr->width; GST_VIDEO_INFO_WIDTH (info) = base->width = frame_hdr->width;
base->height = frame_hdr->height; GST_VIDEO_INFO_HEIGHT (info) = base->height = frame_hdr->height;
base->rt_format = rt_format; base->rt_format = rt_format;
negotiation_needed = TRUE; negotiation_needed = TRUE;
} }
base->min_buffers = 3 + 4; /* max num pic references + scratch surfaces */ base->min_buffers = 3 + 4; /* max num pic references + scratch surfaces */
base->need_negotiation = negotiation_needed; base->need_negotiation = negotiation_needed;
g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
base->input_state = gst_video_codec_state_ref (decoder->input_state);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -471,7 +426,6 @@ gst_va_vp8_dec_class_init (gpointer g_class, gpointer class_data)
GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstVp8DecoderClass *vp8decoder_class = GST_VP8_DECODER_CLASS (g_class); GstVp8DecoderClass *vp8decoder_class = GST_VP8_DECODER_CLASS (g_class);
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_class);
struct CData *cdata = class_data; struct CData *cdata = class_data;
gchar *long_name; gchar *long_name;
@ -504,8 +458,6 @@ gst_va_vp8_dec_class_init (gpointer g_class, gpointer class_data)
gobject_class->dispose = gst_va_vp8_dec_dispose; gobject_class->dispose = gst_va_vp8_dec_dispose;
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_vp8_dec_negotiate);
vp8decoder_class->new_sequence = vp8decoder_class->new_sequence =
GST_DEBUG_FUNCPTR (gst_va_vp8_dec_new_sequence); GST_DEBUG_FUNCPTR (gst_va_vp8_dec_new_sequence);
vp8decoder_class->new_picture = vp8decoder_class->new_picture =