whitespace cosmetics: Break some overly long lines.
[libav.git] / libavformat / rtsp.c
CommitLineData
1617ad97 1/*
93ced3e8 2 * RTSP/SDP client
406792e7 3 * Copyright (c) 2002 Fabrice Bellard
1617ad97 4 *
b78e7197
DB
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
1617ad97
FB
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
1617ad97 11 *
b78e7197 12 * FFmpeg is distributed in the hope that it will be useful,
1617ad97
FB
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
b78e7197 18 * License along with FFmpeg; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1617ad97 20 */
245976da 21
7246177d
AJ
22/* needed by inet_aton() */
23#define _SVID_SOURCE
24
245976da 25#include "libavutil/avstring.h"
6a5d31ac 26#include "libavutil/intreadwrite.h"
1617ad97
FB
27#include "avformat.h"
28
db0ed93e 29#include <sys/time.h>
b250f9c6 30#if HAVE_SYS_SELECT_H
933bd8e2 31#include <sys/select.h>
6ad1c9c9 32#endif
ea452b54 33#include <strings.h>
42572ef5 34#include "network.h"
c971ff19 35#include "rtsp.h"
1617ad97 36
302879cb 37#include "rtpdec.h"
e9dea59f 38#include "rdt.h"
1a30d541 39#include "rtp_asf.h"
4934884a 40
1617ad97 41//#define DEBUG
b6892136 42//#define DEBUG_RTP_TCP
1617ad97 43
ff762d6e
FB
44static int rtsp_read_play(AVFormatContext *s);
45
c482500f 46#if LIBAVFORMAT_VERSION_INT < (53 << 16)
90abbdba 47int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
c482500f 48#endif
85fb7b34 49
1617ad97
FB
50static int rtsp_probe(AVProbeData *p)
51{
f7d78f36 52 if (av_strstart(p->filename, "rtsp:", NULL))
1617ad97
FB
53 return AVPROBE_SCORE_MAX;
54 return 0;
55}
56
1ef36a70 57#define SPACE_CHARS " \t\r\n"
da1e126e
RB
58/* we use memchr() instead of strchr() here because strchr() will return
59 * the terminating '\0' of SPACE_CHARS instead of NULL if c is '\0'. */
60#define redir_isspace(c) memchr(SPACE_CHARS, c, 4)
1617ad97
FB
61static void skip_spaces(const char **pp)
62{
63 const char *p;
64 p = *pp;
65 while (redir_isspace(*p))
66 p++;
67 *pp = p;
68}
69
1ef36a70
RB
70static void get_word_until_chars(char *buf, int buf_size,
71 const char *sep, const char **pp)
1617ad97
FB
72{
73 const char *p;
74 char *q;
75
76 p = *pp;
77 skip_spaces(&p);
78 q = buf;
79 while (!strchr(sep, *p) && *p != '\0') {
80 if ((q - buf) < buf_size - 1)
81 *q++ = *p;
82 p++;
83 }
84 if (buf_size > 0)
85 *q = '\0';
86 *pp = p;
87}
88
1ef36a70
RB
89static void get_word_sep(char *buf, int buf_size, const char *sep,
90 const char **pp)
1617ad97 91{
1ef36a70
RB
92 if (**pp == '/') (*pp)++;
93 get_word_until_chars(buf, buf_size, sep, pp);
94}
1617ad97 95
1ef36a70
RB
96static void get_word(char *buf, int buf_size, const char **pp)
97{
98 get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
1617ad97
FB
99}
100
93ced3e8
FB
101/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
102 params>] */
4934884a 103static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
93ced3e8
FB
104{
105 char buf[256];
d1ccf0e0
RD
106 int i;
107 AVCodec *c;
7b49ce2e 108 const char *c_name;
93ced3e8 109
d1ccf0e0
RD
110 /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
111 see if we can handle this kind of payload */
93ced3e8 112 get_word_sep(buf, sizeof(buf), "/", &p);
d1ccf0e0 113 if (payload_type >= RTP_PT_PRIVATE) {
4934884a
RM
114 RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
115 while(handler) {
743b3890 116 if (!strcasecmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
4934884a
RM
117 codec->codec_id = handler->codec_id;
118 rtsp_st->dynamic_handler= handler;
119 if(handler->open) {
120 rtsp_st->dynamic_protocol_context= handler->open();
121 }
d1ccf0e0
RD
122 break;
123 }
4934884a
RM
124 handler= handler->next;
125 }
93ced3e8 126 } else {
d1ccf0e0
RD
127 /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
128 /* search into AVRtpPayloadTypes[] */
7ed19d7f 129 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
d1ccf0e0
RD
130 }
131
132 c = avcodec_find_decoder(codec->codec_id);
133 if (c && c->name)
7b49ce2e 134 c_name = c->name;
d1ccf0e0
RD
135 else
136 c_name = (char *)NULL;
137
138 if (c_name) {
139 get_word_sep(buf, sizeof(buf), "/", &p);
140 i = atoi(buf);
141 switch (codec->codec_type) {
142 case CODEC_TYPE_AUDIO:
143 av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
144 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
145 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
146 if (i > 0) {
147 codec->sample_rate = i;
148 get_word_sep(buf, sizeof(buf), "/", &p);
149 i = atoi(buf);
150 if (i > 0)
151 codec->channels = i;
d0deedcb
RM
152 // TODO: there is a bug here; if it is a mono stream, and less than 22000Hz, faad upconverts to stereo and twice the
153 // frequency. No problem, but the sample rate is being set here by the sdp line. Upcoming patch forthcoming. (rdm)
d1ccf0e0
RD
154 }
155 av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
156 av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
157 break;
158 case CODEC_TYPE_VIDEO:
159 av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
160 break;
161 default:
162 break;
163 }
164 return 0;
93ced3e8 165 }
d1ccf0e0
RD
166
167 return -1;
93ced3e8
FB
168}
169
170/* return the length and optionnaly the data */
171static int hex_to_data(uint8_t *data, const char *p)
172{
173 int c, len, v;
174
175 len = 0;
176 v = 1;
177 for(;;) {
178 skip_spaces(&p);
6a8c8b36 179 if (*p == '\0')
93ced3e8
FB
180 break;
181 c = toupper((unsigned char)*p++);
182 if (c >= '0' && c <= '9')
183 c = c - '0';
184 else if (c >= 'A' && c <= 'F')
185 c = c - 'A' + 10;
186 else
187 break;
188 v = (v << 4) | c;
189 if (v & 0x100) {
190 if (data)
191 data[len] = v;
192 len++;
193 v = 1;
194 }
195 }
196 return len;
197}
198
d1ccf0e0
RD
199static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
200{
201 switch (codec->codec_id) {
202 case CODEC_ID_MPEG4:
cbee7a69 203 case CODEC_ID_AAC:
d1ccf0e0
RD
204 if (!strcmp(attr, "config")) {
205 /* decode the hexa encoded parameter */
206 int len = hex_to_data(NULL, value);
7d09a993
RB
207 if (codec->extradata)
208 av_free(codec->extradata);
d1ccf0e0
RD
209 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
210 if (!codec->extradata)
211 return;
212 codec->extradata_size = len;
213 hex_to_data(codec->extradata, value);
214 }
215 break;
216 default:
217 break;
218 }
219 return;
220}
221
644e7acb 222typedef struct {
7b49ce2e 223 const char *str;
d1ccf0e0
RD
224 uint16_t type;
225 uint32_t offset;
644e7acb 226} AttrNameMap;
d1ccf0e0
RD
227
228/* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
229#define ATTR_NAME_TYPE_INT 0
230#define ATTR_NAME_TYPE_STR 1
644e7acb 231static const AttrNameMap attr_names[]=
d1ccf0e0 232{
be73a544
LA
233 {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, sizelength)},
234 {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, indexlength)},
235 {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, indexdeltalength)},
236 {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, profile_level_id)},
237 {"StreamType", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, streamtype)},
238 {"mode", ATTR_NAME_TYPE_STR, offsetof(RTPPayloadData, mode)},
d1ccf0e0
RD
239 {NULL, -1, -1},
240};
241
d0deedcb
RM
242/** parse the attribute line from the fmtp a line of an sdp resonse. This is broken out as a function
243* because it is used in rtp_h264.c, which is forthcoming.
244*/
245int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size)
246{
247 skip_spaces(p);
78f731de 248 if(**p) {
d0deedcb
RM
249 get_word_sep(attr, attr_size, "=", p);
250 if (**p == '=')
251 (*p)++;
252 get_word_sep(value, value_size, ";", p);
253 if (**p == ';')
254 (*p)++;
255 return 1;
256 }
257 return 0;
258}
259
d1ccf0e0
RD
260/* parse a SDP line and save stream attributes */
261static void sdp_parse_fmtp(AVStream *st, const char *p)
93ced3e8
FB
262{
263 char attr[256];
373afbaf
RB
264 /* Vorbis setup headers can be up to 12KB and are sent base64
265 * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */
266 char value[16384];
d1ccf0e0
RD
267 int i;
268
269 RTSPStream *rtsp_st = st->priv_data;
01f4895c 270 AVCodecContext *codec = st->codec;
be73a544 271 RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
93ced3e8
FB
272
273 /* loop on each attribute */
1ad20f96
RM
274 while(rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value)))
275 {
bb270c08 276 /* grab the codec extra_data from the config parameter of the fmtp line */
d1ccf0e0
RD
277 sdp_parse_fmtp_config(codec, attr, value);
278 /* Looking for a known attribute */
279 for (i = 0; attr_names[i].str; ++i) {
280 if (!strcasecmp(attr, attr_names[i].str)) {
281 if (attr_names[i].type == ATTR_NAME_TYPE_INT)
282 *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
283 else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
284 *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
bb270c08 285 }
93ced3e8 286 }
93ced3e8
FB
287 }
288}
289
31693e00
RM
290/** Parse a string \p in the form of Range:npt=xx-xx, and determine the start
291 * and end time.
292 * Used for seeking in the rtp stream.
293 */
294static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
295{
296 char buf[256];
297
298 skip_spaces(&p);
f7d78f36 299 if (!av_stristart(p, "npt=", &p))
31693e00
RM
300 return;
301
302 *start = AV_NOPTS_VALUE;
303 *end = AV_NOPTS_VALUE;
304
305 get_word_sep(buf, sizeof(buf), "-", &p);
306 *start = parse_date(buf, 1);
307 if (*p == '-') {
308 p++;
309 get_word_sep(buf, sizeof(buf), "-", &p);
310 *end = parse_date(buf, 1);
311 }
312// av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
313// av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
314}
315
93ced3e8
FB
316typedef struct SDPParseState {
317 /* SDP only */
318 struct in_addr default_ip;
319 int default_ttl;
cb760a47 320 int skip_media; ///< set if an unknown m= line occurs
93ced3e8
FB
321} SDPParseState;
322
323static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
1617ad97
FB
324 int letter, const char *buf)
325{
8b1ab7bf 326 RTSPState *rt = s->priv_data;
1617ad97
FB
327 char buf1[64], st_type[64];
328 const char *p;
fb65d2ca
DP
329 enum CodecType codec_type;
330 int payload_type, i;
1617ad97
FB
331 AVStream *st;
332 RTSPStream *rtsp_st;
93ced3e8
FB
333 struct in_addr sdp_ip;
334 int ttl;
335
1617ad97
FB
336#ifdef DEBUG
337 printf("sdp: %c='%s'\n", letter, buf);
338#endif
339
340 p = buf;
cb760a47
RB
341 if (s1->skip_media && letter != 'm')
342 return;
1617ad97 343 switch(letter) {
93ced3e8
FB
344 case 'c':
345 get_word(buf1, sizeof(buf1), &p);
346 if (strcmp(buf1, "IN") != 0)
347 return;
348 get_word(buf1, sizeof(buf1), &p);
349 if (strcmp(buf1, "IP4") != 0)
350 return;
351 get_word_sep(buf1, sizeof(buf1), "/", &p);
352 if (inet_aton(buf1, &sdp_ip) == 0)
353 return;
354 ttl = 16;
355 if (*p == '/') {
356 p++;
357 get_word_sep(buf1, sizeof(buf1), "/", &p);
358 ttl = atoi(buf1);
359 }
360 if (s->nb_streams == 0) {
361 s1->default_ip = sdp_ip;
362 s1->default_ttl = ttl;
363 } else {
364 st = s->streams[s->nb_streams - 1];
365 rtsp_st = st->priv_data;
366 rtsp_st->sdp_ip = sdp_ip;
367 rtsp_st->sdp_ttl = ttl;
368 }
369 break;
1617ad97 370 case 's':
da61e413 371 av_metadata_set(&s->metadata, "title", p);
1617ad97
FB
372 break;
373 case 'i':
374 if (s->nb_streams == 0) {
da61e413 375 av_metadata_set(&s->metadata, "comment", p);
1617ad97
FB
376 break;
377 }
378 break;
379 case 'm':
380 /* new stream */
cb760a47 381 s1->skip_media = 0;
1617ad97
FB
382 get_word(st_type, sizeof(st_type), &p);
383 if (!strcmp(st_type, "audio")) {
384 codec_type = CODEC_TYPE_AUDIO;
385 } else if (!strcmp(st_type, "video")) {
386 codec_type = CODEC_TYPE_VIDEO;
090438cc
RB
387 } else if (!strcmp(st_type, "application")) {
388 codec_type = CODEC_TYPE_DATA;
1617ad97 389 } else {
cb760a47 390 s1->skip_media = 1;
1617ad97
FB
391 return;
392 }
1617ad97
FB
393 rtsp_st = av_mallocz(sizeof(RTSPStream));
394 if (!rtsp_st)
395 return;
8b1ab7bf
FB
396 rtsp_st->stream_index = -1;
397 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
93ced3e8
FB
398
399 rtsp_st->sdp_ip = s1->default_ip;
400 rtsp_st->sdp_ttl = s1->default_ttl;
401
93ced3e8
FB
402 get_word(buf1, sizeof(buf1), &p); /* port */
403 rtsp_st->sdp_port = atoi(buf1);
404
405 get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
115329f1 406
93ced3e8
FB
407 /* XXX: handle list of formats */
408 get_word(buf1, sizeof(buf1), &p); /* format list */
409 rtsp_st->sdp_payload_type = atoi(buf1);
93ced3e8 410
7ed19d7f 411 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
8b1ab7bf
FB
412 /* no corresponding stream */
413 } else {
414 st = av_new_stream(s, 0);
415 if (!st)
416 return;
417 st->priv_data = rtsp_st;
418 rtsp_st->stream_index = st->index;
01f4895c 419 st->codec->codec_type = codec_type;
d1ccf0e0 420 if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
8b1ab7bf 421 /* if standard payload type, we can find the codec right now */
bf6d9818 422 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
8b1ab7bf
FB
423 }
424 }
1617ad97 425 /* put a default control url */
75e61b0e 426 av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url));
1617ad97
FB
427 break;
428 case 'a':
f7d78f36 429 if (av_strstart(p, "control:", &p) && s->nb_streams > 0) {
1617ad97
FB
430 char proto[32];
431 /* get the control url */
432 st = s->streams[s->nb_streams - 1];
433 rtsp_st = st->priv_data;
115329f1 434
1617ad97 435 /* XXX: may need to add full url resolution */
6ba5cbc6 436 url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
1617ad97
FB
437 if (proto[0] == '\0') {
438 /* relative control URL */
75e61b0e
MR
439 av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url));
440 av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
1617ad97 441 } else {
75e61b0e 442 av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
1617ad97 443 }
83d14c85 444 } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
93ced3e8 445 /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
115329f1 446 get_word(buf1, sizeof(buf1), &p);
93ced3e8 447 payload_type = atoi(buf1);
83d14c85 448 st = s->streams[s->nb_streams - 1];
ff16f551
RB
449 rtsp_st = st->priv_data;
450 sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
f7d78f36 451 } else if (av_strstart(p, "fmtp:", &p)) {
93ced3e8 452 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
115329f1 453 get_word(buf1, sizeof(buf1), &p);
93ced3e8
FB
454 payload_type = atoi(buf1);
455 for(i = 0; i < s->nb_streams;i++) {
456 st = s->streams[i];
457 rtsp_st = st->priv_data;
458 if (rtsp_st->sdp_payload_type == payload_type) {
4934884a 459 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
7b2a0708 460 if(!rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, rtsp_st->dynamic_protocol_context, buf)) {
4934884a
RM
461 sdp_parse_fmtp(st, p);
462 }
463 } else {
ed787542 464 sdp_parse_fmtp(st, p);
4934884a 465 }
93ced3e8
FB
466 }
467 }
f7d78f36 468 } else if(av_strstart(p, "framesize:", &p)) {
d0deedcb
RM
469 // let dynamic protocol handlers have a stab at the line.
470 get_word(buf1, sizeof(buf1), &p);
471 payload_type = atoi(buf1);
472 for(i = 0; i < s->nb_streams;i++) {
473 st = s->streams[i];
474 rtsp_st = st->priv_data;
475 if (rtsp_st->sdp_payload_type == payload_type) {
476 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
7b2a0708 477 rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, rtsp_st->dynamic_protocol_context, buf);
d0deedcb
RM
478 }
479 }
480 }
f7d78f36 481 } else if(av_strstart(p, "range:", &p)) {
31693e00
RM
482 int64_t start, end;
483
484 // this is so that seeking on a streamed file can work.
485 rtsp_parse_range_npt(p, &start, &end);
486 s->start_time= start;
487 s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek)
119b4668
RB
488 } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
489 if (atoi(p) == 1)
490 rt->transport = RTSP_TRANSPORT_RDT;
1a30d541
RB
491 } else {
492 if (rt->server_type == RTSP_SERVER_WMS)
493 ff_wms_parse_sdp_a_line(s, p);
494 if (s->nb_streams > 0) {
c4a3d032
RB
495 if (rt->server_type == RTSP_SERVER_REAL)
496 ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
497
498 rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
499 if (rtsp_st->dynamic_handler &&
500 rtsp_st->dynamic_handler->parse_sdp_a_line)
501 rtsp_st->dynamic_handler->parse_sdp_a_line(s, s->nb_streams - 1,
502 rtsp_st->dynamic_protocol_context, buf);
1a30d541 503 }
1617ad97
FB
504 }
505 break;
506 }
507}
508
5c91a675 509static int sdp_parse(AVFormatContext *s, const char *content)
1617ad97
FB
510{
511 const char *p;
512 int letter;
9211bcdd
RB
513 /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
514 * contain long SDP lines containing complete ASF Headers (several
515 * kB) or arrays of MDPR (RM stream descriptor) headers plus
516 * "rulebooks" describing their properties. Therefore, the SDP line
373afbaf
RB
517 * buffer is large.
518 *
519 * The Vorbis FMTP line can be up to 16KB - see sdp_parse_fmtp. */
520 char buf[16384], *q;
93ced3e8 521 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
115329f1 522
93ced3e8 523 memset(s1, 0, sizeof(SDPParseState));
1617ad97
FB
524 p = content;
525 for(;;) {
526 skip_spaces(&p);
527 letter = *p;
528 if (letter == '\0')
529 break;
530 p++;
531 if (*p != '=')
532 goto next_line;
533 p++;
534 /* get the content */
535 q = buf;
b6892136 536 while (*p != '\n' && *p != '\r' && *p != '\0') {
1617ad97
FB
537 if ((q - buf) < sizeof(buf) - 1)
538 *q++ = *p;
539 p++;
540 }
541 *q = '\0';
93ced3e8 542 sdp_parse_line(s, s1, letter, buf);
1617ad97
FB
543 next_line:
544 while (*p != '\n' && *p != '\0')
545 p++;
546 if (*p == '\n')
547 p++;
548 }
549 return 0;
550}
551
552static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
553{
554 const char *p;
555 int v;
556
557 p = *pp;
558 skip_spaces(&p);
559 v = strtol(p, (char **)&p, 10);
560 if (*p == '-') {
561 p++;
562 *min_ptr = v;
563 v = strtol(p, (char **)&p, 10);
564 *max_ptr = v;
565 } else {
566 *min_ptr = v;
567 *max_ptr = v;
568 }
569 *pp = p;
570}
571
572/* XXX: only one transport specification is parsed */
a9e534d5 573static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
1617ad97
FB
574{
575 char transport_protocol[16];
576 char profile[16];
577 char lower_transport[16];
578 char parameter[16];
579 RTSPTransportField *th;
580 char buf[256];
115329f1 581
1617ad97 582 reply->nb_transports = 0;
115329f1 583
1617ad97
FB
584 for(;;) {
585 skip_spaces(&p);
586 if (*p == '\0')
587 break;
588
589 th = &reply->transports[reply->nb_transports];
590
115329f1 591 get_word_sep(transport_protocol, sizeof(transport_protocol),
1617ad97 592 "/", &p);
e1502118 593 if (!strcasecmp (transport_protocol, "rtp")) {
7ecc634e
LB
594 get_word_sep(profile, sizeof(profile), "/;,", &p);
595 lower_transport[0] = '\0';
596 /* rtp/avp/<protocol> */
597 if (*p == '/') {
7ecc634e
LB
598 get_word_sep(lower_transport, sizeof(lower_transport),
599 ";,", &p);
119b4668
RB
600 }
601 th->transport = RTSP_TRANSPORT_RTP;
602 } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
603 !strcasecmp (transport_protocol, "x-real-rdt")) {
7ecc634e 604 /* x-pn-tng/<protocol> */
e1502118
LB
605 get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
606 profile[0] = '\0';
119b4668 607 th->transport = RTSP_TRANSPORT_RDT;
1617ad97 608 }
b6892136 609 if (!strcasecmp(lower_transport, "TCP"))
90abbdba 610 th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
1617ad97 611 else
90abbdba 612 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
115329f1 613
1617ad97
FB
614 if (*p == ';')
615 p++;
616 /* get each parameter */
617 while (*p != '\0' && *p != ',') {
618 get_word_sep(parameter, sizeof(parameter), "=;,", &p);
619 if (!strcmp(parameter, "port")) {
620 if (*p == '=') {
621 p++;
622 rtsp_parse_range(&th->port_min, &th->port_max, &p);
623 }
624 } else if (!strcmp(parameter, "client_port")) {
625 if (*p == '=') {
626 p++;
115329f1 627 rtsp_parse_range(&th->client_port_min,
1617ad97
FB
628 &th->client_port_max, &p);
629 }
630 } else if (!strcmp(parameter, "server_port")) {
631 if (*p == '=') {
632 p++;
115329f1 633 rtsp_parse_range(&th->server_port_min,
1617ad97
FB
634 &th->server_port_max, &p);
635 }
636 } else if (!strcmp(parameter, "interleaved")) {
637 if (*p == '=') {
638 p++;
115329f1 639 rtsp_parse_range(&th->interleaved_min,
1617ad97
FB
640 &th->interleaved_max, &p);
641 }
642 } else if (!strcmp(parameter, "multicast")) {
90abbdba
RB
643 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
644 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
1617ad97
FB
645 } else if (!strcmp(parameter, "ttl")) {
646 if (*p == '=') {
647 p++;
648 th->ttl = strtol(p, (char **)&p, 10);
649 }
650 } else if (!strcmp(parameter, "destination")) {
651 struct in_addr ipaddr;
652
653 if (*p == '=') {
654 p++;
655 get_word_sep(buf, sizeof(buf), ";,", &p);
115329f1 656 if (inet_aton(buf, &ipaddr))
1617ad97
FB
657 th->destination = ntohl(ipaddr.s_addr);
658 }
659 }
660 while (*p != ';' && *p != '\0' && *p != ',')
661 p++;
662 if (*p == ';')
663 p++;
664 }
665 if (*p == ',')
666 p++;
667
668 reply->nb_transports++;
669 }
670}
671
a9e534d5 672void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
1617ad97
FB
673{
674 const char *p;
675
676 /* NOTE: we do case independent match for broken servers */
677 p = buf;
f7d78f36 678 if (av_stristart(p, "Session:", &p)) {
1617ad97 679 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
f7d78f36 680 } else if (av_stristart(p, "Content-Length:", &p)) {
1617ad97 681 reply->content_length = strtol(p, NULL, 10);
f7d78f36 682 } else if (av_stristart(p, "Transport:", &p)) {
1617ad97 683 rtsp_parse_transport(reply, p);
f7d78f36 684 } else if (av_stristart(p, "CSeq:", &p)) {
1617ad97 685 reply->seq = strtol(p, NULL, 10);
f7d78f36 686 } else if (av_stristart(p, "Range:", &p)) {
31693e00 687 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
30aa6aed
RB
688 } else if (av_stristart(p, "RealChallenge1:", &p)) {
689 skip_spaces(&p);
690 av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
7a86bafa
RB
691 } else if (av_stristart(p, "Server:", &p)) {
692 skip_spaces(&p);
693 av_strlcpy(reply->server, p, sizeof(reply->server));
1617ad97
FB
694 }
695}
696
2a42b5c3
LS
697static int url_readbuf(URLContext *h, unsigned char *buf, int size)
698{
699 int ret, len;
700
701 len = 0;
702 while (len < size) {
703 ret = url_read(h, buf+len, size-len);
704 if (ret < 1)
705 return ret;
706 len += ret;
707 }
708 return len;
709}
710
b7b8fc34
FB
711/* skip a RTP/TCP interleaved packet */
712static void rtsp_skip_packet(AVFormatContext *s)
713{
714 RTSPState *rt = s->priv_data;
715 int ret, len, len1;
716 uint8_t buf[1024];
717
2a42b5c3 718 ret = url_readbuf(rt->rtsp_hd, buf, 3);
b7b8fc34
FB
719 if (ret != 3)
720 return;
80fb8234 721 len = AV_RB16(buf + 1);
b7b8fc34
FB
722#ifdef DEBUG
723 printf("skipping RTP packet len=%d\n", len);
724#endif
725 /* skip payload */
726 while (len > 0) {
727 len1 = len;
728 if (len1 > sizeof(buf))
729 len1 = sizeof(buf);
2a42b5c3 730 ret = url_readbuf(rt->rtsp_hd, buf, len1);
b7b8fc34
FB
731 if (ret != len1)
732 return;
733 len -= len1;
734 }
735}
1617ad97 736
7e726132
RB
737/**
738 * Read a RTSP message from the server, or prepare to read data
739 * packets if we're reading data interleaved over the TCP/RTSP
740 * connection as well.
741 *
742 * @param s RTSP demuxer context
743 * @param reply pointer where the RTSP message header will be stored
744 * @param content_ptr pointer where the RTSP message body, if any, will
745 * be stored (length is in \p reply)
746 * @param return_on_interleaved_data whether the function may return if we
747 * encounter a data marker ('$'), which precedes data
748 * packets over interleaved TCP/RTSP connections. If this
749 * is set, this function will return 1 after encountering
750 * a '$'. If it is not set, the function will skip any
751 * data packets (if they are encountered), until a reply
752 * has been fully parsed. If no more data is available
753 * without parsing a reply, it will return an error.
754 *
755 * @returns 1 if a data packets is ready to be received, -1 on error,
756 * and 0 on success.
757 */
758static int
29b9f58b 759rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
7e726132 760 unsigned char **content_ptr, int return_on_interleaved_data)
1617ad97
FB
761{
762 RTSPState *rt = s->priv_data;
763 char buf[4096], buf1[1024], *q;
764 unsigned char ch;
765 const char *p;
7e726132 766 int ret, content_length, line_count = 0;
1617ad97
FB
767 unsigned char *content = NULL;
768
d541a7d2 769 memset(reply, 0, sizeof(*reply));
1617ad97 770
1617ad97 771 /* parse reply (XXX: use buffers) */
1617ad97
FB
772 rt->last_reply[0] = '\0';
773 for(;;) {
774 q = buf;
775 for(;;) {
7e726132
RB
776 ret = url_readbuf(rt->rtsp_hd, &ch, 1);
777#ifdef DEBUG_RTP_TCP
778 printf("ret=%d c=%02x [%c]\n", ret, ch, ch);
779#endif
780 if (ret != 1)
781 return -1;
1617ad97
FB
782 if (ch == '\n')
783 break;
b7b8fc34
FB
784 if (ch == '$') {
785 /* XXX: only parse it if first char on line ? */
7e726132
RB
786 if (return_on_interleaved_data) {
787 return 1;
788 } else
b7b8fc34
FB
789 rtsp_skip_packet(s);
790 } else if (ch != '\r') {
1617ad97
FB
791 if ((q - buf) < sizeof(buf) - 1)
792 *q++ = ch;
793 }
794 }
795 *q = '\0';
796#ifdef DEBUG
797 printf("line='%s'\n", buf);
798#endif
799 /* test if last line */
800 if (buf[0] == '\0')
801 break;
802 p = buf;
803 if (line_count == 0) {
804 /* get reply code */
805 get_word(buf1, sizeof(buf1), &p);
806 get_word(buf1, sizeof(buf1), &p);
807 reply->status_code = atoi(buf1);
808 } else {
809 rtsp_parse_line(reply, p);
75e61b0e
MR
810 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
811 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
1617ad97
FB
812 }
813 line_count++;
814 }
115329f1 815
1617ad97 816 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
75e61b0e 817 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
115329f1 818
1617ad97
FB
819 content_length = reply->content_length;
820 if (content_length > 0) {
821 /* leave some room for a trailing '\0' (useful for simple parsing) */
822 content = av_malloc(content_length + 1);
2a42b5c3 823 (void)url_readbuf(rt->rtsp_hd, content, content_length);
1617ad97
FB
824 content[content_length] = '\0';
825 }
826 if (content_ptr)
827 *content_ptr = content;
e2e2e7dd
AB
828 else
829 av_free(content);
7e726132
RB
830
831 return 0;
1617ad97
FB
832}
833
29b9f58b
RB
834static void rtsp_send_cmd(AVFormatContext *s,
835 const char *cmd, RTSPMessageHeader *reply,
836 unsigned char **content_ptr)
837{
838 RTSPState *rt = s->priv_data;
839 char buf[4096], buf1[1024];
840
841 rt->seq++;
842 av_strlcpy(buf, cmd, sizeof(buf));
843 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
844 av_strlcat(buf, buf1, sizeof(buf));
845 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
846 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
847 av_strlcat(buf, buf1, sizeof(buf));
848 }
849 av_strlcat(buf, "\r\n", sizeof(buf));
850#ifdef DEBUG
851 printf("Sending:\n%s--\n", buf);
852#endif
853 url_write(rt->rtsp_hd, buf, strlen(buf));
854
7e726132 855 rtsp_read_reply(s, reply, content_ptr, 0);
29b9f58b
RB
856}
857
1617ad97 858
8b1ab7bf
FB
859/* close and free RTSP streams */
860static void rtsp_close_streams(RTSPState *rt)
861{
862 int i;
863 RTSPStream *rtsp_st;
864
865 for(i=0;i<rt->nb_rtsp_streams;i++) {
866 rtsp_st = rt->rtsp_streams[i];
867 if (rtsp_st) {
0a861b6f 868 if (rtsp_st->transport_priv) {
accc248f 869 if (rt->transport == RTSP_TRANSPORT_RDT)
0a861b6f 870 ff_rdt_parse_close(rtsp_st->transport_priv);
accc248f 871 else
0a861b6f 872 rtp_parse_close(rtsp_st->transport_priv);
accc248f 873 }
8b1ab7bf
FB
874 if (rtsp_st->rtp_handle)
875 url_close(rtsp_st->rtp_handle);
4934884a
RM
876 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
877 rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
8b1ab7bf 878 }
8b1ab7bf
FB
879 }
880 av_free(rt->rtsp_streams);
1a30d541
RB
881 if (rt->asf_ctx) {
882 av_close_input_stream (rt->asf_ctx);
883 rt->asf_ctx = NULL;
884 }
8b1ab7bf
FB
885}
886
ee0cb67f
RB
887static int
888rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
889{
accc248f 890 RTSPState *rt = s->priv_data;
ee0cb67f
RB
891 AVStream *st = NULL;
892
a6789dca
RB
893 /* open the RTP context */
894 if (rtsp_st->stream_index >= 0)
895 st = s->streams[rtsp_st->stream_index];
896 if (!st)
897 s->ctx_flags |= AVFMTCTX_NOHEADER;
accc248f
RB
898
899 if (rt->transport == RTSP_TRANSPORT_RDT)
0a861b6f 900 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
accc248f
RB
901 rtsp_st->dynamic_protocol_context,
902 rtsp_st->dynamic_handler);
903 else
0a861b6f 904 rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
5c918b27
RB
905 rtsp_st->sdp_payload_type,
906 &rtsp_st->rtp_payload_data);
a6789dca 907
0a861b6f 908 if (!rtsp_st->transport_priv) {
a6789dca 909 return AVERROR(ENOMEM);
accc248f 910 } else if (rt->transport != RTSP_TRANSPORT_RDT) {
a6789dca 911 if(rtsp_st->dynamic_handler) {
0a861b6f 912 rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
99a1d191
RB
913 rtsp_st->dynamic_protocol_context,
914 rtsp_st->dynamic_handler);
ee0cb67f 915 }
a6789dca 916 }
ee0cb67f
RB
917
918 return 0;
919}
920
53620bba
RB
921/**
922 * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
923 */
924static int
e9dea59f 925make_setup_request (AVFormatContext *s, const char *host, int port,
90abbdba 926 int lower_transport, const char *real_challenge)
1617ad97
FB
927{
928 RTSPState *rt = s->priv_data;
f830c9a4 929 int rtx, j, i, err, interleave = 0;
1617ad97 930 RTSPStream *rtsp_st;
a9e534d5 931 RTSPMessageHeader reply1, *reply = &reply1;
53620bba 932 char cmd[2048];
e9dea59f
RB
933 const char *trans_pref;
934
119b4668 935 if (rt->transport == RTSP_TRANSPORT_RDT)
e9dea59f
RB
936 trans_pref = "x-pn-tng";
937 else
938 trans_pref = "RTP/AVP";
115329f1 939
1617ad97
FB
940 /* for each stream, make the setup request */
941 /* XXX: we assume the same server is used for the control of each
942 RTSP stream */
d1ccf0e0
RD
943
944 for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
1617ad97
FB
945 char transport[2048];
946
f830c9a4
RB
947 /**
948 * WMS serves all UDP data over a single connection, the RTX, which
949 * isn't necessarily the first in the SDP but has to be the first
950 * to be set up, else the second/third SETUP will fail with a 461.
951 */
952 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
953 rt->server_type == RTSP_SERVER_WMS) {
954 if (i == 0) {
955 /* rtx first */
956 for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
957 int len = strlen(rt->rtsp_streams[rtx]->control_url);
958 if (len >= 4 &&
959 !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4, "/rtx"))
960 break;
961 }
962 if (rtx == rt->nb_rtsp_streams)
963 return -1; /* no RTX found */
964 rtsp_st = rt->rtsp_streams[rtx];
965 } else
966 rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
967 } else
2fea9650 968 rtsp_st = rt->rtsp_streams[i];
1617ad97 969
1617ad97 970 /* RTP/UDP */
90abbdba 971 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
85fb7b34 972 char buf[256];
85fb7b34 973
f830c9a4
RB
974 if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
975 port = reply->transports[0].client_port_min;
976 goto have_port;
977 }
978
85fb7b34 979 /* first try in specified port range */
d1ccf0e0
RD
980 if (RTSP_RTP_PORT_MIN != 0) {
981 while(j <= RTSP_RTP_PORT_MAX) {
b316aa1a 982 snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j);
ecdcbbf6 983 j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
dbf30963 984 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
85fb7b34 985 goto rtp_opened;
d1ccf0e0 986 }
85fb7b34 987 }
1617ad97 988 }
85fb7b34 989
d1ccf0e0
RD
990/* then try on any port
991** if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
992** err = AVERROR_INVALIDDATA;
993** goto fail;
994** }
995*/
85fb7b34
FB
996
997 rtp_opened:
8b1ab7bf 998 port = rtp_get_local_port(rtsp_st->rtp_handle);
f830c9a4 999 have_port:
0ad306bc 1000 snprintf(transport, sizeof(transport) - 1,
eee2cbff
RB
1001 "%s/UDP;", trans_pref);
1002 if (rt->server_type != RTSP_SERVER_REAL)
1003 av_strlcat(transport, "unicast;", sizeof(transport));
1004 av_strlcatf(transport, sizeof(transport),
1005 "client_port=%d", port);
f830c9a4
RB
1006 if (rt->transport == RTSP_TRANSPORT_RTP &&
1007 !(rt->server_type == RTSP_SERVER_WMS && i > 0))
e9dea59f 1008 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1617ad97
FB
1009 }
1010
1011 /* RTP/TCP */
90abbdba 1012 else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
090438cc
RB
1013 /** For WMS streams, the application streams are only used for
1014 * UDP. When trying to set it up for TCP streams, the server
1015 * will return an error. Therefore, we skip those streams. */
1016 if (rt->server_type == RTSP_SERVER_WMS &&
1017 s->streams[rtsp_st->stream_index]->codec->codec_type == CODEC_TYPE_DATA)
1018 continue;
0ad306bc 1019 snprintf(transport, sizeof(transport) - 1,
d1c6e47c
RB
1020 "%s/TCP;", trans_pref);
1021 if (rt->server_type == RTSP_SERVER_WMS)
1022 av_strlcat(transport, "unicast;", sizeof(transport));
1023 av_strlcatf(transport, sizeof(transport),
1024 "interleaved=%d-%d",
1025 interleave, interleave + 1);
1026 interleave += 2;
1617ad97
FB
1027 }
1028
90abbdba 1029 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
0ad306bc 1030 snprintf(transport, sizeof(transport) - 1,
e9dea59f 1031 "%s/UDP;multicast", trans_pref);
1617ad97 1032 }
d1c6e47c
RB
1033 if (rt->server_type == RTSP_SERVER_REAL ||
1034 rt->server_type == RTSP_SERVER_WMS)
e9dea59f 1035 av_strlcat(transport, ";mode=play", sizeof(transport));
115329f1 1036 snprintf(cmd, sizeof(cmd),
b6892136
FB
1037 "SETUP %s RTSP/1.0\r\n"
1038 "Transport: %s\r\n",
1617ad97 1039 rtsp_st->control_url, transport);
2e889ae4 1040 if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
e9dea59f
RB
1041 char real_res[41], real_csum[9];
1042 ff_rdt_calc_response_and_checksum(real_res, real_csum,
1043 real_challenge);
1044 av_strlcatf(cmd, sizeof(cmd),
1045 "If-Match: %s\r\n"
1046 "RealChallenge2: %s, sd=%s\r\n",
1047 rt->session_id, real_res, real_csum);
1048 }
1617ad97 1049 rtsp_send_cmd(s, cmd, reply, NULL);
8a8754d8
RB
1050 if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
1051 err = 1;
1052 goto fail;
7e6ca34f
RB
1053 } else if (reply->status_code != RTSP_STATUS_OK ||
1054 reply->nb_transports != 1) {
1617ad97
FB
1055 err = AVERROR_INVALIDDATA;
1056 goto fail;
1057 }
1058
1059 /* XXX: same protocol for all streams is required */
1060 if (i > 0) {
119b4668
RB
1061 if (reply->transports[0].lower_transport != rt->lower_transport ||
1062 reply->transports[0].transport != rt->transport) {
1617ad97
FB
1063 err = AVERROR_INVALIDDATA;
1064 goto fail;
1065 }
1066 } else {
90abbdba 1067 rt->lower_transport = reply->transports[0].lower_transport;
119b4668 1068 rt->transport = reply->transports[0].transport;
1617ad97
FB
1069 }
1070
1071 /* close RTP connection if not choosen */
90abbdba
RB
1072 if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
1073 (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
8b1ab7bf
FB
1074 url_close(rtsp_st->rtp_handle);
1075 rtsp_st->rtp_handle = NULL;
1617ad97
FB
1076 }
1077
90abbdba
RB
1078 switch(reply->transports[0].lower_transport) {
1079 case RTSP_LOWER_TRANSPORT_TCP:
1617ad97
FB
1080 rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
1081 rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
1082 break;
115329f1 1083
90abbdba 1084 case RTSP_LOWER_TRANSPORT_UDP:
1617ad97
FB
1085 {
1086 char url[1024];
115329f1 1087
1617ad97 1088 /* XXX: also use address if specified */
115329f1 1089 snprintf(url, sizeof(url), "rtp://%s:%d",
1617ad97 1090 host, reply->transports[0].server_port_min);
f830c9a4
RB
1091 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
1092 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
1617ad97
FB
1093 err = AVERROR_INVALIDDATA;
1094 goto fail;
1095 }
1096 }
1097 break;
90abbdba 1098 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1617ad97
FB
1099 {
1100 char url[1024];
d02678ec 1101 struct in_addr in;
1617ad97 1102
d02678ec 1103 in.s_addr = htonl(reply->transports[0].destination);
35b74c3d 1104 snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d",
d02678ec
LB
1105 inet_ntoa(in),
1106 reply->transports[0].port_min,
1107 reply->transports[0].ttl);
dbf30963 1108 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1617ad97
FB
1109 err = AVERROR_INVALIDDATA;
1110 goto fail;
1111 }
1112 }
1113 break;
1114 }
d1ccf0e0 1115
ee0cb67f 1116 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
8b1ab7bf 1117 goto fail;
1617ad97
FB
1118 }
1119
2e889ae4 1120 if (rt->server_type == RTSP_SERVER_REAL)
1256d16b
RB
1121 rt->need_subscription = 1;
1122
53620bba
RB
1123 return 0;
1124
1125fail:
8a8754d8
RB
1126 for (i=0; i<rt->nb_rtsp_streams; i++) {
1127 if (rt->rtsp_streams[i]->rtp_handle) {
1128 url_close(rt->rtsp_streams[i]->rtp_handle);
1129 rt->rtsp_streams[i]->rtp_handle = NULL;
1130 }
1131 }
53620bba
RB
1132 return err;
1133}
1134
1135static int rtsp_read_header(AVFormatContext *s,
1136 AVFormatParameters *ap)
1137{
1138 RTSPState *rt = s->priv_data;
1139 char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
1140 URLContext *rtsp_hd;
1141 int port, ret, err;
a9e534d5 1142 RTSPMessageHeader reply1, *reply = &reply1;
53620bba 1143 unsigned char *content = NULL;
90abbdba 1144 int lower_transport_mask = 0;
1cf151e9 1145 char real_challenge[64];
53620bba
RB
1146
1147 /* extract hostname and port */
1148 url_split(NULL, 0, NULL, 0,
1149 host, sizeof(host), &port, path, sizeof(path), s->filename);
1150 if (port < 0)
1151 port = RTSP_DEFAULT_PORT;
1152
1153 /* search for options */
1154 option_list = strchr(path, '?');
1155 if (option_list) {
1156 /* remove the options from the path */
1157 *option_list++ = 0;
1158 while(option_list) {
1159 /* move the option pointer */
1160 option = option_list;
1161 option_list = strchr(option_list, '&');
1162 if (option_list)
1163 *(option_list++) = 0;
1164 /* handle the options */
1165 if (strcmp(option, "udp") == 0)
90abbdba 1166 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP);
53620bba 1167 else if (strcmp(option, "multicast") == 0)
90abbdba 1168 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
53620bba 1169 else if (strcmp(option, "tcp") == 0)
90abbdba 1170 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_TCP);
53620bba
RB
1171 }
1172 }
1173
90abbdba 1174 if (!lower_transport_mask)
2a1d51c5 1175 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
53620bba
RB
1176
1177 /* open the tcp connexion */
1178 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
1179 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
1180 return AVERROR(EIO);
1181 rt->rtsp_hd = rtsp_hd;
1182 rt->seq = 0;
1183
1cf151e9
RB
1184 /* request options supported by the server; this also detects server type */
1185 for (rt->server_type = RTSP_SERVER_RTP;;) {
1186 snprintf(cmd, sizeof(cmd),
1187 "OPTIONS %s RTSP/1.0\r\n", s->filename);
2e889ae4 1188 if (rt->server_type == RTSP_SERVER_REAL)
1cf151e9
RB
1189 av_strlcat(cmd,
1190 /**
1191 * The following entries are required for proper
1192 * streaming from a Realmedia server. They are
1193 * interdependent in some way although we currently
1194 * don't quite understand how. Values were copied
1195 * from mplayer SVN r23589.
1196 * @param CompanyID is a 16-byte ID in base64
1197 * @param ClientChallenge is a 16-byte ID in hex
1198 */
1199 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
1200 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
1201 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
1202 "GUID: 00000000-0000-0000-0000-000000000000\r\n",
1203 sizeof(cmd));
1204 rtsp_send_cmd(s, cmd, reply, NULL);
1205 if (reply->status_code != RTSP_STATUS_OK) {
1206 err = AVERROR_INVALIDDATA;
1207 goto fail;
1208 }
1209
1210 /* detect server type if not standard-compliant RTP */
2e889ae4
RB
1211 if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
1212 rt->server_type = RTSP_SERVER_REAL;
1cf151e9 1213 continue;
7a86bafa
RB
1214 } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
1215 rt->server_type = RTSP_SERVER_WMS;
2e889ae4 1216 } else if (rt->server_type == RTSP_SERVER_REAL) {
1cf151e9
RB
1217 strcpy(real_challenge, reply->real_challenge);
1218 }
1219 break;
1220 }
1221
53620bba
RB
1222 /* describe the stream */
1223 snprintf(cmd, sizeof(cmd),
1224 "DESCRIBE %s RTSP/1.0\r\n"
1225 "Accept: application/sdp\r\n",
1226 s->filename);
2e889ae4 1227 if (rt->server_type == RTSP_SERVER_REAL) {
897ade1b
RB
1228 /**
1229 * The Require: attribute is needed for proper streaming from
1230 * Realmedia servers.
1231 */
1232 av_strlcat(cmd,
1233 "Require: com.real.retain-entity-for-setup\r\n",
1234 sizeof(cmd));
1235 }
53620bba
RB
1236 rtsp_send_cmd(s, cmd, reply, &content);
1237 if (!content) {
1238 err = AVERROR_INVALIDDATA;
1239 goto fail;
1240 }
1241 if (reply->status_code != RTSP_STATUS_OK) {
1242 err = AVERROR_INVALIDDATA;
1243 goto fail;
1244 }
1245
1246 /* now we got the SDP description, we parse it */
1247 ret = sdp_parse(s, (const char *)content);
1248 av_freep(&content);
1249 if (ret < 0) {
1250 err = AVERROR_INVALIDDATA;
1251 goto fail;
1252 }
1253
8a8754d8 1254 do {
90abbdba 1255 int lower_transport = ff_log2_tab[lower_transport_mask & ~(lower_transport_mask - 1)];
8a8754d8 1256
90abbdba 1257 err = make_setup_request(s, host, port, lower_transport,
2e889ae4 1258 rt->server_type == RTSP_SERVER_REAL ?
e9dea59f 1259 real_challenge : NULL);
8a8754d8 1260 if (err < 0)
7e6ca34f 1261 goto fail;
90abbdba
RB
1262 lower_transport_mask &= ~(1 << lower_transport);
1263 if (lower_transport_mask == 0 && err == 1) {
5ee0e139 1264 err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
8a8754d8
RB
1265 goto fail;
1266 }
1267 } while (err);
53620bba 1268
ff762d6e
FB
1269 rt->state = RTSP_STATE_IDLE;
1270 rt->seek_timestamp = 0; /* default is to start stream at position
1271 zero */
c04c3282 1272 if (ap->initial_pause) {
ff762d6e
FB
1273 /* do not start immediately */
1274 } else {
1275 if (rtsp_read_play(s) < 0) {
1276 err = AVERROR_INVALIDDATA;
1617ad97
FB
1277 goto fail;
1278 }
1279 }
1617ad97
FB
1280 return 0;
1281 fail:
8b1ab7bf 1282 rtsp_close_streams(rt);
1617ad97
FB
1283 av_freep(&content);
1284 url_close(rt->rtsp_hd);
1285 return err;
1286}
1287
8b1ab7bf
FB
1288static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1289 uint8_t *buf, int buf_size)
1617ad97
FB
1290{
1291 RTSPState *rt = s->priv_data;
b6892136 1292 int id, len, i, ret;
1617ad97 1293 RTSPStream *rtsp_st;
1617ad97 1294
b6892136
FB
1295#ifdef DEBUG_RTP_TCP
1296 printf("tcp_read_packet:\n");
1297#endif
1617ad97
FB
1298 redo:
1299 for(;;) {
7e726132
RB
1300 RTSPMessageHeader reply;
1301
1302 ret = rtsp_read_reply(s, &reply, NULL, 1);
1303 if (ret == -1)
8b1ab7bf 1304 return -1;
7e726132 1305 if (ret == 1) /* received '$' */
1617ad97 1306 break;
7e726132 1307 /* XXX: parse message */
1617ad97 1308 }
2a42b5c3 1309 ret = url_readbuf(rt->rtsp_hd, buf, 3);
b6892136 1310 if (ret != 3)
8b1ab7bf 1311 return -1;
b6892136 1312 id = buf[0];
80fb8234 1313 len = AV_RB16(buf + 1);
b6892136
FB
1314#ifdef DEBUG_RTP_TCP
1315 printf("id=%d len=%d\n", id, len);
1316#endif
8b1ab7bf 1317 if (len > buf_size || len < 12)
1617ad97
FB
1318 goto redo;
1319 /* get the data */
2a42b5c3 1320 ret = url_readbuf(rt->rtsp_hd, buf, len);
b6892136 1321 if (ret != len)
8b1ab7bf 1322 return -1;
985b05d3 1323 if (rt->transport == RTSP_TRANSPORT_RDT &&
114732f4 1324 ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
985b05d3 1325 return -1;
115329f1 1326
1617ad97 1327 /* find the matching stream */
8b1ab7bf
FB
1328 for(i = 0; i < rt->nb_rtsp_streams; i++) {
1329 rtsp_st = rt->rtsp_streams[i];
115329f1
DB
1330 if (id >= rtsp_st->interleaved_min &&
1331 id <= rtsp_st->interleaved_max)
1617ad97
FB
1332 goto found;
1333 }
1334 goto redo;
1335 found:
8b1ab7bf
FB
1336 *prtsp_st = rtsp_st;
1337 return len;
1617ad97
FB
1338}
1339
115329f1 1340static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
8b1ab7bf 1341 uint8_t *buf, int buf_size)
1617ad97 1342{
8b1ab7bf 1343 RTSPState *rt = s->priv_data;
1617ad97
FB
1344 RTSPStream *rtsp_st;
1345 fd_set rfds;
7e726132 1346 int fd, fd_max, n, i, ret, tcp_fd;
1617ad97
FB
1347 struct timeval tv;
1348
1349 for(;;) {
b7b8fc34 1350 if (url_interrupt_cb())
a960a1e0 1351 return AVERROR(EINTR);
1617ad97 1352 FD_ZERO(&rfds);
7e726132
RB
1353 tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
1354 FD_SET(tcp_fd, &rfds);
8b1ab7bf
FB
1355 for(i = 0; i < rt->nb_rtsp_streams; i++) {
1356 rtsp_st = rt->rtsp_streams[i];
f830c9a4 1357 if (rtsp_st->rtp_handle) {
2fea9650
RB
1358 /* currently, we cannot probe RTCP handle because of
1359 * blocking restrictions */
bc8763cd
RB
1360 fd = url_get_file_handle(rtsp_st->rtp_handle);
1361 if (fd > fd_max)
1362 fd_max = fd;
1363 FD_SET(fd, &rfds);
f830c9a4 1364 }
1617ad97 1365 }
1617ad97 1366 tv.tv_sec = 0;
b7b8fc34 1367 tv.tv_usec = 100 * 1000;
1617ad97
FB
1368 n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1369 if (n > 0) {
8b1ab7bf
FB
1370 for(i = 0; i < rt->nb_rtsp_streams; i++) {
1371 rtsp_st = rt->rtsp_streams[i];
f830c9a4 1372 if (rtsp_st->rtp_handle) {
bc8763cd
RB
1373 fd = url_get_file_handle(rtsp_st->rtp_handle);
1374 if (FD_ISSET(fd, &rfds)) {
2fea9650
RB
1375 ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1376 if (ret > 0) {
1377 *prtsp_st = rtsp_st;
1378 return ret;
1379 }
1617ad97
FB
1380 }
1381 }
1382 }
7e726132
RB
1383 if (FD_ISSET(tcp_fd, &rfds)) {
1384 RTSPMessageHeader reply;
1385
1386 rtsp_read_reply(s, &reply, NULL, 0);
1387 /* XXX: parse message */
1388 }
1617ad97
FB
1389 }
1390 }
1391}
1392
1393static int rtsp_read_packet(AVFormatContext *s,
1394 AVPacket *pkt)
1395{
1396 RTSPState *rt = s->priv_data;
8b1ab7bf
FB
1397 RTSPStream *rtsp_st;
1398 int ret, len;
e49906c3 1399 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
8b1ab7bf 1400
572c6a38 1401 if (rt->server_type == RTSP_SERVER_REAL) {
1256d16b 1402 int i;
a9e534d5 1403 RTSPMessageHeader reply1, *reply = &reply1;
572c6a38 1404 enum AVDiscard cache[MAX_STREAMS];
1256d16b
RB
1405 char cmd[1024];
1406
572c6a38
RB
1407 for (i = 0; i < s->nb_streams; i++)
1408 cache[i] = s->streams[i]->discard;
1409
1410 if (!rt->need_subscription) {
1411 if (memcmp (cache, rt->real_setup_cache,
1412 sizeof(enum AVDiscard) * s->nb_streams)) {
1413 av_strlcatf(cmd, sizeof(cmd),
1414 "SET_PARAMETER %s RTSP/1.0\r\n"
1415 "Unsubscribe: %s\r\n",
1416 s->filename, rt->last_subscription);
1417 rtsp_send_cmd(s, cmd, reply, NULL);
1418 if (reply->status_code != RTSP_STATUS_OK)
1419 return AVERROR_INVALIDDATA;
1420 rt->need_subscription = 1;
1421 }
1256d16b 1422 }
1256d16b 1423
572c6a38
RB
1424 if (rt->need_subscription) {
1425 int r, rule_nr, first = 1;
1426
1427 memcpy(rt->real_setup_cache, cache,
1428 sizeof(enum AVDiscard) * s->nb_streams);
1429 rt->last_subscription[0] = 0;
1430
1431 snprintf(cmd, sizeof(cmd),
1432 "SET_PARAMETER %s RTSP/1.0\r\n"
1433 "Subscribe: ",
1434 s->filename);
1435 for (i = 0; i < rt->nb_rtsp_streams; i++) {
1436 rule_nr = 0;
1437 for (r = 0; r < s->nb_streams; r++) {
1438 if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
1439 if (s->streams[r]->discard != AVDISCARD_ALL) {
1440 if (!first)
1441 av_strlcat(rt->last_subscription, ",",
1442 sizeof(rt->last_subscription));
1443 ff_rdt_subscribe_rule(
1444 rt->last_subscription,
1445 sizeof(rt->last_subscription), i, rule_nr);
1446 first = 0;
1447 }
1448 rule_nr++;
1449 }
1450 }
1451 }
1452 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
1453 rtsp_send_cmd(s, cmd, reply, NULL);
1454 if (reply->status_code != RTSP_STATUS_OK)
1455 return AVERROR_INVALIDDATA;
1456 rt->need_subscription = 0;
1457
1458 if (rt->state == RTSP_STATE_PLAYING)
1459 rtsp_read_play (s);
1460 }
1256d16b
RB
1461 }
1462
8b1ab7bf 1463 /* get next frames from the same RTP packet */
0a861b6f 1464 if (rt->cur_transport_priv) {
119b4668 1465 if (rt->transport == RTSP_TRANSPORT_RDT)
0a861b6f 1466 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
4fce284c 1467 else
0a861b6f 1468 ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
8b1ab7bf 1469 if (ret == 0) {
0a861b6f 1470 rt->cur_transport_priv = NULL;
8b1ab7bf
FB
1471 return 0;
1472 } else if (ret == 1) {
1473 return 0;
1474 } else {
0a861b6f 1475 rt->cur_transport_priv = NULL;
8b1ab7bf
FB
1476 }
1477 }
1617ad97 1478
8b1ab7bf
FB
1479 /* read next RTP packet */
1480 redo:
90abbdba 1481 switch(rt->lower_transport) {
1617ad97 1482 default:
90abbdba 1483 case RTSP_LOWER_TRANSPORT_TCP:
8b1ab7bf 1484 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1617ad97 1485 break;
90abbdba
RB
1486 case RTSP_LOWER_TRANSPORT_UDP:
1487 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
8b1ab7bf 1488 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
0a861b6f
RB
1489 if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
1490 rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
1617ad97
FB
1491 break;
1492 }
8b1ab7bf 1493 if (len < 0)
489b0d4d 1494 return len;
119b4668 1495 if (rt->transport == RTSP_TRANSPORT_RDT)
0a861b6f 1496 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
4fce284c 1497 else
0a861b6f 1498 ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
8b1ab7bf
FB
1499 if (ret < 0)
1500 goto redo;
1501 if (ret == 1) {
1502 /* more packets may follow, so we save the RTP context */
0a861b6f 1503 rt->cur_transport_priv = rtsp_st->transport_priv;
8b1ab7bf
FB
1504 }
1505 return 0;
1617ad97
FB
1506}
1507
ff762d6e 1508static int rtsp_read_play(AVFormatContext *s)
b7b8fc34 1509{
ff762d6e 1510 RTSPState *rt = s->priv_data;
a9e534d5 1511 RTSPMessageHeader reply1, *reply = &reply1;
b7b8fc34
FB
1512 char cmd[1024];
1513
bc874dae 1514 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
ff762d6e 1515
2e889ae4 1516 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
99b2ac07
RB
1517 if (rt->state == RTSP_STATE_PAUSED) {
1518 snprintf(cmd, sizeof(cmd),
1519 "PLAY %s RTSP/1.0\r\n",
1520 s->filename);
1521 } else {
1522 snprintf(cmd, sizeof(cmd),
1523 "PLAY %s RTSP/1.0\r\n"
1524 "Range: npt=%0.3f-\r\n",
1525 s->filename,
1526 (double)rt->seek_timestamp / AV_TIME_BASE);
1527 }
1528 rtsp_send_cmd(s, cmd, reply, NULL);
1529 if (reply->status_code != RTSP_STATUS_OK) {
1530 return -1;
1531 }
1256d16b 1532 }
5f86057f
RB
1533 rt->state = RTSP_STATE_PLAYING;
1534 return 0;
b7b8fc34
FB
1535}
1536
ff762d6e
FB
1537/* pause the stream */
1538static int rtsp_read_pause(AVFormatContext *s)
b7b8fc34 1539{
ff762d6e 1540 RTSPState *rt = s->priv_data;
a9e534d5 1541 RTSPMessageHeader reply1, *reply = &reply1;
b7b8fc34
FB
1542 char cmd[1024];
1543
b7b8fc34 1544 rt = s->priv_data;
115329f1 1545
ff762d6e
FB
1546 if (rt->state != RTSP_STATE_PLAYING)
1547 return 0;
2e889ae4 1548 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
99b2ac07
RB
1549 snprintf(cmd, sizeof(cmd),
1550 "PAUSE %s RTSP/1.0\r\n",
1551 s->filename);
1552 rtsp_send_cmd(s, cmd, reply, NULL);
1553 if (reply->status_code != RTSP_STATUS_OK) {
1554 return -1;
1555 }
1256d16b 1556 }
5f86057f
RB
1557 rt->state = RTSP_STATE_PAUSED;
1558 return 0;
b7b8fc34
FB
1559}
1560
115329f1 1561static int rtsp_read_seek(AVFormatContext *s, int stream_index,
7b3c1382 1562 int64_t timestamp, int flags)
ff762d6e
FB
1563{
1564 RTSPState *rt = s->priv_data;
115329f1 1565
50755217 1566 rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q);
ff762d6e
FB
1567 switch(rt->state) {
1568 default:
1569 case RTSP_STATE_IDLE:
1570 break;
1571 case RTSP_STATE_PLAYING:
1572 if (rtsp_read_play(s) != 0)
1573 return -1;
1574 break;
1575 case RTSP_STATE_PAUSED:
1576 rt->state = RTSP_STATE_IDLE;
1577 break;
1578 }
1579 return 0;
1580}
1581
1617ad97
FB
1582static int rtsp_read_close(AVFormatContext *s)
1583{
1584 RTSPState *rt = s->priv_data;
a9e534d5 1585 RTSPMessageHeader reply1, *reply = &reply1;
1617ad97
FB
1586 char cmd[1024];
1587
b6892136 1588#if 0
1617ad97 1589 /* NOTE: it is valid to flush the buffer here */
90abbdba 1590 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1617ad97
FB
1591 url_fclose(&rt->rtsp_gb);
1592 }
b6892136 1593#endif
115329f1 1594 snprintf(cmd, sizeof(cmd),
b6892136 1595 "TEARDOWN %s RTSP/1.0\r\n",
1617ad97
FB
1596 s->filename);
1597 rtsp_send_cmd(s, cmd, reply, NULL);
1598
8b1ab7bf 1599 rtsp_close_streams(rt);
1617ad97
FB
1600 url_close(rt->rtsp_hd);
1601 return 0;
1602}
1603
b250f9c6 1604#if CONFIG_RTSP_DEMUXER
d2a067d1 1605AVInputFormat rtsp_demuxer = {
1617ad97 1606 "rtsp",
bde15e74 1607 NULL_IF_CONFIG_SMALL("RTSP input format"),
1617ad97
FB
1608 sizeof(RTSPState),
1609 rtsp_probe,
1610 rtsp_read_header,
1611 rtsp_read_packet,
1612 rtsp_read_close,
ff762d6e 1613 rtsp_read_seek,
bb76a117 1614 .flags = AVFMT_NOFILE,
ff762d6e
FB
1615 .read_play = rtsp_read_play,
1616 .read_pause = rtsp_read_pause,
1617ad97 1617};
96862926 1618#endif
1617ad97 1619
cb1fdc61 1620static int sdp_probe(AVProbeData *p1)
93ced3e8 1621{
0e1ceacd 1622 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
cb1fdc61
FB
1623
1624 /* we look for a line beginning "c=IN IP4" */
0e1ceacd 1625 while (p < p_end && *p != '\0') {
f7d78f36 1626 if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL))
cb1fdc61 1627 return AVPROBE_SCORE_MAX / 2;
0e1ceacd
MN
1628
1629 while(p < p_end - 1 && *p != '\n') p++;
1630 if (++p >= p_end)
cb1fdc61 1631 break;
cb1fdc61
FB
1632 if (*p == '\r')
1633 p++;
1634 }
93ced3e8
FB
1635 return 0;
1636}
1637
1638#define SDP_MAX_SIZE 8192
1639
1640static int sdp_read_header(AVFormatContext *s,
1641 AVFormatParameters *ap)
1642{
8b1ab7bf 1643 RTSPState *rt = s->priv_data;
93ced3e8
FB
1644 RTSPStream *rtsp_st;
1645 int size, i, err;
1646 char *content;
1647 char url[1024];
1648
1649 /* read the whole sdp file */
1650 /* XXX: better loading */
1651 content = av_malloc(SDP_MAX_SIZE);
899681cd 1652 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
93ced3e8
FB
1653 if (size <= 0) {
1654 av_free(content);
1655 return AVERROR_INVALIDDATA;
1656 }
1657 content[size] ='\0';
1658
1659 sdp_parse(s, content);
1660 av_free(content);
1661
1662 /* open each RTP stream */
8b1ab7bf
FB
1663 for(i=0;i<rt->nb_rtsp_streams;i++) {
1664 rtsp_st = rt->rtsp_streams[i];
115329f1 1665
d2bf42be 1666 snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d",
115329f1 1667 inet_ntoa(rtsp_st->sdp_ip),
93ced3e8 1668 rtsp_st->sdp_port,
d2bf42be 1669 rtsp_st->sdp_port,
93ced3e8 1670 rtsp_st->sdp_ttl);
dbf30963 1671 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
93ced3e8
FB
1672 err = AVERROR_INVALIDDATA;
1673 goto fail;
1674 }
ee0cb67f 1675 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
8b1ab7bf 1676 goto fail;
93ced3e8
FB
1677 }
1678 return 0;
1679 fail:
8b1ab7bf 1680 rtsp_close_streams(rt);
93ced3e8
FB
1681 return err;
1682}
1683
1684static int sdp_read_packet(AVFormatContext *s,
1685 AVPacket *pkt)
1686{
8b1ab7bf 1687 return rtsp_read_packet(s, pkt);
93ced3e8
FB
1688}
1689
1690static int sdp_read_close(AVFormatContext *s)
1691{
8b1ab7bf
FB
1692 RTSPState *rt = s->priv_data;
1693 rtsp_close_streams(rt);
93ced3e8
FB
1694 return 0;
1695}
1696
b250f9c6 1697#if CONFIG_SDP_DEMUXER
ff70e601 1698AVInputFormat sdp_demuxer = {
93ced3e8 1699 "sdp",
bde15e74 1700 NULL_IF_CONFIG_SMALL("SDP"),
93ced3e8
FB
1701 sizeof(RTSPState),
1702 sdp_probe,
1703 sdp_read_header,
1704 sdp_read_packet,
1705 sdp_read_close,
1706};
ff70e601 1707#endif
93ced3e8 1708
b250f9c6 1709#if CONFIG_REDIR_DEMUXER
1617ad97
FB
1710/* dummy redirector format (used directly in av_open_input_file now) */
1711static int redir_probe(AVProbeData *pd)
1712{
1713 const char *p;
1714 p = pd->buf;
36aa7bc2 1715 skip_spaces(&p);
f7d78f36
MR
1716 if (av_strstart(p, "http://", NULL) ||
1717 av_strstart(p, "rtsp://", NULL))
1617ad97
FB
1718 return AVPROBE_SCORE_MAX;
1719 return 0;
1720}
1721
e8acf0ed 1722static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap)
1617ad97
FB
1723{
1724 char buf[4096], *q;
1725 int c;
1726 AVFormatContext *ic = NULL;
e8acf0ed 1727 ByteIOContext *f = s->pb;
1617ad97
FB
1728
1729 /* parse each URL and try to open it */
1730 c = url_fgetc(f);
1731 while (c != URL_EOF) {
1732 /* skip spaces */
1733 for(;;) {
1734 if (!redir_isspace(c))
1735 break;
1736 c = url_fgetc(f);
1737 }
1738 if (c == URL_EOF)
1739 break;
1740 /* record url */
1741 q = buf;
1742 for(;;) {
1743 if (c == URL_EOF || redir_isspace(c))
1744 break;
1745 if ((q - buf) < sizeof(buf) - 1)
1746 *q++ = c;
1747 c = url_fgetc(f);
1748 }
1749 *q = '\0';
1750 //printf("URL='%s'\n", buf);
1751 /* try to open the media file */
1752 if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1753 break;
1754 }
1617ad97 1755 if (!ic)
6f3e0b21 1756 return AVERROR(EIO);
e8acf0ed
LA
1757
1758 *s = *ic;
1759 url_fclose(f);
1760
1761 return 0;
1617ad97
FB
1762}
1763
d2a067d1 1764AVInputFormat redir_demuxer = {
1617ad97 1765 "redir",
bde15e74 1766 NULL_IF_CONFIG_SMALL("Redirector format"),
1617ad97
FB
1767 0,
1768 redir_probe,
e8acf0ed 1769 redir_read_header,
1617ad97
FB
1770 NULL,
1771 NULL,
1772};
e7047005 1773#endif