]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtspdec.c
mp3: Properly use AVCodecContext API
[ffmpeg] / libavformat / rtspdec.c
index a3565557d47590cf95d4dc5cf3cd80183fd503ee..659c76842369bacb4e0e2964ea6d6aeefc60f6d5 100644 (file)
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/random_seed.h"
+#include "libavutil/time.h"
 #include "avformat.h"
 
 #include "internal.h"
 #include "network.h"
 #include "os_support.h"
+#include "rtpproto.h"
 #include "rtsp.h"
 #include "rdt.h"
 #include "url.h"
@@ -75,8 +77,8 @@ static inline int read_line(AVFormatContext *s, char *rbuf, const int rbufsize,
 
     do {
         ret = ffurl_read_complete(rt->rtsp_hd, rbuf + idx, 1);
-        if (ret < 0)
-            return ret;
+        if (ret <= 0)
+            return ret ? ret : AVERROR_EOF;
         if (rbuf[idx] == '\r') {
             /* Ignore */
         } else if (rbuf[idx] == '\n') {
@@ -112,7 +114,7 @@ static int rtsp_send_reply(AVFormatContext *s, enum RTSPStatusCode code,
         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));
+    ffurl_write(rt->rtsp_hd_out, message, strlen(message));
 
     return 0;
 }
@@ -358,6 +360,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);
@@ -406,7 +412,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;
     }
@@ -435,7 +441,7 @@ static inline int parse_command_line(AVFormatContext *s, const char *line,
         if (*methodcode == ANNOUNCE) {
             av_log(s, AV_LOG_INFO,
                    "Updating control URI to %s\n", uri);
-            strcpy(rt->control_uri, uri);
+            av_strlcpy(rt->control_uri, uri, sizeof(rt->control_uri));
         }
     }
 
@@ -498,6 +504,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++) {
@@ -603,10 +621,12 @@ 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;
@@ -614,14 +634,23 @@ static int rtsp_listen(AVFormatContext *s)
     enum RTSPMethod methodcode;
 
     /* 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 = 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,
@@ -663,7 +692,11 @@ static int rtsp_listen(AVFormatContext *s)
 
 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;
 }
@@ -763,7 +796,7 @@ static int resetup_tcp(AVFormatContext *s)
 
     av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
                  s->filename);
-    ff_rtsp_undo_setup(s);
+    ff_rtsp_undo_setup(s, 0);
     return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP,
                                       rt->real_challenge);
 }
@@ -864,14 +897,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
@@ -918,7 +951,7 @@ static const AVClass rtsp_demuxer_class = {
 
 AVInputFormat ff_rtsp_demuxer = {
     .name           = "rtsp",
-    .long_name      = NULL_IF_CONFIG_SMALL("RTSP input format"),
+    .long_name      = NULL_IF_CONFIG_SMALL("RTSP input"),
     .priv_data_size = sizeof(RTSPState),
     .read_probe     = rtsp_probe,
     .read_header    = rtsp_read_header,