diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 7778005166..06ecaf2bef 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -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; diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c index 1262f7d09a..d6cfc7d5bd 100644 --- a/gst/rtpmanager/rtpjitterbuffer.c +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -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); diff --git a/gst/rtpmanager/rtpjitterbuffer.h b/gst/rtpmanager/rtpjitterbuffer.h index 63eff02b04..7c8e5cbe47 100644 --- a/gst/rtpmanager/rtpjitterbuffer.h +++ b/gst/rtpmanager/rtpjitterbuffer.h @@ -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);