]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtspdec.c
configure: Drop weak dependencies on external libraries for webm muxer
[ffmpeg] / libavformat / rtspdec.c
index 160d49bb3d289c71d751bff669d141ca6e8f0b8f..8e8b3403e5a4637557af019ac52329eefa051746 100644 (file)
@@ -32,6 +32,7 @@
 #include "rtpproto.h"
 #include "rtsp.h"
 #include "rdt.h"
+#include "tls.h"
 #include "url.h"
 
 static const struct RTSPStatusMessage {
@@ -113,8 +114,8 @@ static int rtsp_send_reply(AVFormatContext *s, enum RTSPStatusCode code,
     if (extracontent)
         av_strlcat(message, extracontent, sizeof(message));
     av_strlcat(message, "\r\n", sizeof(message));
-    av_dlog(s, "Sending response:\n%s", message);
-    ffurl_write(rt->rtsp_hd, message, strlen(message));
+    av_log(s, AV_LOG_TRACE, "Sending response:\n%s", message);
+    ffurl_write(rt->rtsp_hd_out, message, strlen(message));
 
     return 0;
 }
@@ -149,8 +150,8 @@ static inline int rtsp_read_request(AVFormatContext *s,
         if (ret)
             return ret;
         if (rbuflen > 1) {
-            av_dlog(s, "Parsing[%d]: %s\n", rbuflen, rbuf);
-            ff_rtsp_parse_line(request, rbuf, rt, method);
+            av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf);
+            ff_rtsp_parse_line(s, request, rbuf, rt, method);
         }
     } while (rbuflen > 0);
     if (request->seq != rt->seq + 1) {
@@ -287,10 +288,15 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
                  request.transports[0].interleaved_max);
     } else {
         do {
+            AVDictionary *opts = NULL;
+            char buf[256];
+            snprintf(buf, sizeof(buf), "%d", rt->buffer_size);
+            av_dict_set(&opts, "buffer_size", buf, 0);
             ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL);
-            av_dlog(s, "Opening: %s", url);
+            av_log(s, AV_LOG_TRACE, "Opening: %s", url);
             ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                             &s->interrupt_callback, NULL);
+                             &s->interrupt_callback, &opts, rt->protocols, NULL);
+            av_dict_free(&opts);
             if (ret)
                 localport += 2;
         } while (ret || localport > rt->rtp_port_max);
@@ -299,7 +305,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
             return ret;
         }
 
-        av_dlog(s, "Listening on: %d",
+        av_log(s, AV_LOG_TRACE, "Listening on: %d",
                 ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle));
         if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) {
             rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq);
