From 1570314609d053a8f1971a781735647fe039d758 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 2 Oct 2018 11:09:33 -0400 Subject: [PATCH] videodecoder: Post QoS when we drop because of QoS At the moment, we only posted QoS messages when frame_drop() was called, but not in finish_frame() when QoS triggered a late push. This should fix applications that tries to account the dropped frames. We also emit a warning on drops so it's more clear what is happening. --- gst-libs/gst/video/gstvideodecoder.c | 58 +++++++++++++++------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index 02d1715053..08dad7cff4 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -2812,34 +2812,14 @@ gst_video_decoder_release_frame (GstVideoDecoder * dec, gst_video_codec_frame_unref (frame); } -/** - * gst_video_decoder_drop_frame: - * @dec: a #GstVideoDecoder - * @frame: (transfer full): the #GstVideoCodecFrame to drop - * - * Similar to gst_video_decoder_finish_frame(), but drops @frame in any - * case and posts a QoS message with the frame's details on the bus. - * In any case, the frame is considered finished and released. - * - * Returns: a #GstFlowReturn, usually GST_FLOW_OK. - */ -GstFlowReturn -gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame) +/* called with STREAM_LOCK */ +static void +gst_video_decoder_post_qos_drop (GstVideoDecoder * dec, GstClockTime timestamp) { - GstClockTime stream_time, jitter, earliest_time, qostime, timestamp; + GstClockTime stream_time, jitter, earliest_time, qostime; GstSegment *segment; GstMessage *qos_msg; gdouble proportion; - - GST_LOG_OBJECT (dec, "drop frame %p", frame); - - GST_VIDEO_DECODER_STREAM_LOCK (dec); - - gst_video_decoder_prepare_finish_frame (dec, frame, TRUE); - - GST_DEBUG_OBJECT (dec, "dropping frame %" GST_TIME_FORMAT, - GST_TIME_ARGS (frame->pts)); - dec->priv->dropped++; /* post QoS message */ @@ -2848,7 +2828,6 @@ gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame) earliest_time = dec->priv->earliest_time; GST_OBJECT_UNLOCK (dec); - timestamp = frame->pts; segment = &dec->output_segment; if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED)) segment = &dec->input_segment; @@ -2863,6 +2842,32 @@ gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame) gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, dec->priv->processed, dec->priv->dropped); gst_element_post_message (GST_ELEMENT_CAST (dec), qos_msg); +} + +/** + * gst_video_decoder_drop_frame: + * @dec: a #GstVideoDecoder + * @frame: (transfer full): the #GstVideoCodecFrame to drop + * + * Similar to gst_video_decoder_finish_frame(), but drops @frame in any + * case and posts a QoS message with the frame's details on the bus. + * In any case, the frame is considered finished and released. + * + * Returns: a #GstFlowReturn, usually GST_FLOW_OK. + */ +GstFlowReturn +gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame) +{ + GST_LOG_OBJECT (dec, "drop frame %p", frame); + + GST_VIDEO_DECODER_STREAM_LOCK (dec); + + gst_video_decoder_prepare_finish_frame (dec, frame, TRUE); + + GST_DEBUG_OBJECT (dec, "dropping frame %" GST_TIME_FORMAT, + GST_TIME_ARGS (frame->pts)); + + gst_video_decoder_post_qos_drop (dec, frame->pts); /* now free the frame */ gst_video_decoder_release_frame (dec, frame); @@ -3129,11 +3134,12 @@ gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf) GstClockTime deadline = gst_segment_to_running_time (segment, GST_FORMAT_TIME, cstart); if (GST_CLOCK_TIME_IS_VALID (deadline) && deadline < priv->earliest_time) { - GST_DEBUG_OBJECT (decoder, + GST_WARNING_OBJECT (decoder, "Dropping frame due to QoS. start:%" GST_TIME_FORMAT " deadline:%" GST_TIME_FORMAT " earliest_time:%" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (deadline), GST_TIME_ARGS (priv->earliest_time)); + gst_video_decoder_post_qos_drop (decoder, cstart); gst_buffer_unref (buf); priv->discont = TRUE; goto done;