diff --git a/ChangeLog b/ChangeLog index 82fc00fc5d..45ba1df6d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2007-05-23 Wim Taymans + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_class_init): + * gst/rtpmanager/gstrtpbin.h: + * gst/rtpmanager/gstrtpclient.c: + * gst/rtpmanager/gstrtpjitterbuffer.c: + (gst_rtp_jitter_buffer_class_init), + (gst_rtp_jitter_buffer_clear_pt_map), (gst_rtp_jitter_buffer_loop): + * gst/rtpmanager/gstrtpjitterbuffer.h: + * gst/rtpmanager/gstrtpptdemux.c: (gst_rtp_pt_demux_class_init), + (gst_rtp_pt_demux_clear_pt_map): + * gst/rtpmanager/gstrtpptdemux.h: + * gst/rtpmanager/gstrtpsession.c: (gst_rtp_session_class_init), + (rtcp_thread), (gst_rtp_session_clear_pt_map): + * gst/rtpmanager/gstrtpsession.h: + * gst/rtpmanager/gstrtpssrcdemux.c: + (gst_rtp_ssrc_demux_class_init): + Document stuff. + Add clear-pt-map action signal where needed. + 2007-05-22 Stefan Kost * configure.ac: diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 73bdbf8370..80c71c1b4e 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -105,6 +105,12 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/replaygain/gstrganalysis.h \ $(top_srcdir)/gst/replaygain/gstrglimiter.h \ $(top_srcdir)/gst/replaygain/gstrgvolume.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpbin.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpclient.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpjitterbuffer.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpptdemux.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpsession.h \ + $(top_srcdir)/gst/rtpmanager/gstrtpssrcdemux.h \ $(top_srcdir)/gst/videocrop/gstvideocrop.h # Images to copy into HTML directory. diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index 2e0f06b3b4..d16a8139c7 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -22,6 +22,11 @@ + + + + + @@ -53,6 +58,7 @@ + diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index bd9ba0d5b3..2859f0588f 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -79,6 +79,96 @@ GstRgVolume GstRgVolumeClass +
+element-rtpbin +GstRTPBin +rtpbin + +GstRTPBinPrivate +GstRTPBinClass +GST_RTP_BIN +GST_IS_RTP_BIN +GST_TYPE_RTP_BIN +gst_rtp_bin_get_type +GST_RTP_BIN_CLASS +GST_IS_RTP_BIN_CLASS +
+ +
+element-rtpclient +rtpclient +GstRTPClient + +GstRTPClientClass +GstRTPClientPrivate +GST_RTP_CLIENT +GST_IS_RTP_CLIENT +GST_TYPE_RTP_CLIENT +gst_rtp_client_get_type +GST_RTP_CLIENT_CLASS +GST_IS_RTP_CLIENT_CLASS +
+ +
+element-rtpjitterbuffer +rtpjitterbuffer +GstRTPJitterBuffer + +GstRTPJitterBufferClass +GstRTPJitterBufferPrivate +GST_RTP_JITTER_BUFFER +GST_IS_RTP_JITTER_BUFFER +GST_TYPE_RTP_JITTER_BUFFER +gst_rtp_jitter_buffer_get_type +GST_RTP_JITTER_BUFFER_CLASS +GST_IS_RTP_JITTER_BUFFER_CLASS +
+ +
+element-rtpptdemux +rtpptdemux +GstRTPPtDemux + +GstRTPPtDemuxClass +GstRTPPtDemuxPad +GST_RTP_PT_DEMUX +GST_IS_RTP_PT_DEMUX +GST_TYPE_RTP_PT_DEMUX +gst_rtp_pt_demux_get_type +GST_RTP_PT_DEMUX_CLASS +GST_IS_RTP_PT_DEMUX_CLASS +
+ +
+element-rtpsession +rtpsession +GstRTPSession + +GstRTPSessionClass +GstRTPSessionPrivate +GST_RTP_SESSION +GST_IS_RTP_SESSION +GST_TYPE_RTP_SESSION +gst_rtp_session_get_type +GST_RTP_SESSION_CLASS +GST_IS_RTP_SESSION_CLASS +
+ +
+element-rtpssrcdemux +rtpssrcdemux +GstRTPSsrcDemux + +GstRTPSsrcDemuxClass +GstRTPSsrcDemuxPad +GST_RTP_SSRC_DEMUX +GST_IS_RTP_SSRC_DEMUX +GST_TYPE_RTP_SSRC_DEMUX +gst_rtp_ssrc_demux_get_type +GST_RTP_SSRC_DEMUX_CLASS +GST_IS_RTP_SSRC_DEMUX_CLASS +
+
element-sdlaudiosink GstSDLAudioSink diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 58a0692638..44fe3386d0 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -20,20 +20,64 @@ /** * SECTION:element-rtpbin * @short_description: handle media from one RTP bin - * @see_also: rtpjitterbuffer, rtpclient, rtpsession + * @see_also: rtpjitterbuffer, rtpsession, rtpptdemux, rtpssrcdemux * * * + * RTP bin combines the functions of rtpsession, rtpssrcdemux, rtpjitterbuffer + * and rtpptdemux in one element. It allows for multiple rtpsessions that will + * be synchronized together using RTCP SR packets. + * + * + * rtpbin is configured with a number of request pads that define the + * functionality that is activated, similar to the rtpsession element. + * + * + * To use rtpbin as an RTP receiver, request a recv_rtp_sink_%%d pad. The session + * number must be specified in the pad name. + * Data received on the recv_rtp_sink_%%d pad will be processed in the rtpsession + * manager and after being validated forwarded on rtpssrcdemuxer element. Each + * RTP stream is demuxed based on the SSRC and send to a rtpjitterbuffer. After + * the packets are released from the jitterbuffer, they will be forwarded to an + * rtpptdemuxer element. The rtpptdemuxer element will demux the packets based + * on the payload type and will create a unique pad recv_rtp_src_%%d_%%d_%%d on + * rtpbin with the session number, SSRC and payload type respectively as the pad + * name. + * + * + * To also use rtpbin as an RTCP receiver, request a recv_rtcp_sink_%%d pad. The + * session number must be specified in the pad name. + * + * + * If you want the session manager to generate and send RTCP packets, request + * the send_rtcp_src_%%d pad with the session number in the pad name. Packet pushed + * on this pad contain SR/RR RTCP reports that should be sent to all participants + * in the session. + * + * + * To use rtpbin as a sender, request a send_rtp_sink_%%d pad, which will + * automatically create a send_rtp_src_%%d pad. The session number must be specified when + * requesting the sink pad. The session manager will modify the + * SSRC in the RTP packets to its own SSRC and wil forward the packets on the + * send_rtp_src_%%d pad after updating its internal state. + * + * + * The session manager needs the clock-rate of the payload types it is handling + * and will signal the GstRTPSession::request-pt-map signal when it needs such a + * mapping. One can clear the cached values with the GstRTPSession::clear-pt-map + * signal. * * Example pipelines * * - * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink + * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \ + * rtpbin ! rtptheoradepay ! theoradec ! xvimagesink * + * Receive RTP data from port 5000 and send to the session 0 in rtpbin. * * * - * Last reviewed on 2007-04-02 (0.10.6) + * Last reviewed on 2007-05-23 (0.10.6) */ #ifdef HAVE_CONFIG_H @@ -50,7 +94,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug); /* elementfactory information */ static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin", - "Filter/Editor/Video", + "Filter/Network/RTP", "Implement an RTP bin", "Wim Taymans "); @@ -485,8 +529,8 @@ gst_rtp_bin_class_init (GstRTPBinClass * klass) g_object_class_install_property (gobject_class, PROP_LATENCY, g_param_spec_uint ("latency", "Buffer latency in ms", - "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS, - G_PARAM_READWRITE)); + "Default amount of ms to buffer in the jitterbuffers", 0, + G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE)); /** * GstRTPBin::request-pt-map: @@ -501,10 +545,16 @@ gst_rtp_bin_class_init (GstRTPBinClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, request_pt_map), NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2, G_TYPE_UINT, G_TYPE_UINT); - + /** + * GstRTPBin::clear-pt-map: + * @rtpbin: the object which received the signal + * + * Clear all previously cached pt-mapping obtained with + * GstRTPBin::request-pt-map. + */ gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] = g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, clear_pt_map), + G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTPBinClass, clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); gstelement_class->provide_clock = diff --git a/gst/rtpmanager/gstrtpbin.h b/gst/rtpmanager/gstrtpbin.h index 24eb38d1d4..ffbdd62cd2 100644 --- a/gst/rtpmanager/gstrtpbin.h +++ b/gst/rtpmanager/gstrtpbin.h @@ -40,6 +40,7 @@ typedef struct _GstRTPBinPrivate GstRTPBinPrivate; struct _GstRTPBin { GstBin bin; + /*< private >*/ /* default latency for sessions */ guint latency; /* a list of session */ diff --git a/gst/rtpmanager/gstrtpclient.c b/gst/rtpmanager/gstrtpclient.c index 34c8afb2aa..86c5f3ccbf 100644 --- a/gst/rtpmanager/gstrtpclient.c +++ b/gst/rtpmanager/gstrtpclient.c @@ -51,7 +51,7 @@ /* elementfactory information */ static const GstElementDetails rtpclient_details = GST_ELEMENT_DETAILS ("RTP Client", - "Filter/Editor/Video", + "Filter/Network/RTP", "Implement an RTP client", "Wim Taymans "); diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index e49f41a6d3..1838ba0b39 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -38,6 +38,15 @@ * * This element acts as a live element and so adds ::latency to the pipeline. * + * + * The element needs the clock-rate of the RTP payload in order to estimate the + * delay. This information is obtained either from the caps on the sink pad or, + * when no caps are present, from the ::request-pt-map signal. To clear the + * previous pt-map use the ::clear-pt-map signal. + * + * + * This element will automatically be used inside rtpbin. + * * Example pipelines * * @@ -49,7 +58,7 @@ * * * - * Last reviewed on 2007-03-27 (0.10.13) + * Last reviewed on 2007-05-22 (0.10.6) */ #ifdef HAVE_CONFIG_H @@ -74,7 +83,7 @@ GST_DEBUG_CATEGORY (rtpjitterbuffer_debug); /* elementfactory information */ static const GstElementDetails gst_rtp_jitter_buffer_details = GST_ELEMENT_DETAILS ("RTP packet jitter-buffer", - "Filter/Network", + "Filter/Network/RTP", "A buffer that deals with network jitter and other transmission faults", "Philippe Kalaf , " "Wim Taymans "); @@ -82,8 +91,8 @@ GST_ELEMENT_DETAILS ("RTP packet jitter-buffer", /* RTPJitterBuffer signals and args */ enum { - /* FILL ME */ SIGNAL_REQUEST_PT_MAP, + SIGNAL_CLEAR_PT_MAP, LAST_SIGNAL }; @@ -187,6 +196,9 @@ gst_rtp_jitter_buffer_src_activate_push (GstPad * pad, gboolean active); static void gst_rtp_jitter_buffer_loop (GstRTPJitterBuffer * jitterbuffer); static gboolean gst_rtp_jitter_buffer_query (GstPad * pad, GstQuery * query); +static void +gst_rtp_jitter_buffer_clear_pt_map (GstRTPJitterBuffer * jitterbuffer); + static void gst_rtp_jitter_buffer_base_init (gpointer klass) { @@ -215,17 +227,26 @@ gst_rtp_jitter_buffer_class_init (GstRTPJitterBufferClass * klass) gobject_class->set_property = gst_rtp_jitter_buffer_set_property; gobject_class->get_property = gst_rtp_jitter_buffer_get_property; + /** + * GstRTPJitterBuffer::latency: + * + * The maximum latency of the jitterbuffer. Packets will be kept in the buffer + * for at most this time. + */ g_object_class_install_property (gobject_class, PROP_LATENCY, g_param_spec_uint ("latency", "Buffer latency in ms", "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE)); - + /** + * GstRTPJitterBuffer::drop-on-latency: + * + * Drop oldest buffers when the queue is completely filled. + */ g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY, - g_param_spec_boolean ("drop_on_latency", + g_param_spec_boolean ("drop-on-latency", "Drop buffers when maximum latency is reached", "Tells the jitterbuffer to never exceed the given latency in size", DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE)); - /** * GstRTPJitterBuffer::request-pt-map: * @buffer: the object which received the signal @@ -238,9 +259,22 @@ gst_rtp_jitter_buffer_class_init (GstRTPJitterBufferClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPJitterBufferClass, request_pt_map), NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1, G_TYPE_UINT); + /** + * GstRTPJitterBuffer::clear-pt-map: + * @buffer: the object which received the signal + * + * Invalidate the clock-rate as obtained with the ::request-pt-map signal. + */ + gst_rtp_jitter_buffer_signals[SIGNAL_CLEAR_PT_MAP] = + g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPJitterBufferClass, + clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, G_TYPE_NONE); gstelement_class->change_state = gst_rtp_jitter_buffer_change_state; + klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_jitter_buffer_clear_pt_map); + GST_DEBUG_CATEGORY_INIT (rtpjitterbuffer_debug, "rtpjitterbuffer", 0, "RTP Jitter Buffer"); } @@ -305,6 +339,17 @@ gst_rtp_jitter_buffer_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_rtp_jitter_buffer_clear_pt_map (GstRTPJitterBuffer * jitterbuffer) +{ + GstRTPJitterBufferPrivate *priv; + + priv = jitterbuffer->priv; + + /* this will trigger a new pt-map request signal, FIXME, do something better. */ + priv->clock_rate = -1; +} + static GstCaps * gst_rtp_jitter_buffer_getcaps (GstPad * pad) { diff --git a/gst/rtpmanager/gstrtpjitterbuffer.h b/gst/rtpmanager/gstrtpjitterbuffer.h index 3cbcd62f1e..0b0ac1af01 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.h +++ b/gst/rtpmanager/gstrtpjitterbuffer.h @@ -49,13 +49,18 @@ typedef struct _GstRTPJitterBuffer GstRTPJitterBuffer; typedef struct _GstRTPJitterBufferClass GstRTPJitterBufferClass; typedef struct _GstRTPJitterBufferPrivate GstRTPJitterBufferPrivate; +/** + * GstRTPJitterBuffer: + * + * Opaque jitterbuffer structure. + */ struct _GstRTPJitterBuffer { GstElement parent; + /*< private >*/ GstRTPJitterBufferPrivate *priv; - /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; @@ -66,6 +71,8 @@ struct _GstRTPJitterBufferClass /* signals */ GstCaps* (*request_pt_map) (GstRTPJitterBuffer *buffer, guint pt); + void (*clear_pt_map) (GstRTPJitterBuffer *buffer); + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; diff --git a/gst/rtpmanager/gstrtpptdemux.c b/gst/rtpmanager/gstrtpptdemux.c index 139665eab4..578f03532a 100644 --- a/gst/rtpmanager/gstrtpptdemux.c +++ b/gst/rtpmanager/gstrtpptdemux.c @@ -23,11 +23,42 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-rtpptdemux + * @short_description: separate RTP payloads based on the payload type + * + * + * + * rtpptdemux acts as a demuxer for RTP packets based on the payload type of the + * packets. Its main purpose is to allow an application to easily receive and + * decode an RTP stream with multiple payload types. + * + * + * For each payload type that is detected, a new pad will be created and the + * ::new-payload-type signal will be emitted. When the payload for the RTP + * stream changes, the ::payload-type-change signal will be emitted. + * + * + * The element will try to set complete and unique application/x-rtp caps on the + * outgoing buffers and pads based on the result of the ::request-pt-map signal. + * + * Example pipelines + * + * + * gst-launch udpsrc caps="application/x-rtp" ! rtpptdemux ! fakesink + * + * Takes an RTP stream and send the RTP packets with the first detected payload + * type to fakesink, discarding the other payload types. + * + * + * + * Last reviewed on 2007-05-22 (0.10.6) + */ + /* * Contributors: * Andre Moreira Magalhaes */ - /* * Status: * - works with the test_rtpdemux.c tool @@ -86,6 +117,7 @@ enum SIGNAL_REQUEST_PT_MAP, SIGNAL_NEW_PAYLOAD_TYPE, SIGNAL_PAYLOAD_TYPE_CHANGE, + SIGNAL_CLEAR_PT_MAP, LAST_SIGNAL }; @@ -99,6 +131,7 @@ static gboolean gst_rtp_pt_demux_setup (GstElement * element); static GstFlowReturn gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf); static GstStateChangeReturn gst_rtp_pt_demux_change_state (GstElement * element, GstStateChange transition); +static void gst_rtp_pt_demux_clear_pt_map (GstRTPPtDemux * rtpdemux); static GstPad *find_pad_for_pt (GstRTPPtDemux * rtpdemux, guint8 pt); @@ -106,8 +139,7 @@ static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 }; static GstElementDetails gst_rtp_pt_demux_details = { "RTP Demux", - /* XXX: what's the correct hierarchy? */ - "Codec/Demux/Network", + "Demux/Network/RTP", "Parses codec streams transmitted in the same RTP session", "Kai Vehmanen " }; @@ -148,7 +180,7 @@ gst_rtp_pt_demux_class_init (GstRTPPtDemuxClass * klass) G_TYPE_UINT); /** - * GstRTPPtDemux::new-payload-type + * GstRTPPtDemux::new-payload-type: * @demux: the object which received the signal * @pt: the payload type * @pad: the pad with the new payload @@ -162,7 +194,7 @@ gst_rtp_pt_demux_class_init (GstRTPPtDemuxClass * klass) G_TYPE_UINT, GST_TYPE_PAD); /** - * GstRTPPtDemux::payload-type-change + * GstRTPPtDemux::payload-type-change: * @demux: the object which received the signal * @pt: the new payload type * @@ -174,14 +206,28 @@ gst_rtp_pt_demux_class_init (GstRTPPtDemuxClass * klass) payload_type_change), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); + /** + * GstRTPPtDemux::clear-pt-map: + * @demux: the object which received the signal + * + * The application can call this signal to instruct the element to discard the + * currently cached payload type map. + */ + gst_rtp_pt_demux_signals[SIGNAL_CLEAR_PT_MAP] = + g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass, + clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, G_TYPE_NONE); + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_finalize); gstelement_klass->change_state = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_change_state); + klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_clear_pt_map); + GST_DEBUG_CATEGORY_INIT (gst_rtp_pt_demux_debug, "rtpptdemux", 0, "RTP codec demuxer"); - } static void @@ -207,6 +253,12 @@ gst_rtp_pt_demux_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gst_rtp_pt_demux_clear_pt_map (GstRTPPtDemux * rtpdemux) +{ + /* FIXME, do something */ +} + static GstFlowReturn gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) { diff --git a/gst/rtpmanager/gstrtpptdemux.h b/gst/rtpmanager/gstrtpptdemux.h index 7d6d7b4f31..e45ae28660 100644 --- a/gst/rtpmanager/gstrtpptdemux.h +++ b/gst/rtpmanager/gstrtpptdemux.h @@ -53,6 +53,8 @@ struct _GstRTPPtDemuxClass /* signal emitted when the payload type changes */ void (*payload_type_change) (GstRTPPtDemux *demux, guint pt); + + void (*clear_pt_map) (GstRTPPtDemux *demux); }; GType gst_rtp_pt_demux_get_type (void); diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index 80f340a532..431098d929 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -20,20 +20,112 @@ /** * SECTION:element-rtpsession * @short_description: an RTP session manager - * @see_also: rtpjitterbuffer, rtpbin + * @see_also: rtpjitterbuffer, rtpbin, rtpptdemux, rtpssrcdemux * * * + * The RTP session manager models one participant with a unique SSRC in an RTP + * session. This session can be used to send and receive RTP and RTCP packets. + * Based on what REQUEST pads are requested from the session manager, specific + * functionality can be activated. + * + * + * The session manager currently implements RFC 3550 including: + * + * + * RTP packet validation based on consecutive sequence numbers. + * + * + * Maintainance of the SSRC participant database. + * + * + * Keeping per participant statistics based on received RTCP packets. + * + * + * Scheduling of RR/SR RTCP packets. + * + * + * + * + * The rtpsession will not demux packets based on SSRC or payload type, nor will + * it correct for packet reordering and jitter. Use rtpssrcdemux, rtpptdemux and + * rtpjitterbuffer in addition to rtpsession to perform these tasks. It is + * usually a good idea to use rtpbin, which combines all these features in one + * element. + * + * + * To use rtpsession as an RTP receiver, request a recv_rtp_sink pad, which will + * automatically create recv_rtp_src pad. Data received on the recv_rtp_sink pad + * will be processed in the session and after being validated forwarded on the + * recv_rtp_src pad. + * + * + * To also use rtpsession as an RTCP receiver, request a recv_rtcp_sink pad, + * which will automatically create a sync_src pad. Packets received on the RTCP + * pad will be used by the session manager to update the stats and database of + * the other participants. SR packets will be forwarded on the sync_src pad + * so that they can be used to perform inter-stream synchronisation when needed. + * + * + * If you want the session manager to generate and send RTCP packets, request + * the send_rtcp_src pad. Packet pushed on this pad contain SR/RR RTCP reports + * that should be sent to all participants in the session. + * + * + * To use rtpsession as a sender, request a send_rtp_sink pad, which will + * automatically create a send_rtp_src pad. The session manager will modify the + * SSRC in the RTP packets to its own SSRC and wil forward the packets on the + * send_rtp_src pad after updating its internal state. + * + * + * The session manager needs the clock-rate of the payload types it is handling + * and will signal the GstRTPSession::request-pt-map signal when it needs such a + * mapping. One can clear the cached values with the GstRTPSession::clear-pt-map + * signal. * * Example pipelines * * - * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink + * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink rtpsession .recv_rtp_src ! rtptheoradepay ! theoradec ! xvimagesink * + * Receive theora RTP packets from port 5000 and send them to the depayloader, + * decoder and display. Note that the application/x-rtp caps on udpsrc should be + * configured based on some negotiation process such as RTSP for this pipeline + * to work correctly. + * + * + * + * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink rtpsession name=session \ + * .recv_rtp_src ! rtptheoradepay ! theoradec ! xvimagesink \ + * udpsrc port=5001 caps="application/x-rtcp" ! session.recv_rtcp_sink + * + * Receive theora RTP packets from port 5000 and send them to the depayloader, + * decoder and display. Receive RTCP packets from port 5001 and process them in + * the session manager. + * Note that the application/x-rtp caps on udpsrc should be + * configured based on some negotiation process such as RTSP for this pipeline + * to work correctly. + * + * + * + * gst-launch videotestsrc ! theoraenc ! rtptheorapay ! .send_rtp_sink rtpsession .send_rtp_src ! udpsink port=5000 + * + * Send theora RTP packets through the session manager and out on UDP port 5000. + * + * + * + * gst-launch videotestsrc ! theoraenc ! rtptheorapay ! .send_rtp_sink rtpsession name=session .send_rtp_src \ + * ! udpsink port=5000 session.send_rtcp_src ! udpsink port=5001 + * + * Send theora RTP packets through the session manager and out on UDP port 5000. + * Send RTCP packets on port 5001. Not that this pipeline will not preroll + * correctly because the second udpsink will not preroll correctly (no RTCP + * packets are sent in the PAUSED state). Applications should manually set and + * keep (see #gst_element_set_locked_state()) the RTCP udpsink to the PLAYING state. * * * - * Last reviewed on 2007-04-02 (0.10.6) + * Last reviewed on 2007-05-23 (0.10.6) */ #ifdef HAVE_CONFIG_H @@ -50,7 +142,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_rtp_session_debug); /* elementfactory information */ static const GstElementDetails rtpsession_details = GST_ELEMENT_DETAILS ("RTP Session", - "Filter/Editor/Video", + "Filter/Network/RTP", "Implement an RTP session", "Wim Taymans "); @@ -109,6 +201,7 @@ GST_STATIC_PAD_TEMPLATE ("send_rtcp_src", enum { SIGNAL_REQUEST_PT_MAP, + SIGNAL_CLEAR_PT_MAP, LAST_SIGNAL }; @@ -169,6 +262,8 @@ static GstPad *gst_rtp_session_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name); static void gst_rtp_session_release_pad (GstElement * element, GstPad * pad); +static void gst_rtp_session_clear_pt_map (GstRTPSession * rtpsession); + static guint gst_rtp_session_signals[LAST_SIGNAL] = { 0 }; GST_BOILERPLATE (GstRTPSession, gst_rtp_session, GstElement, GST_TYPE_ELEMENT); @@ -226,6 +321,16 @@ gst_rtp_session_class_init (GstRTPSessionClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPSessionClass, request_pt_map), NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1, G_TYPE_UINT); + /** + * GstRTPSession::clear-pt-map: + * @sess: the object which received the signal + * + * Clear the cached pt-maps requested with GstRTPSession::request-pt-map. + */ + gst_rtp_session_signals[SIGNAL_CLEAR_PT_MAP] = + g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTPSessionClass, clear_pt_map), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_session_change_state); @@ -234,6 +339,8 @@ gst_rtp_session_class_init (GstRTPSessionClass * klass) gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_session_release_pad); + klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_session_clear_pt_map); + GST_DEBUG_CATEGORY_INIT (gst_rtp_session_debug, "rtpsession", 0, "RTP Session"); } @@ -315,7 +422,6 @@ rtcp_thread (GstRTPSession * rtpsession) next_timeout = rtp_session_next_timeout (rtpsession->priv->session, current_time); - GST_DEBUG_OBJECT (rtpsession, "next check time %" GST_TIME_FORMAT, GST_TIME_ARGS (next_timeout)); @@ -438,6 +544,12 @@ failed_thread: } } +static void +gst_rtp_session_clear_pt_map (GstRTPSession * rtpsession) +{ + /* FIXME, do something */ +} + /* called when the session manager has an RTP packet ready for further * processing */ static GstFlowReturn diff --git a/gst/rtpmanager/gstrtpsession.h b/gst/rtpmanager/gstrtpsession.h index 25bbb6ebd0..c58f23e90a 100644 --- a/gst/rtpmanager/gstrtpsession.h +++ b/gst/rtpmanager/gstrtpsession.h @@ -59,6 +59,8 @@ struct _GstRTPSessionClass { /* signals */ GstCaps* (*request_pt_map) (GstRTPSession *sess, guint pt); + + void (*clear_pt_map) (GstRTPSession *sess); }; GType gst_rtp_session_get_type (void); diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c index 17e421fe42..bd0c6b05c4 100644 --- a/gst/rtpmanager/gstrtpssrcdemux.c +++ b/gst/rtpmanager/gstrtpssrcdemux.c @@ -19,6 +19,33 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-rtpssrcdemux + * @short_description: separate RTP payloads based on the SSRC + * + * + * + * rtpssrcdemux acts as a demuxer for RTP packets based on the SSRC of the + * packets. Its main purpose is to allow an application to easily receive and + * decode an RTP stream with multiple SSRCs. + * + * + * For each SSRC that is detected, a new pad will be created and the + * ::new-ssrc-pad signal will be emitted. + * + * Example pipelines + * + * + * gst-launch udpsrc caps="application/x-rtp" ! rtpssrcdemux ! fakesink + * + * Takes an RTP stream and send the RTP packets with the first detected SSRC + * to fakesink, discarding the other SSRCs. + * + * + * + * Last reviewed on 2007-05-23 (0.10.6) + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -49,7 +76,7 @@ GST_STATIC_PAD_TEMPLATE ("src_%d", static GstElementDetails gst_rtp_ssrc_demux_details = { "RTP SSRC Demux", - "Codec/Demux/Network", + "Demux/Network/RTP", "Splits RTP streams based on the SSRC", "Wim Taymans " }; @@ -165,6 +192,14 @@ gst_rtp_ssrc_demux_class_init (GstRTPSsrcDemuxClass * klass) gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_finalize); + /** + * GstRTPSsrcDemux::new-ssrc-pad: + * @demux: the object which received the signal + * @ssrc: the SSRC of the pad + * @pad: the new pad. + * + * Emited when a new SSRC pad has been created. + */ gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD] = g_signal_new ("new-ssrc-pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,