From: Sebastian Dröge Date: Wed, 1 Jul 2020 15:14:40 +0000 (+0300) Subject: videodecoder: Add API for subclasses to signal that they need the stream to start... X-Git-Tag: 1.19.3~511^2~431 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fdf79a786caba9c3853933a3897a722221fbe4d8;p=platform%2Fupstream%2Fgstreamer.git videodecoder: Add API for subclasses to signal that they need the stream to start with a sync point If the first frame(s) at the very beginning or after a flush are not a sync point then the base class would discard them before passing them to the subclass. This also fixes the previously broken distance_from_sync handling: it was never reset at sync points. Part-of: --- diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index a16256d..151bb42 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -377,10 +377,14 @@ struct _GstVideoDecoderPrivate /* combine with base_picture_number, framerate and calcs to yield (presentation) ts */ GstClockTime base_timestamp; - int distance_from_sync; /* Properties */ gboolean discard_corrupted_frames; + /* Key unit related state */ + gboolean needs_sync_point; + /* -1 if we saw no sync point yet */ + guint64 distance_from_sync; + guint32 system_frame_number; guint32 decode_frame_number; @@ -2180,6 +2184,7 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full, priv->proportion = 0.5; priv->decode_flags_override = FALSE; GST_OBJECT_UNLOCK (decoder); + priv->distance_from_sync = -1; } if (full) { @@ -3571,8 +3576,6 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder, * implementation, or it doesn't) */ g_return_val_if_fail (decoder_class->handle_frame != NULL, GST_FLOW_ERROR); - frame->distance_from_sync = priv->distance_from_sync; - priv->distance_from_sync++; frame->pts = GST_BUFFER_PTS (frame->input_buffer); frame->dts = GST_BUFFER_DTS (frame->input_buffer); frame->duration = GST_BUFFER_DURATION (frame->input_buffer); @@ -3582,16 +3585,31 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder, /* FIXME upstream can be quite wrong about the keyframe aspect, * so we could be going off here as well, * maybe let subclass decide if it really is/was a keyframe */ - if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && - GST_CLOCK_TIME_IS_VALID (frame->pts) - && GST_CLOCK_TIME_IS_VALID (frame->dts)) { - /* just in case they are not equal as might ideally be, - * e.g. quicktime has a (positive) delta approach */ - priv->pts_delta = frame->pts - frame->dts; - GST_DEBUG_OBJECT (decoder, "PTS delta %d ms", - (gint) (priv->pts_delta / GST_MSECOND)); + if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) { + priv->distance_from_sync = 0; + + if (GST_CLOCK_TIME_IS_VALID (frame->pts) + && GST_CLOCK_TIME_IS_VALID (frame->dts)) { + /* just in case they are not equal as might ideally be, + * e.g. quicktime has a (positive) delta approach */ + priv->pts_delta = frame->pts - frame->dts; + GST_DEBUG_OBJECT (decoder, "PTS delta %d ms", + (gint) (priv->pts_delta / GST_MSECOND)); + } + } else { + if (priv->needs_sync_point && priv->distance_from_sync == -1) { + GST_WARNING_OBJECT (decoder, + "Subclass requires a sync point but we didn't receive one yet, discarding input"); + GST_OBJECT_UNLOCK (decoder); + gst_video_decoder_release_frame (decoder, frame); + return GST_FLOW_OK; + } + + priv->distance_from_sync++; } + frame->distance_from_sync = priv->distance_from_sync; + frame->abidata.ABI.ts = frame->dts; frame->abidata.ABI.ts2 = frame->pts; @@ -4683,3 +4701,49 @@ gst_video_decoder_set_use_default_pad_acceptcaps (GstVideoDecoder * decoder, { decoder->priv->use_default_pad_acceptcaps = use; } + +/** + * gst_video_decoder_set_needs_sync_point: + * @dec: a #GstVideoDecoder + * @enabled: new state + * + * Configures whether the decoder requires a sync point before it starts + * outputting data in the beginning. If enabled, the base class will discard + * all non-sync point frames in the beginning and after a flush and does not + * pass it to the subclass. + * + * If the first frame is not a sync point, the base class will request a sync + * point via the force-key-unit event. + * + * Since: 1.20 + */ +void +gst_video_decoder_set_needs_sync_point (GstVideoDecoder * dec, gboolean enabled) +{ + g_return_if_fail (GST_IS_VIDEO_DECODER (dec)); + + dec->priv->needs_sync_point = enabled; +} + +/** + * gst_video_decoder_get_needs_sync_point: + * @dec: a #GstVideoDecoder + * + * Queries if the decoder requires a sync point before it starts outputting + * data in the beginning. + * + * Returns: %TRUE if a sync point is required in the beginning. + * + * Since: 1.20 + */ +gboolean +gst_video_decoder_get_needs_sync_point (GstVideoDecoder * dec) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_VIDEO_DECODER (dec), FALSE); + + result = dec->priv->needs_sync_point; + + return result; +} diff --git a/gst-libs/gst/video/gstvideodecoder.h b/gst-libs/gst/video/gstvideodecoder.h index 27f9efe..255395c 100644 --- a/gst-libs/gst/video/gstvideodecoder.h +++ b/gst-libs/gst/video/gstvideodecoder.h @@ -375,6 +375,13 @@ GST_VIDEO_API gboolean gst_video_decoder_get_needs_format (GstVideoDecoder * dec); GST_VIDEO_API +void gst_video_decoder_set_needs_sync_point (GstVideoDecoder * dec, + gboolean enabled); + +GST_VIDEO_API +gboolean gst_video_decoder_get_needs_sync_point (GstVideoDecoder * dec); + +GST_VIDEO_API void gst_video_decoder_set_latency (GstVideoDecoder *decoder, GstClockTime min_latency, GstClockTime max_latency);