fixed RTP/TCP client support
authorFabrice Bellard <fabrice@bellard.org>
Tue, 15 Jul 2003 16:57:35 +0000 (16:57 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Tue, 15 Jul 2003 16:57:35 +0000 (16:57 +0000)
Originally committed as revision 2045 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/rtsp.c
libavformat/utils.c

index e6108cc..601f20d 100644 (file)
 #endif
 
 //#define DEBUG
+//#define DEBUG_RTP_TCP
 
 typedef struct RTSPState {
     URLContext *rtsp_hd; /* RTSP TCP connexion handle */
-    ByteIOContext rtsp_gb;
+    /* XXX: currently we use unbuffered input */
+    //    ByteIOContext rtsp_gb;
     int seq;        /* RTSP command sequence number */
     char session_id[512];
     enum RTSPProtocol protocol;
@@ -55,7 +57,12 @@ int rtsp_abort_req = 0;
 
 /* XXX: currently, the only way to change the protocols consists in
    changing this variable */
+#if 1
 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+#else
+/* try it if a proxy is used */
+int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
+#endif
 
 /* if non zero, then set a range for RTP ports */
 int rtsp_rtp_port_min = 0;
@@ -365,7 +372,7 @@ static int sdp_parse(AVFormatContext *s, const char *content)
         p++;
         /* get the content */
         q = buf;
-        while (*p != '\n' && *p != '\0') {
+        while (*p != '\n' && *p != '\r' && *p != '\0') {
             if ((q - buf) < sizeof(buf) - 1)
                 *q++ = *p;
             p++;
@@ -427,10 +434,11 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
         get_word_sep(profile, sizeof(profile), "/;,", &p);
         lower_transport[0] = '\0';
         if (*p == '/') {
+            p++;
             get_word_sep(lower_transport, sizeof(lower_transport), 
                          ";,", &p);
         }
-        if (!strcmp(lower_transport, "TCP"))
+        if (!strcasecmp(lower_transport, "TCP"))
             th->protocol = RTSP_PROTOCOL_RTP_TCP;
         else
             th->protocol = RTSP_PROTOCOL_RTP_UDP;
@@ -526,13 +534,13 @@ static void rtsp_send_cmd(AVFormatContext *s,
 
     rt->seq++;
     pstrcpy(buf, sizeof(buf), cmd);
-    snprintf(buf1, sizeof(buf1), "CSeq: %d\n", rt->seq);
+    snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
     pstrcat(buf, sizeof(buf), buf1);
     if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
-        snprintf(buf1, sizeof(buf1), "Session: %s\n", rt->session_id);
+        snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
         pstrcat(buf, sizeof(buf), buf1);
     }
-    pstrcat(buf, sizeof(buf), "\n");
+    pstrcat(buf, sizeof(buf), "\r\n");
 #ifdef DEBUG
     printf("Sending:\n%s--\n", buf);
 #endif
@@ -626,8 +634,8 @@ static int rtsp_read_header(AVFormatContext *s,
     
     /* describe the stream */
     snprintf(cmd, sizeof(cmd), 
-             "DESCRIBE %s RTSP/1.0\n"
-             "Accept: application/sdp\n",
+             "DESCRIBE %s RTSP/1.0\r\n"
+             "Accept: application/sdp\r\n",
              s->filename);
     rtsp_send_cmd(s, cmd, reply, &content);
     if (!content) {
@@ -708,10 +716,9 @@ static int rtsp_read_header(AVFormatContext *s,
                      sizeof(transport) - strlen(transport) - 1,
                      "RTP/AVP/UDP;multicast");
         }
-        
         snprintf(cmd, sizeof(cmd), 
-                 "SETUP %s RTSP/1.0\n"
-                 "Transport: %s\n",
+                 "SETUP %s RTSP/1.0\r\n"
+                 "Transport: %s\r\n",
                  rtsp_st->control_url, transport);
         rtsp_send_cmd(s, cmd, reply, NULL);
         if (reply->status_code != RTSP_STATUS_OK ||
@@ -794,7 +801,8 @@ static int rtsp_read_header(AVFormatContext *s,
                          
     /* start playing */
     snprintf(cmd, sizeof(cmd), 
-             "PLAY %s RTSP/1.0\n",
+             "PLAY %s RTSP/1.0\r\n"
+             "Range: npt=0-\r\n",
              s->filename);
     rtsp_send_cmd(s, cmd, reply, NULL);
     if (reply->status_code != RTSP_STATUS_OK) {
@@ -802,6 +810,7 @@ static int rtsp_read_header(AVFormatContext *s,
         goto fail;
     }
 
+#if 0
     /* open TCP with bufferized input */
     if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
         if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {
@@ -809,6 +818,7 @@ static int rtsp_read_header(AVFormatContext *s,
             goto fail;
         }
     }
+#endif
 
     return 0;
  fail:
@@ -830,33 +840,46 @@ static int tcp_read_packet(AVFormatContext *s,
                            AVPacket *pkt)
 {
     RTSPState *rt = s->priv_data;
-    ByteIOContext *rtsp_gb = &rt->rtsp_gb;
-    int c, id, len, i, ret;
+    int id, len, i, ret;
     AVStream *st;
     RTSPStream *rtsp_st;
-    char buf[RTP_MAX_PACKET_LENGTH];
+    uint8_t buf[RTP_MAX_PACKET_LENGTH];
 
+#ifdef DEBUG_RTP_TCP
+    printf("tcp_read_packet:\n");
+#endif
  redo:
     for(;;) {
-        c = url_fgetc(rtsp_gb);
-        if (c == URL_EOF)
+        ret = url_read(rt->rtsp_hd, buf, 1);
+#ifdef DEBUG_RTP_TCP
+        printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
+#endif
+        if (ret != 1)
             return AVERROR_IO;
-        if (c == '$')
+        if (buf[0] == '$')
             break;
     }
-    id = get_byte(rtsp_gb);
-    len = get_be16(rtsp_gb);
+    ret = url_read(rt->rtsp_hd, buf, 3);
+    if (ret != 3)
+        return AVERROR_IO;
+    id = buf[0];
+    len = (buf[1] << 8) | buf[2];
+#ifdef DEBUG_RTP_TCP
+    printf("id=%d len=%d\n", id, len);
+#endif
     if (len > RTP_MAX_PACKET_LENGTH || len < 12)
         goto redo;
     /* get the data */
-    get_buffer(rtsp_gb, buf, len);
-    
+    ret = url_read(rt->rtsp_hd, buf, len);
+    if (ret != len)
+        return AVERROR_IO;
+        
     /* find the matching stream */
     for(i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
         rtsp_st = st->priv_data;
-        if (i >= rtsp_st->interleaved_min && 
-            i <= rtsp_st->interleaved_max) 
+        if (id >= rtsp_st->interleaved_min && 
+            id <= rtsp_st->interleaved_max) 
             goto found;
     }
     goto redo;
@@ -945,13 +968,14 @@ static int rtsp_read_close(AVFormatContext *s)
     int i;
     char cmd[1024];
 
+#if 0
     /* NOTE: it is valid to flush the buffer here */
     if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
         url_fclose(&rt->rtsp_gb);
     }
-
+#endif
     snprintf(cmd, sizeof(cmd), 
-             "TEARDOWN %s RTSP/1.0\n",
+             "TEARDOWN %s RTSP/1.0\r\n",
              s->filename);
     rtsp_send_cmd(s, cmd, reply, NULL);
 
index 3c54ea4..90088e1 100644 (file)
@@ -312,7 +312,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
                        AVFormatParameters *ap)
 {
     AVFormatContext *ic = NULL;
-    int err;
+    int err, must_open_file;
     char buf[PROBE_BUF_SIZE];
     AVProbeData probe_data, *pd = &probe_data;
 
@@ -331,7 +331,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
         fmt = av_probe_input_format(pd, 0);
     }
 
-    if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
+    /* do not open file if the format does not need it. XXX: specific
+       hack needed to handle RTSP/TCP */
+    must_open_file = 1;
+    if ((fmt->flags & AVFMT_NOFILE) ||
+        (fmt == &rtp_demux && !strcmp(filename, "null"))) {
+        must_open_file = 0;
+    }
+
+    if (!fmt || must_open_file) {
         /* if no file needed do not try to open one */
         if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) {
             err = AVERROR_IO;
@@ -397,7 +405,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
     *ic_ptr = ic;
     return 0;
  fail1:
-    if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
+    if (!fmt || must_open_file) {
         url_fclose(&ic->pb);
     }
  fail:
@@ -664,7 +672,7 @@ int av_find_stream_info(AVFormatContext *ic)
  */
 void av_close_input_file(AVFormatContext *s)
 {
-    int i;
+    int i, must_open_file;
 
     if (s->iformat->read_close)
         s->iformat->read_close(s);
@@ -682,7 +690,12 @@ void av_close_input_file(AVFormatContext *s)
         }
         s->packet_buffer = NULL;
     }
-    if (!(s->iformat->flags & AVFMT_NOFILE)) {
+    must_open_file = 1;
+    if ((s->iformat->flags & AVFMT_NOFILE) ||
+        (s->iformat == &rtp_demux && !strcmp(s->filename, "null"))) {
+        must_open_file = 0;
+    }
+    if (must_open_file) {
         url_fclose(&s->pb);
     }
     av_freep(&s->priv_data);