]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
Fix book_idx check.
[ffmpeg] / libavformat / rtsp.c
index 1e9f2877dff6d604da44098961cc2666261533f9..ddf51ed746c915b9f5d8134bcc5631b4366d412a 100644 (file)
@@ -22,6 +22,7 @@
 /* needed by inet_aton() */
 #define _SVID_SOURCE
 
+#include "libavutil/base64.h"
 #include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
 #include "avformat.h"
@@ -700,6 +701,9 @@ void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
     } else if (av_stristart(p, "Server:", &p)) {
         skip_spaces(&p);
         av_strlcpy(reply->server, p, sizeof(reply->server));
+    } else if (av_stristart(p, "Notice:", &p) ||
+               av_stristart(p, "X-Notice:", &p)) {
+        reply->notice = strtol(p, NULL, 10);
     }
 }
 
@@ -823,6 +827,17 @@ rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
     else
         av_free(content);
 
+    /* EOS */
+    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
+        reply->notice == 2104 /* Start-of-Stream Reached */    ||
+        reply->notice == 2306 /* Continuous Feed Terminated */)
+        rt->state = RTSP_STATE_IDLE;
+    else if (reply->notice >= 4400 && reply->notice < 5500)
+        return AVERROR(EIO); /* data or server error */
+    else if (reply->notice == 2401 /* Ticket Expired */ ||
+             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
+        return AVERROR(EPERM);
+
     return 0;
 }
 
@@ -841,6 +856,10 @@ static void rtsp_send_cmd_async (AVFormatContext *s,
         snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
         av_strlcat(buf, buf1, sizeof(buf));
     }
+    if (rt->auth_b64)
+        av_strlcatf(buf, sizeof(buf),
+                    "Authorization: Basic %s\r\n",
+                    rt->auth_b64);
     av_strlcat(buf, "\r\n", sizeof(buf));
 
     dprintf(s, "Sending:\n%s--\n", buf);
@@ -885,6 +904,7 @@ static void rtsp_close_streams(RTSPState *rt)
         av_close_input_stream (rt->asf_ctx);
         rt->asf_ctx = NULL;
     }
+    av_freep(&rt->auth_b64);
 }
 
 static int
@@ -1145,7 +1165,7 @@ 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;
+    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128], *option_list, *option;
     URLContext *rtsp_hd;
     int port, ret, err;
     RTSPMessageHeader reply1, *reply = &reply1;
@@ -1154,8 +1174,18 @@ static int rtsp_read_header(AVFormatContext *s,
     char real_challenge[64];
 
     /* extract hostname and port */
-    url_split(NULL, 0, NULL, 0,
+    url_split(NULL, 0, auth, sizeof(auth),
               host, sizeof(host), &port, path, sizeof(path), s->filename);
+    if (*auth) {
+        int auth_len = strlen(auth), b64_len = ((auth_len + 2) / 3) * 4 + 1;
+
+        if (!(rt->auth_b64 = av_malloc(b64_len)))
+            return AVERROR(ENOMEM);
+        if (!av_base64_encode(rt->auth_b64, b64_len, auth, auth_len)) {
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+    }
     if (port < 0)
         port = RTSP_DEFAULT_PORT;
 
@@ -1185,8 +1215,10 @@ static int rtsp_read_header(AVFormatContext *s,
 
     /* 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);
+    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
+        err = AVERROR(EIO);
+        goto fail;
+    }
     rt->rtsp_hd = rtsp_hd;
     rt->seq = 0;
 
@@ -1291,6 +1323,7 @@ static int rtsp_read_header(AVFormatContext *s,
     rtsp_close_streams(rt);
     av_freep(&content);
     url_close(rt->rtsp_hd);
+    av_freep(&rt->auth_b64);
     return err;
 }
 
@@ -1314,6 +1347,8 @@ static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
         if (ret == 1) /* received '$' */
             break;
         /* XXX: parse message */
+        if (rt->state != RTSP_STATE_PLAYING)
+            return 0;
     }
     ret = url_read_complete(rt->rtsp_hd, buf, 3);
     if (ret != 3)
@@ -1399,6 +1434,8 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
 
                 rtsp_read_reply(s, &reply, NULL, 0);
                 /* XXX: parse message */
+                if (rt->state != RTSP_STATE_PLAYING)
+                    return 0;
             }
         }
     }
@@ -1506,6 +1543,8 @@ static int rtsp_read_packet(AVFormatContext *s,
     }
     if (len < 0)
         return len;
+    if (len == 0)
+        return AVERROR_EOF;
     if (rt->transport == RTSP_TRANSPORT_RDT)
         ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
     else
@@ -1599,6 +1638,9 @@ static int rtsp_read_seek(AVFormatContext *s, int stream_index,
     case RTSP_STATE_IDLE:
         break;
     case RTSP_STATE_PLAYING:
+        if (rtsp_read_pause(s) != 0)
+            return -1;
+        rt->state = RTSP_STATE_SEEKING;
         if (rtsp_read_play(s) != 0)
             return -1;
         break;