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