Commit c4ccff78 authored by Matthew Waters's avatar Matthew Waters 🐨 Committed by Edward Hervey

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.
parent e1be0652
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment