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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/852>
This commit is contained in:
Guillaume Desmottes 2020-10-05 12:07:22 +02:00
parent a19a27a4ca
commit a3a2992bc8

View file

@ -736,16 +736,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;
}
@ -757,7 +758,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. */
@ -3733,6 +3735,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
@ -3763,8 +3812,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);
}
/**
@ -3773,7 +3822,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
@ -3785,42 +3834,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);
}