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