gst/rtpmanager/gstrtpbin-marshal.list: Some more custom marshallers.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 11 Apr 2007 13:49:54 +0000 (13:49 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 11 Aug 2009 01:30:24 +0000 (02:30 +0100)
Original commit message from CVS:
* gst/rtpmanager/gstrtpbin-marshal.list:
Some more custom marshallers.
* gst/rtpmanager/gstrtpbin.c: (create_session), (get_pt_map),
(clock_rate_request), (create_stream), (gst_rtp_bin_class_init),
(pt_map_requested), (new_ssrc_pad_found), (create_recv_rtp):
* gst/rtpmanager/gstrtpbin.h:
Prepare for caching pt maps.
Connect to signals to collect pt maps.
* gst/rtpmanager/gstrtpjitterbuffer.c:
(gst_rtp_jitter_buffer_class_init),
(gst_jitter_buffer_sink_setcaps), (gst_rtp_jitter_buffer_loop):
* gst/rtpmanager/gstrtpjitterbuffer.h:
Add request_clock_rate signal.
Use scale insteat of scale_int because the later does not deal with
negative numbers.
* gst/rtpmanager/gstrtpptdemux.c: (gst_rtp_pt_demux_class_init),
(gst_rtp_pt_demux_chain):
* gst/rtpmanager/gstrtpptdemux.h:
Implement request-pt-map signal.

gst/rtpmanager/gstrtpbin-marshal.list
gst/rtpmanager/gstrtpbin.c
gst/rtpmanager/gstrtpbin.h
gst/rtpmanager/gstrtpjitterbuffer.c
gst/rtpmanager/gstrtpjitterbuffer.h
gst/rtpmanager/gstrtpptdemux.c
gst/rtpmanager/gstrtpptdemux.h

index 7ad3f16..d0b9103 100644 (file)
@@ -1,2 +1,4 @@
+UINT:UINT
 BOXED:UINT
+BOXED:UINT,UINT
 VOID:UINT,OBJECT
index 68d97f7..39e1fc8 100644 (file)
@@ -123,6 +123,8 @@ typedef struct _GstRTPBinSession GstRTPBinSession;
 typedef struct _GstRTPBinStream GstRTPBinStream;
 typedef struct _GstRTPBinClient GstRTPBinClient;
 
+static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
+
 /* Manages the RTP stream for one SSRC.
  *
  * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
@@ -143,6 +145,7 @@ struct _GstRTPBinStream
   /* the PT demuxer of the SSRC */
   GstElement *demux;
   gulong demux_newpad_sig;
+  gulong demux_ptreq_sig;
 };
 
 /* Manages the receiving end of the packets.
@@ -168,6 +171,9 @@ struct _GstRTPBinSession
   /* list of GstRTPBinStream */
   GSList *streams;
 
+  /* mapping of payload type to caps */
+  GHashTable *ptmap;
+
   /* the pads of the session */
   GstPad *recv_rtp_sink;
   GstPad *recv_rtp_src;
@@ -211,6 +217,7 @@ create_session (GstRTPBin * rtpbin, gint id)
   sess->bin = rtpbin;
   sess->session = elem;
   sess->demux = demux;
+  sess->ptmap = g_hash_table_new (g_int_hash, g_int_equal);
   rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
 
   gst_bin_add (GST_BIN_CAST (rtpbin), elem);
@@ -250,6 +257,80 @@ find_stream_by_ssrc (GstRTPBinSession * session, guint32 ssrc)
 }
 #endif
 
