diff options
| -rw-r--r-- | ChangeLog | 27 | ||||
| -rw-r--r-- | gst/rtsp/Makefile.am | 3 | ||||
| -rw-r--r-- | gst/rtsp/gstrtpdec.c | 25 | ||||
| -rw-r--r-- | gst/rtsp/gstrtspsrc.c | 108 | ||||
| -rw-r--r-- | gst/rtsp/gstrtspsrc.h | 8 | ||||
| -rw-r--r-- | gst/rtsp/rtspdefs.c | 7 | ||||
| -rw-r--r-- | gst/rtsp/rtspdefs.h | 6 | ||||
| -rw-r--r-- | gst/rtsp/rtspext.h | 77 | ||||
| -rw-r--r-- | gst/rtsp/rtspextwms.c | 104 | ||||
| -rw-r--r-- | gst/rtsp/rtspextwms.h | 56 | ||||
| -rw-r--r-- | gst/rtsp/rtsptransport.c | 77 | ||||
| -rw-r--r-- | gst/rtsp/rtsptransport.h | 21 | 
12 files changed, 452 insertions, 67 deletions
@@ -1,3 +1,30 @@ +2006-10-04  Wim Taymans  <wim@fluendo.com> + +	* gst/rtsp/Makefile.am: +	* gst/rtsp/gstrtpdec.c: (gst_rtpdec_getcaps), +	(gst_rtpdec_chain_rtp), (gst_rtpdec_chain_rtcp): +	* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init), +	(gst_rtspsrc_finalize), (gst_rtspsrc_create_stream), +	(gst_rtspsrc_parse_rtpmap), +	(gst_rtspsrc_stream_configure_transport), (gst_rtspsrc_send), +	(gst_rtspsrc_parse_methods), (gst_rtspsrc_open), +	(gst_rtspsrc_play), (gst_rtspsrc_handle_message): +	* gst/rtsp/gstrtspsrc.h: +	* gst/rtsp/rtspdefs.c: (rtsp_strresult): +	* gst/rtsp/rtspdefs.h: +	* gst/rtsp/rtspext.h: +	* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_parse_sdp), +	(rtsp_ext_wms_get_context): +	* gst/rtsp/rtspextwms.h: +	* gst/rtsp/rtsptransport.c: (rtsp_transport_init), (parse_mode), +	(rtsp_transport_parse): +	* gst/rtsp/rtsptransport.h: +	Factor out extension in separate module. +	Fix getcaps to filter against the padtemplate. +	Use Content-Base if the server gives one. +	Rework the transport parsing a bit for future extensions. +	Added some Real Header field definitions. +  2006-10-04  Thomas Vander Stichele  <thomas at apestaart dot org>  	* docs/plugins/Makefile.am: diff --git a/gst/rtsp/Makefile.am b/gst/rtsp/Makefile.am index 86e0a2a2..95eeca69 100644 --- a/gst/rtsp/Makefile.am +++ b/gst/rtsp/Makefile.am @@ -4,6 +4,7 @@ libgstrtsp_la_SOURCES = gstrtsp.c gstrtspsrc.c \  			gstrtpdec.c		\  			rtspconnection.c	\  			rtspdefs.c		\ +			rtspextwms.c		\  			rtspmessage.c		\  			rtsptransport.c		\  			rtspurl.c		\ @@ -19,4 +20,4 @@ test_SOURCES = test.c rtspdefs.c rtspurl.c rtspconnection.c rtspmessage.c rtsptr  test_CFLAGS = $(GST_CFLAGS)  test_LDFLAGS = $(GST_LIBS) $(WIN32_LIBS) -noinst_HEADERS = gstrtspsrc.h gstrtsp.h gstrtpdec.h rtsptransport.h rtsp.h rtspurl.h rtspconnection.h rtspdefs.h rtspmessage.h sdp.h sdpmessage.h +noinst_HEADERS = gstrtspsrc.h gstrtsp.h gstrtpdec.h rtsptransport.h rtsp.h rtspurl.h rtspconnection.h rtspdefs.h rtspmessage.h sdp.h sdpmessage.h rtspextwms.h diff --git a/gst/rtsp/gstrtpdec.c b/gst/rtsp/gstrtpdec.c index 728a1381..a4ea0d46 100644 --- a/gst/rtsp/gstrtpdec.c +++ b/gst/rtsp/gstrtpdec.c @@ -222,6 +222,7 @@ gst_rtpdec_getcaps (GstPad * pad)    GstRTPDec *src;    GstPad *other;    GstCaps *caps; +  const GstCaps *templ;    src = GST_RTPDEC (GST_PAD_PARENT (pad)); @@ -229,8 +230,20 @@ gst_rtpdec_getcaps (GstPad * pad)    caps = gst_pad_peer_get_caps (other); -  if (caps == NULL) -    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); +  templ = gst_pad_get_pad_template_caps (pad); +  if (caps == NULL) { +    GST_DEBUG_OBJECT (src, "copy template"); +    caps = gst_caps_copy (templ); +  } else { +    GstCaps *intersect; + +    GST_DEBUG_OBJECT (src, "intersect with template"); + +    intersect = gst_caps_intersect (caps, templ); +    gst_caps_unref (caps); + +    caps = intersect; +  }    return caps;  } @@ -242,14 +255,18 @@ gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer)    src = GST_RTPDEC (GST_PAD_PARENT (pad)); -  GST_DEBUG ("got rtp packet"); +  GST_DEBUG_OBJECT (src, "got rtp packet");    return gst_pad_push (src->src_rtp, buffer);  }  static GstFlowReturn  gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer)  { -  GST_DEBUG ("got rtcp packet"); +  GstRTPDec *src; + +  src = GST_RTPDEC (GST_PAD_PARENT (pad)); + +  GST_DEBUG_OBJECT (src, "got rtcp packet");    gst_buffer_unref (buffer);    return GST_FLOW_OK; diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index c95362f7..2494f532 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -95,6 +95,8 @@  #include "gstrtspsrc.h"  #include "sdp.h" +#include "rtspextwms.h" +  GST_DEBUG_CATEGORY_STATIC (rtspsrc_debug);  #define GST_CAT_DEFAULT (rtspsrc_debug) @@ -265,8 +267,12 @@ gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)    src->loop_cond = g_cond_new (); -  src->location = DEFAULT_LOCATION; +  src->location = g_strdup (DEFAULT_LOCATION);    src->url = NULL; + +  /* install WMS extension by default */ +  src->extension = rtsp_ext_wms_get_context (); +  src->extension->src = (gpointer) src;  }  static void @@ -279,6 +285,9 @@ gst_rtspsrc_finalize (GObject * object)    g_static_rec_mutex_free (rtspsrc->stream_rec_lock);    g_free (rtspsrc->stream_rec_lock);    g_cond_free (rtspsrc->loop_cond); +  g_free (rtspsrc->location); +  g_free (rtspsrc->content_base); +  rtsp_url_free (rtspsrc->url);    G_OBJECT_CLASS (parent_class)->finalize (object);  } @@ -409,6 +418,9 @@ gst_rtspsrc_create_stream (GstRTSPSrc * src, SDPMessage * sdp, gint idx)      /* check absolute/relative URL */      if (g_str_has_prefix (control_url, "rtsp://"))        stream->setup_url = g_strdup (control_url); +    else if (src->content_base) +      stream->setup_url = +          g_strdup_printf ("%s%s", src->content_base, control_url);      else        stream->setup_url = g_strdup_printf ("%s/%s", src->location, control_url);    } @@ -487,8 +499,12 @@ gst_rtspsrc_parse_rtpmap (gchar * rtpmap, gint * payload, gchar ** name,      return FALSE;    PARSE_STRING (p, "/", *name); -  if (*name == NULL) -    return FALSE; +  if (*name == NULL) { +    /* no rate, assume 0 then */ +    *name = p; +    *rate = -1; +    return TRUE; +  }    t = p;    p = strstr (p, "/"); @@ -792,7 +808,7 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,    } else {      /* multicast was selected, create UDP sources and join the multicast       * group. */ -    if (transport->multicast) { +    if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST) {        gchar *uri;        /* creating RTP source */ @@ -1143,12 +1159,16 @@ gst_rtspsrc_loop (GstRTSPSrc * src)   *   * Returns: TRUE if the processing was successful.   */ -static gboolean +gboolean  gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,      RTSPMessage * response, RTSPStatusCode * code)  {    RTSPResult res;    RTSPStatusCode thecode; +  gchar *content_base = NULL; + +  if (src->extension && src->extension->before_send) +    src->extension->before_send (src->extension, request);    if (src->debug)      rtsp_message_dump (request); @@ -1170,6 +1190,16 @@ gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,    else if (thecode != RTSP_STS_OK)      goto error_response; +  /* store new content base if any */ +  rtsp_message_get_header (response, RTSP_HDR_CONTENT_BASE, &content_base); +  if (content_base) { +    g_free (src->content_base); +    src->content_base = g_strdup (content_base); +  } + +  if (src->extension && src->extension->after_send) +    src->extension->after_send (src->extension, request, response); +    return TRUE;    /* ERRORS */ @@ -1233,7 +1263,7 @@ gst_rtspsrc_parse_methods (GstRTSPSrc * src, RTSPMessage * response)      /* this field is not required, assume the server supports       * DESCRIBE, SETUP and PLAY */      GST_DEBUG_OBJECT (src, "could not get OPTIONS"); -    src->methods = RTSP_DESCRIBE | RTSP_SETUP | RTSP_PLAY; +    src->methods = RTSP_DESCRIBE | RTSP_SETUP | RTSP_PLAY | RTSP_PAUSE;      goto done;    } @@ -1333,6 +1363,12 @@ gst_rtspsrc_open (GstRTSPSrc * src)    /* we only accept SDP for now */    rtsp_message_add_header (&request, RTSP_HDR_ACCEPT, "application/sdp"); +  /* prepare global stream caps properties */ +  if (src->props) +    gst_structure_remove_all_fields (src->props); +  else +    src->props = gst_structure_empty_new ("RTSP Properties"); +    /* send DESCRIBE */    GST_DEBUG_OBJECT (src, "send describe...");    if (!gst_rtspsrc_send (src, &request, &response, NULL)) @@ -1357,29 +1393,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)    if (src->debug)      sdp_message_dump (&sdp); -  /* prepare global stream caps properties */ -  if (src->props) -    gst_structure_remove_all_fields (src->props); -  else -    src->props = gst_structure_empty_new ("RTSP Properties"); - -  /* FIXME, WMServer specific, move to extensions */ -#define HEADER_PREFIX "data:application/vnd.ms.wms-hdr.asfv1;base64," -  { -    gchar *config, *maxps; - -    for (i = 0; (config = sdp_message_get_attribute_val_n (&sdp, "pgmpu", i)); -        i++) { -      if (g_str_has_prefix (config, HEADER_PREFIX)) { -        config += strlen (HEADER_PREFIX); -        gst_structure_set (src->props, "config", G_TYPE_STRING, config, NULL); -        break; -      } -    } -    maxps = sdp_message_get_attribute_val (&sdp, "maxps"); -    if (maxps) -      gst_structure_set (src->props, "maxps", G_TYPE_STRING, maxps, NULL); -  } +  if (src->extension && src->extension->parse_sdp) +    src->extension->parse_sdp (src->extension, &sdp);    /* we initially allow all configured protocols. based on the replies from the     * server we narrow them down. */ @@ -1393,7 +1408,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)      /* create stream from the media, can never return NULL */      stream = gst_rtspsrc_create_stream (src, &sdp, i); -    /* merge global caps */ +    /* merge/overwrite global caps */      if (stream->caps) {        guint j, num;        GstStructure *s; @@ -1408,6 +1423,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)          name = gst_structure_nth_field_name (src->props, j);          val = gst_structure_get_value (src->props, name);          gst_structure_set_value (s, name, val); + +        GST_DEBUG_OBJECT (src, "copied %s", name);        }      } @@ -1494,20 +1511,26 @@ gst_rtspsrc_open (GstRTSPSrc * src)        /* update allowed transports for other streams. once the transport of         * one stream has been determined, we make sure that all other streams         * are configured in the same way */ -      if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) { -        GST_DEBUG_OBJECT (src, "stream %d as TCP", i); -        protocols = GST_RTSP_PROTO_TCP; -        src->interleaved = TRUE; -      } else { -        if (transport.multicast) { +      switch (transport.lower_transport) { +        case RTSP_LOWER_TRANS_TCP: +          GST_DEBUG_OBJECT (src, "stream %d as TCP interleaved", i); +          protocols = GST_RTSP_PROTO_TCP; +          src->interleaved = TRUE; +          break; +        case RTSP_LOWER_TRANS_UDP_MCAST:            /* only allow multicast for other streams */ -          GST_DEBUG_OBJECT (src, "stream %d as MULTICAST", i); +          GST_DEBUG_OBJECT (src, "stream %d as UDP multicast", i);            protocols = GST_RTSP_PROTO_UDP_MULTICAST; -        } else { +          break; +        case RTSP_LOWER_TRANS_UDP:            /* only allow unicast for other streams */ -          GST_DEBUG_OBJECT (src, "stream %d as UNICAST", i); +          GST_DEBUG_OBJECT (src, "stream %d as UDP unicast", i);            protocols = GST_RTSP_PROTO_UDP_UNICAST; -        } +          break; +        default: +          GST_DEBUG_OBJECT (src, "stream %d unknown transport %d", i, +              transport.lower_transport); +          break;        }        if (!stream->container || !src->interleaved) { @@ -1522,6 +1545,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)        rtsp_transport_init (&transport);      }    } +  if (src->extension && src->extension->stream_select) +    src->extension->stream_select (src->extension);    /* if we got here all was configured. We have dynamic pads so we notify that     * we are done */ @@ -1735,7 +1760,8 @@ gst_rtspsrc_play (GstRTSPSrc * src)    rtsp_message_unset (&response);    /* for interleaved transport, we receive the data on the RTSP connection -   * instead of UDP. We start a task to select and read from that connection. */ +   * instead of UDP. We start a task to select and read from that connection. +   * For UDP we start the task as well to look for server info and UDP timeouts. */    if (src->task == NULL) {      src->task = gst_task_create ((GstTaskFunction) gst_rtspsrc_loop, src);      gst_task_set_lock (src->task, src->stream_rec_lock); diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 21fb073e..8a9c74fe 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -50,6 +50,7 @@ G_BEGIN_DECLS  #include "gstrtsp.h"  #include "rtsp.h" +#include "rtspext.h"  #define GST_TYPE_RTSPSRC \    (gst_rtspsrc_get_type()) @@ -142,6 +143,7 @@ struct _GstRTSPSrc {    gchar           *location;    RTSPUrl         *url; +  gchar           *content_base;    GstRTSPProto     protocols;    gboolean         debug;    guint   	   retry; @@ -153,6 +155,8 @@ struct _GstRTSPSrc {    RTSPConnection  *connection;    RTSPMessage     *request;    RTSPMessage     *response; + +  RTSPExtensionCtx *extension;  };  struct _GstRTSPSrcClass { @@ -161,6 +165,10 @@ struct _GstRTSPSrcClass {  GType gst_rtspsrc_get_type(void); +gboolean   gst_rtspsrc_send 		(GstRTSPSrc * src, RTSPMessage * request, +		   			 RTSPMessage * response, RTSPStatusCode * code); + +  G_END_DECLS  #endif /* __GST_RTSPSRC_H__ */ diff --git a/gst/rtsp/rtspdefs.c b/gst/rtsp/rtspdefs.c index 0e760940..706e5aad 100644 --- a/gst/rtsp/rtspdefs.c +++ b/gst/rtsp/rtspdefs.c @@ -122,6 +122,13 @@ static const gchar *rtsp_headers[] = {    "User-Agent",                 /* User-Agent           R      opt.      all */    "Via",                        /* Via                  g      opt.      all */    "WWW-Authenticate",           /* WWW-Authenticate     r      opt.      all */ + +  /* Real extensions */ +  "ClientChallenge",            /* ClientChallenge */ +  "RealChallenge1",             /* RealChallenge1 */ +  "RealChallenge2",             /* RealChallenge2 */ +  "Subscribe",                  /* Subscribe */ +    NULL  }; diff --git a/gst/rtsp/rtspdefs.h b/gst/rtsp/rtspdefs.h index 4a0d6f49..4067488c 100644 --- a/gst/rtsp/rtspdefs.h +++ b/gst/rtsp/rtspdefs.h @@ -150,6 +150,12 @@ typedef enum {    RTSP_HDR_VIA,                 /* Via                  g      opt.      all */    RTSP_HDR_WWW_AUTHENTICATE,    /* WWW-Authenticate     r      opt.      all */ +  /* Real extensions */ +  RTSP_HDR_CLIENT_CHALLENGE,    /* ClientChallenge */ +  RTSP_HDR_REAL_CHALLENGE1,     /* RealChallenge1 */ +  RTSP_HDR_REAL_CHALLENGE2,     /* RealChallenge2 */ +  RTSP_HDR_SUBSCRIBE,           /* Subscribe */ +  } RTSPHeaderField;  typedef enum { diff --git a/gst/rtsp/rtspext.h b/gst/rtsp/rtspext.h new file mode 100644 index 00000000..779c109b --- /dev/null +++ b/gst/rtsp/rtspext.h @@ -0,0 +1,77 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __RTSP_EXT_H__ +#define __RTSP_EXT_H__ + +#include <glib.h> + +#include "sdp.h" + +G_BEGIN_DECLS + +typedef struct _RTSPExtensionCtx RTSPExtensionCtx; + +struct _RTSPExtensionCtx +{ +  GstRank     rank; +  gchar      *name; +  gpointer   *src; + +  gboolean   (*detect_server)  (RTSPExtensionCtx *ctx, RTSPMessage *resp); + +  RTSPResult (*before_send)    (RTSPExtensionCtx *ctx, RTSPMessage *req); +  RTSPResult (*after_send)     (RTSPExtensionCtx *ctx, RTSPMessage *req, RTSPMessage *resp); + +  RTSPResult (*parse_sdp)      (RTSPExtensionCtx *ctx, SDPMessage *sdp); +  RTSPResult (*setup_media)    (RTSPExtensionCtx *ctx, SDPMedia *media); + +  RTSPResult (*stream_select)  (RTSPExtensionCtx *ctx); +}; + +RTSPExtensionCtx*     	rtsp_extension_detect    	(RTSPMessage *resp); + +gboolean     		rtsp_extension_register  	(RTSPExtensionCtx *ctx); + +G_END_DECLS + +#endif /* __RTSP_EXT_H__ */ diff --git a/gst/rtsp/rtspextwms.c b/gst/rtsp/rtspextwms.c new file mode 100644 index 00000000..3769fcdb --- /dev/null +++ b/gst/rtsp/rtspextwms.c @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <string.h> + +#include "gstrtspsrc.h" +#include "rtspextwms.h" + +typedef struct _RTSPExtWMSCtx RTSPExtWMSCtx; + +struct _RTSPExtWMSCtx +{ +  RTSPExtensionCtx ctx; +}; + +#define HEADER_PREFIX "data:application/vnd.ms.wms-hdr.asfv1;base64," + +static RTSPResult +rtsp_ext_wms_parse_sdp (RTSPExtensionCtx * ctx, SDPMessage * sdp) +{ +  GstRTSPSrc *src = (GstRTSPSrc *) ctx->src; +  gchar *config, *maxps; +  gint i; + +  for (i = 0; (config = sdp_message_get_attribute_val_n (sdp, "pgmpu", i)); i++) { +    if (g_str_has_prefix (config, HEADER_PREFIX)) { +      config += strlen (HEADER_PREFIX); +      gst_structure_set (src->props, "config", G_TYPE_STRING, config, NULL); +      break; +    } +  } +  if (config == NULL) +    goto no_config; + +  gst_structure_set (src->props, "config", G_TYPE_STRING, config, NULL); + +  maxps = sdp_message_get_attribute_val (sdp, "maxps"); +  if (maxps) +    gst_structure_set (src->props, "maxps", G_TYPE_STRING, maxps, NULL); + +  gst_structure_set (src->props, "encoding-name", G_TYPE_STRING, "x-asf-pf", +      NULL); +  gst_structure_set (src->props, "media", G_TYPE_STRING, "application", NULL); + +  return RTSP_OK; + +  /* ERRORS */ +no_config: +  { +    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), +        ("Could not find config SDP field.")); +    return RTSP_ENOTIMPL; +  } +} + +RTSPExtensionCtx * +rtsp_ext_wms_get_context (void) +{ +  RTSPExtWMSCtx *res; + +  res = g_new0 (RTSPExtWMSCtx, 1); +  res->ctx.parse_sdp = rtsp_ext_wms_parse_sdp; + +  return (RTSPExtensionCtx *) res; +} diff --git a/gst/rtsp/rtspextwms.h b/gst/rtsp/rtspextwms.h new file mode 100644 index 00000000..48f14472 --- /dev/null +++ b/gst/rtsp/rtspextwms.h @@ -0,0 +1,56 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __RTSP_EXT_WMS_H__ +#define __RTSP_EXT_WMS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +#include "rtspext.h" + +RTSPExtensionCtx*     rtsp_ext_wms_get_context    (void); + +G_END_DECLS + +#endif /* __RTSP_EXT_WMS_H__ */ diff --git a/gst/rtsp/rtsptransport.c b/gst/rtsp/rtsptransport.c index 2eaaa5b1..f9848c48 100644 --- a/gst/rtsp/rtsptransport.c +++ b/gst/rtsp/rtsptransport.c @@ -45,6 +45,45 @@  #include "rtsptransport.h" +typedef struct +{ +  const gchar *name; +  const RTSPTransMode mode; +  const gchar *gst_mime; +} RTSPTransMap; + +static const RTSPTransMap transports[] = { +  {"rtp", RTSP_TRANS_RTP, "application/x-rtp"}, +  {"x-real-rdt", RTSP_TRANS_RDT, "application/x-rdt"}, +  {"x-pn-tng", RTSP_TRANS_RDT, "application/x-rdt"}, +  {NULL, RTSP_TRANS_UNKNOWN, "application/x-unknown"} +}; + +typedef struct +{ +  const gchar *name; +  const RTSPProfile profile; +} RTSPProfileMap; + +static const RTSPProfileMap profiles[] = { +  {"avp", RTSP_PROFILE_AVP}, +  {"savp", RTSP_PROFILE_SAVP}, +  {NULL, RTSP_PROFILE_UNKNOWN} +}; + +typedef struct +{ +  const gchar *name; +  const RTSPLowerTrans ltrans; +} RTSPLTransMap; + +static const RTSPLTransMap ltrans[] = { +  {"udp", RTSP_LOWER_TRANS_UDP}, +  {"mcast", RTSP_LOWER_TRANS_UDP_MCAST}, +  {"tcp", RTSP_LOWER_TRANS_TCP}, +  {NULL, RTSP_LOWER_TRANS_UNKNOWN} +}; +  RTSPResult  rtsp_transport_new (RTSPTransport ** transport)  { @@ -72,7 +111,7 @@ rtsp_transport_init (RTSPTransport * transport)    transport->trans = RTSP_TRANS_RTP;    transport->profile = RTSP_PROFILE_AVP; -  transport->lower_transport = RTSP_LOWER_TRANS_UNKNOWN; +  transport->lower_transport = RTSP_LOWER_TRANS_UDP;    transport->mode_play = TRUE;    transport->mode_record = FALSE; @@ -82,8 +121,8 @@ rtsp_transport_init (RTSPTransport * transport)  static void  parse_mode (RTSPTransport * transport, gchar * str)  { -  transport->mode_play = (strstr (str, "\"PLAY\"") != NULL); -  transport->mode_record = (strstr (str, "\"RECORD\"") != NULL); +  transport->mode_play = (strstr (str, "\"play\"") != NULL); +  transport->mode_record = (strstr (str, "\"record\"") != NULL);  }  static void @@ -102,7 +141,7 @@ parse_range (RTSPTransport * transport, gchar * str, RTSPRange * range)  }  RTSPResult -rtsp_transport_parse (gchar * str, RTSPTransport * transport) +rtsp_transport_parse (const gchar * str, RTSPTransport * transport)  {    gchar **split, *down;    gint i; @@ -116,18 +155,30 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport)    down = g_ascii_strdown (str, -1);    split = g_strsplit (down, ";", 0); + +  /* First field contains the transport/profile/lower_transport */    i = 0; +  if (split[0]) { +    for (i = 0; transports[i].name; i++) +      if (strstr (split[0], transports[i].name)) +        break; +    transport->trans = transports[i].mode; +    for (i = 1; profiles[i].name; i++) +      if (strstr (split[0], profiles[i].name)) +        break; +    transport->profile = profiles[i].profile; +    for (i = 1; ltrans[i].name; i++) +      if (strstr (split[0], ltrans[i].name)) +        break; +    transport->lower_transport = ltrans[i].ltrans; +    i = 1; +  }    while (split[i]) { -    if (g_str_has_prefix (split[i], "rtp/avp/udp")) { -      transport->lower_transport = RTSP_LOWER_TRANS_UDP; -    } else if (g_str_has_prefix (split[i], "rtp/avp/tcp")) { -      transport->lower_transport = RTSP_LOWER_TRANS_TCP; -    } else if (g_str_has_prefix (split[i], "rtp/avp")) { -      transport->lower_transport = RTSP_LOWER_TRANS_UDP; -    } else if (g_str_has_prefix (split[i], "multicast")) { -      transport->multicast = TRUE; +    if (g_str_has_prefix (split[i], "multicast")) { +      transport->lower_transport = RTSP_LOWER_TRANS_UDP_MCAST;      } else if (g_str_has_prefix (split[i], "unicast")) { -      transport->multicast = FALSE; +      if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST) +        transport->lower_transport = RTSP_LOWER_TRANS_UDP;      } else if (g_str_has_prefix (split[i], "destination=")) {        transport->destination = g_strdup (split[i] + 12);      } else if (g_str_has_prefix (split[i], "source=")) { diff --git a/gst/rtsp/rtsptransport.h b/gst/rtsp/rtsptransport.h index 40e16d50..32a347b7 100644 --- a/gst/rtsp/rtsptransport.h +++ b/gst/rtsp/rtsptransport.h @@ -48,17 +48,22 @@  G_BEGIN_DECLS  typedef enum { -  RTSP_TRANS_RTP, +  RTSP_TRANS_UNKNOWN =  0, +  RTSP_TRANS_RTP     = (1 << 0), +  RTSP_TRANS_RDT     = (1 << 1)  } RTSPTransMode;  typedef enum { -  RTSP_PROFILE_AVP, +  RTSP_PROFILE_UNKNOWN =  0, +  RTSP_PROFILE_AVP     = (1 << 0), +  RTSP_PROFILE_SAVP    = (1 << 1)  } RTSPProfile;  typedef enum { -  RTSP_LOWER_TRANS_UNKNOWN, -  RTSP_LOWER_TRANS_UDP, -  RTSP_LOWER_TRANS_TCP, +  RTSP_LOWER_TRANS_UNKNOWN   = 0, +  RTSP_LOWER_TRANS_UDP       = (1 << 0), +  RTSP_LOWER_TRANS_UDP_MCAST = (1 << 1), +  RTSP_LOWER_TRANS_TCP       = (1 << 2)  } RTSPLowerTrans;  typedef struct @@ -72,7 +77,6 @@ typedef struct _RTSPTransport {    RTSPProfile    profile;    RTSPLowerTrans lower_transport; -  gboolean       multicast;    gchar         *destination;    gchar         *source;    gint           layers; @@ -84,10 +88,11 @@ typedef struct _RTSPTransport {    /* mulitcast specific */    gint  ttl; -  /* RTP specific */ +  /* UDP specific */    RTSPRange      port;    RTSPRange      client_port;    RTSPRange      server_port; +  /* RTP specific */    gchar         *ssrc;  } RTSPTransport; @@ -95,7 +100,7 @@ typedef struct _RTSPTransport {  RTSPResult      rtsp_transport_new      (RTSPTransport **transport);  RTSPResult      rtsp_transport_init     (RTSPTransport *transport); -RTSPResult      rtsp_transport_parse    (gchar *str, RTSPTransport *transport); +RTSPResult      rtsp_transport_parse    (const gchar *str, RTSPTransport *transport);  RTSPResult      rtsp_transport_free     (RTSPTransport *transport);  | 
