From 4b6cb930255e407c803bd4a7a9828a615a2250fa Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Wed, 2 Jun 2010 13:39:10 +0200 Subject: [PATCH] rtpjitterbuffer: stop buffering and emit EOS at the end of a stream When using RTP_JITTER_BUFFER_MODE_BUFFER, make sure that the ringbuffer doesn't get stuck buffering forever when there isn't enough data left to fill the buffer. --- common | 2 +- gst/rtpmanager/gstrtpjitterbuffer.c | 87 +++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/common b/common index 47683c1bbe..4d67bd6f51 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 47683c1bbe3be3c8b2468039aa4cd860bbe03e6c +Subproject commit 4d67bd6f51003ea5c7e7ae75f53ce95acc4c4175 diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index ddf84a1d6f..62b9ad1ba7 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -1090,7 +1090,7 @@ gst_rtp_jitter_buffer_sink_event (GstPad * pad, GstEvent * event) * we are flushing */ ret = priv->srcresult == GST_FLOW_OK; if (ret && !priv->eos) { - GST_DEBUG_OBJECT (jitterbuffer, "queuing EOS"); + GST_INFO_OBJECT (jitterbuffer, "queuing EOS"); priv->eos = TRUE; JBUF_SIGNAL (priv); } else if (priv->eos) { @@ -1485,7 +1485,7 @@ eos_reached (GstClock * clock, GstClockTime time, GstClockID id, JBUF_LOCK_CHECK (priv, flushing); if (priv->waiting) { - GST_DEBUG_OBJECT (jitterbuffer, "got the NPT timeout"); + GST_INFO_OBJECT (jitterbuffer, "got the NPT timeout"); priv->reached_npt_stop = TRUE; JBUF_SIGNAL (priv); } @@ -1500,6 +1500,33 @@ flushing: return FALSE; } } +static GstClockTime +compute_elapsed (GstRtpJitterBuffer * jitterbuffer, GstBuffer * outbuf) +{ + guint64 ext_time, elapsed, estimated; + guint32 rtp_time; + GstRtpJitterBufferPrivate *priv; + + priv = jitterbuffer->priv; + rtp_time = gst_rtp_buffer_get_timestamp (outbuf); + + GST_LOG_OBJECT (jitterbuffer, "rtp %" G_GUINT32_FORMAT ", ext %" + G_GUINT64_FORMAT, rtp_time, priv->ext_timestamp); + + if (rtp_time < priv->ext_timestamp) { + ext_time = priv->ext_timestamp; + } else { + ext_time = gst_rtp_buffer_ext_timestamp (&priv->ext_timestamp, rtp_time); + } + + if (ext_time > priv->clock_base) + elapsed = ext_time - priv->clock_base; + else + elapsed = 0; + + elapsed = gst_util_uint64_scale_int (elapsed, GST_SECOND, priv->clock_rate); + return elapsed; +} /* * This funcion will push out buffers on the source pad. @@ -1535,8 +1562,37 @@ again: if (G_LIKELY (!priv->blocked)) { /* we're buffering but not EOS, wait. */ if (!priv->eos && (!priv->active - || rtp_jitter_buffer_is_buffering (priv->jbuf))) - goto do_wait; + || rtp_jitter_buffer_is_buffering (priv->jbuf))) { + GstClockTime elapsed, delay, left; + + if (priv->estimated_eos == -1) + goto do_wait; + + outbuf = rtp_jitter_buffer_peek (priv->jbuf); + if (outbuf != NULL) { + elapsed = compute_elapsed (jitterbuffer, outbuf); + if (GST_BUFFER_DURATION_IS_VALID (outbuf)) + elapsed += GST_BUFFER_DURATION (outbuf); + } else { + GST_INFO_OBJECT (jitterbuffer, "no buffer, using last_elapsed"); + elapsed = priv->last_elapsed; + } + + delay = rtp_jitter_buffer_get_delay (priv->jbuf); + + if (priv->estimated_eos > elapsed) + left = priv->estimated_eos - elapsed; + else + left = 0; + + GST_INFO_OBJECT (jitterbuffer, "buffering, elapsed %" GST_TIME_FORMAT + " estimated_eos %" GST_TIME_FORMAT " left %" GST_TIME_FORMAT + " delay %" GST_TIME_FORMAT, + GST_TIME_ARGS (elapsed), GST_TIME_ARGS (priv->estimated_eos), + GST_TIME_ARGS (left), GST_TIME_ARGS (delay)); + if (left > delay) + goto do_wait; + } /* if we have a packet, we can exit the loop and grab it */ if (rtp_jitter_buffer_num_packets (priv->jbuf) > 0) break; @@ -1551,7 +1607,7 @@ again: GST_OBJECT_LOCK (jitterbuffer); clock = GST_ELEMENT_CLOCK (jitterbuffer); if (clock) { - GST_DEBUG_OBJECT (jitterbuffer, "scheduling timeout"); + GST_INFO_OBJECT (jitterbuffer, "scheduling timeout"); id = gst_clock_new_single_shot_id (clock, sync_time); gst_clock_id_wait_async (id, (GstClockCallback) eos_reached, jitterbuffer); @@ -1768,26 +1824,9 @@ push_buffer: /* update the elapsed time when we need to check against the npt stop time. */ if (priv->npt_stop != -1 && priv->ext_timestamp != -1 && priv->clock_base != -1 && priv->clock_rate > 0) { - guint64 ext_time, elapsed, estimated; - guint32 rtp_time; + guint64 elapsed, estimated; - rtp_time = gst_rtp_buffer_get_timestamp (outbuf); - - GST_LOG_OBJECT (jitterbuffer, "rtp %" G_GUINT32_FORMAT ", ext %" - G_GUINT64_FORMAT, rtp_time, priv->ext_timestamp); - - if (rtp_time < priv->ext_timestamp) { - ext_time = priv->ext_timestamp; - } else { - ext_time = gst_rtp_buffer_ext_timestamp (&priv->ext_timestamp, rtp_time); - } - - if (ext_time > priv->clock_base) - elapsed = ext_time - priv->clock_base; - else - elapsed = 0; - - elapsed = gst_util_uint64_scale_int (elapsed, GST_SECOND, priv->clock_rate); + elapsed = compute_elapsed (jitterbuffer, outbuf); if (elapsed > priv->last_elapsed) { guint64 left;