[FFmpeg-devel] [PATCH] RTSP-MS 8/15: fix RTSP-MS UDP (was: disallow UDP/RTSP-MS)
Ronald S. Bultje
rsbultje
Sun Jan 25 20:14:10 CET 2009
Hi,
On Tue, Jan 6, 2009 at 12:07 AM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
> I haven't gotten UDP/RTSP-MS to work yet, so this patch explicitely
> disallows anything else than TCP/RTSP-MS.
Attached patch fixes this, I think. Negotiation succeeds, the data is
slightly different than for TCP but that will be handled in a
different patch.
The patch is dirty, in a way, because for UDP in RTSP-MS:
- the server expects the RTX stream to be SETUP'ed first, even if it's
not the first in the SDP. (For TCP, we ignore the RTX.)
- right now I create a RTSPStream+AVStream pair for the RTX stream. I
could in theory just create a AVStream-less RTSPStream since the
client doesn't need this, it's just for the session.
- we should use two ports for the RTX, and then the next (one) for all
data streams, so:
SETUP x.y.z/x.asf/rtx
Transport: client_port=[x]-[x+1]
OK
SETUP x.y.z/x.asf/stream=1
Transport: client_port=[x+2]
OK
SETUP x.y.z/x.asf/stream=2
Transport: client_port=[x+2]
OK
(etc. for stream=3-n)
This is what wireshark dumps of MS sessions give me and it works, so I
kept it simple for now. I tried different orders or port numbers but
it all fails at the second or third SETUP with either a 500 (Internal
Server Error) or a 461 (Unsupported Transport).
Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavformat/rtsp.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rtsp.c 2009-01-24 14:19:22.000000000 -0500
+++ ffmpeg-svn/libavformat/rtsp.c 2009-01-25 09:17:45.000000000 -0500
@@ -392,6 +392,8 @@
codec_type = CODEC_TYPE_AUDIO;
} else if (!strcmp(st_type, "video")) {
codec_type = CODEC_TYPE_VIDEO;
+ } else if (!strcmp(st_type, "application")) {
+ codec_type = CODEC_TYPE_DATA;
} else {
s1->skip_media = 1;
return;
@@ -886,7 +888,7 @@
int lower_transport, const char *real_challenge)
{
RTSPState *rt = s->priv_data;
- int j, i, err, interleave = 0;
+ int rtx, j, i, err, interleave = 0;
RTSPStream *rtsp_st;
RTSPHeader reply1, *reply = &reply1;
char cmd[2048];
@@ -904,12 +906,38 @@
for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
char transport[2048];
+ /**
+ * WMS serves all UDP data over a single connection, the RTX, which
+ * isn't necessarily the first in the SDP but has to be the first
+ * to be set up, else the second/third SETUP will fail with a 461.
+ */
+ if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
+ rt->server_type == RTSP_SERVER_WMS) {
+ if (i == 0) {
+ /* rtx first */
+ for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
+ int len = strlen(rt->rtsp_streams[rtx]->control_url);
+ if (len >= 4 &&
+ !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4, "/rtx"))
+ break;
+ }
+ if (rtx == rt->nb_rtsp_streams)
+ return -1; /* no RTX found */
+ rtsp_st = rt->rtsp_streams[rtx];
+ } else
+ rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
+ } else
rtsp_st = rt->rtsp_streams[i];
/* RTP/UDP */
if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
char buf[256];
+ if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
+ port = reply->transports[0].client_port_min;
+ goto have_port;
+ }
+
/* first try in specified port range */
if (RTSP_RTP_PORT_MIN != 0) {
while(j <= RTSP_RTP_PORT_MAX) {
@@ -930,18 +958,23 @@
rtp_opened:
port = rtp_get_local_port(rtsp_st->rtp_handle);
+ have_port:
snprintf(transport, sizeof(transport) - 1,
"%s/UDP;", trans_pref);
if (rt->server_type != RTSP_SERVER_REAL)
av_strlcat(transport, "unicast;", sizeof(transport));
av_strlcatf(transport, sizeof(transport),
"client_port=%d", port);
- if (rt->transport == RTSP_TRANSPORT_RTP)
+ if (rt->transport == RTSP_TRANSPORT_RTP &&
+ !(rt->server_type == RTSP_SERVER_WMS && i > 0))
av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
}
/* RTP/TCP */
else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
+ if (rt->server_type == RTSP_SERVER_WMS &&
+ s->streams[rtsp_st->stream_index]->codec->codec_type == CODEC_TYPE_DATA)
+ continue;
snprintf(transport, sizeof(transport) - 1,
"%s/TCP;", trans_pref);
if (rt->server_type != RTSP_SERVER_REAL)
@@ -1014,7 +1047,7 @@
/* XXX: also use address if specified */
snprintf(url, sizeof(url), "rtp://%s:%d",
host, reply->transports[0].server_port_min);
- if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
+ if (i < 2 && rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
err = AVERROR_INVALIDDATA;
goto fail;
}
@@ -1278,11 +1311,13 @@
fd_max = -1;
for(i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
+ if (rtsp_st->rtp_handle) {
/* currently, we cannot probe RTCP handle because of blocking restrictions */
rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
if (fd1 > fd_max)
fd_max = fd1;
FD_SET(fd1, &rfds);
+ }
}
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
@@ -1290,6 +1325,7 @@
if (n > 0) {
for(i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
+ if (rtsp_st->rtp_handle) {
rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
if (FD_ISSET(fd1, &rfds)) {
ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
@@ -1298,6 +1334,7 @@
return ret;
}
}
+ }
}
}
}
More information about the ffmpeg-devel
mailing list