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