summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-10-04 17:24:40 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-10-04 17:24:40 +0000
commit63c87f18994eb446e2d84d38c7be3dc81232de7d (patch)
tree6fd484a2c931e99e23fd96583a302cc48bb2b0f4 /gst
parentc85684e2d83ffabe661bdd8aaea1309fa9915a16 (diff)
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.
Diffstat (limited to 'gst')
-rw-r--r--gst/rtsp/Makefile.am3
-rw-r--r--gst/rtsp/gstrtpdec.c25
-rw-r--r--gst/rtsp/gstrtspsrc.c108
-rw-r--r--gst/rtsp/gstrtspsrc.h8
-rw-r--r--gst/rtsp/rtspdefs.c7
-rw-r--r--gst/rtsp/rtspdefs.h6
-rw-r--r--gst/rtsp/rtspext.h77
-rw-r--r--gst/rtsp/rtspextwms.c104
-rw-r--r--gst/rtsp/rtspextwms.h56
-rw-r--r--gst/rtsp/rtsptransport.c77
-rw-r--r--gst/rtsp/rtsptransport.h21
11 files changed, 425 insertions, 67 deletions
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);