rtpbin: more buffering work
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 27 Jan 2010 16:57:55 +0000 (17:57 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 12 Feb 2010 16:22:56 +0000 (17:22 +0100)
When deactivating jitterbuffers when the buffering starts, keep the current
percent of the jitterbuffer and also set the jitterbuffer in the buffering state
so that we know when it's filled again.
Add property to get the buffering percentage of the jitterbuffer.

gst/rtpmanager/gstrtpbin.c
gst/rtpmanager/gstrtpjitterbuffer.c
gst/rtpmanager/rtpjitterbuffer.c
gst/rtpmanager/rtpjitterbuffer.h

index 49284fa4156318eedbbbdda3e4024536353a8174..407c366bde9094e300d04619767d1576cb5c1cdd 100644 (file)
@@ -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;
-
-            g_signal_emit_by_name (element, "set-active", active, offset,
-                &last_out);
-
-            if (!active) {
-              if (last_out == -1)
-                last_out = 0;
-              if (last_out < min_out_time)
-                min_out_time = last_out;
+          for (sessions = rtpbin->sessions; sessions;
+              sessions = g_slist_next (sessions)) {
+            GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
+
+            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;
+
+              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);
index e480252adea6387c340f3d4735316f8751a27c7c..ddadd97ab69f963bed7271801a5892408f129a00 100644 (file)
@@ -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;
index d6a4d3756ba06e66ba3d3726066cf6aecb26ea0c..7e018d2677a33641eb45d4a13fad6e5a8cb87449 100644 (file)
@@ -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
index 310cec0a25a43b38757efe1da8f7de6019bc1287..85bf9775de5563647ee7c7dac403207763a79e95 100644 (file)
@@ -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);