From 12192a5fac0b6405ba3d608ba6d09ee71b6dc1f9 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 4 Apr 2007 10:23:15 +0000 Subject: gst/rtpmanager/: Added simple SSRC demuxer. Original commit message from CVS: * gst/rtpmanager/Makefile.am: * gst/rtpmanager/gstrtpmanager.c: (plugin_init): * gst/rtpmanager/gstrtpssrcdemux.c: (find_pad_for_ssrc), (create_pad_for_ssrc), (gst_rtp_ssrc_demux_base_init), (gst_rtp_ssrc_demux_class_init), (gst_rtp_ssrc_demux_init), (gst_rtp_ssrc_demux_finalize), (gst_rtp_ssrc_demux_sink_event), (gst_rtp_ssrc_demux_chain), (gst_rtp_ssrc_demux_src_event), (gst_rtp_ssrc_demux_change_state): * gst/rtpmanager/gstrtpssrcdemux.h: Added simple SSRC demuxer. --- ChangeLog | 13 ++ gst/rtpmanager/Makefile.am | 2 + gst/rtpmanager/gstrtpmanager.c | 5 + gst/rtpmanager/gstrtpssrcdemux.c | 303 +++++++++++++++++++++++++++++++++++++++ gst/rtpmanager/gstrtpssrcdemux.h | 50 +++++++ 5 files changed, 373 insertions(+) create mode 100644 gst/rtpmanager/gstrtpssrcdemux.c create mode 100644 gst/rtpmanager/gstrtpssrcdemux.h diff --git a/ChangeLog b/ChangeLog index 488a1fd0..dd83846d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-04-04 Wim Taymans + + * gst/rtpmanager/Makefile.am: + * gst/rtpmanager/gstrtpmanager.c: (plugin_init): + * gst/rtpmanager/gstrtpssrcdemux.c: (find_pad_for_ssrc), + (create_pad_for_ssrc), (gst_rtp_ssrc_demux_base_init), + (gst_rtp_ssrc_demux_class_init), (gst_rtp_ssrc_demux_init), + (gst_rtp_ssrc_demux_finalize), (gst_rtp_ssrc_demux_sink_event), + (gst_rtp_ssrc_demux_chain), (gst_rtp_ssrc_demux_src_event), + (gst_rtp_ssrc_demux_change_state): + * gst/rtpmanager/gstrtpssrcdemux.h: + Added simple SSRC demuxer. + 2007-04-04 Stefan Kost * ext/jack/gstjackaudiosink.c: (gst_jack_ring_buffer_open_device), diff --git a/gst/rtpmanager/Makefile.am b/gst/rtpmanager/Makefile.am index e51cafad..dc7f2a72 100644 --- a/gst/rtpmanager/Makefile.am +++ b/gst/rtpmanager/Makefile.am @@ -7,6 +7,7 @@ libgstrtpmanager_la_SOURCES = gstrtpmanager.c \ async_jitter_queue.c \ gstrtpjitterbuffer.c \ gstrtpptdemux.c \ + gstrtpssrcdemux.c \ gstrtpsession.c noinst_HEADERS = gstrtpbin.h \ @@ -14,6 +15,7 @@ noinst_HEADERS = gstrtpbin.h \ async_jitter_queue.h \ gstrtpjitterbuffer.h \ gstrtpptdemux.h \ + gstrtpssrcdemux.h \ gstrtpsession.h libgstrtpmanager_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) diff --git a/gst/rtpmanager/gstrtpmanager.c b/gst/rtpmanager/gstrtpmanager.c index a059cad8..d71d850c 100644 --- a/gst/rtpmanager/gstrtpmanager.c +++ b/gst/rtpmanager/gstrtpmanager.c @@ -25,6 +25,7 @@ #include "gstrtpjitterbuffer.h" #include "gstrtpptdemux.h" #include "gstrtpsession.h" +#include "gstrtpssrcdemux.h" static gboolean plugin_init (GstPlugin * plugin) @@ -45,6 +46,10 @@ plugin_init (GstPlugin * plugin) GST_TYPE_RTP_SESSION)) return FALSE; + if (!gst_element_register (plugin, "rtpssrcdemux", GST_RANK_NONE, + GST_TYPE_RTP_SSRC_DEMUX)) + return FALSE; + return TRUE; } diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c new file mode 100644 index 00000000..fe6f1bee --- /dev/null +++ b/gst/rtpmanager/gstrtpssrcdemux.c @@ -0,0 +1,303 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * RTP SSRC demuxer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstrtpssrcdemux.h" + +/* generic templates */ +static GstStaticPadTemplate rtp_ssrc_demux_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + +static GstStaticPadTemplate rtp_ssrc_demux_src_template = +GST_STATIC_PAD_TEMPLATE ("src_%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("application/x-rtp") + ); + +static GstElementDetails gst_rtp_ssrc_demux_details = { + "RTP SSRC Demux", + "Codec/Demux/Network", + "Splits RTP streams based on the SSRC", + "Wim Taymans " +}; + +GST_DEBUG_CATEGORY_STATIC (gst_rtp_ssrc_demux_debug); +#define GST_CAT_DEFAULT gst_rtp_ssrc_demux_debug + +/* signals */ +enum +{ + LAST_SIGNAL +}; + +GST_BOILERPLATE (GstRTPSsrcDemux, gst_rtp_ssrc_demux, GstElement, + GST_TYPE_ELEMENT); + + +/* GObject vmethods */ +static void gst_rtp_ssrc_demux_finalize (GObject * object); + +/* GstElement vmethods */ +static GstStateChangeReturn gst_rtp_ssrc_demux_change_state (GstElement * + element, GstStateChange transition); + +/* sinkpad stuff */ +static GstFlowReturn gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event); + +/* srcpad stuff */ +static gboolean gst_rtp_ssrc_demux_src_event (GstPad * pad, GstEvent * event); + +/* static guint gst_rtp_ssrc_demux_signals[LAST_SIGNAL] = { 0 }; */ + +/** + * Item for storing GstPad <-> SSRC pairs. + */ +struct _GstRTPSsrcDemuxPad +{ + GstPad *pad; + guint32 ssrc; +}; + +/* find a src pad for a given SSRC, returns NULL if the SSRC was not found + */ +static GstPad * +find_pad_for_ssrc (GstRTPSsrcDemux * demux, guint32 ssrc) +{ + GSList *walk; + + for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) { + GstRTPSsrcDemuxPad *pad = (GstRTPSsrcDemuxPad *) walk->data; + + if (pad->ssrc == ssrc) + return pad->pad; + } + return NULL; +} + +static GstPad * +create_pad_for_ssrc (GstRTPSsrcDemux * demux, guint32 ssrc) +{ + GstPad *result; + GstElementClass *klass; + GstPadTemplate *templ; + gchar *padname; + GstRTPSsrcDemuxPad *demuxpad; + + klass = GST_ELEMENT_GET_CLASS (demux); + templ = gst_element_class_get_pad_template (klass, "src_%d"); + padname = g_strdup_printf ("src_%d", ssrc); + result = gst_pad_new_from_template (templ, padname); + g_free (padname); + + /* wrap in structure and add to list */ + demuxpad = g_new0 (GstRTPSsrcDemuxPad, 1); + demuxpad->ssrc = ssrc; + demuxpad->pad = result; + demux->srcpads = g_slist_prepend (demux->srcpads, demuxpad); + + /* copy caps from input */ + gst_pad_set_caps (result, GST_PAD_CAPS (demux->sinkpad)); + + gst_pad_set_event_function (result, gst_rtp_ssrc_demux_src_event); + gst_pad_set_active (result, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (demux), result); + + return result; +} + +static void +gst_rtp_ssrc_demux_base_init (gpointer g_class) +{ + GstElementClass *gstelement_klass = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&rtp_ssrc_demux_sink_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&rtp_ssrc_demux_src_template)); + + gst_element_class_set_details (gstelement_klass, &gst_rtp_ssrc_demux_details); +} + +static void +gst_rtp_ssrc_demux_class_init (GstRTPSsrcDemuxClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_finalize); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_change_state); + + GST_DEBUG_CATEGORY_INIT (gst_rtp_ssrc_demux_debug, + "rtpssrcdemux", 0, "RTP SSRC demuxer"); +} + +static void +gst_rtp_ssrc_demux_init (GstRTPSsrcDemux * demux, + GstRTPSsrcDemuxClass * g_class) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux); + + demux->sinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "sink"), "sink"); + gst_pad_set_chain_function (demux->sinkpad, gst_rtp_ssrc_demux_chain); + gst_pad_set_event_function (demux->sinkpad, gst_rtp_ssrc_demux_sink_event); + gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->sinkpad); +} + +static void +gst_rtp_ssrc_demux_finalize (GObject * object) +{ + GstRTPSsrcDemux *demux; + + demux = GST_RTP_SSRC_DEMUX (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event) +{ + GstRTPSsrcDemux *demux; + gboolean res = FALSE; + + demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (demux); + return res; +} + +static GstFlowReturn +gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf) +{ + GstFlowReturn ret; + GstRTPSsrcDemux *demux; + guint32 ssrc; + GstPad *srcpad; + + demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad)); + + if (!gst_rtp_buffer_validate (buf)) + goto invalid_payload; + + ssrc = gst_rtp_buffer_get_ssrc (buf); + + srcpad = find_pad_for_ssrc (demux, ssrc); + if (srcpad == NULL) { + srcpad = create_pad_for_ssrc (demux, ssrc); + if (!srcpad) + goto create_failed; + } + + /* push to srcpad */ + ret = gst_pad_push (srcpad, buf); + + return ret; + + /* ERRORS */ +invalid_payload: + { + /* this is not fatal yet */ + GST_ELEMENT_WARNING (demux, STREAM, DECODE, (NULL), + ("Dropping invalid RTP payload")); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } +create_failed: + { + /* this is not fatal yet */ + GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), + ("Could not create new pad")); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_rtp_ssrc_demux_src_event (GstPad * pad, GstEvent * event) +{ + GstRTPSsrcDemux *demux; + gboolean res = FALSE; + + demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + default: + res = gst_pad_event_default (pad, event); + break; + } + gst_object_unref (demux); + return res; +} + +static GstStateChangeReturn +gst_rtp_ssrc_demux_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret; + GstRTPSsrcDemux *demux; + + demux = GST_RTP_SSRC_DEMUX (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_READY_TO_PAUSED: + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + default: + break; + } + return ret; +} diff --git a/gst/rtpmanager/gstrtpssrcdemux.h b/gst/rtpmanager/gstrtpssrcdemux.h new file mode 100644 index 00000000..6e1c2303 --- /dev/null +++ b/gst/rtpmanager/gstrtpssrcdemux.h @@ -0,0 +1,50 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_SSRC_DEMUX_H__ +#define __GST_RTP_SSRC_DEMUX_H__ + +#include + +#define GST_TYPE_RTP_SSRC_DEMUX (gst_rtp_ssrc_demux_get_type()) +#define GST_RTP_SSRC_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SSRC_DEMUX,GstRTPSsrcDemux)) +#define GST_RTP_SSRC_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SSRC_DEMUX,GstRTPSsrcDemuxClass)) +#define GST_IS_RTP_SSRC_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SSRC_DEMUX)) +#define GST_IS_RTP_SSRC_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SSRC_DEMUX)) + +typedef struct _GstRTPSsrcDemux GstRTPSsrcDemux; +typedef struct _GstRTPSsrcDemuxClass GstRTPSsrcDemuxClass; +typedef struct _GstRTPSsrcDemuxPad GstRTPSsrcDemuxPad; + +struct _GstRTPSsrcDemux +{ + GstElement parent; + + GstPad *sinkpad; + GSList *srcpads; +}; + +struct _GstRTPSsrcDemuxClass +{ + GstElementClass parent_class; +}; + +GType gst_rtp_ssrc_demux_get_type (void); + +#endif /* __GST_RTP_SSRC_DEMUX_H__ */ -- cgit v1.2.1