[FFmpeg-devel] [PATCH] rtsp.c: keep-alive
Ronald S. Bultje
rsbultje
Sat Mar 7 02:25:25 CET 2009
Hi Luca,
On Fri, Mar 6, 2009 at 4:21 PM, Luca Barbato <lu_zero at gentoo.org> wrote:
> Ronald S. Bultje wrote:
>> On Fri, Mar 6, 2009 at 1:32 PM, Luca Barbato <lu_zero at gentoo.org> wrote:
>>> Shouldn't be enough sending rtcp RR as usual?
>>
>> RM doesn't use RTCP.
>
> Once you have it tested on wms and darwin (and feng if you like) you may
> commit it then.
MS doesn't like the OPTIONS and ignores it. MSDN [1] tells me to use
an empty GET_PARAMETER, and that indeed appears to work in my tests
(tried ~30min, worked fine). Attached patch works for WMS and Real
servers.
Feng / Darwin yet untested, any fancy test-sites you recommend for DSS?
Ronald
[1] http://msdn.microsoft.com/en-us/library/cc245366(PROT.10).aspx
-------------- next part --------------
Index: ffmpeg-svn/libavformat/rtsp.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rtsp.c 2009-03-06 18:41:02.000000000 -0500
+++ ffmpeg-svn/libavformat/rtsp.c 2009-03-06 20:21:05.000000000 -0500
@@ -686,7 +686,12 @@
/* 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)) {
@@ -855,7 +860,7 @@
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)
{
@@ -875,6 +880,14 @@
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);
}
@@ -957,6 +970,9 @@
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 */
@@ -1137,6 +1153,9 @@
goto fail;
}
+ if (reply->timeout > 0)
+ rt->timeout = reply->timeout;
+
if (rt->server_type == RTSP_SERVER_REAL)
rt->need_subscription = 1;
@@ -1419,12 +1438,12 @@
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;
@@ -1526,6 +1545,22 @@
/* 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;
}
Index: ffmpeg-svn/libavformat/rtsp.h
===================================================================
--- ffmpeg-svn.orig/libavformat/rtsp.h 2009-03-06 18:41:02.000000000 -0500
+++ ffmpeg-svn/libavformat/rtsp.h 2009-03-06 18:41:57.000000000 -0500
@@ -137,6 +137,14 @@
* http://tools.ietf.org/html/draft-stiemerling-rtsp-announce-00
* for a complete list of supported values. */
int notice;
+
+ /** The "timeout" comes as part of the server response to the "SETUP"
+ * command, in the "Session: <xyz>[;timeout=<value>]" line. It is the
+ * time, in seconds, that the server will go without traffic over the
+ * RTSP/TCP connection before it closes the connection. To prevent
+ * this, sent dummy requests (e.g. OPTIONS) with intervals smaller
+ * than this value. */
+ int timeout;
} RTSPMessageHeader;
/**
@@ -195,6 +203,16 @@
* identifier that the client should re-transmit in each RTSP command */
char session_id[512];
+ /** copy of RTSPMessageHeader->timeout, i.e. the time (in seconds) that
+ * the server will go without traffic on the RTSP/TCP line before it
+ * closes the connection. */
+ int timeout;
+
+ /** timestamp of the last RTSP command that we sent to the RTSP server.
+ * This is used to calculate when to send dummy commands to keep the
+ * connection alive, in conjunction with \p timeout. */
+ int64_t last_cmd_time;
+
/** the negotiated data/packet transport protocol; e.g. RTP or RDT */
enum RTSPTransport transport;
More information about the ffmpeg-devel
mailing list