Split the SETUP request into a separate function, as a prelude into allowing
authorRonald S. Bultje <rsbultje@gmail.com>
Mon, 17 Mar 2008 12:16:39 +0000 (12:16 +0000)
committerRonald S. Bultje <rsbultje@gmail.com>
Mon, 17 Mar 2008 12:16:39 +0000 (12:16 +0000)
multiple SETUPs to be send to cycle protocols rather than bailing if one
fails.

Discussed and approved in "[PATCH] RTSP alternate protocol 1/3".

Originally committed as revision 12476 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/rtsp.c

index 14f0a5c..e1ef8c2 100644 (file)
@@ -846,78 +846,18 @@ static void rtsp_close_streams(RTSPState *rt)
     av_free(rt->rtsp_streams);
 }
 
-static int rtsp_read_header(AVFormatContext *s,
-                            AVFormatParameters *ap)
+/**
+ * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
+ */
+static int
+make_setup_request (AVFormatContext *s, const char *host, int port, int protocol_mask)
 {
     RTSPState *rt = s->priv_data;
-    char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
-    URLContext *rtsp_hd;
-    int port, i, j, ret, err;
-    RTSPHeader reply1, *reply = &reply1;
-    unsigned char *content = NULL;
+    int j, i, err;
     RTSPStream *rtsp_st;
-    int protocol_mask = 0;
     AVStream *st;
-
-    /* extract hostname and port */
-    url_split(NULL, 0, NULL, 0,
-              host, sizeof(host), &port, path, sizeof(path), s->filename);
-    if (port < 0)
-        port = RTSP_DEFAULT_PORT;
-
-    /* search for options */
-    option_list = strchr(path, '?');
-    if (option_list) {
-        /* remove the options from the path */
-        *option_list++ = 0;
-        while(option_list) {
-            /* move the option pointer */
-            option = option_list;
-            option_list = strchr(option_list, '&');
-            if (option_list)
-                *(option_list++) = 0;
-            /* handle the options */
-            if (strcmp(option, "udp") == 0)
-                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP);
-            else if (strcmp(option, "multicast") == 0)
-                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST);
-            else if (strcmp(option, "tcp") == 0)
-                protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP);
-        }
-    }
-
-    if (!protocol_mask)
-        protocol_mask = rtsp_default_protocols;
-
-    /* open the tcp connexion */
-    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
-    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
-        return AVERROR(EIO);
-    rt->rtsp_hd = rtsp_hd;
-    rt->seq = 0;
-
-    /* describe the stream */
-    snprintf(cmd, sizeof(cmd),
-             "DESCRIBE %s RTSP/1.0\r\n"
-             "Accept: application/sdp\r\n",
-             s->filename);
-    rtsp_send_cmd(s, cmd, reply, &content);
-    if (!content) {
-        err = AVERROR_INVALIDDATA;
-        goto fail;
-    }
-    if (reply->status_code != RTSP_STATUS_OK) {
-        err = AVERROR_INVALIDDATA;
-        goto fail;
-    }
-
-    /* now we got the SDP description, we parse it */
-    ret = sdp_parse(s, (const char *)content);
-    av_freep(&content);
-    if (ret < 0) {
-        err = AVERROR_INVALIDDATA;
-        goto fail;
-    }
+    RTSPHeader reply1, *reply = &reply1;
+    char cmd[2048];
 
     /* for each stream, make the setup request */
     /* XXX: we assume the same server is used for the control of each
@@ -1060,6 +1000,87 @@ static int rtsp_read_header(AVFormatContext *s,
         }
     }
 
+    return 0;
+
+fail:
+    return err;
+}
+
+static int rtsp_read_header(AVFormatContext *s,
+                            AVFormatParameters *ap)
+{
+    RTSPState *rt = s->priv_data;
+    char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
+    URLContext *rtsp_hd;
+    int port, ret, err;
+    RTSPHeader reply1, *reply = &reply1;
+    unsigned char *content = NULL;
+    int protocol_mask = 0;
+
+    /* extract hostname and port */
+    url_split(NULL, 0, NULL, 0,
+              host, sizeof(host), &port, path, sizeof(path), s->filename);
+    if (port < 0)
+        port = RTSP_DEFAULT_PORT;
+
+    /* search for options */
+    option_list = strchr(path, '?');
+    if (option_list) {
+        /* remove the options from the path */
+        *option_list++ = 0;
+        while(option_list) {
+            /* move the option pointer */
+            option = option_list;
+            option_list = strchr(option_list, '&');
+            if (option_list)
+                *(option_list++) = 0;
+            /* handle the options */
+            if (strcmp(option, "udp") == 0)
+                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP);
+            else if (strcmp(option, "multicast") == 0)
+                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+            else if (strcmp(option, "tcp") == 0)
+                protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP);
+        }
+    }
+
+    if (!protocol_mask)
+        protocol_mask = rtsp_default_protocols;
+
+    /* open the tcp connexion */
+    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
+    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
+        return AVERROR(EIO);
+    rt->rtsp_hd = rtsp_hd;
+    rt->seq = 0;
+
+    /* describe the stream */
+    snprintf(cmd, sizeof(cmd),
+             "DESCRIBE %s RTSP/1.0\r\n"
+             "Accept: application/sdp\r\n",
+             s->filename);
+    rtsp_send_cmd(s, cmd, reply, &content);
+    if (!content) {
+        err = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+    if (reply->status_code != RTSP_STATUS_OK) {
+        err = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
+    /* now we got the SDP description, we parse it */
+    ret = sdp_parse(s, (const char *)content);
+    av_freep(&content);
+    if (ret < 0) {
+        err = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
+    err = make_setup_request(s, host, port, protocol_mask);
+    if (err)
+        goto fail;
+
     rt->state = RTSP_STATE_IDLE;
     rt->seek_timestamp = 0; /* default is to start stream at position
                                zero */