]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
tiertexseq: set audio stream start time to 0
[ffmpeg] / libavformat / rtsp.c
index c47cb0e4f106d0ba90515b7742c5c9570c85ac40..dd794070369fedc78b398051893301308622d5ac 100644 (file)
@@ -73,7 +73,7 @@
 
 const AVOption ff_rtsp_options[] = {
     { "initial_pause",  "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC },
-    FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
+    FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags)
     { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
     { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
     { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
@@ -900,9 +900,13 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
     char buf[4096], buf1[1024], *q;
     unsigned char ch;
     const char *p;
-    int ret, content_length, line_count = 0;
+    int ret, content_length, line_count = 0, request = 0;
     unsigned char *content = NULL;
 
+start:
+    line_count = 0;
+    request = 0;
+    content = NULL;
     memset(reply, 0, sizeof(*reply));
 
     /* parse reply (XXX: use buffers) */
@@ -938,9 +942,15 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
         if (line_count == 0) {
             /* get reply code */
             get_word(buf1, sizeof(buf1), &p);
-            get_word(buf1, sizeof(buf1), &p);
-            reply->status_code = atoi(buf1);
-            av_strlcpy(reply->reason, p, sizeof(reply->reason));
+            if (!strncmp(buf1, "RTSP/", 5)) {
+                get_word(buf1, sizeof(buf1), &p);
+                reply->status_code = atoi(buf1);
+                av_strlcpy(reply->reason, p, sizeof(reply->reason));
+            } else {
+                av_strlcpy(reply->reason, buf1, sizeof(reply->reason)); // method
+                get_word(buf1, sizeof(buf1), &p); // object
+                request = 1;
+            }
         } else {
             ff_rtsp_parse_line(reply, p, rt, method);
             av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
@@ -949,7 +959,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
         line_count++;
     }
 
-    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
+    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0' && !request)
         av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
 
     content_length = reply->content_length;
@@ -964,6 +974,44 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
     else
         av_free(content);
 
+    if (request) {
+        char buf[1024];
+        char base64buf[AV_BASE64_SIZE(sizeof(buf))];
+        const char* ptr = buf;
+
+        if (!strcmp(reply->reason, "OPTIONS")) {
+            snprintf(buf, sizeof(buf), "RTSP/1.0 200 OK\r\n");
+            if (reply->seq)
+                av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", reply->seq);
+            if (reply->session_id[0])
+                av_strlcatf(buf, sizeof(buf), "Session: %s\r\n",
+                                              reply->session_id);
+        } else {
+            snprintf(buf, sizeof(buf), "RTSP/1.0 501 Not Implemented\r\n");
+        }
+        av_strlcat(buf, "\r\n", sizeof(buf));
+
+        if (rt->control_transport == RTSP_MODE_TUNNEL) {
+            av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
+            ptr = base64buf;
+        }
+        ffurl_write(rt->rtsp_hd_out, ptr, strlen(ptr));
+
+        rt->last_cmd_time = av_gettime();
+        /* Even if the request from the server had data, it is not the data
+         * that the caller wants or expects. The memory could also be leaked
+         * if the actual following reply has content data. */
+        if (content_ptr)
+            av_freep(content_ptr);
+        /* If method is set, this is called from ff_rtsp_send_cmd,
+         * where a reply to exactly this request is awaited. For
+         * callers from within packet reciving, we just want to
+         * return to the caller and go back to receiving packets. */
+        if (method)
+            goto start;
+        return 0;
+    }
+
     if (rt->seq != reply->seq) {
         av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
             rt->seq, reply->seq);
@@ -1357,7 +1405,6 @@ int ff_rtsp_connect(AVFormatContext *s)
 {
     RTSPState *rt = s->priv_data;
     char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
-    char *option_list, *option, *filename;
     int port, err, tcp_fd;
     RTSPMessageHeader reply1 = {0}, *reply = &reply1;
     int lower_transport_mask = 0;
@@ -1928,6 +1975,9 @@ static int rtp_read_header(AVFormatContext *s)
             continue;
         }
 
+        if (RTP_PT_IS_RTCP(recvbuf[1]))
+            continue;
+
         payload_type = recvbuf[1] & 0x7f;
         break;
     }
@@ -1997,4 +2047,3 @@ AVInputFormat ff_rtp_demuxer = {
     .priv_class     = &rtp_demuxer_class
 };
 #endif /* CONFIG_RTP_DEMUXER */
-