+/* get the payload type caps for the specific payload @pt in @session */
+static GstCaps *
+get_pt_map (GstRTPBinSession * session, guint pt)
+{
+  GstCaps *caps = NULL;
+  GstRTPBin *bin;
+
+  GST_DEBUG ("finding pt %d in cache", pt);
+
+  /* first look in the cache */
+  caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
+  if (caps)
+    goto done;
+
+  bin = session->bin;
+
+  GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
+
+  /* not in cache, send signal to request caps */
+  g_signal_emit (G_OBJECT (bin), gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0,
+      session->id, pt, &caps);
+  if (!caps)
+    goto no_caps;
+
+  /* store in cache */
+  g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
+
+done:
+  return caps;
+
+  /* ERRORS */
+no_caps:
+  {
+    GST_DEBUG ("no pt map could be obtained");
+    return NULL;
+  }
+}
+
+/* callback from the jitterbuffer when it needs to know the clockrate of a
+ * specific payload type. */
+static guint32
+clock_rate_request (GstElement * buffer, guint pt, GstRTPBinStream * stream)
+{
+  GstCaps *caps;
+  GstRTPBinSession *session;
+  GstStructure *s;
+  gint32 clock_rate;
+
+  session = stream->session;
+
+  caps = get_pt_map (session, pt);
+  if (!caps)
+    goto no_map;
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "clock-rate", &clock_rate))
+    goto no_clock_rate;
+
+  return clock_rate;
+
+  /* ERRORS */
+no_map:
+  {
+    GST_DEBUG ("no pt map found");
+    return 0;
+  }
+no_clock_rate:
+  {
+    GST_DEBUG ("no clock-rate in caps found");
+    return 0;
+  }
+}
+
 static GstRTPBinStream *
 create_stream (GstRTPBinSession * session, guint32 ssrc)
 {
@@ -270,6 +351,10 @@ create_stream (GstRTPBinSession * session, guint32 ssrc)
   stream->demux = demux;
   session->streams = g_slist_prepend (session->streams, stream);
 
+  /* provide clock_rate to the jitterbuffer when needed */
+  g_signal_connect (buffer, "request-clock-rate",
+      (GCallback) clock_rate_request, stream);
+
   gst_bin_add (GST_BIN_CAST (session->bin), buffer);
   gst_element_set_state (buffer, GST_STATE_PLAYING);
   gst_bin_add (GST_BIN_CAST (session->bin), demux);
@@ -320,8 +405,6 @@ static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
     GstPadTemplate * templ, const gchar * name);
 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
 
-static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
-
 GST_BOILERPLATE (GstRTPBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
 
 static void
@@ -363,11 +446,19 @@ gst_rtp_bin_class_init (GstRTPBinClass * klass)
   gobject_class->set_property = gst_rtp_bin_set_property;
   gobject_class->get_property = gst_rtp_bin_get_property;
 
+  /**
+   * GstRTPBin::request-pt-map:
+   * @rtpbin: the object which received the signal
+   * @session: the session
+   * @pt: the pt
+   *
+   * Request the payload type as #GstCaps for @pt in @session.
+   */
   gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
       g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, request_pt_map),
-      NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1,
-      G_TYPE_UINT);
+      NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 1,
+      G_TYPE_UINT, G_TYPE_UINT);
 
   gstelement_class->provide_clock =
       GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
@@ -497,6 +588,25 @@ new_payload_found (GstElement * element, guint pt, GstPad * pad,
   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
 }
 
+static GstCaps *
+pt_map_requested (GstElement * element, guint pt, GstRTPBinStream * stream)
+{
+  GstRTPBin *rtpbin;
+  GstRTPBinSession *session;
+  gint id;
+
+  rtpbin = stream->bin;
+  session = stream->session;
+
+  /* find session id */
+  id = session->id;
+
+  GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
+      id);
+
+  return NULL;
+}
+
 /* a new pad (SSRC) was created in @session */
 static void
 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
@@ -518,9 +628,15 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
   gst_pad_link (pad, sinkpad);
   gst_object_unref (sinkpad);
 
-  /* connect to the new-pad signal of the payload demuxer */
+  /* connect to the new-pad signal of the payload demuxer, this will expose the
+   * new pad by ghosting it. */
   stream->demux_newpad_sig = g_signal_connect (stream->demux,
       "new-payload-type", (GCallback) new_payload_found, stream);
