mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-29 02:28:27 +00:00
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.
This commit is contained in:
parent
9a5c8cd25e
commit
c831aef495
6 changed files with 160 additions and 29 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
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>
|
2005-08-18 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/rtp/Makefile.am:
|
* gst/rtp/Makefile.am:
|
||||||
|
|
|
@ -495,7 +495,7 @@ need_pause:
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
|
gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
|
||||||
RTSPMessage * response)
|
RTSPMessage * response, RTSPStatusCode * code)
|
||||||
{
|
{
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
|
||||||
|
@ -507,6 +507,11 @@ gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
|
||||||
|
|
||||||
if ((res = rtsp_connection_receive (src->connection, response)) < 0)
|
if ((res = rtsp_connection_receive (src->connection, response)) < 0)
|
||||||
goto receive_error;
|
goto receive_error;
|
||||||
|
|
||||||
|
if (code) {
|
||||||
|
*code = response->type_data.response.code;
|
||||||
|
}
|
||||||
|
|
||||||
if (response->type_data.response.code != RTSP_STS_OK)
|
if (response->type_data.response.code != RTSP_STS_OK)
|
||||||
goto error_response;
|
goto error_response;
|
||||||
|
|
||||||
|
@ -559,6 +564,48 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
if ((res = rtsp_connection_open (url, &src->connection)) < 0)
|
if ((res = rtsp_connection_open (url, &src->connection)) < 0)
|
||||||
goto could_not_open;
|
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 */
|
/* create DESCRIBE */
|
||||||
GST_DEBUG ("create describe...");
|
GST_DEBUG ("create describe...");
|
||||||
if ((res =
|
if ((res =
|
||||||
|
@ -570,9 +617,22 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
|
|
||||||
/* send DESCRIBE */
|
/* send DESCRIBE */
|
||||||
GST_DEBUG ("send describe...");
|
GST_DEBUG ("send describe...");
|
||||||
if (!gst_rtspsrc_send (src, &request, &response))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
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 */
|
/* parse SDP */
|
||||||
rtsp_message_get_body (&response, &data, &size);
|
rtsp_message_get_body (&response, &data, &size);
|
||||||
|
|
||||||
|
@ -622,7 +682,6 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
}
|
}
|
||||||
g_free (setup_url);
|
g_free (setup_url);
|
||||||
|
|
||||||
|
|
||||||
transports = g_strdup ("");
|
transports = g_strdup ("");
|
||||||
if (protocols & GST_RTSP_PROTO_UDP_UNICAST) {
|
if (protocols & GST_RTSP_PROTO_UDP_UNICAST) {
|
||||||
gchar *new;
|
gchar *new;
|
||||||
|
@ -662,15 +721,17 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports);
|
rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports);
|
||||||
g_free (transports);
|
g_free (transports);
|
||||||
|
|
||||||
if (!gst_rtspsrc_send (src, &request, &response))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
/* parse response transport */
|
/* parse response transport */
|
||||||
{
|
{
|
||||||
gchar *resptrans;
|
gchar *resptrans = NULL;
|
||||||
RTSPTransport transport = { 0 };
|
RTSPTransport transport = { 0 };
|
||||||
|
|
||||||
rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans);
|
rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans);
|
||||||
|
if (!resptrans)
|
||||||
|
goto no_transport;
|
||||||
|
|
||||||
/* parse transport */
|
/* parse transport */
|
||||||
rtsp_transport_parse (resptrans, &transport);
|
rtsp_transport_parse (resptrans, &transport);
|
||||||
|
@ -723,14 +784,44 @@ send_error:
|
||||||
("Could not send message."), (NULL));
|
("Could not send message."), (NULL));
|
||||||
return FALSE;
|
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:
|
setup_rtp_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not setup rtp."), (NULL));
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not setup rtp."), (NULL));
|
||||||
return FALSE;
|
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)
|
gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
RTSPMessage request = { 0 };
|
RTSPMessage request = { 0 };
|
||||||
|
@ -746,14 +837,16 @@ gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
src->task = NULL;
|
src->task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src->options & RTSP_PLAY) {
|
||||||
/* do TEARDOWN */
|
/* do TEARDOWN */
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_TEARDOWN, src->location,
|
rtsp_message_init_request (RTSP_TEARDOWN, src->location,
|
||||||
&request)) < 0)
|
&request)) < 0)
|
||||||
goto create_request_failed;
|
goto create_request_failed;
|
||||||
|
|
||||||
if (!gst_rtspsrc_send (src, &request, &response))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
}
|
||||||
|
|
||||||
/* close connection */
|
/* close connection */
|
||||||
GST_DEBUG ("closing connection...");
|
GST_DEBUG ("closing connection...");
|
||||||
|
@ -788,6 +881,9 @@ gst_rtspsrc_play (GstRTSPSrc * src)
|
||||||
RTSPMessage response = { 0 };
|
RTSPMessage response = { 0 };
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
|
||||||
|
if (!(src->options & RTSP_PLAY))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG ("PLAY...");
|
GST_DEBUG ("PLAY...");
|
||||||
|
|
||||||
/* do play */
|
/* do play */
|
||||||
|
@ -795,7 +891,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
|
||||||
rtsp_message_init_request (RTSP_PLAY, src->location, &request)) < 0)
|
rtsp_message_init_request (RTSP_PLAY, src->location, &request)) < 0)
|
||||||
goto create_request_failed;
|
goto create_request_failed;
|
||||||
|
|
||||||
if (!gst_rtspsrc_send (src, &request, &response))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
if (src->interleaved) {
|
if (src->interleaved) {
|
||||||
|
@ -827,13 +923,16 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
|
||||||
RTSPMessage response = { 0 };
|
RTSPMessage response = { 0 };
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
|
||||||
|
if (!(src->options & RTSP_PAUSE))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG ("PAUSE...");
|
GST_DEBUG ("PAUSE...");
|
||||||
/* do pause */
|
/* do pause */
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_PAUSE, src->location, &request)) < 0)
|
rtsp_message_init_request (RTSP_PAUSE, src->location, &request)) < 0)
|
||||||
goto create_request_failed;
|
goto create_request_failed;
|
||||||
|
|
||||||
if (!gst_rtspsrc_send (src, &request, &response))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -868,6 +967,7 @@ gst_rtspsrc_change_state (GstElement * element)
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
rtspsrc->interleaved = FALSE;
|
rtspsrc->interleaved = FALSE;
|
||||||
|
rtspsrc->options = 0;
|
||||||
if (!gst_rtspsrc_open (rtspsrc))
|
if (!gst_rtspsrc_open (rtspsrc))
|
||||||
goto open_failed;
|
goto open_failed;
|
||||||
break;
|
break;
|
||||||
|
@ -891,6 +991,7 @@ gst_rtspsrc_change_state (GstElement * element)
|
||||||
gst_rtspsrc_pause (rtspsrc);
|
gst_rtspsrc_pause (rtspsrc);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
|
gst_rtspsrc_close (rtspsrc);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_NULL:
|
case GST_STATE_READY_TO_NULL:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -88,6 +88,8 @@ struct _GstRTSPSrc {
|
||||||
gboolean debug;
|
gboolean debug;
|
||||||
|
|
||||||
GstRTSPProto protocols;
|
GstRTSPProto protocols;
|
||||||
|
/* supported options */
|
||||||
|
gint options;
|
||||||
|
|
||||||
RTSPConnection *connection;
|
RTSPConnection *connection;
|
||||||
RTSPMessage *request;
|
RTSPMessage *request;
|
||||||
|
|
|
@ -136,7 +136,17 @@ rtsp_init_status (void)
|
||||||
const gchar *
|
const gchar *
|
||||||
rtsp_method_as_text (RTSPMethod method)
|
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 *
|
const gchar *
|
||||||
|
@ -176,8 +186,8 @@ rtsp_find_method (gchar * method)
|
||||||
gint idx;
|
gint idx;
|
||||||
|
|
||||||
for (idx = 0; rtsp_methods[idx]; idx++) {
|
for (idx = 0; rtsp_methods[idx]; idx++) {
|
||||||
if (g_ascii_strcasecmp (rtsp_headers[idx], method) == 0) {
|
if (g_ascii_strcasecmp (rtsp_methods[idx], method) == 0) {
|
||||||
return idx;
|
return (1 << idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -54,17 +54,17 @@ typedef enum {
|
||||||
} RTSPState;
|
} RTSPState;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RTSP_DESCRIBE,
|
RTSP_DESCRIBE = (1 << 0),
|
||||||
RTSP_ANNOUNCE,
|
RTSP_ANNOUNCE = (1 << 1),
|
||||||
RTSP_GET_PARAMETER,
|
RTSP_GET_PARAMETER = (1 << 2),
|
||||||
RTSP_OPTIONS,
|
RTSP_OPTIONS = (1 << 3),
|
||||||
RTSP_PAUSE,
|
RTSP_PAUSE = (1 << 4),
|
||||||
RTSP_PLAY,
|
RTSP_PLAY = (1 << 5),
|
||||||
RTSP_RECORD,
|
RTSP_RECORD = (1 << 6),
|
||||||
RTSP_REDIRECT,
|
RTSP_REDIRECT = (1 << 7),
|
||||||
RTSP_SETUP,
|
RTSP_SETUP = (1 << 8),
|
||||||
RTSP_SET_PARAMETER,
|
RTSP_SET_PARAMETER = (1 << 9),
|
||||||
RTSP_TEARDOWN,
|
RTSP_TEARDOWN = (1 << 10),
|
||||||
} RTSPMethod;
|
} RTSPMethod;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -95,6 +95,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport)
|
||||||
transport->lower_transport = RTSP_LOWER_TRANS_UDP;
|
transport->lower_transport = RTSP_LOWER_TRANS_UDP;
|
||||||
} else if (g_str_has_prefix (split[i], "RTP/AVP/TCP")) {
|
} else if (g_str_has_prefix (split[i], "RTP/AVP/TCP")) {
|
||||||
transport->lower_transport = RTSP_LOWER_TRANS_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")) {
|
} else if (g_str_has_prefix (split[i], "multicast")) {
|
||||||
transport->multicast = TRUE;
|
transport->multicast = TRUE;
|
||||||
} else if (g_str_has_prefix (split[i], "unicast")) {
|
} else if (g_str_has_prefix (split[i], "unicast")) {
|
||||||
|
|
Loading…
Reference in a new issue