summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2005-08-18 16:53:14 +0000
committerWim Taymans <wim.taymans@gmail.com>2005-08-18 16:53:14 +0000
commitc831aef4958834733bffe44941c5b8c12f51d40f (patch)
treed80abf5f7645f85de63ca61e2e952dafb2cbfda0 /gst
parent9a5c8cd25ef8fe33fb8b189f88725bfac5c68768 (diff)
gst/rtsp/: Handle RTSP defaults better.
Original commit message from CVS: * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send), (gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play), (gst_rtspsrc_pause), (gst_rtspsrc_change_state): * gst/rtsp/gstrtspsrc.h: * gst/rtsp/rtspdefs.c: (rtsp_method_as_text), (rtsp_find_method): * gst/rtsp/rtspdefs.h: * gst/rtsp/rtsptransport.c: (rtsp_transport_parse): Handle RTSP defaults better. Issue OPTIONS request to figure out what we are allowed to do. Make the methods a bitfield so we can easily collect supported options. Fix rtsp_find_method. Do proper RTSP connection shutdown.
Diffstat (limited to 'gst')
-rw-r--r--gst/rtsp/gstrtspsrc.c131
-rw-r--r--gst/rtsp/gstrtspsrc.h2
-rw-r--r--gst/rtsp/rtspdefs.c16
-rw-r--r--gst/rtsp/rtspdefs.h22
-rw-r--r--gst/rtsp/rtsptransport.c2
5 files changed, 144 insertions, 29 deletions
diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c
index 94977517..b27378d0 100644
--- a/gst/rtsp/gstrtspsrc.c
+++ b/gst/rtsp/gstrtspsrc.c
@@ -495,7 +495,7 @@ need_pause:
static gboolean
gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
- RTSPMessage * response)
+ RTSPMessage * response, RTSPStatusCode * code)
{
RTSPResult res;
@@ -507,6 +507,11 @@ gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
if ((res = rtsp_connection_receive (src->connection, response)) < 0)
goto receive_error;
+
+ if (code) {
+ *code = response->type_data.response.code;
+ }
+
if (response->type_data.response.code != RTSP_STS_OK)
goto error_response;
@@ -559,6 +564,48 @@ gst_rtspsrc_open (GstRTSPSrc * src)
if ((res = rtsp_connection_open (url, &src->connection)) < 0)
goto could_not_open;
+ /* create OPTIONS */
+ GST_DEBUG ("create options...");
+ if ((res =
+ rtsp_message_init_request (RTSP_OPTIONS, src->location,
+ &request)) < 0)
+ goto create_request_failed;
+
+ /* send OPTIONS */
+ GST_DEBUG ("send options...");
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
+ goto send_error;
+
+ {
+ gchar *respoptions = NULL;
+ gchar **options;
+ gint i;
+
+ rtsp_message_get_header (&response, RTSP_HDR_ALLOW, &respoptions);
+ if (!respoptions)
+ goto no_options;
+
+ /* parse options */
+ options = g_strsplit (respoptions, ",", 0);
+
+ i = 0;
+ while (options[i]) {
+ gint method = rtsp_find_method (options[i]);
+
+ /* keep bitfield of supported methods */
+ if (method != -1)
+ src->options |= method;
+ i++;
+ }
+ g_strfreev (options);
+
+ /* we need describe and setup */
+ if (!(src->options & RTSP_DESCRIBE))
+ goto no_describe;
+ if (!(src->options & RTSP_SETUP))
+ goto no_setup;
+ }
+
/* create DESCRIBE */
GST_DEBUG ("create describe...");
if ((res =
@@ -570,9 +617,22 @@ gst_rtspsrc_open (GstRTSPSrc * src)
/* send DESCRIBE */
GST_DEBUG ("send describe...");
- if (!gst_rtspsrc_send (src, &request, &response))
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
goto send_error;
+ /* check if reply is SDP */
+ {
+ gchar *respcont = NULL;
+
+ rtsp_message_get_header (&response, RTSP_HDR_CONTENT_TYPE, &respcont);
+ /* could not be set but since the request returned OK, we assume it
+ * was SDP, else check it. */
+ if (respcont) {
+ if (!g_ascii_strcasecmp (respcont, "application/sdp") == 0)
+ goto wrong_content_type;
+ }
+ }
+
/* parse SDP */
rtsp_message_get_body (&response, &data, &size);
@@ -622,7 +682,6 @@ gst_rtspsrc_open (GstRTSPSrc * src)
}
g_free (setup_url);
-
transports = g_strdup ("");
if (protocols & GST_RTSP_PROTO_UDP_UNICAST) {
gchar *new;
@@ -662,15 +721,17 @@ gst_rtspsrc_open (GstRTSPSrc * src)
rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports);
g_free (transports);
- if (!gst_rtspsrc_send (src, &request, &response))
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
goto send_error;
/* parse response transport */
{
- gchar *resptrans;
+ gchar *resptrans = NULL;
RTSPTransport transport = { 0 };
rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans);
+ if (!resptrans)
+ goto no_transport;
/* parse transport */
rtsp_transport_parse (resptrans, &transport);
@@ -723,14 +784,44 @@ send_error:
("Could not send message."), (NULL));
return FALSE;
}
+no_options:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
+ ("Invalid OPTIONS response."), (NULL));
+ return FALSE;
+ }
+no_describe:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
+ ("Server does not support DESCRIBE."), (NULL));
+ return FALSE;
+ }
+no_setup:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
+ ("Server does not support SETUP."), (NULL));
+ return FALSE;
+ }
+wrong_content_type:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
+ ("Server does not support SDP."), (NULL));
+ return FALSE;
+ }
setup_rtp_failed:
{
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not setup rtp."), (NULL));
return FALSE;
}
+no_transport:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
+ ("Server did not select transport."), (NULL));
+ return FALSE;
+ }
}
-G_GNUC_UNUSED static gboolean
+static gboolean
gst_rtspsrc_close (GstRTSPSrc * src)
{
RTSPMessage request = { 0 };
@@ -746,14 +837,16 @@ gst_rtspsrc_close (GstRTSPSrc * src)
src->task = NULL;
}
- /* do TEARDOWN */
- if ((res =
- rtsp_message_init_request (RTSP_TEARDOWN, src->location,
- &request)) < 0)
- goto create_request_failed;
+ if (src->options & RTSP_PLAY) {
+ /* do TEARDOWN */
+ if ((res =
+ rtsp_message_init_request (RTSP_TEARDOWN, src->location,
+ &request)) < 0)
+ goto create_request_failed;
- if (!gst_rtspsrc_send (src, &request, &response))
- goto send_error;
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
+ goto send_error;
+ }
/* close connection */
GST_DEBUG ("closing connection...");
@@ -788,6 +881,9 @@ gst_rtspsrc_play (GstRTSPSrc * src)
RTSPMessage response = { 0 };
RTSPResult res;
+ if (!(src->options & RTSP_PLAY))
+ return TRUE;
+
GST_DEBUG ("PLAY...");
/* do play */
@@ -795,7 +891,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
rtsp_message_init_request (RTSP_PLAY, src->location, &request)) < 0)
goto create_request_failed;
- if (!gst_rtspsrc_send (src, &request, &response))
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
goto send_error;
if (src->interleaved) {
@@ -827,13 +923,16 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
RTSPMessage response = { 0 };
RTSPResult res;
+ if (!(src->options & RTSP_PAUSE))
+ return TRUE;
+
GST_DEBUG ("PAUSE...");
/* do pause */
if ((res =
rtsp_message_init_request (RTSP_PAUSE, src->location, &request)) < 0)
goto create_request_failed;
- if (!gst_rtspsrc_send (src, &request, &response))
+ if (!gst_rtspsrc_send (src, &request, &response, NULL))
goto send_error;
return TRUE;
@@ -868,6 +967,7 @@ gst_rtspsrc_change_state (GstElement * element)
break;
case GST_STATE_READY_TO_PAUSED:
rtspsrc->interleaved = FALSE;
+ rtspsrc->options = 0;
if (!gst_rtspsrc_open (rtspsrc))
goto open_failed;
break;
@@ -891,6 +991,7 @@ gst_rtspsrc_change_state (GstElement * element)
gst_rtspsrc_pause (rtspsrc);
break;
case GST_STATE_PAUSED_TO_READY:
+ gst_rtspsrc_close (rtspsrc);
break;
case GST_STATE_READY_TO_NULL:
break;
diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h
index 1cc1bb5c..89604d2e 100644
--- a/gst/rtsp/gstrtspsrc.h
+++ b/gst/rtsp/gstrtspsrc.h
@@ -88,6 +88,8 @@ struct _GstRTSPSrc {
gboolean debug;
GstRTSPProto protocols;
+ /* supported options */
+ gint options;
RTSPConnection *connection;
RTSPMessage *request;
diff --git a/gst/rtsp/rtspdefs.c b/gst/rtsp/rtspdefs.c
index 61b9a87d..ebc848de 100644
--- a/gst/rtsp/rtspdefs.c
+++ b/gst/rtsp/rtspdefs.c
@@ -136,7 +136,17 @@ rtsp_init_status (void)
const gchar *
rtsp_method_as_text (RTSPMethod method)
{
- return rtsp_methods[method];
+ gint i;
+
+ if (method == 0)
+ return NULL;
+
+ i = 0;
+ while ((method & 1) == 0) {
+ i++;
+ method >>= 1;
+ }
+ return rtsp_methods[i];
}
const gchar *
@@ -176,8 +186,8 @@ rtsp_find_method (gchar * method)
gint idx;
for (idx = 0; rtsp_methods[idx]; idx++) {
- if (g_ascii_strcasecmp (rtsp_headers[idx], method) == 0) {
- return idx;
+ if (g_ascii_strcasecmp (rtsp_methods[idx], method) == 0) {
+ return (1 << idx);
}
}
return -1;
diff --git a/gst/rtsp/rtspdefs.h b/gst/rtsp/rtspdefs.h
index 7995efb7..9ba100fe 100644
--- a/gst/rtsp/rtspdefs.h
+++ b/gst/rtsp/rtspdefs.h
@@ -54,17 +54,17 @@ typedef enum {
} RTSPState;
typedef enum {
- RTSP_DESCRIBE,
- RTSP_ANNOUNCE,
- RTSP_GET_PARAMETER,
- RTSP_OPTIONS,
- RTSP_PAUSE,
- RTSP_PLAY,
- RTSP_RECORD,
- RTSP_REDIRECT,
- RTSP_SETUP,
- RTSP_SET_PARAMETER,
- RTSP_TEARDOWN,
+ RTSP_DESCRIBE = (1 << 0),
+ RTSP_ANNOUNCE = (1 << 1),
+ RTSP_GET_PARAMETER = (1 << 2),
+ RTSP_OPTIONS = (1 << 3),
+ RTSP_PAUSE = (1 << 4),
+ RTSP_PLAY = (1 << 5),
+ RTSP_RECORD = (1 << 6),
+ RTSP_REDIRECT = (1 << 7),
+ RTSP_SETUP = (1 << 8),
+ RTSP_SET_PARAMETER = (1 << 9),
+ RTSP_TEARDOWN = (1 << 10),
} RTSPMethod;
typedef enum {
diff --git a/gst/rtsp/rtsptransport.c b/gst/rtsp/rtsptransport.c
index 95ac87ee..3c208ee2 100644
--- a/gst/rtsp/rtsptransport.c
+++ b/gst/rtsp/rtsptransport.c
@@ -95,6 +95,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport)
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;
} else if (g_str_has_prefix (split[i], "unicast")) {