]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
Make MMX registers parametrized in the YSCALEYUV2PACKEDX_YA macro
[ffmpeg] / libavformat / rtsp.c
index 1db4a7feb2f1fa483c8e4c24d67ed2b45f4e3e1c..6806736ed24c5b43d93415db352014c5bea0cc34 100644 (file)
@@ -34,7 +34,7 @@
 #include "network.h"
 #include "rtsp.h"
 
-#include "rtp.h"
+#include "rtpdec.h"
 #include "rdt.h"
 
 //#define DEBUG
@@ -124,7 +124,7 @@ static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payl
     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) {
@@ -376,11 +376,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
         }
         break;
     case 's':
-        av_strlcpy(s->title, p, sizeof(s->title));
+        av_metadata_set(&s->metadata, "title", p);
         break;
     case 'i':
         if (s->nb_streams == 0) {
-            av_strlcpy(s->comment, p, sizeof(s->comment));
+            av_metadata_set(&s->metadata, "comment", p);
             break;
         }
         break;
@@ -392,6 +392,8 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
             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;
@@ -425,7 +427,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
             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 */
@@ -570,7 +572,7 @@ static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
 }
 
 /* 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];
@@ -672,7 +674,7 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
     }
 }
 
-void rtsp_parse_line(RTSPHeader *reply, const char *buf)
+void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
 {
     const char *p;
 
@@ -737,35 +739,20 @@ static void rtsp_skip_packet(AVFormatContext *s)
     }
 }
 
-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;
@@ -819,6 +806,30 @@ static void rtsp_send_cmd(AVFormatContext *s,
         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)
@@ -829,11 +840,11 @@ static void rtsp_close_streams(RTSPState *rt)
     for(i=0;i<rt->nb_rtsp_streams;i++) {
         rtsp_st = rt->rtsp_streams[i];
         if (rtsp_st) {
-            if (rtsp_st->tx_ctx) {
+            if (rtsp_st->transport_priv) {
                 if (rt->transport == RTSP_TRANSPORT_RDT)
-                    ff_rdt_parse_close(rtsp_st->tx_ctx);
+                    ff_rdt_parse_close(rtsp_st->transport_priv);
                 else
-                    rtp_parse_close(rtsp_st->tx_ctx);
+                    rtp_parse_close(rtsp_st->transport_priv);
             }
             if (rtsp_st->rtp_handle)
                 url_close(rtsp_st->rtp_handle);
@@ -857,19 +868,19 @@ rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
         s->ctx_flags |= AVFMTCTX_NOHEADER;
 
     if (rt->transport == RTSP_TRANSPORT_RDT)
-        rtsp_st->tx_ctx = ff_rdt_parse_open(s, st->index,
+        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                             rtsp_st->dynamic_protocol_context,
                                             rtsp_st->dynamic_handler);
     else
-        rtsp_st->tx_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle,
+        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
                                          rtsp_st->sdp_payload_type,
                                          &rtsp_st->rtp_payload_data);
 
-    if (!rtsp_st->tx_ctx) {
+    if (!rtsp_st->transport_priv) {
          return AVERROR(ENOMEM);
     } else if (rt->transport != RTSP_TRANSPORT_RDT) {
         if(rtsp_st->dynamic_handler) {
-            rtp_parse_set_dynamic_protocol(rtsp_st->tx_ctx,
+            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
         }
@@ -886,9 +897,9 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
                     int lower_transport, const char *real_challenge)
 {
     RTSPState *rt = s->priv_data;
-    int j, i, err;
+    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;
 
@@ -904,12 +915,38 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
     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) {
@@ -930,27 +967,42 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
 
         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);
+                     "%s/TCP;", trans_pref);
+            if (rt->server_type == RTSP_SERVER_WMS)
+                av_strlcat(transport, "unicast;", sizeof(transport));
+            av_strlcatf(transport, sizeof(transport),
+                        "interleaved=%d-%d",
+                        interleave, interleave + 1);
+            interleave += 2;
         }
 
         else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
             snprintf(transport, sizeof(transport) - 1,
                      "%s/UDP;multicast", trans_pref);
         }
-        if (rt->server_type == RTSP_SERVER_REAL)
+        if (rt->server_type == RTSP_SERVER_REAL ||
+            rt->server_type == RTSP_SERVER_WMS)
             av_strlcat(transport, ";mode=play", sizeof(transport));
         snprintf(cmd, sizeof(cmd),
                  "SETUP %s RTSP/1.0\r\n"
@@ -1007,7 +1059,8 @@ make_setup_request (AVFormatContext *s, const char *host, int port,
                 /* 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;
                 }
@@ -1057,7 +1110,7 @@ static int rtsp_read_header(AVFormatContext *s,
     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];
@@ -1090,7 +1143,7 @@ static int rtsp_read_header(AVFormatContext *s,
     }
 
     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);
@@ -1261,7 +1314,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
     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(;;) {
@@ -1271,11 +1324,14 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
         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;
@@ -1283,12 +1339,14 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
         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;
+                        }
                     }
                 }
             }
@@ -1306,7 +1364,7 @@ static int rtsp_read_packet(AVFormatContext *s,
 
     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];
 
@@ -1367,18 +1425,18 @@ static int rtsp_read_packet(AVFormatContext *s,
     }
 
     /* get next frames from the same RTP packet */
-    if (rt->cur_tx) {
+    if (rt->cur_transport_priv) {
         if (rt->transport == RTSP_TRANSPORT_RDT)
-            ret = ff_rdt_parse_packet(rt->cur_tx, pkt, NULL, 0);
+            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
         else
-            ret = rtp_parse_packet(rt->cur_tx, pkt, NULL, 0);
+            ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
         if (ret == 0) {
-            rt->cur_tx = NULL;
+            rt->cur_transport_priv = NULL;
             return 0;
         } else if (ret == 1) {
             return 0;
         } else {
-            rt->cur_tx = NULL;
+            rt->cur_transport_priv = NULL;
         }
     }
 
@@ -1392,21 +1450,21 @@ static int rtsp_read_packet(AVFormatContext *s,
     case RTSP_LOWER_TRANSPORT_UDP:
     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
         len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
-        if (len >=0 && rtsp_st->tx_ctx && rt->transport == RTSP_TRANSPORT_RTP)
-            rtp_check_and_send_back_rr(rtsp_st->tx_ctx, len);
+        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
+            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
         break;
     }
     if (len < 0)
         return len;
     if (rt->transport == RTSP_TRANSPORT_RDT)
-        ret = ff_rdt_parse_packet(rtsp_st->tx_ctx, pkt, buf, len);
+        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
     else
-        ret = rtp_parse_packet(rtsp_st->tx_ctx, pkt, buf, len);
+        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
     if (ret < 0)
         goto redo;
     if (ret == 1) {
         /* more packets may follow, so we save the RTP context */
-        rt->cur_tx = rtsp_st->tx_ctx;
+        rt->cur_transport_priv = rtsp_st->transport_priv;
     }
     return 0;
 }
@@ -1414,7 +1472,7 @@ static int rtsp_read_packet(AVFormatContext *s,
 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);
@@ -1444,7 +1502,7 @@ static int rtsp_read_play(AVFormatContext *s)
 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;
@@ -1488,7 +1546,7 @@ static int rtsp_read_seek(AVFormatContext *s, int stream_index,
 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