]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
rtsp: Make make_setup_request a nonstatic function
[ffmpeg] / libavformat / rtsp.c
index 431703e205a0ce5227ccb5448584a008eedf425e..feb61937fb8e0ddce2f63c5a5d98114c99a32417 100644 (file)
@@ -684,6 +684,61 @@ static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
     }
 }
 
+static void handle_rtp_info(RTSPState *rt, const char *url,
+                            uint32_t seq, uint32_t rtptime)
+{
+    int i;
+    if (!rtptime || !url[0])
+        return;
+    if (rt->transport != RTSP_TRANSPORT_RTP)
+        return;
+    for (i = 0; i < rt->nb_rtsp_streams; i++) {
+        RTSPStream *rtsp_st = rt->rtsp_streams[i];
+        RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
+        if (!rtpctx)
+            continue;
+        if (!strcmp(rtsp_st->control_url, url)) {
+            rtpctx->base_timestamp = rtptime;
+            break;
+        }
+    }
+}
+
+static void rtsp_parse_rtp_info(RTSPState *rt, const char *p)
+{
+    int read = 0;
+    char key[20], value[1024], url[1024] = "";
+    uint32_t seq = 0, rtptime = 0;
+
+    for (;;) {
+        p += strspn(p, SPACE_CHARS);
+        if (!*p)
+            break;
+        get_word_sep(key, sizeof(key), "=", &p);
+        if (*p != '=')
+            break;
+        p++;
+        get_word_sep(value, sizeof(value), ";, ", &p);
+        read++;
+        if (!strcmp(key, "url"))
+            av_strlcpy(url, value, sizeof(url));
+        else if (!strcmp(key, "seq"))
+            seq = strtol(value, NULL, 10);
+        else if (!strcmp(key, "rtptime"))
+            rtptime = strtol(value, NULL, 10);
+        if (*p == ',') {
+            handle_rtp_info(rt, url, seq, rtptime);
+            url[0] = '\0';
+            seq = rtptime = 0;
+            read = 0;
+        }
+        if (*p)
+            p++;
+    }
+    if (read > 0)
+        handle_rtp_info(rt, url, seq, rtptime);
+}
+
 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
                         RTSPState *rt, const char *method)
 {
@@ -728,6 +783,10 @@ void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
         p += strspn(p, SPACE_CHARS);
         if (method && !strcmp(method, "DESCRIBE"))
             av_strlcpy(rt->control_uri, p , sizeof(rt->control_uri));
+    } else if (av_stristart(p, "RTP-Info:", &p) && rt) {
+        p += strspn(p, SPACE_CHARS);
+        if (method && !strcmp(method, "PLAY"))
+            rtsp_parse_rtp_info(rt, p);
     }
 }
 
@@ -958,7 +1017,7 @@ retry:
 /**
  * @return 0 on success, <0 on error, 1 if protocol is unavailable.
  */
-static int make_setup_request(AVFormatContext *s, const char *host, int port,
+int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                               int lower_transport, const char *real_challenge)
 {
     RTSPState *rt = s->priv_data;
@@ -1034,6 +1093,10 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port,
                 err = AVERROR_INVALIDDATA;
                 goto fail;
             }
+#else
+            av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
+            err = AVERROR(EIO);
+            goto fail;
 #endif
 
         rtp_opened:
@@ -1127,16 +1190,18 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port,
             break;
 
         case RTSP_LOWER_TRANSPORT_UDP: {
-            char url[1024];
+            char url[1024], options[30] = "";
 
+            if (rt->filter_source)
+                av_strlcpy(options, "?connect=1", sizeof(options));
             /* Use source address if specified */
             if (reply->transports[0].source[0]) {
                 ff_url_join(url, sizeof(url), "rtp", NULL,
                             reply->transports[0].source,
-                            reply->transports[0].server_port_min, NULL);
+                            reply->transports[0].server_port_min, options);
             } else {
                 ff_url_join(url, sizeof(url), "rtp", NULL, host,
-                            reply->transports[0].server_port_min, NULL);
+                            reply->transports[0].server_port_min, options);
             }
             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
                 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
@@ -1256,6 +1321,8 @@ redirect:
             } else if(!strcmp(option, "http")) {
                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
                 rt->control_transport = RTSP_MODE_TUNNEL;
+            } else if (!strcmp(option, "filter_src")) {
+                rt->filter_source = 1;
             } else {
                 /* Write options back into the buffer, using memmove instead
                  * of strcpy since the strings may overlap. */
@@ -1426,7 +1493,7 @@ redirect:
         int lower_transport = ff_log2_tab[lower_transport_mask &
                                   ~(lower_transport_mask - 1)];
 
-        err = make_setup_request(s, host, port, lower_transport,
+        err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
                                  rt->server_type == RTSP_SERVER_REAL ?
                                      real_challenge : NULL);
         if (err < 0)