Hi Tommy,

On Fri, 24 Feb 2012, Tommy Winther wrote:

The patch checks for the OPTIONS request from the server and sends a
RTSP/1.0 200 OK response, this fixes the keep-alive and the stream keeps
playing.

I've actually written a similar patch some ago already, but I never found the actual need for trying to get it included. Attached is a touched up version of it, incorporating some parts of your changes. Does this still fix your issue?

// Martin
From 33d74adf56799c0c9c46d413a33288bc5936faec Mon Sep 17 00:00:00 2001
From: Tommy Winther <[email protected]>
Date: Wed, 12 Oct 2011 12:26:45 +0300
Subject: [PATCH] rtsp: Handle requests from server to client

---
 libavformat/rtsp.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 4ecf90c..c61b73d 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -903,9 +903,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) */
@@ -941,9 +945,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));
@@ -952,7 +962,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;
@@ -967,6 +977,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);
-- 
1.7.3.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to