+  /* connect to the request-pt-map signal. This signal will be emited by the
+   * demuxer so that it can apply a proper caps on the buffers for the
+   * depayloaders. */
+  stream->demux_ptreq_sig = g_signal_connect (stream->demux,
+      "request-pt-map", (GCallback) pt_map_requested, stream);
 
   return;
 
@@ -582,7 +698,7 @@ create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
   if (lres != GST_PAD_LINK_OK)
     goto link_failed;
 
-  /* connect to the new-ssrc-pad signal of the demuxer */
+  /* connect to the new-ssrc-pad signal of the SSRC demuxer */
   session->demux_newpad_sig = g_signal_connect (session->demux,
       "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
 
index 53a1e5a..649c3f3 100644 (file)
@@ -52,7 +52,7 @@ struct _GstRTPBinClass {
   GstBinClass  parent_class;
 
   /* get the caps for pt */
-  GstCaps (*request_pt_map)  (GstRTPBin *rtpbin, guint pt);
+  GstCaps* (*request_pt_map)  (GstRTPBin *rtpbin, guint session, guint pt);
 };
 
 GType gst_rtp_bin_get_type (void);
index 21fecf8..39b476d 100644 (file)
 
 #include <string.h>
 #include <gst/rtp/gstrtpbuffer.h>
-#include "gstrtpjitterbuffer.h"
 
+#include "gstrtpbin-marshal.h"
+
+#include "gstrtpjitterbuffer.h"
 #include "async_jitter_queue.h"
 
 GST_DEBUG_CATEGORY (rtpjitterbuffer_debug);
@@ -81,6 +83,7 @@ GST_ELEMENT_DETAILS ("RTP packet jitter-buffer",
 enum
 {
   /* FILL ME */
+  SIGNAL_REQUEST_CLOCK_RATE,
   LAST_SIGNAL
 };
 
@@ -152,6 +155,8 @@ GST_STATIC_PAD_TEMPLATE ("src",
          */ )
     );
 
+static guint gst_rtp_jitter_buffer_signals[LAST_SIGNAL] = { 0 };
+
 GST_BOILERPLATE (GstRTPJitterBuffer, gst_rtp_jitter_buffer, GstElement,
     GST_TYPE_ELEMENT);
 
@@ -221,6 +226,19 @@ gst_rtp_jitter_buffer_class_init (GstRTPJitterBufferClass * klass)
           "Tells the jitterbuffer to never exceed the given latency in size",
           DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE));
 
+  /**
+   * GstRTPJitterBuffer::request-clock-rate:
+   * @buffer: the object which received the signal
+   * @pt: the pt
+   *
+   * Request the payload type as #GstCaps for @pt.
+   */
+  gst_rtp_jitter_buffer_signals[SIGNAL_REQUEST_CLOCK_RATE] =
+      g_signal_new ("request-clock-rate", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPJitterBufferClass,
+          request_clock_rate), NULL, NULL, gst_rtp_bin_marshal_UINT__UINT,
+      G_TYPE_UINT, 1, G_TYPE_UINT);
+
   gstelement_class->change_state = gst_rtp_jitter_buffer_change_state;
 
   GST_DEBUG_CATEGORY_INIT
@@ -366,8 +384,6 @@ gst_jitter_buffer_sink_setcaps (GstPad * pad, GstCaps * caps)
   } else
     priv->next_seqnum = -1;
 
-
-
   async_jitter_queue_set_max_queue_length (priv->queue,
       priv->latency_ms * priv->clock_rate / 1000);
 
@@ -859,8 +875,7 @@ again:
     rtp_time -= priv->clock_base;
 
     /* bring timestamp to gst time */
-    timestamp =
-        gst_util_uint64_scale_int (GST_SECOND, rtp_time, priv->clock_rate);
+    timestamp = gst_util_uint64_scale (GST_SECOND, rtp_time, priv->clock_rate);
 
     GST_DEBUG_OBJECT (jitterbuffer, "timestamp %" GST_TIME_FORMAT,
         GST_TIME_ARGS (timestamp));
