rtpdtmfmux: Add last-stop to dtmf-event upstream events
authorOlivier Crête <olivier.crete@collabora.co.uk>
Thu, 14 Apr 2011 18:34:26 +0000 (14:34 -0400)
committerTim-Philipp Müller <tim@centricular.net>
Sun, 16 Dec 2012 16:35:22 +0000 (16:35 +0000)
Add the running time of the last outputted buffer to the
upstream "dtmf-event" events so that the dtmf source does not
leave a gap.

gst/rtpmanager/gstrtpdtmfmux.c
gst/rtpmanager/gstrtpmux.c
gst/rtpmanager/gstrtpmux.h

index f62c626..97ffacd 100644 (file)
@@ -64,6 +64,8 @@ static GstStateChangeReturn gst_rtp_dtmf_mux_change_state (GstElement * element,
 
 static gboolean gst_rtp_dtmf_mux_accept_buffer_locked (GstRTPMux * rtp_mux,
     GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer);
+static gboolean gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux,
+    GstEvent * event);
 
 GST_BOILERPLATE (GstRTPDTMFMux, gst_rtp_dtmf_mux, GstRTPMux, GST_TYPE_RTP_MUX);
 
@@ -100,6 +102,7 @@ gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_change_state);
   gstrtpmux_class->accept_buffer_locked = gst_rtp_dtmf_mux_accept_buffer_locked;
+  gstrtpmux_class->src_event = gst_rtp_dtmf_mux_src_event;
 }
 
 static gboolean
@@ -173,6 +176,28 @@ gst_rtp_dtmf_mux_request_new_pad (GstElement * element, GstPadTemplate * templ,
   return pad;
 }
 
+static gboolean
+gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux, GstEvent * event)
+{
+  if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) {
+    const GstStructure *s = gst_event_get_structure (event);
+
+    if (s && gst_structure_has_name (s, "dtmf-event")) {
+      GST_OBJECT_LOCK (rtp_mux);
+      if (GST_CLOCK_TIME_IS_VALID (rtp_mux->last_stop)) {
+        event = (GstEvent *)
+            gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (event));
+        s = gst_event_get_structure (event);
+        gst_structure_set ((GstStructure *) s,
+            "last-stop", G_TYPE_UINT64, rtp_mux->last_stop, NULL);
+      }
+      GST_OBJECT_UNLOCK (rtp_mux);
+    }
+  }
+
+  return GST_RTP_MUX_CLASS (parent_class)->src_event (rtp_mux, event);
+}
+
 
 static GstStateChangeReturn
 gst_rtp_dtmf_mux_change_state (GstElement * element, GstStateChange transition)
index 57929ec..f86fd5d 100644 (file)
@@ -107,6 +107,9 @@ static void gst_rtp_mux_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_rtp_mux_dispose (GObject * object);
 
+static gboolean gst_rtp_mux_src_event_real (GstRTPMux *rtp_mux,
+    GstEvent * event);
+
 GST_BOILERPLATE (GstRTPMux, gst_rtp_mux, GstElement, GST_TYPE_ELEMENT);
 
 static void
@@ -137,6 +140,8 @@ gst_rtp_mux_class_init (GstRTPMuxClass * klass)
   gobject_class->set_property = gst_rtp_mux_set_property;
   gobject_class->dispose = gst_rtp_mux_dispose;
 
