From 03bf43d50edb50f8114419cd62278afd7f67922b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 11 Apr 2007 13:49:54 +0000 Subject: [PATCH] gst/rtpmanager/gstrtpbin-marshal.list: Some more custom marshallers. 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 | 2 + gst/rtpmanager/gstrtpbin.c | 128 ++++++++++++++++++++++++++++++++-- gst/rtpmanager/gstrtpbin.h | 2 +- gst/rtpmanager/gstrtpjitterbuffer.c | 25 +++++-- gst/rtpmanager/gstrtpjitterbuffer.h | 2 + gst/rtpmanager/gstrtpptdemux.c | 52 ++++++++++---- gst/rtpmanager/gstrtpptdemux.h | 7 +- 7 files changed, 191 insertions(+), 27 deletions(-) diff --git a/gst/rtpmanager/gstrtpbin-marshal.list b/gst/rtpmanager/gstrtpbin-marshal.list index 7ad3f16..d0b9103 100644 --- a/gst/rtpmanager/gstrtpbin-marshal.list +++ b/gst/rtpmanager/gstrtpbin-marshal.list @@ -1,2 +1,4 @@ +UINT:UINT BOXED:UINT +BOXED:UINT,UINT VOID:UINT,OBJECT diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 68d97f7..39e1fc8 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -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); diff --git a/gst/rtpmanager/gstrtpbin.h b/gst/rtpmanager/gstrtpbin.h index 53a1e5a..649c3f3 100644 --- a/gst/rtpmanager/gstrtpbin.h +++ b/gst/rtpmanager/gstrtpbin.h @@ -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); diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 21fecf8..39b476d 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -58,8 +58,10 @@ #include #include -#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)); diff --git a/gst/rtpmanager/gstrtpjitterbuffer.h b/gst/rtpmanager/gstrtpjitterbuffer.h index a867144..215d8b7 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.h +++ b/gst/rtpmanager/gstrtpjitterbuffer.h @@ -63,6 +63,8 @@ struct _GstRTPJitterBufferClass { GstElementClass parent_class; + guint (*request_clock_rate) (GstRTPJitterBuffer *buffer, guint pt); + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; diff --git a/gst/rtpmanager/gstrtpptdemux.c b/gst/rtpmanager/gstrtpptdemux.c index 705210b..7ac6e90 100644 --- a/gst/rtpmanager/gstrtpptdemux.c +++ b/gst/rtpmanager/gstrtpptdemux.c @@ -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); diff --git a/gst/rtpmanager/gstrtpptdemux.h b/gst/rtpmanager/gstrtpptdemux.h index 93be395..7d6d7b4 100644 --- a/gst/rtpmanager/gstrtpptdemux.h +++ b/gst/rtpmanager/gstrtpptdemux.h @@ -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); -- 2.7.4