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 49284fa..407c366 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 e480252..ddadd97 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
 };
 
@@ -356,6 +358,15 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
           "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
    * @pt: the pt
@@ -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 d6a4d37..7e018d2 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;
@@ -724,6 +734,40 @@ rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf)
 }
 
 /**
+ * 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 310cec0..85bf977 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);