diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 49284fa415..407c366bde 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -1771,7 +1771,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) gst_structure_set ((GstStructure *) s, "session", G_TYPE_UINT, sess->id, NULL); } - GST_RTP_BIN_UNLOCK (rtpbin); } GST_BIN_CLASS (parent_class)->handle_message (bin, message); break; @@ -1780,7 +1779,7 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) { gint percent; gint min_percent = 100; - GSList *sessions, *streams, *elements = NULL; + GSList *sessions, *streams; GstRtpBinStream *stream; gboolean change = FALSE, active = FALSE; GstClockTime min_out_time; @@ -1808,7 +1807,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) for (streams = session->streams; streams; streams = g_slist_next (streams)) { GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; - GstElement *element = stream->buffer; GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream, stream->percent); @@ -1816,8 +1814,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) /* find min percent */ if (min_percent > stream->percent) min_percent = stream->percent; - - elements = g_slist_prepend (elements, gst_object_ref (element)); } GST_RTP_SESSION_UNLOCK (session); } @@ -1863,6 +1859,8 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) "running time now %" GST_TIME_FORMAT, GST_TIME_ARGS (running_time)); + GST_RTP_BIN_LOCK (rtpbin); + /* when we reactivate, calculate the offsets so that all streams have * an output time that is at least as big as the running_time */ offset = 0; @@ -1876,28 +1874,38 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) } } + /* pause all streams */ min_out_time = -1; - while (G_LIKELY (elements)) { - GstElement *element = elements->data; - GstClockTime last_out; + for (sessions = rtpbin->sessions; sessions; + sessions = g_slist_next (sessions)) { + GstRtpBinSession *session = (GstRtpBinSession *) sessions->data; - g_signal_emit_by_name (element, "set-active", active, offset, - &last_out); + GST_RTP_SESSION_LOCK (session); + for (streams = session->streams; streams; + streams = g_slist_next (streams)) { + GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; + GstElement *element = stream->buffer; + guint64 last_out; - if (!active) { - if (last_out == -1) - last_out = 0; - if (last_out < min_out_time) - min_out_time = last_out; + g_signal_emit_by_name (element, "set-active", active, offset, + &last_out); + + if (!active) { + g_object_get (element, "percent", &stream->percent, NULL); + + if (last_out == -1) + last_out = 0; + if (last_out < min_out_time) + min_out_time = last_out; + } + + GST_DEBUG_OBJECT (bin, + "setting %p to %d, offset %" GST_TIME_FORMAT ", last %" + GST_TIME_FORMAT ", percent %d", element, active, + GST_TIME_ARGS (offset), GST_TIME_ARGS (last_out), + stream->percent); } - - GST_DEBUG_OBJECT (bin, - "setting %p to %d, offset %" GST_TIME_FORMAT ", last %" - GST_TIME_FORMAT, element, active, GST_TIME_ARGS (offset), - GST_TIME_ARGS (last_out)); - - gst_object_unref (element); - elements = g_slist_delete_link (elements, elements); + GST_RTP_SESSION_UNLOCK (session); } GST_DEBUG_OBJECT (bin, "min out time %" GST_TIME_FORMAT, GST_TIME_ARGS (min_out_time)); @@ -1905,6 +1913,8 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) /* the buffer_start is the min out time of all paused jitterbuffers */ if (!active) rtpbin->buffer_start = min_out_time; + + GST_RTP_BIN_UNLOCK (rtpbin); } } GST_BIN_CLASS (parent_class)->handle_message (bin, message); diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index e480252ade..ddadd97ab6 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -94,6 +94,7 @@ enum #define DEFAULT_TS_OFFSET 0 #define DEFAULT_DO_LOST FALSE #define DEFAULT_MODE RTP_JITTER_BUFFER_MODE_SLAVE +#define DEFAULT_PERCENT 0 enum { @@ -103,6 +104,7 @@ enum PROP_TS_OFFSET, PROP_DO_LOST, PROP_MODE, + PROP_PERCENT, PROP_LAST }; @@ -355,6 +357,15 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) g_param_spec_enum ("mode", "Mode", "Control the buffering algorithm in use", RTP_TYPE_JITTER_BUFFER_MODE, DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRtpJitterBuffer::percent: + * + * The percent of the jitterbuffer that is filled. + */ + g_object_class_install_property (gobject_class, PROP_PERCENT, + g_param_spec_int ("percent", "percent", + "The buffer filled percent", 0, 100, + 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** * GstRtpJitterBuffer::request-pt-map: * @buffer: the object which received the signal @@ -673,6 +684,9 @@ gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jbuf, gboolean active, priv->active = active; JBUF_SIGNAL (priv); } + if (!active) { + rtp_jitter_buffer_set_buffering (priv->jbuf, TRUE); + } if ((head = rtp_jitter_buffer_peek (priv->jbuf))) { /* head buffer timestamp and offset gives our output time */ last_out = GST_BUFFER_TIMESTAMP (head) + priv->ts_offset; @@ -2131,6 +2145,20 @@ gst_rtp_jitter_buffer_get_property (GObject * object, g_value_set_enum (value, rtp_jitter_buffer_get_mode (priv->jbuf)); JBUF_UNLOCK (priv); break; + case PROP_PERCENT: + { + gint percent; + + JBUF_LOCK (priv); + if (priv->srcresult != GST_FLOW_OK) + percent = 100; + else + percent = rtp_jitter_buffer_get_percent (priv->jbuf); + + g_value_set_int (value, percent); + JBUF_UNLOCK (priv); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c index d6a4d3756b..7e018d2677 100644 --- a/gst/rtpmanager/rtpjitterbuffer.c +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -162,7 +162,7 @@ rtp_jitter_buffer_set_delay (RTPJitterBuffer * jbuf, GstClockTime delay) jbuf->high_level = (delay * 90) / 100; GST_DEBUG ("delay %" GST_TIME_FORMAT ", min %" GST_TIME_FORMAT ", max %" - GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->level), + GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->delay), GST_TIME_ARGS (jbuf->low_level), GST_TIME_ARGS (jbuf->high_level)); } @@ -209,17 +209,17 @@ rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time, } } -static void -update_buffer_level (RTPJitterBuffer * jbuf, gint * percent) +static guint64 +get_buffer_level (RTPJitterBuffer * jbuf) { GstBuffer *high_buf, *low_buf; - gboolean post = FALSE; + guint64 level; high_buf = g_queue_peek_head (jbuf->packets); low_buf = g_queue_peek_tail (jbuf->packets); if (!high_buf || !low_buf || high_buf == low_buf) { - jbuf->level = 0; + level = 0; } else { guint64 high_ts, low_ts; @@ -227,20 +227,30 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent) low_ts = GST_BUFFER_TIMESTAMP (low_buf); if (high_ts > low_ts) - jbuf->level = high_ts - low_ts; + level = high_ts - low_ts; else - jbuf->level = 0; + level = 0; } - GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->level)); + return level; +} + +static void +update_buffer_level (RTPJitterBuffer * jbuf, gint * percent) +{ + gboolean post = FALSE; + guint64 level; + + level = get_buffer_level (jbuf); + GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (level)); if (jbuf->buffering) { post = TRUE; - if (jbuf->level > jbuf->high_level) { + if (level > jbuf->high_level) { GST_DEBUG ("buffering finished"); jbuf->buffering = FALSE; } } else { - if (jbuf->level < jbuf->low_level) { + if (level < jbuf->low_level) { GST_DEBUG ("buffering started"); jbuf->buffering = TRUE; post = TRUE; @@ -250,7 +260,7 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent) gint perc; if (jbuf->buffering) { - perc = (jbuf->level * 100 / jbuf->high_level); + perc = (level * 100 / jbuf->high_level); perc = MIN (perc, 100); } else { perc = 100; @@ -323,7 +333,7 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent) */ static GstClockTime calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time, - guint32 clock_rate, GstClockTime max_delay) + guint32 clock_rate) { guint64 ext_rtptime; guint64 send_diff, recv_diff; @@ -723,6 +733,40 @@ rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf) return jbuf->buffering; } +/** + * rtp_jitter_buffer_set_buffering: + * @jbuf: an #RTPJitterBuffer + * @buffering: the new buffering state + * + * Forces @jbuf to go into the buffering state. + */ +void +rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering) +{ + jbuf->buffering = buffering; +} + +/** + * rtp_jitter_buffer_get_percent: + * @jbuf: an #RTPJitterBuffer + * + * Get the buffering percent of the jitterbuffer. + * + * Returns: the buffering percent + */ +gint +rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf) +{ + gint percent; + guint64 level; + + level = get_buffer_level (jbuf); + percent = (level * 100 / jbuf->high_level); + percent = MIN (percent, 100); + + return percent; +} + /** * rtp_jitter_buffer_num_packets: * @jbuf: an #RTPJitterBuffer diff --git a/gst/rtpmanager/rtpjitterbuffer.h b/gst/rtpmanager/rtpjitterbuffer.h index 310cec0a25..85bf9775de 100644 --- a/gst/rtpmanager/rtpjitterbuffer.h +++ b/gst/rtpmanager/rtpjitterbuffer.h @@ -75,7 +75,6 @@ struct _RTPJitterBuffer { /* for buffering */ gboolean buffering; - guint64 level; guint64 low_level; guint64 high_level; @@ -123,6 +122,8 @@ GstBuffer * rtp_jitter_buffer_pop (RTPJitterBuffer *jbuf, void rtp_jitter_buffer_flush (RTPJitterBuffer *jbuf); gboolean rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf); +void rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering); +gint rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf); guint rtp_jitter_buffer_num_packets (RTPJitterBuffer *jbuf); guint32 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer *jbuf);