diff options
| -rw-r--r-- | gst/rtpmanager/Makefile.am | 2 | ||||
| -rw-r--r-- | gst/rtpmanager/gstrtpmanager.c | 5 | ||||
| -rw-r--r-- | gst/rtpmanager/gstrtpssrcdemux.c | 303 | ||||
| -rw-r--r-- | gst/rtpmanager/gstrtpssrcdemux.h | 50 | 
4 files changed, 360 insertions, 0 deletions
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 <wim@fluendo.com> + * + * 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 <string.h> +#include <gst/rtp/gstrtpbuffer.h> + +#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 <wim@fluendo.com>" +}; + +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 <wim@fluendo.com> + * + * 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 <gst/gst.h> + +#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__ */  | 
