From 4b0a139714e9ac85ead7b7f8e491f6e705cf62a1 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Mon, 5 Oct 2020 12:07:22 +0200 Subject: videodecoder: fix output state interlace-mode When user is passing the actual interlace-mode when calling gst_video_decoder_set_interlaced_output_state() it should not be overidden by the input interlace-mode. Needed to fix #825 as we want to keep interlace-mode=interleaved from parsers and have the OMX decoder producing interlace-mode=alternate. Part-of: --- gst-libs/gst/video/gstvideodecoder.c | 104 ++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index 7e8f37579..9a750b7c9 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -619,16 +619,17 @@ parse_fail: } static GstVideoCodecState * -_new_output_state (GstVideoFormat fmt, GstVideoInterlaceMode mode, guint width, - guint height, GstVideoCodecState * reference) +_new_output_state (GstVideoFormat fmt, GstVideoInterlaceMode interlace_mode, + guint width, guint height, GstVideoCodecState * reference, + gboolean copy_interlace_mode) { GstVideoCodecState *state; state = g_slice_new0 (GstVideoCodecState); state->ref_count = 1; gst_video_info_init (&state->info); - if (!gst_video_info_set_interlaced_format (&state->info, fmt, mode, width, - height)) { + if (!gst_video_info_set_interlaced_format (&state->info, fmt, interlace_mode, + width, height)) { g_slice_free (GstVideoCodecState, state); return NULL; } @@ -640,7 +641,8 @@ _new_output_state (GstVideoFormat fmt, GstVideoInterlaceMode mode, guint width, ref = &reference->info; /* Copy over extra fields from reference state */ - tgt->interlace_mode = ref->interlace_mode; + if (copy_interlace_mode) + tgt->interlace_mode = ref->interlace_mode; tgt->flags = ref->flags; /* only copy values that are not unknown so that we don't override the * defaults. subclasses should really fill these in when they know. */ @@ -3430,6 +3432,53 @@ gst_video_decoder_get_output_state (GstVideoDecoder * decoder) return state; } +static GstVideoCodecState * +_set_interlaced_output_state (GstVideoDecoder * decoder, + GstVideoFormat fmt, GstVideoInterlaceMode interlace_mode, guint width, + guint height, GstVideoCodecState * reference, gboolean copy_interlace_mode) +{ + GstVideoDecoderPrivate *priv = decoder->priv; + GstVideoCodecState *state; + + g_assert ((copy_interlace_mode + && interlace_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE) + || !copy_interlace_mode); + + GST_DEBUG_OBJECT (decoder, + "fmt:%d, width:%d, height:%d, interlace-mode: %s, reference:%p", fmt, + width, height, gst_video_interlace_mode_to_string (interlace_mode), + reference); + + /* Create the new output state */ + state = + _new_output_state (fmt, interlace_mode, width, height, reference, + copy_interlace_mode); + if (!state) + return NULL; + + GST_VIDEO_DECODER_STREAM_LOCK (decoder); + + GST_OBJECT_LOCK (decoder); + /* Replace existing output state by new one */ + if (priv->output_state) + gst_video_codec_state_unref (priv->output_state); + priv->output_state = gst_video_codec_state_ref (state); + + if (priv->output_state != NULL && priv->output_state->info.fps_n > 0) { + priv->qos_frame_duration = + gst_util_uint64_scale (GST_SECOND, priv->output_state->info.fps_d, + priv->output_state->info.fps_n); + } else { + priv->qos_frame_duration = 0; + } + priv->output_state_changed = TRUE; + GST_OBJECT_UNLOCK (decoder); + + GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); + + return state; +} + /** * gst_video_decoder_set_output_state: * @decoder: a #GstVideoDecoder @@ -3460,8 +3509,8 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder, GstVideoFormat fmt, guint width, guint height, GstVideoCodecState * reference) { - return gst_video_decoder_set_interlaced_output_state (decoder, fmt, - GST_VIDEO_INTERLACE_MODE_PROGRESSIVE, width, height, reference); + return _set_interlaced_output_state (decoder, fmt, + GST_VIDEO_INTERLACE_MODE_PROGRESSIVE, width, height, reference, TRUE); } /** @@ -3470,7 +3519,7 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder, * @fmt: a #GstVideoFormat * @width: The width in pixels * @height: The height in pixels - * @mode: A #GstVideoInterlaceMode + * @interlace_mode: A #GstVideoInterlaceMode * @reference: (allow-none) (transfer none): An optional reference #GstVideoCodecState * * Same as #gst_video_decoder_set_output_state() but also allows you to also set @@ -3482,42 +3531,11 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder, */ GstVideoCodecState * gst_video_decoder_set_interlaced_output_state (GstVideoDecoder * decoder, - GstVideoFormat fmt, GstVideoInterlaceMode mode, guint width, guint height, - GstVideoCodecState * reference) + GstVideoFormat fmt, GstVideoInterlaceMode interlace_mode, guint width, + guint height, GstVideoCodecState * reference) { - GstVideoDecoderPrivate *priv = decoder->priv; - GstVideoCodecState *state; - - GST_DEBUG_OBJECT (decoder, - "fmt:%d, width:%d, height:%d, interlace-mode: %s, reference:%p", fmt, - width, height, gst_video_interlace_mode_to_string (mode), reference); - - /* Create the new output state */ - state = _new_output_state (fmt, mode, width, height, reference); - if (!state) - return NULL; - - GST_VIDEO_DECODER_STREAM_LOCK (decoder); - - GST_OBJECT_LOCK (decoder); - /* Replace existing output state by new one */ - if (priv->output_state) - gst_video_codec_state_unref (priv->output_state); - priv->output_state = gst_video_codec_state_ref (state); - - if (priv->output_state != NULL && priv->output_state->info.fps_n > 0) { - priv->qos_frame_duration = - gst_util_uint64_scale (GST_SECOND, priv->output_state->info.fps_d, - priv->output_state->info.fps_n); - } else { - priv->qos_frame_duration = 0; - } - priv->output_state_changed = TRUE; - GST_OBJECT_UNLOCK (decoder); - - GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); - - return state; + return _set_interlaced_output_state (decoder, fmt, interlace_mode, width, + height, reference, FALSE); } -- cgit v1.2.1