@@ -360,6 +366,10 @@ static inline int parse_command_line(AVFormatContext *s, const char *line,
     RTSPState *rt = s->priv_data;
     const char *linept, *searchlinept;
     linept = strchr(line, ' ');
+
+    if (!linept)
+        return AVERROR_INVALIDDATA;
+
     if (linept - line > methodsize - 1) {
         av_log(s, AV_LOG_ERROR, "Method string too long\n");
         return AVERROR(EIO);
@@ -408,7 +418,7 @@ static inline int parse_command_line(AVFormatContext *s, const char *line,
     }
 
     searchlinept = strchr(linept, ' ');
-    if (searchlinept == NULL) {
+    if (!searchlinept) {
         av_log(s, AV_LOG_ERROR, "Error parsing message URI\n");
         return AVERROR_INVALIDDATA;
     }
@@ -500,6 +510,18 @@ static int rtsp_read_play(AVFormatContext *s)
     av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
     rt->nb_byes = 0;
 
+    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
+        for (i = 0; i < rt->nb_rtsp_streams; i++) {
+            RTSPStream *rtsp_st = rt->rtsp_streams[i];
+            /* Try to initialize the connection state in a
+             * potential NAT router by sending dummy packets.
+             * RTP/RTCP dummy packets are used for RDT, too.
+             */
+            if (rtsp_st->rtp_handle &&
+                !(rt->server_type == RTSP_SERVER_WMS && i > 1))
+                ff_rtp_send_punch_packets(rtsp_st->rtp_handle);
+        }
+    }
     if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
         if (rt->transport == RTSP_TRANSPORT_RTP) {
             for (i = 0; i < rt->nb_rtsp_streams; i++) {
@@ -605,33 +627,47 @@ int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
 static int rtsp_listen(AVFormatContext *s)
 {
     RTSPState *rt = s->priv_data;
-    char host[128], path[512], auth[128];
+    char proto[128], host[128], path[512], auth[128];
     char uri[500];
     int port;
+    int default_port = RTSP_DEFAULT_PORT;
     char tcpname[500];
+    const char *lower_proto = "tcp";
     unsigned char rbuf[4096];
     unsigned char method[10];
     int rbuflen = 0;
     int ret;
     enum RTSPMethod methodcode;
 
+    if (!rt->protocols) {
+        rt->protocols = ffurl_get_protocols(s->protocol_whitelist,
+                                            s->protocol_blacklist);
+        if (!rt->protocols)
+            return AVERROR(ENOMEM);
+    }
+
     /* extract hostname and port */
-    av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port,
-                 path, sizeof(path), s->filename);
+    av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host),
+                 &port, path, sizeof(path), s->filename);
 
     /* ff_url_join. No authorization by now (NULL) */
-    ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL, host,
+    ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host,
                 port, "%s", path);
 
+    if (!strcmp(proto, "rtsps")) {
+        lower_proto  = "tls";
+        default_port = RTSPS_DEFAULT_PORT;
+    }
+
     if (port < 0)
-        port = RTSP_DEFAULT_PORT;
+        port = default_port;
 
     /* Create TCP connection */
-    ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port,
+    ff_url_join(tcpname, sizeof(tcpname), lower_proto, NULL, host, port,
                 "?listen&listen_timeout=%d", rt->initial_timeout * 1000);
 
     if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                         &s->interrupt_callback, NULL)) {
+                         &s->interrupt_callback, NULL, rt->protocols, NULL)) {
         av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
         return ret;
     }
@@ -664,12 +700,15 @@ static int rtsp_listen(AVFormatContext *s)
             return AVERROR_INVALIDDATA;
         }
     }
-    return 0;
 }
 
 static int rtsp_probe(AVProbeData *p)
 {
-    if (av_strstart(p->filename, "rtsp:", NULL))
+    if (
+#if CONFIG_TLS_PROTOCOL
+        av_strstart(p->filename, "rtsps:", NULL) ||
+#endif
+        av_strstart(p->filename, "rtsp:", NULL))
         return AVPROBE_SCORE_MAX;
     return 0;
 }
@@ -718,7 +757,7 @@ int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
     int id, len, i, ret;
     RTSPStream *rtsp_st;
 
-    av_dlog(s, "tcp_read_packet:\n");
+    av_log(s, AV_LOG_TRACE, "tcp_read_packet:\n");
 redo:
     for (;;) {
         RTSPMessageHeader reply;
@@ -737,7 +776,7 @@ redo:
         return -1;
     id  = buf[0];
     len = AV_RB16(buf + 1);
-    av_dlog(s, "id=%d len=%d\n", id, len);
+    av_log(s, AV_LOG_TRACE, "id=%d len=%d\n", id, len);
     if (len > buf_size || len < 12)
         goto redo;
     /* get the data */
@@ -870,14 +909,14 @@ retry:
 
     if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
         /* send dummy request to keep TCP connection alive */
-        if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
+        if ((av_gettime_relative() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
             rt->auth_state.stale) {
             if (rt->server_type == RTSP_SERVER_WMS ||
                 (rt->server_type != RTSP_SERVER_REAL &&
                  rt->get_parameter_supported)) {
                 ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
             } else {
-                ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
+                ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL);
             }
             /* The stale flag should be reset when creating the auth response in
              * ff_rtsp_send_cmd_async, but reset it here just in case we never