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