+  klass->src_event = gst_rtp_mux_src_event_real;
+
   g_object_class_install_property (G_OBJECT_CLASS (klass),
       PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset",
           "Timestamp Offset",
@@ -183,16 +188,30 @@ restart:
 static gboolean
 gst_rtp_mux_src_event (GstPad * pad, GstEvent * event)
 {
-  GstElement *rtp_mux;
+  GstRTPMux *rtp_mux;
+  GstRTPMuxClass *klass;
+  gboolean ret = FALSE;
+
+  rtp_mux = (GstRTPMux *) gst_pad_get_parent_element (pad);
+  g_return_val_if_fail (rtp_mux != NULL, FALSE);
+  klass = GST_RTP_MUX_GET_CLASS (rtp_mux);
+
+  ret = klass->src_event (rtp_mux, event);
+
+  gst_object_unref (rtp_mux);
+
+  return ret;
+}
+
+static gboolean
+gst_rtp_mux_src_event_real (GstRTPMux *rtp_mux, GstEvent * event)
+{
   GstIterator *iter;
   GstPad *sinkpad;
   gboolean result = FALSE;
   gboolean done = FALSE;
 
-  rtp_mux = gst_pad_get_parent_element (pad);
-  g_return_val_if_fail (rtp_mux != NULL, FALSE);
-
-  iter = gst_element_iterate_sink_pads (rtp_mux);
+  iter = gst_element_iterate_sink_pads (GST_ELEMENT (rtp_mux));
 
   while (!done) {
     switch (gst_iterator_next (iter, (gpointer) & sinkpad)) {
@@ -213,7 +232,6 @@ gst_rtp_mux_src_event (GstPad * pad, GstEvent * event)
     }
   }
   gst_iterator_free (iter);
-  gst_object_unref (rtp_mux);
   gst_event_unref (event);
 
   return result;
@@ -236,6 +254,7 @@ gst_rtp_mux_init (GstRTPMux * object, GstRTPMuxClass * g_class)
   object->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
 
   object->segment_pending = TRUE;
+  object->last_stop = GST_CLOCK_TIME_NONE;
 }
 
 static void
@@ -394,6 +413,20 @@ gst_rtp_mux_chain_list (GstPad * pad, GstBufferList * bufferlist)
       break;
 
     gst_buffer_list_iterator_take (it, rtpbuf);
+
+    do {
+      if (GST_BUFFER_DURATION_IS_VALID (rtpbuf) &&
+          GST_BUFFER_TIMESTAMP_IS_VALID (rtpbuf))
+        rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (rtpbuf) +
+            GST_BUFFER_DURATION (rtpbuf);
+      else
+        rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
+
+      gst_buffer_list_iterator_take (it, rtpbuf);
+
+    } while ((rtpbuf = gst_buffer_list_iterator_next (it)) != NULL);
+
+
   }
   gst_buffer_list_iterator_free (it);
 
@@ -456,15 +489,25 @@ gst_rtp_mux_chain (GstPad * pad, GstBuffer * buffer)
 
   drop = !process_buffer_locked (rtp_mux, padpriv, buffer);
 
-  if (!drop && rtp_mux->segment_pending) {
-    /*
-     * We set the start at 0, because we re-timestamps to the running time
-     */
-    newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
-        GST_FORMAT_TIME, 0, -1, 0);
+  if (!drop) {
+    if (rtp_mux->segment_pending) {
+      /*
+       * We set the start at 0, because we re-timestamps to the running time
+       */
+      newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
+          GST_FORMAT_TIME, 0, -1, 0);
 
-    rtp_mux->segment_pending = FALSE;
+      rtp_mux->segment_pending = FALSE;
+    }
+
+    if (GST_BUFFER_DURATION_IS_VALID (buffer) &&
+        GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
+      rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (buffer) +
+          GST_BUFFER_DURATION (buffer);
+    else
+      rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
   }
+
   GST_OBJECT_UNLOCK (rtp_mux);
 
   if (newseg_event)
@@ -709,6 +752,7 @@ gst_rtp_mux_sink_event (GstPad * pad, GstEvent * event)
       GstRTPMuxPadPrivate *padpriv;
 
       GST_OBJECT_LOCK (mux);
+      mux->last_stop = GST_CLOCK_TIME_NONE;
       mux->segment_pending = TRUE;
       padpriv = gst_pad_get_element_private (pad);
       if (padpriv)
@@ -801,6 +845,8 @@ gst_rtp_mux_ready_to_paused (GstRTPMux * rtp_mux)
   else
     rtp_mux->ts_base = rtp_mux->ts_offset;
 
+  rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
+
   GST_DEBUG_OBJECT (rtp_mux, "set clock-base to %u", rtp_mux->ts_base);
 
   GST_OBJECT_UNLOCK (rtp_mux);
index 9651383..7bfea60 100644 (file)
@@ -31,7 +31,7 @@
 G_BEGIN_DECLS
 #define GST_TYPE_RTP_MUX (gst_rtp_mux_get_type())
 #define GST_RTP_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MUX, GstRTPMux))
-#define GST_RTP_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MUX, GstRTPMux))
+#define GST_RTP_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MUX, GstRTPMuxClass))
 #define GST_RTP_MUX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTP_MUX, GstRTPMuxClass))
 #define GST_IS_RTP_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MUX))
 #define GST_IS_RTP_MUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MUX))
@@ -74,6 +74,8 @@ struct _GstRTPMux
   guint current_ssrc;
 
   gboolean segment_pending;
+
+  GstClockTime last_stop;
 };
 
 struct _GstRTPMuxClass
@@ -82,6 +84,8 @@ struct _GstRTPMuxClass
 
   gboolean (*accept_buffer_locked) (GstRTPMux *rtp_mux,
       GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer);
+
+  gboolean (*src_event) (GstRTPMux *rtp_mux, GstEvent *event);
 };