From c4ccff786152a70f42f13b9406e1c992fffedf7a Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 17 May 2018 21:09:36 +1000 Subject: [PATCH] queue2: avoid ping-pong between 0% and 100% buffering messages If upstream is pushing buffers larger than our limits, only 1 buffer is ever in the queue at a time. Once that single buffer has left the queue, a 0% buffering message would be posted followed immediately by a 100% buffering message when the next buffer was inserted into the queue a very short time later. As per the recommendations, This would result in the application pausing for a short while causing the appearance of a short stutter. The first step of a solution involves not posting a buffering message if there is still data waiting on the sink pad for insertion into the queue. This successfully drops the 0% messages from being posted however a message is still posted on each transition to 100% when the new buffer arrives resulting in a string of 100% buffering messages. We silence these by storing the last posted buffering percentage and only posting a new message when it is different from or last posted message. --- plugins/elements/gstqueue2.c | 33 ++++++++++++++++++++++++--------- plugins/elements/gstqueue2.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c index bc3627f..f227a2b 100644 --- a/plugins/elements/gstqueue2.c +++ b/plugins/elements/gstqueue2.c @@ -531,6 +531,7 @@ gst_queue2_init (GstQueue2 * queue) g_mutex_init (&queue->buffering_post_lock); queue->buffering_percent = 100; + queue->last_posted_buffering_percent = -1; /* tempfile related */ queue->temp_template = NULL; @@ -1056,17 +1057,31 @@ static GstMessage * gst_queue2_get_buffering_message (GstQueue2 * queue) { GstMessage *msg = NULL; - if (queue->percent_changed) { - gint percent = queue->buffering_percent; - + /* Don't change the buffering level if the sinkpad is waiting for + * space to become available. This prevents the situation where, + * upstream is pushing buffers larger than our limits so only 1 buffer + * is ever in the queue at a time. + * Changing the level causes a buffering message to be posted saying that + * we are buffering which the application may pause to wait for another + * 100% buffering message which would be posted very soon after the + * waiting sink thread adds it's buffer to the queue */ + /* FIXME: This situation above can still occur later if + * the sink pad is waiting to push a serialized event into the queue and + * the queue becomes empty for a short period of time. */ + if (!queue->waiting_del + && queue->last_posted_buffering_percent != queue->buffering_percent) { + gint percent = queue->buffering_percent; + + GST_DEBUG_OBJECT (queue, "Going to post buffering: %d%%", percent); + msg = gst_message_new_buffering (GST_OBJECT_CAST (queue), percent); + + gst_message_set_buffering_stats (msg, queue->mode, queue->avg_in, + queue->avg_out, queue->buffering_left); + + queue->last_posted_buffering_percent = percent; + } queue->percent_changed = FALSE; - - GST_DEBUG_OBJECT (queue, "Going to post buffering: %d%%", percent); - msg = gst_message_new_buffering (GST_OBJECT_CAST (queue), percent); - - gst_message_set_buffering_stats (msg, queue->mode, queue->avg_in, - queue->avg_out, queue->buffering_left); } return msg; diff --git a/plugins/elements/gstqueue2.h b/plugins/elements/gstqueue2.h index fed3656..cd0ab2b 100644 --- a/plugins/elements/gstqueue2.h +++ b/plugins/elements/gstqueue2.h @@ -119,6 +119,7 @@ struct _GstQueue2 /* current buffering state */ gboolean is_buffering; gint buffering_percent; + gint last_posted_buffering_percent; /* for measuring input/output rates */ GTimer *in_timer; -- 2.7.4