index a867144..215d8b7 100644 (file)
@@ -63,6 +63,8 @@ struct _GstRTPJitterBufferClass
 {
   GstElementClass parent_class;
 
+  guint (*request_clock_rate) (GstRTPJitterBuffer *buffer, guint pt);
+
   /*< private > */
   gpointer _gst_reserved[GST_PADDING];
 };
index 705210b..7ac6e90 100644 (file)
@@ -83,6 +83,7 @@ struct _GstRTPPtDemuxPad
 /* signals */
 enum
 {
+  SIGNAL_REQUEST_PT_MAP,
   SIGNAL_NEW_PAYLOAD_TYPE,
   SIGNAL_PAYLOAD_TYPE_CHANGE,
   LAST_SIGNAL
@@ -134,20 +135,45 @@ gst_rtp_pt_demux_class_init (GstRTPPtDemuxClass * klass)
   gobject_klass = (GObjectClass *) klass;
   gstelement_klass = (GstElementClass *) klass;
 
+  /**
+   * GstRTPPtDemux::request-pt-map:
+   * @demux: the object which received the signal
+   * @pt: the payload type
+   *
+   * Request the payload type as #GstCaps for @pt.
+   */
+  gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP] =
+      g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass, request_pt_map),
+      NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1,
+      G_TYPE_UINT);
+
+  /**
+   * GstRTPPtDemux::new-payload-type
+   * @demux: the object which received the signal
+   * @pt: the payload type
+   * @pad: the pad with the new payload
+   *
+   * Emited when a new payload type pad has been created in @demux.
+   */
   gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE] =
-      g_signal_new ("new-payload-type",
-      G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstRTPPtDemuxClass, new_payload_type),
-      NULL, NULL,
-      gst_rtp_bin_marshal_VOID__UINT_OBJECT,
-      G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_PAD);
+      g_signal_new ("new-payload-type", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass, new_payload_type),
+      NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_OBJECT, G_TYPE_NONE, 2,
+      G_TYPE_UINT, GST_TYPE_PAD);
+
+  /**
+   * GstRTPPtDemux::payload-type-change
+   * @demux: the object which received the signal
+   * @pt: the new payload type
+   *
+   * Emited when the payload type changed.
+   */
   gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] =
-      g_signal_new ("payload-type-change",
-      G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstRTPPtDemuxClass, payload_type_change),
-      NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+      g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass,
+          payload_type_change), NULL, NULL, g_cclosure_marshal_VOID__UINT,
+      G_TYPE_NONE, 1, G_TYPE_UINT);
 
   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_finalize);
 
@@ -215,7 +241,7 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf)
     srcpad = gst_pad_new_from_template (templ, padname);
     g_free (padname);
 
-    caps = gst_pad_get_caps (srcpad);
+    caps = gst_buffer_get_caps (buf);
     caps = gst_caps_make_writable (caps);
     gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
     gst_pad_set_caps (srcpad, caps);
index 93be395..7d6d7b4 100644 (file)
@@ -45,11 +45,14 @@ struct _GstRTPPtDemuxClass
 {
   GstElementClass parent_class;
 
+  /* get the caps for pt */
+  GstCaps* (*request_pt_map)      (GstRTPPtDemux *demux, guint pt);
+
   /* signal emmited when a new PT is found from the incoming stream */
-  void (*new_payload_type) (GstElement * element, gint pt, GstPad * pad);
+  void     (*new_payload_type)    (GstRTPPtDemux *demux, guint pt, GstPad * pad);
 
   /* signal emitted when the payload type changes */
-  void (*payload_type_change) (GstElement * element, gint pt);
+  void     (*payload_type_change) (GstRTPPtDemux *demux, guint pt);
 };
 
 GType gst_rtp_pt_demux_get_type (void);