summaryrefslogtreecommitdiff
path: root/libavformat/rtsp.c
diff options
context:
space:
mode:
authorRonald S. Bultje <rsbultje@gmail.com>2009-04-15 13:04:34 +0000
committerRonald S. Bultje <rsbultje@gmail.com>2009-04-15 13:04:34 +0000
commit30e79845b464bd93172bfe1a3ce5f6815178f18e (patch)
treeb52c4c142f10fa26495591deba48e4d4a7a2ae3b /libavformat/rtsp.c
parent888505df22aebba26db7cd3b65e4201d8097e582 (diff)
Send dummy requests over the TCP connection (WMS wants GET_PARAMETER,
Real wants OPTIONS) while the connection is idle, otherwise it will be aborted after a short period (usually a minute). See the thread "[PATCH] rtsp.c: keep-alive" on the mailinglist. Originally committed as revision 18525 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/rtsp.c')
-rw-r--r--libavformat/rtsp.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 362714b4a4..9a4b1e2c49 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -682,7 +682,12 @@ void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
/* NOTE: we do case independent match for broken servers */
p = buf;
if (av_stristart(p, "Session:", &p)) {
+ int t;
get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
+ if (av_stristart(p, ";timeout=", &p) &&
+ (t = strtol(p, NULL, 10)) > 0) {
+ reply->timeout = t;
+ }
} else if (av_stristart(p, "Content-Length:", &p)) {
reply->content_length = strtol(p, NULL, 10);
} else if (av_stristart(p, "Transport:", &p)) {
@@ -837,7 +842,7 @@ rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
return 0;
}
-static void rtsp_send_cmd(AVFormatContext *s,
+static void rtsp_send_cmd_async (AVFormatContext *s,
const char *cmd, RTSPMessageHeader *reply,
unsigned char **content_ptr)
{
@@ -857,6 +862,14 @@ static void rtsp_send_cmd(AVFormatContext *s,
printf("Sending:\n%s--\n", buf);
#endif
url_write(rt->rtsp_hd, buf, strlen(buf));
+ rt->last_cmd_time = av_gettime();
+}
+
+static void rtsp_send_cmd (AVFormatContext *s,
+ const char *cmd, RTSPMessageHeader *reply,
+ unsigned char **content_ptr)
+{
+ rtsp_send_cmd_async(s, cmd, reply, content_ptr);
rtsp_read_reply(s, reply, content_ptr, 0);
}
@@ -943,6 +956,9 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
else
trans_pref = "RTP/AVP";
+ /* default timeout: 1 minute */
+ rt->timeout = 60;
+
/* for each stream, make the setup request */
/* XXX: we assume the same server is used for the control of each
RTSP stream */
@@ -1123,6 +1139,9 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
goto fail;
}
+ if (reply->timeout > 0)
+ rt->timeout = reply->timeout;
+
if (rt->server_type == RTSP_SERVER_REAL)
rt->need_subscription = 1;
@@ -1403,12 +1422,12 @@ static int rtsp_read_packet(AVFormatContext *s,
RTSPStream *rtsp_st;
int ret, len;
uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
+ RTSPMessageHeader reply1, *reply = &reply1;
+ char cmd[1024];
if (rt->server_type == RTSP_SERVER_REAL) {
int i;
- RTSPMessageHeader reply1, *reply = &reply1;
enum AVDiscard cache[MAX_STREAMS];
- char cmd[1024];
for (i = 0; i < s->nb_streams; i++)
cache[i] = s->streams[i]->discard;
@@ -1508,6 +1527,22 @@ static int rtsp_read_packet(AVFormatContext *s,
/* more packets may follow, so we save the RTP context */
rt->cur_transport_priv = rtsp_st->transport_priv;
}
+
+ /* send dummy request to keep TCP connection alive */
+ if ((rt->server_type == RTSP_SERVER_WMS ||
+ rt->server_type == RTSP_SERVER_REAL) &&
+ (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
+ if (rt->server_type == RTSP_SERVER_WMS) {
+ snprintf(cmd, sizeof(cmd) - 1,
+ "GET_PARAMETER %s RTSP/1.0\r\n",
+ s->filename);
+ rtsp_send_cmd_async(s, cmd, reply, NULL);
+ } else {
+ rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n",
+ reply, NULL);
+ }
+ }
+
return 0;
}