]> git.sesse.net Git - ffmpeg/blob - libavformat/rtsp.c
initial seek support - more generic play/pause support
[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, 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 /* skip a RTP/TCP interleaved packet */
566 static void rtsp_skip_packet(AVFormatContext *s)
567 {
568     RTSPState *rt = s->priv_data;
569     int ret, len, len1;
570     uint8_t buf[1024];
571
572     ret = url_read(rt->rtsp_hd, buf, 3);
573     if (ret != 3)
574         return;
575     len = (buf[1] << 8) | buf[2];
576 #ifdef DEBUG
577     printf("skipping RTP packet len=%d\n", len);
578 #endif
579     /* skip payload */
580     while (len > 0) {
581         len1 = len;
582         if (len1 > sizeof(buf))
583             len1 = sizeof(buf);
584         ret = url_read(rt->rtsp_hd, buf, len1);
585         if (ret != len1)
586             return;
587         len -= len1;
588     }
589 }
590
591 static void rtsp_send_cmd(AVFormatContext *s, 
592                           const char *cmd, RTSPHeader *reply, 
593                           unsigned char **content_ptr)
594 {
595     RTSPState *rt = s->priv_data;
596     char buf[4096], buf1[1024], *q;
597     unsigned char ch;
598     const char *p;
599     int content_length, line_count;
600     unsigned char *content = NULL;
601
602     memset(reply, 0, sizeof(RTSPHeader));
603
604     rt->seq++;
605     pstrcpy(buf, sizeof(buf), cmd);
606     snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
607     pstrcat(buf, sizeof(buf), buf1);
608     if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
609         snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
610         pstrcat(buf, sizeof(buf), buf1);
611     }
612     pstrcat(buf, sizeof(buf), "\r\n");
613 #ifdef DEBUG
614     printf("Sending:\n%s--\n", buf);
615 #endif
616     url_write(rt->rtsp_hd, buf, strlen(buf));
617
618     /* parse reply (XXX: use buffers) */
619     line_count = 0;
620     rt->last_reply[0] = '\0';
621     for(;;) {
622         q = buf;
623         for(;;) {
624             if (url_read(rt->rtsp_hd, &ch, 1) != 1)
625                 break;
626             if (ch == '\n')
627                 break;
628             if (ch == '$') {
629                 /* XXX: only parse it if first char on line ? */
630                 rtsp_skip_packet(s);
631             } else if (ch != '\r') {
632                 if ((q - buf) < sizeof(buf) - 1)
633                     *q++ = ch;
634             }
635         }
636         *q = '\0';
637 #ifdef DEBUG
638         printf("line='%s'\n", buf);
639 #endif
640         /* test if last line */
641         if (buf[0] == '\0')
642             break;
643         p = buf;
644         if (line_count == 0) {
645             /* get reply code */
646             get_word(buf1, sizeof(buf1), &p);
647             get_word(buf1, sizeof(buf1), &p);
648             reply->status_code = atoi(buf1);
649         } else {
650             rtsp_parse_line(reply, p);
651             pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
652             pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
653         }
654         line_count++;
655     }
656     
657     if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
658         pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
659     
660     content_length = reply->content_length;
661     if (content_length > 0) {
662         /* leave some room for a trailing '\0' (useful for simple parsing) */
663         content = av_malloc(content_length + 1);
664         url_read(rt->rtsp_hd, content, content_length);
665         content[content_length] = '\0';
666     }
667     if (content_ptr)
668         *content_ptr = content;
669 }
670
671 /* useful for modules: set RTSP callback function */
672
673 void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
674 {
675     ff_rtsp_callback = rtsp_cb;
676 }
677
678
679 /* close and free RTSP streams */
680 static void rtsp_close_streams(RTSPState *rt)
681 {
682     int i;
683     RTSPStream *rtsp_st;
684
685     for(i=0;i<rt->nb_rtsp_streams;i++) {
686         rtsp_st = rt->rtsp_streams[i];
687         if (rtsp_st) {
688             if (rtsp_st->rtp_ctx)
689                 rtp_parse_close(rtsp_st->rtp_ctx);
690             if (rtsp_st->rtp_handle)
691                 url_close(rtsp_st->rtp_handle);
692         }
693         av_free(rtsp_st);
694     }
695     av_free(rt->rtsp_streams);
696 }
697
698 static int rtsp_read_header(AVFormatContext *s,
699                             AVFormatParameters *ap)
700 {
701     RTSPState *rt = s->priv_data;
702     char host[1024], path[1024], tcpname[1024], cmd[2048];
703     URLContext *rtsp_hd;
704     int port, i, ret, err;
705     RTSPHeader reply1, *reply = &reply1;
706     unsigned char *content = NULL;
707     RTSPStream *rtsp_st;
708     int protocol_mask;
709     AVStream *st;
710
711     /* extract hostname and port */
712     url_split(NULL, 0,
713               host, sizeof(host), &port, path, sizeof(path), s->filename);
714     if (port < 0)
715         port = RTSP_DEFAULT_PORT;
716
717     /* open the tcp connexion */
718     snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
719     if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
720         return AVERROR_IO;
721     rt->rtsp_hd = rtsp_hd;
722     rt->seq = 0;
723     
724     /* describe the stream */
725     snprintf(cmd, sizeof(cmd), 
726              "DESCRIBE %s RTSP/1.0\r\n"
727              "Accept: application/sdp\r\n",
728              s->filename);
729     rtsp_send_cmd(s, cmd, reply, &content);
730     if (!content) {
731         err = AVERROR_INVALIDDATA;
732         goto fail;
733     }
734     if (reply->status_code != RTSP_STATUS_OK) {
735         err = AVERROR_INVALIDDATA;
736         goto fail;
737     }
738         
739     /* now we got the SDP description, we parse it */
740     ret = sdp_parse(s, (const char *)content);
741     av_freep(&content);
742     if (ret < 0) {
743         err = AVERROR_INVALIDDATA;
744         goto fail;
745     }
746     
747     protocol_mask = rtsp_default_protocols;
748
749     /* for each stream, make the setup request */
750     /* XXX: we assume the same server is used for the control of each
751        RTSP stream */
752     for(i=0;i<rt->nb_rtsp_streams;i++) {
753         char transport[2048];
754
755         rtsp_st = rt->rtsp_streams[i];
756
757         /* compute available transports */
758         transport[0] = '\0';
759
760         /* RTP/UDP */
761         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
762             char buf[256];
763             int j;
764
765             /* first try in specified port range */
766             if (rtsp_rtp_port_min != 0) {
767                 for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) {
768                     snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
769                     if (url_open(&rtsp_st->rtp_handle, buf, URL_RDONLY) == 0)
770                         goto rtp_opened;
771                 }
772             }
773
774             /* then try on any port */
775             if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
776                 err = AVERROR_INVALIDDATA;
777                 goto fail;
778             }
779
780         rtp_opened:
781             port = rtp_get_local_port(rtsp_st->rtp_handle);
782             if (transport[0] != '\0')
783                 pstrcat(transport, sizeof(transport), ",");
784             snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
785                      "RTP/AVP/UDP;unicast;client_port=%d-%d",
786                      port, port + 1);
787         }
788
789         /* RTP/TCP */
790         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
791             if (transport[0] != '\0')
792                 pstrcat(transport, sizeof(transport), ",");
793             snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
794                      "RTP/AVP/TCP");
795         }
796
797         if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
798             if (transport[0] != '\0')
799                 pstrcat(transport, sizeof(transport), ",");
800             snprintf(transport + strlen(transport), 
801                      sizeof(transport) - strlen(transport) - 1,
802                      "RTP/AVP/UDP;multicast");
803         }
804         snprintf(cmd, sizeof(cmd), 
805                  "SETUP %s RTSP/1.0\r\n"
806                  "Transport: %s\r\n",
807                  rtsp_st->control_url, transport);
808         rtsp_send_cmd(s, cmd, reply, NULL);
809         if (reply->status_code != RTSP_STATUS_OK ||
810             reply->nb_transports != 1) {
811             err = AVERROR_INVALIDDATA;
812             goto fail;
813         }
814
815         /* XXX: same protocol for all streams is required */
816         if (i > 0) {
817             if (reply->transports[0].protocol != rt->protocol) {
818                 err = AVERROR_INVALIDDATA;
819                 goto fail;
820             }
821         } else {
822             rt->protocol = reply->transports[0].protocol;
823         }
824
825         /* close RTP connection if not choosen */
826         if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
827             (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
828             url_close(rtsp_st->rtp_handle);
829             rtsp_st->rtp_handle = NULL;
830         }
831
832         switch(reply->transports[0].protocol) {
833         case RTSP_PROTOCOL_RTP_TCP:
834             rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
835             rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
836             break;
837             
838         case RTSP_PROTOCOL_RTP_UDP:
839             {
840                 char url[1024];
841                 
842                 /* XXX: also use address if specified */
843                 snprintf(url, sizeof(url), "rtp://%s:%d", 
844                          host, reply->transports[0].server_port_min);
845                 if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
846                     err = AVERROR_INVALIDDATA;
847                     goto fail;
848                 }
849             }
850             break;
851         case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
852             {
853                 char url[1024];
854                 int ttl;
855
856                 ttl = reply->transports[0].ttl;
857                 if (!ttl)
858                     ttl = 16;
859                 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
860                          host, 
861                          reply->transports[0].server_port_min,
862                          ttl);
863                 if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {
864                     err = AVERROR_INVALIDDATA;
865                     goto fail;
866                 }
867             }
868             break;
869         }
870         /* open the RTP context */
871         st = NULL;
872         if (rtsp_st->stream_index >= 0)
873             st = s->streams[rtsp_st->stream_index];
874         if (!st)
875             s->ctx_flags |= AVFMTCTX_NOHEADER;
876         rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type);
877         if (!rtsp_st->rtp_ctx) {
878             err = AVERROR_NOMEM;
879             goto fail;
880         }
881     }
882
883     /* use callback if available to extend setup */
884     if (ff_rtsp_callback) {
885         if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, 
886                              NULL, 0, rt->last_reply) < 0) {
887             err = AVERROR_INVALIDDATA;
888             goto fail;
889         }
890     }
891                          
892
893     rt->state = RTSP_STATE_IDLE;
894     rt->seek_timestamp = 0; /* default is to start stream at position
895                                zero */
896     if (ap && ap->initial_pause) {
897         /* do not start immediately */
898     } else {
899         if (rtsp_read_play(s) < 0) {
900             err = AVERROR_INVALIDDATA;
901             goto fail;
902         }
903     }
904     return 0;
905  fail:
906     rtsp_close_streams(rt);
907     av_freep(&content);
908     url_close(rt->rtsp_hd);
909     return err;
910 }
911
912 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
913                            uint8_t *buf, int buf_size)
914 {
915     RTSPState *rt = s->priv_data;
916     int id, len, i, ret;
917     RTSPStream *rtsp_st;
918
919 #ifdef DEBUG_RTP_TCP
920     printf("tcp_read_packet:\n");
921 #endif
922  redo:
923     for(;;) {
924         ret = url_read(rt->rtsp_hd, buf, 1);
925 #ifdef DEBUG_RTP_TCP
926         printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
927 #endif
928         if (ret != 1)
929             return -1;
930         if (buf[0] == '$')
931             break;
932     }
933     ret = url_read(rt->rtsp_hd, buf, 3);
934     if (ret != 3)
935         return -1;
936     id = buf[0];
937     len = (buf[1] << 8) | buf[2];
938 #ifdef DEBUG_RTP_TCP
939     printf("id=%d len=%d\n", id, len);
940 #endif
941     if (len > buf_size || len < 12)
942         goto redo;
943     /* get the data */
944     ret = url_read(rt->rtsp_hd, buf, len);
945     if (ret != len)
946         return -1;
947         
948     /* find the matching stream */
949     for(i = 0; i < rt->nb_rtsp_streams; i++) {
950         rtsp_st = rt->rtsp_streams[i];
951         if (id >= rtsp_st->interleaved_min && 
952             id <= rtsp_st->interleaved_max) 
953             goto found;
954     }
955     goto redo;
956  found:
957     *prtsp_st = rtsp_st;
958     return len;
959 }
960
961 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, 
962                            uint8_t *buf, int buf_size)
963 {
964     RTSPState *rt = s->priv_data;
965     RTSPStream *rtsp_st;
966     fd_set rfds;
967     int fd1, fd2, fd_max, n, i, ret;
968     struct timeval tv;
969
970     for(;;) {
971         if (url_interrupt_cb())
972             return -1;
973         FD_ZERO(&rfds);
974         fd_max = -1;
975         for(i = 0; i < rt->nb_rtsp_streams; i++) {
976             rtsp_st = rt->rtsp_streams[i];
977             /* currently, we cannot probe RTCP handle because of blocking restrictions */
978             rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
979             if (fd1 > fd_max)
980                 fd_max = fd1;
981             FD_SET(fd1, &rfds);
982         }
983         tv.tv_sec = 0;
984         tv.tv_usec = 100 * 1000;
985         n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
986         if (n > 0) {
987             for(i = 0; i < rt->nb_rtsp_streams; i++) {
988                 rtsp_st = rt->rtsp_streams[i];
989                 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
990                 if (FD_ISSET(fd1, &rfds)) {
991                     ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
992                     if (ret > 0) {
993                         *prtsp_st = rtsp_st;
994                         return ret;
995                     }
996                 }
997             }
998         }
999     }
1000 }
1001
1002 static int rtsp_read_packet(AVFormatContext *s,
1003                             AVPacket *pkt)
1004 {
1005     RTSPState *rt = s->priv_data;
1006     RTSPStream *rtsp_st;
1007     int ret, len;
1008     uint8_t buf[RTP_MAX_PACKET_LENGTH];
1009
1010     /* get next frames from the same RTP packet */
1011     if (rt->cur_rtp) {
1012         ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);
1013         if (ret == 0) {
1014             rt->cur_rtp = NULL;
1015             return 0;
1016         } else if (ret == 1) {
1017             return 0;
1018         } else {
1019             rt->cur_rtp = NULL;
1020         }
1021     }
1022
1023     /* read next RTP packet */
1024  redo:
1025     switch(rt->protocol) {
1026     default:
1027     case RTSP_PROTOCOL_RTP_TCP:
1028         len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1029         break;
1030     case RTSP_PROTOCOL_RTP_UDP:
1031     case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
1032         len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1033         break;
1034     }
1035     if (len < 0)
1036         return AVERROR_IO;
1037     ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
1038     if (ret < 0)
1039         goto redo;
1040     if (ret == 1) {
1041         /* more packets may follow, so we save the RTP context */
1042         rt->cur_rtp = rtsp_st->rtp_ctx;
1043     }
1044     return 0;
1045 }
1046
1047 static int rtsp_read_play(AVFormatContext *s)
1048 {
1049     RTSPState *rt = s->priv_data;
1050     RTSPHeader reply1, *reply = &reply1;
1051     char cmd[1024];
1052
1053     printf("hello state=%d\n", rt->state);
1054
1055     if (rt->state == RTSP_STATE_PAUSED) {
1056         snprintf(cmd, sizeof(cmd), 
1057                  "PLAY %s RTSP/1.0\r\n",
1058                  s->filename);
1059     } else {
1060         snprintf(cmd, sizeof(cmd), 
1061                  "PLAY %s RTSP/1.0\r\n"
1062                  "Range: npt=%0.3f-\r\n",
1063                  s->filename,
1064                  (double)rt->seek_timestamp / AV_TIME_BASE);
1065     }
1066     rtsp_send_cmd(s, cmd, reply, NULL);
1067     if (reply->status_code != RTSP_STATUS_OK) {
1068         return -1;
1069     } else {
1070         rt->state = RTSP_STATE_PLAYING;
1071         return 0;
1072     }
1073 }
1074
1075 /* pause the stream */
1076 static int rtsp_read_pause(AVFormatContext *s)
1077 {
1078     RTSPState *rt = s->priv_data;
1079     RTSPHeader reply1, *reply = &reply1;
1080     char cmd[1024];
1081
1082     rt = s->priv_data;
1083     
1084     if (rt->state != RTSP_STATE_PLAYING)
1085         return 0;
1086
1087     snprintf(cmd, sizeof(cmd), 
1088              "PAUSE %s RTSP/1.0\r\n",
1089              s->filename);
1090     rtsp_send_cmd(s, cmd, reply, NULL);
1091     if (reply->status_code != RTSP_STATUS_OK) {
1092         return -1;
1093     } else {
1094         rt->state = RTSP_STATE_PAUSED;
1095         return 0;
1096     }
1097 }
1098
1099 static int rtsp_read_seek(AVFormatContext *s, int stream_index, 
1100                           int64_t timestamp)
1101 {
1102     RTSPState *rt = s->priv_data;
1103     
1104     rt->seek_timestamp = timestamp;
1105     switch(rt->state) {
1106     default:
1107     case RTSP_STATE_IDLE:
1108         break;
1109     case RTSP_STATE_PLAYING:
1110         if (rtsp_read_play(s) != 0)
1111             return -1;
1112         break;
1113     case RTSP_STATE_PAUSED:
1114         rt->state = RTSP_STATE_IDLE;
1115         break;
1116     }
1117     return 0;
1118 }
1119
1120 static int rtsp_read_close(AVFormatContext *s)
1121 {
1122     RTSPState *rt = s->priv_data;
1123     RTSPHeader reply1, *reply = &reply1;
1124     char cmd[1024];
1125
1126 #if 0
1127     /* NOTE: it is valid to flush the buffer here */
1128     if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
1129         url_fclose(&rt->rtsp_gb);
1130     }
1131 #endif
1132     snprintf(cmd, sizeof(cmd), 
1133              "TEARDOWN %s RTSP/1.0\r\n",
1134              s->filename);
1135     rtsp_send_cmd(s, cmd, reply, NULL);
1136
1137     if (ff_rtsp_callback) {
1138         ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, 
1139                          NULL, 0, NULL);
1140     }
1141
1142     rtsp_close_streams(rt);
1143     url_close(rt->rtsp_hd);
1144     return 0;
1145 }
1146
1147 AVInputFormat rtsp_demux = {
1148     "rtsp",
1149     "RTSP input format",
1150     sizeof(RTSPState),
1151     rtsp_probe,
1152     rtsp_read_header,
1153     rtsp_read_packet,
1154     rtsp_read_close,
1155     rtsp_read_seek,
1156     .flags = AVFMT_NOFILE,
1157     .read_play = rtsp_read_play,
1158     .read_pause = rtsp_read_pause,
1159 };
1160
1161 static int sdp_probe(AVProbeData *p1)
1162 {
1163     const char *p;
1164
1165     /* we look for a line beginning "c=IN IP4" */
1166     p = p1->buf;
1167     while (*p != '\0') {
1168         if (strstart(p, "c=IN IP4", NULL))
1169             return AVPROBE_SCORE_MAX / 2;
1170         p = strchr(p, '\n');
1171         if (!p)
1172             break;
1173         p++;
1174         if (*p == '\r')
1175             p++;
1176     }
1177     return 0;
1178 }
1179
1180 #define SDP_MAX_SIZE 8192
1181
1182 static int sdp_read_header(AVFormatContext *s,
1183                            AVFormatParameters *ap)
1184 {
1185     RTSPState *rt = s->priv_data;
1186     RTSPStream *rtsp_st;
1187     int size, i, err;
1188     char *content;
1189     char url[1024];
1190     AVStream *st;
1191
1192     /* read the whole sdp file */
1193     /* XXX: better loading */
1194     content = av_malloc(SDP_MAX_SIZE);
1195     size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);
1196     if (size <= 0) {
1197         av_free(content);
1198         return AVERROR_INVALIDDATA;
1199     }
1200     content[size] ='\0';
1201
1202     sdp_parse(s, content);
1203     av_free(content);
1204
1205     /* open each RTP stream */
1206     for(i=0;i<rt->nb_rtsp_streams;i++) {
1207         rtsp_st = rt->rtsp_streams[i];
1208         
1209         snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
1210                  inet_ntoa(rtsp_st->sdp_ip), 
1211                  rtsp_st->sdp_port,
1212                  rtsp_st->sdp_ttl);
1213         if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {
1214             err = AVERROR_INVALIDDATA;
1215             goto fail;
1216         }
1217         /* open the RTP context */
1218         st = NULL;
1219         if (rtsp_st->stream_index >= 0)
1220             st = s->streams[rtsp_st->stream_index];
1221         if (!st)
1222             s->ctx_flags |= AVFMTCTX_NOHEADER;
1223         rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type);
1224         if (!rtsp_st->rtp_ctx) {
1225             err = AVERROR_NOMEM;
1226             goto fail;
1227         }
1228     }
1229     return 0;
1230  fail:
1231     rtsp_close_streams(rt);
1232     return err;
1233 }
1234
1235 static int sdp_read_packet(AVFormatContext *s,
1236                             AVPacket *pkt)
1237 {
1238     return rtsp_read_packet(s, pkt);
1239 }
1240
1241 static int sdp_read_close(AVFormatContext *s)
1242 {
1243     RTSPState *rt = s->priv_data;
1244     rtsp_close_streams(rt);
1245     return 0;
1246 }
1247
1248
1249 static AVInputFormat sdp_demux = {
1250     "sdp",
1251     "SDP",
1252     sizeof(RTSPState),
1253     sdp_probe,
1254     sdp_read_header,
1255     sdp_read_packet,
1256     sdp_read_close,
1257 };
1258
1259
1260 /* dummy redirector format (used directly in av_open_input_file now) */
1261 static int redir_probe(AVProbeData *pd)
1262 {
1263     const char *p;
1264     p = pd->buf;
1265     while (redir_isspace(*p))
1266         p++;
1267     if (strstart(p, "http://", NULL) ||
1268         strstart(p, "rtsp://", NULL))
1269         return AVPROBE_SCORE_MAX;
1270     return 0;
1271 }
1272
1273 /* called from utils.c */
1274 int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
1275 {
1276     char buf[4096], *q;
1277     int c;
1278     AVFormatContext *ic = NULL;
1279
1280     /* parse each URL and try to open it */
1281     c = url_fgetc(f);
1282     while (c != URL_EOF) {
1283         /* skip spaces */
1284         for(;;) {
1285             if (!redir_isspace(c))
1286                 break;
1287             c = url_fgetc(f);
1288         }
1289         if (c == URL_EOF)
1290             break;
1291         /* record url */
1292         q = buf;
1293         for(;;) {
1294             if (c == URL_EOF || redir_isspace(c))
1295                 break;
1296             if ((q - buf) < sizeof(buf) - 1)
1297                 *q++ = c;
1298             c = url_fgetc(f);
1299         }
1300         *q = '\0';
1301         //printf("URL='%s'\n", buf);
1302         /* try to open the media file */
1303         if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1304             break;
1305     }
1306     *ic_ptr = ic;
1307     if (!ic)
1308         return AVERROR_IO;
1309     else
1310         return 0;
1311 }
1312
1313 AVInputFormat redir_demux = {
1314     "redir",
1315     "Redirector format",
1316     0,
1317     redir_probe,
1318     NULL,
1319     NULL,
1320     NULL,
1321 };
1322
1323 int rtsp_init(void)
1324 {
1325     av_register_input_format(&rtsp_demux);
1326     av_register_input_format(&redir_demux);
1327     av_register_input_format(&sdp_demux);
1328     return 0;
1329 }