#include "rtpdec.h"
#include "rdt.h"
+#include "rtp_asf.h"
//#define DEBUG
//#define DEBUG_RTP_TCP
if (payload_type >= RTP_PT_PRIVATE) {
RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
while(handler) {
- if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
+ if (!strcasecmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
codec->codec_id = handler->codec_id;
rtsp_st->dynamic_handler= handler;
if(handler->open) {
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;
st->codec->codec_type = codec_type;
if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
/* if standard payload type, we can find the codec right now */
- rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
+ ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
}
}
/* put a default control url */
} else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
if (atoi(p) == 1)
rt->transport = RTSP_TRANSPORT_RDT;
- } else if (s->nb_streams > 0) {
- if (rt->server_type == RTSP_SERVER_REAL)
- ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
-
- rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
- if (rtsp_st->dynamic_handler &&
- rtsp_st->dynamic_handler->parse_sdp_a_line)
- rtsp_st->dynamic_handler->parse_sdp_a_line(s, s->nb_streams - 1,
- rtsp_st->dynamic_protocol_context, buf);
+ } else {
+ if (rt->server_type == RTSP_SERVER_WMS)
+ ff_wms_parse_sdp_a_line(s, p);
+ if (s->nb_streams > 0) {
+ if (rt->server_type == RTSP_SERVER_REAL)
+ ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
+
+ rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
+ if (rtsp_st->dynamic_handler &&
+ rtsp_st->dynamic_handler->parse_sdp_a_line)
+ rtsp_st->dynamic_handler->parse_sdp_a_line(s, s->nb_streams - 1,
+ rtsp_st->dynamic_protocol_context, buf);
+ }
}
break;
}
}
/* XXX: only one transport specification is parsed */
-static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
+static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
{
char transport_protocol[16];
char profile[16];
}
}
-void rtsp_parse_line(RTSPHeader *reply, const char *buf)
+void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
{
const char *p;
}
}
-static void rtsp_send_cmd(AVFormatContext *s,
- const char *cmd, RTSPHeader *reply,
- unsigned char **content_ptr)
+static void
+rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
+ unsigned char **content_ptr)
{
RTSPState *rt = s->priv_data;
char buf[4096], buf1[1024], *q;
unsigned char ch;
const char *p;
- int content_length, line_count;
+ int content_length, line_count = 0;
unsigned char *content = NULL;
- memset(reply, 0, sizeof(RTSPHeader));
-
- rt->seq++;
- av_strlcpy(buf, cmd, sizeof(buf));
- snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
- av_strlcat(buf, buf1, sizeof(buf));
- if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
- snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
- av_strlcat(buf, buf1, sizeof(buf));
- }
- av_strlcat(buf, "\r\n", sizeof(buf));
-#ifdef DEBUG
- printf("Sending:\n%s--\n", buf);
-#endif
- url_write(rt->rtsp_hd, buf, strlen(buf));
+ memset(reply, 0, sizeof(*reply));
/* parse reply (XXX: use buffers) */
- line_count = 0;
rt->last_reply[0] = '\0';
for(;;) {
q = buf;
av_free(content);
}
+static void rtsp_send_cmd(AVFormatContext *s,
+ const char *cmd, RTSPMessageHeader *reply,
+ unsigned char **content_ptr)
+{
+ RTSPState *rt = s->priv_data;
+ char buf[4096], buf1[1024];
+
+ rt->seq++;
+ av_strlcpy(buf, cmd, sizeof(buf));
+ snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
+ av_strlcat(buf, buf1, sizeof(buf));
+ if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
+ snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
+ av_strlcat(buf, buf1, sizeof(buf));
+ }
+ av_strlcat(buf, "\r\n", sizeof(buf));
+#ifdef DEBUG
+ printf("Sending:\n%s--\n", buf);
+#endif
+ url_write(rt->rtsp_hd, buf, strlen(buf));
+
+ rtsp_read_reply(s, reply, content_ptr);
+}
+
/* close and free RTSP streams */
static void rtsp_close_streams(RTSPState *rt)
}
}
av_free(rt->rtsp_streams);
+ if (rt->asf_ctx) {
+ av_close_input_stream (rt->asf_ctx);
+ rt->asf_ctx = NULL;
+ }
}
static int
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;
+ RTSPMessageHeader reply1, *reply = &reply1;
char cmd[2048];
const char *trans_pref;
for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
char transport[2048];
- rtsp_st = rt->rtsp_streams[i];
+ /**
+ * 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) {
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) {
+ /** For WMS streams, the application streams are only used for
+ * UDP. When trying to set it up for TCP streams, the server
+ * will return an error. Therefore, we skip those streams. */
+ 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_WMS)
/* 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 (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
+ rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
err = AVERROR_INVALIDDATA;
goto fail;
}
char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
URLContext *rtsp_hd;
int port, ret, err;
- RTSPHeader reply1, *reply = &reply1;
+ RTSPMessageHeader reply1, *reply = &reply1;
unsigned char *content = NULL;
int lower_transport_mask = 0;
char real_challenge[64];
}
if (!lower_transport_mask)
- lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_LAST) - 1;
+ lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
/* open the tcp connexion */
snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
RTSPState *rt = s->priv_data;
RTSPStream *rtsp_st;
fd_set rfds;
- int fd1, fd2, fd_max, n, i, ret;
+ int fd, fd_max, n, i, ret;
struct timeval tv;
for(;;) {
fd_max = -1;
for(i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
- /* 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);
+ if (rtsp_st->rtp_handle) {
+ /* currently, we cannot probe RTCP handle because of
+ * blocking restrictions */
+ fd = url_get_file_handle(rtsp_st->rtp_handle);
+ if (fd > fd_max)
+ fd_max = fd;
+ FD_SET(fd, &rfds);
+ }
}
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
if (n > 0) {
for(i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
- 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);
- if (ret > 0) {
- *prtsp_st = rtsp_st;
- return ret;
+ if (rtsp_st->rtp_handle) {
+ fd = url_get_file_handle(rtsp_st->rtp_handle);
+ if (FD_ISSET(fd, &rfds)) {
+ ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
+ if (ret > 0) {
+ *prtsp_st = rtsp_st;
+ return ret;
+ }
}
}
}
if (rt->server_type == RTSP_SERVER_REAL) {
int i;
- RTSPHeader reply1, *reply = &reply1;
+ RTSPMessageHeader reply1, *reply = &reply1;
enum AVDiscard cache[MAX_STREAMS];
char cmd[1024];
static int rtsp_read_play(AVFormatContext *s)
{
RTSPState *rt = s->priv_data;
- RTSPHeader reply1, *reply = &reply1;
+ RTSPMessageHeader reply1, *reply = &reply1;
char cmd[1024];
av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
static int rtsp_read_pause(AVFormatContext *s)
{
RTSPState *rt = s->priv_data;
- RTSPHeader reply1, *reply = &reply1;
+ RTSPMessageHeader reply1, *reply = &reply1;
char cmd[1024];
rt = s->priv_data;
static int rtsp_read_close(AVFormatContext *s)
{
RTSPState *rt = s->priv_data;
- RTSPHeader reply1, *reply = &reply1;
+ RTSPMessageHeader reply1, *reply = &reply1;
char cmd[1024];
#if 0