fixed RTP/TCP client support
[ffmpeg.git] / libavformat / rtsp.c
1 /*
2  * RTSP/SDP client
3  * Copyright (c) 2002 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 #include "avformat.h"
20
21 #include <sys/time.h>
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <ctype.h>
25 #ifndef __BEOS__
26 # include <arpa/inet.h>
27 #else
28 # include "barpainet.h"
29 #endif
30
31 //#define DEBUG
32 //#define DEBUG_RTP_TCP
33
34 typedef struct RTSPState {
35     URLContext *rtsp_hd; /* RTSP TCP connexion handle */
36     /* XXX: currently we use unbuffered input */
37     //    ByteIOContext rtsp_gb;
38     int seq;        /* RTSP command sequence number */
39     char session_id[512];
40     enum RTSPProtocol protocol;
41     char last_reply[2048]; /* XXX: allocate ? */
42 } RTSPState;
43
44 typedef struct RTSPStream {
45     AVFormatContext *ic;
46     int interleaved_min, interleaved_max;  /* interleave ids, if TCP transport */
47     char control_url[1024]; /* url for this stream (from SDP) */
48
49     int sdp_port; /* port (from SDP content - not used in RTSP) */
50     struct in_addr sdp_ip; /* IP address  (from SDP content - not used in RTSP) */
51     int sdp_ttl;  /* IP TTL (from SDP content - not used in RTSP) */
52     int sdp_payload_type; /* payload type - only used in SDP */
53 } RTSPStream;
54
55 /* suppress this hack */
56 int rtsp_abort_req = 0;
57
58 /* XXX: currently, the only way to change the protocols consists in
59    changing this variable */
60 #if 1
61 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST);
62 #else
63 /* try it if a proxy is used */
64 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
65 #endif
66
67 /* if non zero, then set a range for RTP ports */
68 int rtsp_rtp_port_min = 0;
69 int rtsp_rtp_port_max = 0;
70
71 FFRTSPCallback *ff_rtsp_callback = NULL;
72
73 static int rtsp_probe(AVProbeData *p)
74 {
75     if (strstart(p->filename, "rtsp:", NULL))
76         return AVPROBE_SCORE_MAX;
77     return 0;
78 }
79
80 static int redir_isspace(int c)
81 {
82     return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
83 }
84
85 static void skip_spaces(const char **pp)
86 {
87     const char *p;
88     p = *pp;
89     while (redir_isspace(*p))
90         p++;
91     *pp = p;
92 }
93
94 static void get_word_sep(char *buf, int buf_size, const char *sep, 
95                          const char **pp)
96 {
97     const char *p;
98     char *q;
99
100     p = *pp;
101     skip_spaces(&p);
102     q = buf;
103     while (!strchr(sep, *p) && *p != '\0') {
104         if ((q - buf) < buf_size - 1)
105             *q++ = *p;
106         p++;
107     }
108     if (buf_size > 0)
109         *q = '\0';
110     *pp = p;
111 }
112
113 static void get_word(char *buf, int buf_size, const char **pp)
114 {
115     const char *p;
116     char *q;
117
118     p = *pp;
119     skip_spaces(&p);
120     q = buf;
121     while (!redir_isspace(*p) && *p != '\0') {
122         if ((q - buf) < buf_size - 1)
123             *q++ = *p;
124         p++;
125     }
126     if (buf_size > 0)
127         *q = '\0';
128     *pp = p;
129 }
130
131 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
132    params>] */
133 static int sdp_parse_rtpmap(AVCodecContext *codec, const char *p)
134 {
135     char buf[256];
136
137     /* codec name */
138     get_word_sep(buf, sizeof(buf), "/", &p);
139     if (!strcmp(buf, "MP4V-ES")) {
140         codec->codec_id = CODEC_ID_MPEG4;
141         return 0;
142     } else {
143         return -1;
144     }
145 }
146
147 /* return the length and optionnaly the data */
148 static int hex_to_data(uint8_t *data, const char *p)
149 {
150     int c, len, v;
151
152     len = 0;
153     v = 1;
154     for(;;) {
155         skip_spaces(&p);
156         if (p == '\0')
157             break;
158         c = toupper((unsigned char)*p++);
159         if (c >= '0' && c <= '9')
160             c = c - '0';
161         else if (c >= 'A' && c <= 'F')
162             c = c - 'A' + 10;
163         else
164             break;
165         v = (v << 4) | c;
166         if (v & 0x100) {
167             if (data)
168                 data[len] = v;
169             len++;
170             v = 1;
171         }
172     }
173     return len;
174 }
175
176 static void sdp_parse_fmtp(AVCodecContext *codec, const char *p)
177 {
178     char attr[256];
179     char value[4096];
180     int len;
181
182     /* loop on each attribute */
183     for(;;) {
184         skip_spaces(&p);
185         if (*p == '\0')
186             break;
187         get_word_sep(attr, sizeof(attr), "=", &p);
188         if (*p == '=') 
189             p++;
190         get_word_sep(value, sizeof(value), ";", &p);
191         if (*p == ';')
192             p++;
193         /* handle MPEG4 video */
194         switch(codec->codec_id) {
195         case CODEC_ID_MPEG4:
196             if (!strcmp(attr, "config")) {
197                 /* decode the hexa encoded parameter */
198                 len = hex_to_data(NULL, value);
199                 codec->extradata = av_mallocz(len);
200                 if (!codec->extradata)
201                     goto fail;
202                 codec->extradata_size = len;
203                 hex_to_data(codec->extradata, value);
204             }
205             break;
206         default:
207             /* ignore data for other codecs */
208             break;
209         }
210     fail: ;
211         //        printf("'%s' = '%s'\n", attr, value);
212     }
213 }
214
215 typedef struct SDPParseState {
216     /* SDP only */
217     struct in_addr default_ip;
218     int default_ttl;
219 } SDPParseState;
220
221 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
222                            int letter, const char *buf)
223 {
224     char buf1[64], st_type[64];
225     const char *p;
226     int codec_type, payload_type, i;
227     AVStream *st;
228     RTSPStream *rtsp_st;
229     struct in_addr sdp_ip;
230     int ttl;
231
232 #ifdef DEBUG
233     printf("sdp: %c='%s'\n", letter, buf);
234 #endif
235
236     p = buf;
237     switch(letter) {
238     case 'c':
239         get_word(buf1, sizeof(buf1), &p);
240         if (strcmp(buf1, "IN") != 0)
241             return;
242         get_word(buf1, sizeof(buf1), &p);
243         if (strcmp(buf1, "IP4") != 0)
244             return;
245         get_word_sep(buf1, sizeof(buf1), "/", &p);
246         if (inet_aton(buf1, &sdp_ip) == 0)
247             return;
248         ttl = 16;
249         if (*p == '/') {
250             p++;
251             get_word_sep(buf1, sizeof(buf1), "/", &p);
252             ttl = atoi(buf1);
253         }
254         if (s->nb_streams == 0) {
255             s1->default_ip = sdp_ip;
256             s1->default_ttl = ttl;
257         } else {
258             st = s->streams[s->nb_streams - 1];
259             rtsp_st = st->priv_data;
260             rtsp_st->sdp_ip = sdp_ip;
261             rtsp_st->sdp_ttl = ttl;
262         }
263         break;
264     case 's':
265         pstrcpy(s->title, sizeof(s->title), p);
266         break;
267     case 'i':
268         if (s->nb_streams == 0) {
269             pstrcpy(s->comment, sizeof(s->comment), p);
270             break;
271         }
272         break;
273     case 'm':
274         /* new stream */
275         get_word(st_type, sizeof(st_type), &p);
276         if (!strcmp(st_type, "audio")) {
277             codec_type = CODEC_TYPE_AUDIO;
278         } else if (!strcmp(st_type, "video")) {
279             codec_type = CODEC_TYPE_VIDEO;
280         } else {
281             return;
282         }
283         rtsp_st = av_mallocz(sizeof(RTSPStream));
284         if (!rtsp_st)
285             return;
286         st = av_new_stream(s, s->nb_streams);
287         if (!st) 
288             return;
289         st->priv_data = rtsp_st;
290
291         rtsp_st->sdp_ip = s1->default_ip;
292         rtsp_st->sdp_ttl = s1->default_ttl;
293
294         st->codec.codec_type = codec_type;
295
296         get_word(buf1, sizeof(buf1), &p); /* port */
297         rtsp_st->sdp_port = atoi(buf1);
298
299         get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
300         
301         /* XXX: handle list of formats */
302         get_word(buf1, sizeof(buf1), &p); /* format list */
303         rtsp_st->sdp_payload_type = atoi(buf1);
304         if (rtsp_st->sdp_payload_type < 96) {
305             /* if standard payload type, we can find the codec right now */
306             rtp_get_codec_info(&st->codec, rtsp_st->sdp_payload_type);
307         }
308
309         /* put a default control url */
310         pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename);
311         break;
312     case 'a':
313         if (strstart(p, "control:", &p) && s->nb_streams > 0) {
314             char proto[32];
315             /* get the control url */
316             st = s->streams[s->nb_streams - 1];
317             rtsp_st = st->priv_data;
318             
319             /* XXX: may need to add full url resolution */
320             url_split(proto, sizeof(proto), NULL, 0, NULL, NULL, 0, p);
321             if (proto[0] == '\0') {
322                 /* relative control URL */
323                 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
324                 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
325             } else {
326                 pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
327             }
328         } else if (strstart(p, "rtpmap:", &p)) {
329             /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
330             get_word(buf1, sizeof(buf1), &p); 
331             payload_type = atoi(buf1);
332             for(i = 0; i < s->nb_streams;i++) {
333                 st = s->streams[i];
334                 rtsp_st = st->priv_data;
335                 if (rtsp_st->sdp_payload_type == payload_type) {
336                     sdp_parse_rtpmap(&st->codec, p);
337                 }
338             }
339         } else if (strstart(p, "fmtp:", &p)) {
340             /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
341             get_word(buf1, sizeof(buf1), &p); 
342             payload_type = atoi(buf1);
343             for(i = 0; i < s->nb_streams;i++) {
344                 st = s->streams[i];
345                 rtsp_st = st->priv_data;
346                 if (rtsp_st->sdp_payload_type == payload_type) {
347                     sdp_parse_fmtp(&st->codec, p);
348                 }
349             }
350         }
351         break;
352     }
353 }
354
355 static int sdp_parse(AVFormatContext *s, const char *content)
356 {
357     const char *p;
358     int letter;
359     char buf[1024], *q;
360     SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
361     
362     memset(s1, 0, sizeof(SDPParseState));
363     p = content;
364     for(;;) {
365         skip_spaces(&p);
366         letter = *p;
367         if (letter == '\0')
368             break;
369         p++;
370         if (*p != '=')
371             goto next_line;
372         p++;
373         /* get the content */
374         q = buf;
375         while (*p != '\n' && *p != '\r' && *p != '\0') {
376             if ((q - buf) < sizeof(buf) - 1)
377                 *q++ = *p;
378             p++;
379         }
380         *q = '\0';
381         sdp_parse_line(s, s1, letter, buf);
382     next_line:
383         while (*p != '\n' && *p != '\0')
384             p++;
385         if (*p == '\n')
386             p++;
387     }
388     return 0;
389 }
390
391 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
392 {
393     const char *p;
394     int v;
395
396     p = *pp;
397     skip_spaces(&p);
398     v = strtol(p, (char **)&p, 10);
399     if (*p == '-') {
400         p++;
401         *min_ptr = v;
402         v = strtol(p, (char **)&p, 10);
403         *max_ptr = v;
404     } else {
405         *min_ptr = v;
406         *max_ptr = v;
407     }
408     *pp = p;
409 }
410
411 /* XXX: only one transport specification is parsed */
412 static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
413 {
414     char transport_protocol[16];
415     char profile[16];
416     char lower_transport[16];
417     char parameter[16];
418     RTSPTransportField *th;
419     char buf[256];
420     
421     reply->nb_transports = 0;
422     
423     for(;;) {
424         skip_spaces(&p);
425         if (*p == '\0')
426             break;
427
428         th = &reply->transports[reply->nb_transports];
429
430         get_word_sep(transport_protocol, sizeof(transport_protocol), 
431                      "/", &p);
432         if (*p == '/')
433             p++;
434         get_word_sep(profile, sizeof(profile), "/;,", &p);
435         lower_transport[0] = '\0';
436         if (*p == '/') {
437             p++;
438             get_word_sep(lower_transport, sizeof(lower_transport), 
439                          ";,", &p);
440         }
441         if (!strcasecmp(lower_transport, "TCP"))
442             th->protocol = RTSP_PROTOCOL_RTP_TCP;
443         else
444             th->protocol = RTSP_PROTOCOL_RTP_UDP;
445         
446         if (*p == ';')
447             p++;
448         /* get each parameter */
449         while (*p != '\0' && *p != ',') {
450             get_word_sep(parameter, sizeof(parameter), "=;,", &p);
451             if (!strcmp(parameter, "port")) {
452                 if (*p == '=') {
453                     p++;
454                     rtsp_parse_range(&th->port_min, &th->port_max, &p);
455                 }
456             } else if (!strcmp(parameter, "client_port")) {
457                 if (*p == '=') {
458                     p++;
459                     rtsp_parse_range(&th->client_port_min, 
460                                      &th->client_port_max, &p);
461                 }
462             } else if (!strcmp(parameter, "server_port")) {
463                 if (*p == '=') {
464                     p++;
465                     rtsp_parse_range(&th->server_port_min, 
466                                      &th->server_port_max, &p);
467                 }
468             } else if (!strcmp(parameter, "interleaved")) {
469                 if (*p == '=') {
470                     p++;
471                     rtsp_parse_range(&th->interleaved_min, 
472                                      &th->interleaved_max, &p);
473                 }
474             } else if (!strcmp(parameter, "multicast")) {
475                 if (th->protocol == RTSP_PROTOCOL_RTP_UDP)
476                     th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST;
477             } else if (!strcmp(parameter, "ttl")) {
478                 if (*p == '=') {
479                     p++;
480                     th->ttl = strtol(p, (char **)&p, 10);
481                 }
482             } else if (!strcmp(parameter, "destination")) {
483                 struct in_addr ipaddr;
484
485                 if (*p == '=') {
486                     p++;
487                     get_word_sep(buf, sizeof(buf), ";,", &p);
488                     if (inet_aton(buf, &ipaddr)) 
489                         th->destination = ntohl(ipaddr.s_addr);
490                 }
491             }
492             while (*p != ';' && *p != '\0' && *p != ',')
493                 p++;
494             if (*p == ';')
495                 p++;
496         }
497         if (*p == ',')
498             p++;
499
500         reply->nb_transports++;
501     }
502 }
503
504 void rtsp_parse_line(RTSPHeader *reply, const char *buf)
505 {
506     const char *p;
507
508     /* NOTE: we do case independent match for broken servers */
509     p = buf;
510     if (stristart(p, "Session:", &p)) {
511         get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
512     } else if (stristart(p, "Content-Length:", &p)) {
513         reply->content_length = strtol(p, NULL, 10);
514     } else if (stristart(p, "Transport:", &p)) {
515         rtsp_parse_transport(reply, p);
516     } else if (stristart(p, "CSeq:", &p)) {
517         reply->seq = strtol(p, NULL, 10);
518     }
519 }
520
521
522 static void rtsp_send_cmd(AVFormatContext *s, 
523                           const char *cmd, RTSPHeader *reply, 
524                           unsigned char **content_ptr)
525 {
526     RTSPState *rt = s->priv_data;
527     char buf[4096], buf1[1024], *q;
528     unsigned char ch;
529     const char *p;
530     int content_length, line_count;
531     unsigned char *content = NULL;
532
533     memset(reply, 0, sizeof(RTSPHeader));
534
535     rt->seq++;
536     pstrcpy(buf, sizeof(buf), cmd);
537     snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
538     pstrcat(buf, sizeof(buf), buf1);
539     if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
540         snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
541         pstrcat(buf, sizeof(buf), buf1);
542     }
543     pstrcat(buf, sizeof(buf), "\r\n");
544 #ifdef DEBUG
545     printf("Sending:\n%s--\n", buf);
546 #endif
547     url_write(rt->rtsp_hd, buf, strlen(buf));
548
549     /* parse reply (XXX: use buffers) */
550     line_count = 0;
551     rt->last_reply[0] = '\0';
552     for(;;) {
553         q = buf;
554         for(;;) {
555             if (url_read(rt->rtsp_hd, &ch, 1) == 0)
556                 break;
557             if (ch == '\n')
558                 break;
559             if (ch != '\r') {
560                 if ((q - buf) < sizeof(buf) - 1)
561                     *q++ = ch;
562             }
563         }
564         *q = '\0';
565 #ifdef DEBUG
566         printf("line='%s'\n", buf);
567 #endif
568         /* test if last line */
569         if (buf[0] == '\0')
570             break;
571         p = buf;
572         if (line_count == 0) {
573             /* get reply code */
574             get_word(buf1, sizeof(buf1), &p);
575             get_word(buf1, sizeof(buf1), &p);
576             reply->status_code = atoi(buf1);
577         } else {
578             rtsp_parse_line(reply, p);
579             pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
580             pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
581         }
582         line_count++;
583     }
584     
585     if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
586         pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
587     
588     content_length = reply->content_length;
589     if (content_length > 0) {
590         /* leave some room for a trailing '\0' (useful for simple parsing) */
591         content = av_malloc(content_length + 1);
592         url_read(rt->rtsp_hd, content, content_length);
593         content[content_length] = '\0';
594     }
595     if (content_ptr)
596         *content_ptr = content;
597 }
598
599 /* useful for modules: set RTSP callback function */
600
601 void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
602 {
603     ff_rtsp_callback = rtsp_cb;
604 }
605
606
607 static int rtsp_read_header(AVFormatContext *s,
608                             AVFormatParameters *ap)
609 {
610     RTSPState *rt = s->priv_data;
611     char host[1024], path[1024], tcpname[1024], cmd[2048];
612     URLContext *rtsp_hd;
613     int port, i, ret, err;
614     RTSPHeader reply1, *reply = &reply1;
615     unsigned char *content = NULL;
616     AVStream *st;
617     RTSPStream *rtsp_st;
618     int protocol_mask;
619
620     rtsp_abort_req = 0;
621     
622     /* extract hostname and port */
623     url_split(NULL, 0,
624               host, sizeof(host), &port, path, sizeof(path), s->filename);
625     if (port < 0)
626         port = RTSP_DEFAULT_PORT;
627
628     /* open the tcp connexion */
629     snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
630     if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
631         return AVERROR_IO;
632     rt->rtsp_hd = rtsp_hd;
633     rt->seq = 0;
634     
635     /* describe the stream */
636     snprintf(cmd, sizeof(cmd), 
637              "DESCRIBE %s RTSP/1.0\r\n"
638              "Accept: application/sdp\r\n",
639              s->filename);
640     rtsp_send_cmd(s, cmd, reply, &content);
641     if (!content) {
642         err = AVERROR_INVALIDDATA;
643         goto fail;
644     }
645     if (reply->status_code != RTSP_STATUS_OK) {
646         err = AVERROR_INVALIDDATA;
647         goto fail;
648     }
649         
650     /* now we got the SDP description, we parse it */
651     ret = sdp_parse(s, (const char *)content);
652     av_freep(&content);
653     if (ret < 0) {
654         err = AVERROR_INVALIDDATA;
655         goto fail;
656     }
657     
658     protocol_mask = rtsp_default_protocols;
659
660     /* for each stream, make the setup request */
661     /* XXX: we assume the same server is used for the control of each
662        RTSP stream */
663     for(i=0;i<s->nb_streams;i++) {
664         char transport[2048];
665         AVInputFormat *fmt;
666
667         st = s->streams[i];
668         rtsp_st = st->priv_data;
669
670         /* compute available transports */
671         transport[0] = '\0';
672
673         /* RTP/UDP */
674         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
675             char buf[256];
676             int j;
677
678             /* first try in specified port range */
679             if (rtsp_rtp_port_min != 0) {
680                 for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) {
681                     snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
682                     if (!av_open_input_file(&rtsp_st->ic, buf, 
683                                             &rtp_demux, 0, NULL))
684                         goto rtp_opened;
685                 }
686             }
687
688             /* then try on any port */
689             if (av_open_input_file(&rtsp_st->ic, "rtp://", 
690                                        &rtp_demux, 0, NULL) < 0) {
691                     err = AVERROR_INVALIDDATA;
692                     goto fail;
693             }
694
695         rtp_opened:
696             port = rtp_get_local_port(url_fileno(&rtsp_st->ic->pb));
697             if (transport[0] != '\0')
698                 pstrcat(transport, sizeof(transport), ",");
699             snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
700                      "RTP/AVP/UDP;unicast;client_port=%d-%d",
701                      port, port + 1);
702         }
703
704         /* RTP/TCP */
705         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
706             if (transport[0] != '\0')
707                 pstrcat(transport, sizeof(transport), ",");
708             snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
709                      "RTP/AVP/TCP");
710         }
711
712         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
713             if (transport[0] != '\0')
714                 pstrcat(transport, sizeof(transport), ",");
715             snprintf(transport + strlen(transport), 
716                      sizeof(transport) - strlen(transport) - 1,
717                      "RTP/AVP/UDP;multicast");
718         }
719         snprintf(cmd, sizeof(cmd), 
720                  "SETUP %s RTSP/1.0\r\n"
721                  "Transport: %s\r\n",
722                  rtsp_st->control_url, transport);
723         rtsp_send_cmd(s, cmd, reply, NULL);
724         if (reply->status_code != RTSP_STATUS_OK ||
725             reply->nb_transports != 1) {
726             err = AVERROR_INVALIDDATA;
727             goto fail;
728         }
729
730         /* XXX: same protocol for all streams is required */
731         if (i > 0) {
732             if (reply->transports[0].protocol != rt->protocol) {
733                 err = AVERROR_INVALIDDATA;
734                 goto fail;
735             }
736         } else {
737             rt->protocol = reply->transports[0].protocol;
738         }
739
740         /* close RTP connection if not choosen */
741         if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
742             (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
743             av_close_input_file(rtsp_st->ic);
744             rtsp_st->ic = NULL;
745         }
746
747         switch(reply->transports[0].protocol) {
748         case RTSP_PROTOCOL_RTP_TCP:
749             fmt = &rtp_demux;
750             if (av_open_input_file(&rtsp_st->ic, "null", fmt, 0, NULL) < 0) {
751                 err = AVERROR_INVALIDDATA;
752                 goto fail;
753             }
754             rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
755             rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
756             break;
757             
758         case RTSP_PROTOCOL_RTP_UDP:
759             {
760                 char url[1024];
761                 
762                 /* XXX: also use address if specified */
763                 snprintf(url, sizeof(url), "rtp://%s:%d", 
764                          host, reply->transports[0].server_port_min);
765                 if (rtp_set_remote_url(url_fileno(&rtsp_st->ic->pb), url) < 0) {
766                     err = AVERROR_INVALIDDATA;
767                     goto fail;
768                 }
769             }
770             break;
771         case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
772             {
773                 char url[1024];
774                 int ttl;
775
776                 fmt = &rtp_demux;
777                 ttl = reply->transports[0].ttl;
778                 if (!ttl)
779                     ttl = 16;
780                 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
781                          host, 
782                          reply->transports[0].server_port_min,
783                          ttl);
784                 if (av_open_input_file(&rtsp_st->ic, url, fmt, 0, NULL) < 0) {
785                     err = AVERROR_INVALIDDATA;
786                     goto fail;
787                 }
788             }
789             break;
790         }
791     }
792
793     /* use callback if available to extend setup */
794     if (ff_rtsp_callback) {
795         if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, 
796                              NULL, 0, rt->last_reply) < 0) {
797             err = AVERROR_INVALIDDATA;
798             goto fail;
799         }
800     }
801                          
802     /* start playing */
803     snprintf(cmd, sizeof(cmd), 
804              "PLAY %s RTSP/1.0\r\n"
805              "Range: npt=0-\r\n",
806              s->filename);
807     rtsp_send_cmd(s, cmd, reply, NULL);
808     if (reply->status_code != RTSP_STATUS_OK) {
809         err = AVERROR_INVALIDDATA;
810         goto fail;
811     }
812
813 #if 0
814     /* open TCP with bufferized input */
815     if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
816         if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {
817             err = AVERROR_NOMEM;
818             goto fail;
819         }
820     }
821 #endif
822
823     return 0;
824  fail:
825     for(i=0;i<s->nb_streams;i++) {
826         st = s->streams[i];
827         rtsp_st = st->priv_data;
828         if (rtsp_st) {
829             if (rtsp_st->ic)
830                 av_close_input_file(rtsp_st->ic);
831         }
832         av_free(rtsp_st);
833     }
834     av_freep(&content);
835     url_close(rt->rtsp_hd);
836     return err;
837 }
838
839 static int tcp_read_packet(AVFormatContext *s,
840                            AVPacket *pkt)
841 {
842     RTSPState *rt = s->priv_data;
843     int id, len, i, ret;
844     AVStream *st;
845     RTSPStream *rtsp_st;
846     uint8_t buf[RTP_MAX_PACKET_LENGTH];
847
848 #ifdef DEBUG_RTP_TCP
849     printf("tcp_read_packet:\n");
850 #endif
851  redo:
852     for(;;) {
853         ret = url_read(rt->rtsp_hd, buf, 1);
854 #ifdef DEBUG_RTP_TCP
855         printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
856 #endif
857         if (ret != 1)
858             return AVERROR_IO;
859         if (buf[0] == '$')
860             break;
861     }
862     ret = url_read(rt->rtsp_hd, buf, 3);
863     if (ret != 3)
864         return AVERROR_IO;
865     id = buf[0];
866     len = (buf[1] << 8) | buf[2];
867 #ifdef DEBUG_RTP_TCP
868     printf("id=%d len=%d\n", id, len);
869 #endif
870     if (len > RTP_MAX_PACKET_LENGTH || len < 12)
871         goto redo;
872     /* get the data */
873     ret = url_read(rt->rtsp_hd, buf, len);
874     if (ret != len)
875         return AVERROR_IO;
876         
877     /* find the matching stream */
878     for(i = 0; i < s->nb_streams; i++) {
879         st = s->streams[i];
880         rtsp_st = st->priv_data;
881         if (id >= rtsp_st->interleaved_min && 
882             id <= rtsp_st->interleaved_max) 
883             goto found;
884     }
885     goto redo;
886  found:
887     ret = rtp_parse_packet(rtsp_st->ic, pkt, buf, len);
888     if (ret < 0)
889         goto redo;
890     pkt->stream_index = i;
891     return ret;
892 }
893
894 /* NOTE: output one packet at a time. May need to add a small fifo */
895 static int udp_read_packet(AVFormatContext *s,
896                            AVPacket *pkt)
897 {
898     AVFormatContext *ic;
899     AVStream *st;
900     RTSPStream *rtsp_st;
901     fd_set rfds;
902     int fd1, fd2, fd_max, n, i, ret;
903     char buf[RTP_MAX_PACKET_LENGTH];
904     struct timeval tv;
905
906     for(;;) {
907         if (rtsp_abort_req)
908             return -EIO;
909         FD_ZERO(&rfds);
910         fd_max = -1;
911         for(i = 0; i < s->nb_streams; i++) {
912             st = s->streams[i];
913             rtsp_st = st->priv_data;
914             ic = rtsp_st->ic;
915             /* currently, we cannot probe RTCP handle because of blocking restrictions */
916             rtp_get_file_handles(url_fileno(&ic->pb), &fd1, &fd2);
917             if (fd1 > fd_max)
918                 fd_max = fd1;
919             FD_SET(fd1, &rfds);
920         }
921         /* XXX: also add proper API to abort */
922         tv.tv_sec = 0;
923         tv.tv_usec = 500000;
924         n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
925         if (n > 0) {
926             for(i = 0; i < s->nb_streams; i++) {
927                 st = s->streams[i];
928                 rtsp_st = st->priv_data;
929                 ic = rtsp_st->ic;
930                 rtp_get_file_handles(url_fileno(&ic->pb), &fd1, &fd2);
931                 if (FD_ISSET(fd1, &rfds)) {
932                     ret = url_read(url_fileno(&ic->pb), buf, sizeof(buf));
933                     if (ret >= 0 && 
934                         rtp_parse_packet(ic, pkt, buf, ret) == 0) {
935                         pkt->stream_index = i;
936                         return ret;
937                     }
938                 }
939             }
940         }
941     }
942 }
943
944 static int rtsp_read_packet(AVFormatContext *s,
945                             AVPacket *pkt)
946 {
947     RTSPState *rt = s->priv_data;
948     int ret;
949
950     switch(rt->protocol) {
951     default:
952     case RTSP_PROTOCOL_RTP_TCP:
953         ret = tcp_read_packet(s, pkt);
954         break;
955     case RTSP_PROTOCOL_RTP_UDP:
956         ret = udp_read_packet(s, pkt);
957         break;
958     }
959     return ret;
960 }
961
962 static int rtsp_read_close(AVFormatContext *s)
963 {
964     RTSPState *rt = s->priv_data;
965     AVStream *st;
966     RTSPStream *rtsp_st;
967     RTSPHeader reply1, *reply = &reply1;
968     int i;
969     char cmd[1024];
970
971 #if 0
972     /* NOTE: it is valid to flush the buffer here */
973     if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
974         url_fclose(&rt->rtsp_gb);
975     }
976 #endif
977     snprintf(cmd, sizeof(cmd), 
978              "TEARDOWN %s RTSP/1.0\r\n",
979              s->filename);
980     rtsp_send_cmd(s, cmd, reply, NULL);
981
982     if (ff_rtsp_callback) {
983         ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, 
984                          NULL, 0, NULL);
985     }
986
987     for(i=0;i<s->nb_streams;i++) {
988         st = s->streams[i];
989         rtsp_st = st->priv_data;
990         if (rtsp_st) {
991             if (rtsp_st->ic)
992                 av_close_input_file(rtsp_st->ic);
993         }
994         av_free(rtsp_st);
995     }
996     url_close(rt->rtsp_hd);
997     return 0;
998 }
999
1000 static AVInputFormat rtsp_demux = {
1001     "rtsp",
1002     "RTSP input format",
1003     sizeof(RTSPState),
1004     rtsp_probe,
1005     rtsp_read_header,
1006     rtsp_read_packet,
1007     rtsp_read_close,
1008     .flags = AVFMT_NOFILE,
1009 };
1010
1011 static int sdp_probe(AVProbeData *p1)
1012 {
1013     const char *p;
1014
1015     /* we look for a line beginning "c=IN IP4" */
1016     p = p1->buf;
1017     while (*p != '\0') {
1018         if (strstart(p, "c=IN IP4", NULL))
1019             return AVPROBE_SCORE_MAX / 2;
1020         p = strchr(p, '\n');
1021         if (!p)
1022             break;
1023         p++;
1024         if (*p == '\r')
1025             p++;
1026     }
1027     return 0;
1028 }
1029
1030 #define SDP_MAX_SIZE 8192
1031
1032 static int sdp_read_header(AVFormatContext *s,
1033                            AVFormatParameters *ap)
1034 {
1035     AVStream *st;
1036     RTSPStream *rtsp_st;
1037     int size, i, err;
1038     char *content;
1039     char url[1024];
1040
1041     /* read the whole sdp file */
1042     /* XXX: better loading */
1043     content = av_malloc(SDP_MAX_SIZE);
1044     size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);
1045     if (size <= 0) {
1046         av_free(content);
1047         return AVERROR_INVALIDDATA;
1048     }
1049     content[size] ='\0';
1050
1051     sdp_parse(s, content);
1052     av_free(content);
1053
1054     /* open each RTP stream */
1055     for(i=0;i<s->nb_streams;i++) {
1056         st = s->streams[i];
1057         rtsp_st = st->priv_data;
1058         
1059         snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
1060                  inet_ntoa(rtsp_st->sdp_ip), 
1061                  rtsp_st->sdp_port,
1062                  rtsp_st->sdp_ttl);
1063         if (av_open_input_file(&rtsp_st->ic, url, &rtp_demux, 0, NULL) < 0) {
1064             err = AVERROR_INVALIDDATA;
1065             goto fail;
1066         }
1067     }
1068     return 0;
1069  fail:
1070     for(i=0;i<s->nb_streams;i++) {
1071         st = s->streams[i];
1072         rtsp_st = st->priv_data;
1073         if (rtsp_st) {
1074             if (rtsp_st->ic)
1075                 av_close_input_file(rtsp_st->ic);
1076         }
1077         av_free(rtsp_st);
1078     }
1079     return err;
1080 }
1081
1082 static int sdp_read_packet(AVFormatContext *s,
1083                             AVPacket *pkt)
1084 {
1085     return udp_read_packet(s, pkt);
1086 }
1087
1088 static int sdp_read_close(AVFormatContext *s)
1089 {
1090     AVStream *st;
1091     RTSPStream *rtsp_st;
1092     int i;
1093
1094     for(i=0;i<s->nb_streams;i++) {
1095         st = s->streams[i];
1096         rtsp_st = st->priv_data;
1097         if (rtsp_st) {
1098             if (rtsp_st->ic)
1099                 av_close_input_file(rtsp_st->ic);
1100         }
1101         av_free(rtsp_st);
1102     }
1103     return 0;
1104 }
1105
1106
1107 static AVInputFormat sdp_demux = {
1108     "sdp",
1109     "SDP",
1110     sizeof(RTSPState),
1111     sdp_probe,
1112     sdp_read_header,
1113     sdp_read_packet,
1114     sdp_read_close,
1115 };
1116
1117
1118 /* dummy redirector format (used directly in av_open_input_file now) */
1119 static int redir_probe(AVProbeData *pd)
1120 {
1121     const char *p;
1122     p = pd->buf;
1123     while (redir_isspace(*p))
1124         p++;
1125     if (strstart(p, "http://", NULL) ||
1126         strstart(p, "rtsp://", NULL))
1127         return AVPROBE_SCORE_MAX;
1128     return 0;
1129 }
1130
1131 /* called from utils.c */
1132 int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
1133 {
1134     char buf[4096], *q;
1135     int c;
1136     AVFormatContext *ic = NULL;
1137
1138     /* parse each URL and try to open it */
1139     c = url_fgetc(f);
1140     while (c != URL_EOF) {
1141         /* skip spaces */
1142         for(;;) {
1143             if (!redir_isspace(c))
1144                 break;
1145             c = url_fgetc(f);
1146         }
1147         if (c == URL_EOF)
1148             break;
1149         /* record url */
1150         q = buf;
1151         for(;;) {
1152             if (c == URL_EOF || redir_isspace(c))
1153                 break;
1154             if ((q - buf) < sizeof(buf) - 1)
1155                 *q++ = c;
1156             c = url_fgetc(f);
1157         }
1158         *q = '\0';
1159         //printf("URL='%s'\n", buf);
1160         /* try to open the media file */
1161         if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1162             break;
1163     }
1164     *ic_ptr = ic;
1165     if (!ic)
1166         return AVERROR_IO;
1167     else
1168         return 0;
1169 }
1170
1171 AVInputFormat redir_demux = {
1172     "redir",
1173     "Redirector format",
1174     0,
1175     redir_probe,
1176     NULL,
1177     NULL,
1178     NULL,
1179 };
1180
1181 int rtsp_init(void)
1182 {
1183     av_register_input_format(&rtsp_demux);
1184     av_register_input_format(&redir_demux);
1185     av_register_input_format(&sdp_demux);
1186     return 0;
1187 }