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.
This commit is contained in:
Matthew Waters 2018-05-17 21:09:36 +10:00 committed by Edward Hervey
parent e1be065293
commit c4ccff7861
2 changed files with 24 additions and 8 deletions

View file

@ -531,6 +531,7 @@ gst_queue2_init (GstQueue2 * queue)
g_mutex_init (&queue->buffering_post_lock); g_mutex_init (&queue->buffering_post_lock);
queue->buffering_percent = 100; queue->buffering_percent = 100;
queue->last_posted_buffering_percent = -1;
/* tempfile related */ /* tempfile related */
queue->temp_template = NULL; queue->temp_template = NULL;
@ -1056,17 +1057,31 @@ static GstMessage *
gst_queue2_get_buffering_message (GstQueue2 * queue) gst_queue2_get_buffering_message (GstQueue2 * queue)
{ {
GstMessage *msg = NULL; GstMessage *msg = NULL;
if (queue->percent_changed) { 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; 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; return msg;

View file

@ -119,6 +119,7 @@ struct _GstQueue2
/* current buffering state */ /* current buffering state */
gboolean is_buffering; gboolean is_buffering;
gint buffering_percent; gint buffering_percent;
gint last_posted_buffering_percent;
/* for measuring input/output rates */ /* for measuring input/output rates */
GTimer *in_timer; GTimer *in_timer;