aboutsummaryrefslogtreecommitdiff
path: root/gst/rtpmanager/gstrtpjitterbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/rtpmanager/gstrtpjitterbuffer.c')
-rw-r--r--gst/rtpmanager/gstrtpjitterbuffer.c135
1 files changed, 77 insertions, 58 deletions
diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
index 2529f2bb..a0e4aad3 100644
--- a/gst/rtpmanager/gstrtpjitterbuffer.c
+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
@@ -250,6 +250,7 @@ struct _GstRtpJitterBufferPrivate
/* state */
gboolean eos;
+ guint last_percent;
/* clock rate and rtp timestamp offset */
gint last_pt;
@@ -1124,6 +1125,7 @@ gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer)
priv->ext_timestamp = -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);
@@ -1354,6 +1356,7 @@ gst_rtp_jitter_buffer_sink_event (GstPad * pad, GstObject * parent,
if (ret && !priv->eos) {
GST_INFO_OBJECT (jitterbuffer, "queuing EOS");
priv->eos = TRUE;
+ rtp_jitter_buffer_disable_buffering (priv->jbuf, TRUE);
JBUF_SIGNAL_EVENT (priv);
} else if (priv->eos) {
GST_DEBUG_OBJECT (jitterbuffer, "dropping EOS, we are already EOS");
@@ -1472,31 +1475,24 @@ parse_failed:
}
/* call with jbuf lock held */
-static void
-check_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint * percent)
+static GstMessage *
+check_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint percent)
{
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
+ GstMessage *message = NULL;
- /* too short a stream, or too close to EOS will never really fill buffer */
- if (*percent != -1 && 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;
- }
-}
-
-static void
-post_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint percent)
-{
- GstMessage *message;
+ if (percent == -1)
+ return NULL;
/* Post a buffering message */
- message = gst_message_new_buffering (GST_OBJECT_CAST (jitterbuffer), percent);
- gst_message_set_buffering_stats (message, GST_BUFFERING_LIVE, -1, -1, -1);
+ if (priv->last_percent != percent) {
+ priv->last_percent = percent;
+ message =
+ gst_message_new_buffering (GST_OBJECT_CAST (jitterbuffer), percent);
+ gst_message_set_buffering_stats (message, GST_BUFFERING_LIVE, -1, -1, -1);
+ }
- gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer), message);
+ return message;
}
static GstClockTime
@@ -1916,6 +1912,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
gboolean do_next_seqnum = FALSE;
RTPJitterBufferItem *item;
+ GstMessage *msg = NULL;
jitterbuffer = GST_RTP_JITTER_BUFFER (parent);
@@ -2117,13 +2114,13 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
GST_DEBUG_OBJECT (jitterbuffer, "Pushed packet #%d, now %d packets, tail: %d",
seqnum, rtp_jitter_buffer_num_packets (priv->jbuf), tail);
- check_buffering_percent (jitterbuffer, &percent);
+ msg = check_buffering_percent (jitterbuffer, percent);
finished:
JBUF_UNLOCK (priv);
- if (percent != -1)
- post_buffering_percent (jitterbuffer, percent);
+ if (msg)
+ gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer), msg);
return ret;
@@ -2207,45 +2204,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;
-
- elapsed = compute_elapsed (jitterbuffer, item);
-
- if (elapsed > priv->last_elapsed || !priv->last_elapsed) {
- guint64 left;
- GstClockTime out_time;
+ if (priv->npt_stop == -1 || priv->ext_timestamp == -1
+ || priv->clock_base == -1 || priv->clock_rate <= 0)
+ return;
- priv->last_elapsed = elapsed;
+ /* compute the elapsed time */
+ elapsed = compute_elapsed (jitterbuffer, item);
- left = priv->npt_stop - priv->npt_start;
- GST_LOG_OBJECT (jitterbuffer, "left %" GST_TIME_FORMAT,
- GST_TIME_ARGS (left));
+ /* do nothing if elapsed time doesn't increment */
+ if (priv->last_elapsed && elapsed <= priv->last_elapsed)
+ return;
- out_time = item->dts;
+ priv->last_elapsed = elapsed;
- 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;
- }
+ /* 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));
- GST_LOG_OBJECT (jitterbuffer, "elapsed %" GST_TIME_FORMAT ", estimated %"
- GST_TIME_FORMAT, GST_TIME_ARGS (elapsed), GST_TIME_ARGS (estimated));
+ /* this is how much time there is left */
+ if (total > elapsed)
+ left = total - elapsed;
+ else
+ left = 0;
+
+ /* 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);
+ }
+
+ /* this is the current time as running-time */
+ out_time = item->dts;
+
+ 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;
- }
- }
+ if (estimated != -1 && priv->estimated_eos != estimated) {
+ set_timer (jitterbuffer, TIMER_TYPE_EOS, -1, estimated);
+ priv->estimated_eos = estimated;
}
}
@@ -2261,6 +2274,7 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum)
GstClockTime dts, pts;
gint percent = -1;
gboolean is_buffer, do_push = TRUE;
+ GstMessage *msg;
/* when we get here we are ready to pop and push the buffer */
item = rtp_jitter_buffer_pop (priv->jbuf, &percent);
@@ -2268,8 +2282,6 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum)
is_buffer = GST_IS_BUFFER (item->data);
if (is_buffer) {
- check_buffering_percent (jitterbuffer, &percent);
-
/* we need to make writable to change the flags and timestamps */
outbuf = gst_buffer_make_writable (item->data);
@@ -2309,16 +2321,18 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum)
* so the other end can push stuff in the queue again. */
priv->last_popped_seqnum = seqnum;
priv->next_seqnum = (seqnum + item->count) & 0xffff;
+
+ msg = check_buffering_percent (jitterbuffer, percent);
JBUF_UNLOCK (priv);
item->data = NULL;
free_item (item);
+ if (msg)
+ gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer), msg);
+
if (is_buffer) {
/* push buffer */
- if (percent != -1)
- post_buffering_percent (jitterbuffer, percent);
-
GST_DEBUG_OBJECT (jitterbuffer,
"Pushing buffer %d, dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT,
seqnum, GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
@@ -2537,6 +2551,11 @@ 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, assume there is now */
+ priv->eos = TRUE;
+ rtp_jitter_buffer_disable_buffering (priv->jbuf, TRUE);
+ }
JBUF_SIGNAL_EVENT (priv);
return TRUE;