Commit 63c87f18 authored by Wim Taymans's avatar Wim Taymans

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.
parent c85684e2
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:
......
......@@ -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
......@@ -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;
......
......@@ -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);
......
......@@ -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__ */
......@@ -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
};
......
......@@ -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 {
......
/* 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__ */
/* 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;
}
/* 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__ */
......@@ -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=")) {
......
......@@ -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 {