From 63c87f18994eb446e2d84d38c7be3dc81232de7d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 4 Oct 2006 17:24:40 +0000 Subject: [PATCH] gst/rtsp/: Factor out extension in separate module. Original commit message from CVS: * 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. --- ChangeLog | 27 ++++++++++ gst/rtsp/Makefile.am | 3 +- gst/rtsp/gstrtpdec.c | 25 +++++++-- gst/rtsp/gstrtspsrc.c | 108 ++++++++++++++++++++++++--------------- gst/rtsp/gstrtspsrc.h | 8 +++ gst/rtsp/rtspdefs.c | 7 +++ gst/rtsp/rtspdefs.h | 6 +++ gst/rtsp/rtspext.h | 77 ++++++++++++++++++++++++++++ gst/rtsp/rtspextwms.c | 104 +++++++++++++++++++++++++++++++++++++ gst/rtsp/rtspextwms.h | 56 ++++++++++++++++++++ gst/rtsp/rtsptransport.c | 77 +++++++++++++++++++++++----- gst/rtsp/rtsptransport.h | 21 +++++--- 12 files changed, 452 insertions(+), 67 deletions(-) create mode 100644 gst/rtsp/rtspext.h create mode 100644 gst/rtsp/rtspextwms.c create mode 100644 gst/rtsp/rtspextwms.h diff --git a/ChangeLog b/ChangeLog index 1064b5f6dc..34024eb1a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2006-10-04 Wim Taymans + + * 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 * docs/plugins/Makefile.am: diff --git a/gst/rtsp/Makefile.am b/gst/rtsp/Makefile.am index 86e0a2a235..95eeca69c1 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 728a138120..a4ea0d4647 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 c95362f77d..2494f53222 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 21fb073edf..8a9c74fe21 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 0e760940ea..706e5aadbc 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 4a0d6f49d7..4067488c3c 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 0000000000..779c109b65 --- /dev/null +++ b/gst/rtsp/rtspext.h @@ -0,0 +1,77 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * 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 + +#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 0000000000..3769fcdb4c --- /dev/null +++ b/gst/rtsp/rtspextwms.c @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * 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 + +#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 0000000000..48f14472c6 --- /dev/null +++ b/gst/rtsp/rtspextwms.h @@ -0,0 +1,56 @@ +/* GStreamer + * Copyright (C) <2006> 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. + */ +/* + * 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 + +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 2eaaa5b1bc..f9848c486c 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 40e16d504a..32a347b79b 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);