mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 00:58:12 +00:00
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.
This commit is contained in:
parent
c85684e2d8
commit
63c87f1899
12 changed files with 452 additions and 67 deletions
27
ChangeLog
27
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
77
gst/rtsp/rtspext.h
Normal file
77
gst/rtsp/rtspext.h
Normal file
|
@ -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__ */
|
104
gst/rtsp/rtspextwms.c
Normal file
104
gst/rtsp/rtspextwms.c
Normal file
|
@ -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;
|
||||
}
|
56
gst/rtsp/rtspextwms.h
Normal file
56
gst/rtsp/rtspextwms.h
Normal file
|
@ -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__ */
|
|
@ -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 {
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue