diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2005-08-18 16:53:14 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2005-08-18 16:53:14 +0000 |
commit | c831aef4958834733bffe44941c5b8c12f51d40f (patch) | |
tree | d80abf5f7645f85de63ca61e2e952dafb2cbfda0 | |
parent | 9a5c8cd25ef8fe33fb8b189f88725bfac5c68768 (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.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.c | 131 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.h | 2 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.c | 16 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.h | 22 | ||||
-rw-r--r-- | gst/rtsp/rtsptransport.c | 2 |
6 files changed, 160 insertions, 29 deletions
@@ -1,5 +1,21 @@ 2005-08-18 Wim Taymans <wim@fluendo.com> + * 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. + +2005-08-18 Wim Taymans <wim@fluendo.com> + * gst/rtp/Makefile.am: * gst/rtp/gstrtp-common.h: * gst/rtp/gstrtp.c: (plugin_init): 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")) { |