mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
jitterbuffer: improve EOS handling
Make a new method to disable the jitterbuffer buffering. Rework the update_estimated_eos() method. Calculate how much time there is left to play. If we have less than the delay of the jitterbuffer, we disabled buffering because we might never be able to fill the complete jitterbuffer again. If we receive an EOS event, disable buffering. We will drain the buffer and eventually push the EOS event out. When we reach the estimated NPT timeout and we didn't receive an EOS event, make one and queue it so that it can be pushed. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728017
This commit is contained in:
parent
38a486b374
commit
3e11ce43b9
3 changed files with 78 additions and 39 deletions
|
@ -1184,6 +1184,7 @@ gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer)
|
|||
priv->last_rtptime = -1;
|
||||
GST_DEBUG_OBJECT (jitterbuffer, "flush and reset jitterbuffer");
|
||||
rtp_jitter_buffer_flush (priv->jbuf, (GFunc) free_item, NULL);
|
||||
rtp_jitter_buffer_disable_buffering (priv->jbuf, FALSE);
|
||||
rtp_jitter_buffer_reset_skew (priv->jbuf);
|
||||
remove_all_timers (jitterbuffer);
|
||||
JBUF_UNLOCK (priv);
|
||||
|
@ -1378,6 +1379,7 @@ queue_event (GstRtpJitterBuffer * jitterbuffer, GstEvent * event)
|
|||
break;
|
||||
case GST_EVENT_EOS:
|
||||
priv->eos = TRUE;
|
||||
rtp_jitter_buffer_disable_buffering (priv->jbuf, TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1575,14 +1577,6 @@ check_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint percent)
|
|||
if (percent == -1)
|
||||
return NULL;
|
||||
|
||||
if (priv->eos || (priv->npt_stop != -1 &&
|
||||
priv->npt_stop - priv->npt_start <=
|
||||
rtp_jitter_buffer_get_delay (priv->jbuf))) {
|
||||
GST_DEBUG_OBJECT (jitterbuffer, "short stream; faking full buffer");
|
||||
rtp_jitter_buffer_set_buffering (priv->jbuf, FALSE);
|
||||
percent = 100;
|
||||
}
|
||||
|
||||
/* Post a buffering message */
|
||||
if (priv->last_percent != percent) {
|
||||
priv->last_percent = percent;
|
||||
|
@ -2387,45 +2381,61 @@ static void
|
|||
update_estimated_eos (GstRtpJitterBuffer * jitterbuffer,
|
||||
RTPJitterBufferItem * item)
|
||||
{
|
||||
guint64 total, elapsed, left, estimated;
|
||||
GstClockTime out_time;
|
||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||
|
||||
if (priv->npt_stop != -1 && priv->ext_timestamp != -1
|
||||
&& priv->clock_base != -1 && priv->clock_rate > 0) {
|
||||
guint64 elapsed, estimated;
|
||||
if (priv->npt_stop == -1 || priv->ext_timestamp == -1
|
||||
|| priv->clock_base == -1 || priv->clock_rate <= 0)
|
||||
return;
|
||||
|
||||
elapsed = compute_elapsed (jitterbuffer, item);
|
||||
/* compute the elapsed time */
|
||||
elapsed = compute_elapsed (jitterbuffer, item);
|
||||
|
||||
if (elapsed > priv->last_elapsed || !priv->last_elapsed) {
|
||||
guint64 left;
|
||||
GstClockTime out_time;
|
||||
/* do nothing if elapsed time doesn't increment */
|
||||
if (priv->last_elapsed && elapsed <= priv->last_elapsed)
|
||||
return;
|
||||
|
||||
priv->last_elapsed = elapsed;
|
||||
priv->last_elapsed = elapsed;
|
||||
|
||||
left = priv->npt_stop - priv->npt_start;
|
||||
GST_LOG_OBJECT (jitterbuffer, "left %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (left));
|
||||
/* this is the total time we need to play */
|
||||
total = priv->npt_stop - priv->npt_start;
|
||||
GST_LOG_OBJECT (jitterbuffer, "total %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (total));
|
||||
|
||||
out_time = item->dts;
|
||||
/* this is how much time there is left */
|
||||
if (total > elapsed)
|
||||
left = total - elapsed;
|
||||
else
|
||||
left = 0;
|
||||
|
||||
if (elapsed > 0)
|
||||
estimated = gst_util_uint64_scale (out_time, left, elapsed);
|
||||
else {
|
||||
/* if there is almost nothing left,
|
||||
* we may never advance enough to end up in the above case */
|
||||
if (left < GST_SECOND)
|
||||
estimated = GST_SECOND;
|
||||
else
|
||||
estimated = -1;
|
||||
}
|
||||
/* if we have less time left that the size of the buffer, we will not
|
||||
* be able to keep it filled, disabled buffering then */
|
||||
if (left < rtp_jitter_buffer_get_delay (priv->jbuf)) {
|
||||
GST_DEBUG_OBJECT (jitterbuffer, "left %" GST_TIME_FORMAT
|
||||
", disable buffering close to EOS", GST_TIME_ARGS (left));
|
||||
rtp_jitter_buffer_disable_buffering (priv->jbuf, TRUE);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (jitterbuffer, "elapsed %" GST_TIME_FORMAT ", estimated %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (elapsed), GST_TIME_ARGS (estimated));
|
||||
/* this is the current time as running-time */
|
||||
out_time = item->dts;
|
||||
|
||||
if (estimated != -1 && priv->estimated_eos != estimated) {
|
||||
set_timer (jitterbuffer, TIMER_TYPE_EOS, -1, estimated);
|
||||
priv->estimated_eos = estimated;
|
||||
}
|
||||
}
|
||||
if (elapsed > 0)
|
||||
estimated = gst_util_uint64_scale (out_time, total, elapsed);
|
||||
else {
|
||||
/* if there is almost nothing left,
|
||||
* we may never advance enough to end up in the above case */
|
||||
if (total < GST_SECOND)
|
||||
estimated = GST_SECOND;
|
||||
else
|
||||
estimated = -1;
|
||||
}
|
||||
GST_LOG_OBJECT (jitterbuffer, "elapsed %" GST_TIME_FORMAT ", estimated %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (elapsed), GST_TIME_ARGS (estimated));
|
||||
|
||||
if (estimated != -1 && priv->estimated_eos != estimated) {
|
||||
set_timer (jitterbuffer, TIMER_TYPE_EOS, -1, estimated);
|
||||
priv->estimated_eos = estimated;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2787,6 +2797,10 @@ do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
|||
|
||||
GST_INFO_OBJECT (jitterbuffer, "got the NPT timeout");
|
||||
remove_timer (jitterbuffer, timer);
|
||||
if (!priv->eos) {
|
||||
/* there was no EOS in the buffer, put one in there now */
|
||||
queue_event (jitterbuffer, gst_event_new_eos ());
|
||||
}
|
||||
JBUF_SIGNAL_EVENT (priv);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -226,6 +226,19 @@ rtp_jitter_buffer_reset_skew (RTPJitterBuffer * jbuf)
|
|||
GST_DEBUG ("reset skew correction");
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_jitter_buffer_disable_buffering:
|
||||
* @jbuf: an #RTPJitterBuffer
|
||||
* @disabled: the new state
|
||||
*
|
||||
* Enable or disable buffering on @jbuf.
|
||||
*/
|
||||
void
|
||||
rtp_jitter_buffer_disable_buffering (RTPJitterBuffer * jbuf, gboolean disabled)
|
||||
{
|
||||
jbuf->buffering_disabled = disabled;
|
||||
}
|
||||
|
||||
static void
|
||||
rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time,
|
||||
GstClockTime gstrtptime, guint64 ext_rtptime, gboolean reset_skew)
|
||||
|
@ -297,9 +310,14 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
|||
level = get_buffer_level (jbuf);
|
||||
GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (level));
|
||||
|
||||
if (jbuf->buffering_disabled) {
|
||||
GST_DEBUG ("buffering is disabled");
|
||||
level = jbuf->high_level;
|
||||
}
|
||||
|
||||
if (jbuf->buffering) {
|
||||
post = TRUE;
|
||||
if (level > jbuf->high_level) {
|
||||
if (level >= jbuf->high_level) {
|
||||
GST_DEBUG ("buffering finished");
|
||||
jbuf->buffering = FALSE;
|
||||
}
|
||||
|
@ -850,7 +868,7 @@ rtp_jitter_buffer_flush (RTPJitterBuffer * jbuf, GFunc free_func,
|
|||
gboolean
|
||||
rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf)
|
||||
{
|
||||
return jbuf->buffering;
|
||||
return jbuf->buffering && !jbuf->buffering_disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -883,6 +901,9 @@ rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf)
|
|||
if (G_UNLIKELY (jbuf->high_level == 0))
|
||||
return 100;
|
||||
|
||||
if (G_UNLIKELY (jbuf->buffering_disabled))
|
||||
return 100;
|
||||
|
||||
level = get_buffer_level (jbuf);
|
||||
percent = (level * 100 / jbuf->high_level);
|
||||
percent = MIN (percent, 100);
|
||||
|
|
|
@ -100,6 +100,7 @@ struct _RTPJitterBuffer {
|
|||
gint64 window_min;
|
||||
gint64 skew;
|
||||
gint64 prev_send_diff;
|
||||
gboolean buffering_disabled;
|
||||
};
|
||||
|
||||
struct _RTPJitterBufferClass {
|
||||
|
@ -153,6 +154,9 @@ void rtp_jitter_buffer_reset_skew (RTPJitterBuffer *jbuf)
|
|||
gboolean rtp_jitter_buffer_insert (RTPJitterBuffer *jbuf,
|
||||
RTPJitterBufferItem *item,
|
||||
gboolean *tail, gint *percent);
|
||||
|
||||
void rtp_jitter_buffer_disable_buffering (RTPJitterBuffer *jbuf, gboolean disabled);
|
||||
|
||||
RTPJitterBufferItem * rtp_jitter_buffer_peek (RTPJitterBuffer *jbuf);
|
||||
RTPJitterBufferItem * rtp_jitter_buffer_pop (RTPJitterBuffer *jbuf, gint *percent);
|
||||
|
||||
|
|
Loading…
Reference in a new issue