[FFmpeg-devel] [PATCH 5/5] rtspdec: Retry with TCP if UDP failed

Martin Storsjö martin
Mon Jan 24 11:49:05 CET 2011


---
 libavformat/rtsp.c    |    1 +
 libavformat/rtsp.h    |   10 ++++++++++
 libavformat/rtspdec.c |   34 +++++++++++++++++++++++++++++++++-
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index dddaaf4..0364812 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1515,6 +1515,7 @@ redirect:
         }
     } while (err);
 
+    rt->lower_transport_mask = lower_transport_mask;
     rt->state = RTSP_STATE_IDLE;
     rt->seek_timestamp = 0; /* default is to start stream at position zero */
     return 0;
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 6dc64b1..9376fae 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -313,6 +313,16 @@ typedef struct RTSPState {
     /** Filter incoming UDP packets - receive packets only from the right
      * source address and port. */
     int filter_source;
+
+    /**
+     * A mask with all requested transport methods
+     */
+    int lower_transport_mask;
+
+    /**
+     * The number of returned packets
+     */
+    uint64_t packets;
 } RTSPState;
 
 /**
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index b910d4c..ca0b574 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -229,6 +229,20 @@ found:
     *prtsp_st = rtsp_st;
     return len;
 }
+
+static int resetup_tcp(AVFormatContext *s)
+{
+    char host[1024];
+    int port;
+
+    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
+                 s->filename);
+    ff_rtsp_undo_setup(s);
+    // TODO: Handle the real_challenge for Real-RTSP
+    return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP,
+                                      NULL);
+}
+
 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     RTSPState *rt = s->priv_data;
@@ -294,9 +308,27 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
 
+retry:
     ret = ff_rtsp_fetch_packet(s, pkt);
-    if (ret < 0)
+    if (ret < 0) {
+        if (ret == FF_NETERROR(ETIMEDOUT) && !rt->packets) {
+            if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
+                rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP) &&
+                rt->server_type != RTSP_SERVER_REAL) {
+                av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n");
+                if (rtsp_read_pause(s) != 0)
+                    return -1;
+                if (resetup_tcp(s) == 0) {
+                    rt->state = RTSP_STATE_IDLE;
+                    if (rtsp_read_play(s) != 0)
+                        return -1;
+                    goto retry;
+                }
+            }
+        }
         return ret;
+    }
+    rt->packets++;
 
     /* send dummy request to keep TCP connection alive */
     if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
-- 
1.7.3.1




More information about the ffmpeg-devel mailing list