Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtsp.c @ 7eaa646f

History | View | Annotate | Download (59.4 KB)

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

    
22
/* needed by inet_aton() */
23
#define _SVID_SOURCE
24

    
25
#include "libavutil/base64.h"
26
#include "libavutil/avstring.h"
27
#include "libavutil/intreadwrite.h"
28
#include "avformat.h"
29

    
30
#include <sys/time.h>
31
#if HAVE_SYS_SELECT_H
32
#include <sys/select.h>
33
#endif
34
#include <strings.h>
35
#include "network.h"
36
#include "rtsp.h"
37

    
38
#include "rtpdec.h"
39
#include "rdt.h"
40
#include "rtp_asf.h"
41
#include "rtp_vorbis.h"
42

    
43
//#define DEBUG
44
//#define DEBUG_RTP_TCP
45

    
46
#if LIBAVFORMAT_VERSION_INT < (53 << 16)
47
int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
48
#endif
49

    
50
#define SPACE_CHARS " \t\r\n"
51
/* we use memchr() instead of strchr() here because strchr() will return
52
 * the terminating '\0' of SPACE_CHARS instead of NULL if c is '\0'. */
53
#define redir_isspace(c) memchr(SPACE_CHARS, c, 4)
54
static void skip_spaces(const char **pp)
55
{
56
    const char *p;
57
    p = *pp;
58
    while (redir_isspace(*p))
59
        p++;
60
    *pp = p;
61
}
62

    
63
static void get_word_until_chars(char *buf, int buf_size,
64
                                 const char *sep, const char **pp)
65
{
66
    const char *p;
67
    char *q;
68

    
69
    p = *pp;
70
    skip_spaces(&p);
71
    q = buf;
72
    while (!strchr(sep, *p) && *p != '\0') {
73
        if ((q - buf) < buf_size - 1)
74
            *q++ = *p;
75
        p++;
76
    }
77
    if (buf_size > 0)
78
        *q = '\0';
79
    *pp = p;
80
}
81

    
82
static void get_word_sep(char *buf, int buf_size, const char *sep,
83
                         const char **pp)
84
{
85
    if (**pp == '/') (*pp)++;
86
    get_word_until_chars(buf, buf_size, sep, pp);
87
}
88

    
89
static void get_word(char *buf, int buf_size, const char **pp)
90
{
91
    get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
92
}
93

    
94
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
95
static int sdp_parse_rtpmap(AVFormatContext *s,
96
                            AVCodecContext *codec, RTSPStream *rtsp_st,
97
                            int payload_type, const char *p)
98
{
99
    char buf[256];
100
    int i;
101
    AVCodec *c;
102
    const char *c_name;
103

    
104
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
105
     * see if we can handle this kind of payload.
106
     * The space should normally not be there but some Real streams or
107
     * particular servers ("RealServer Version 6.1.3.970", see issue 1658)
108
     * have a trailing space. */
109
    get_word_sep(buf, sizeof(buf), "/ ", &p);
110
    if (payload_type >= RTP_PT_PRIVATE) {
111
        RTPDynamicProtocolHandler *handler;
112
        for (handler = RTPFirstDynamicPayloadHandler;
113
             handler; handler = handler->next) {
114
            if (!strcasecmp(buf, handler->enc_name) &&
115
                codec->codec_type == handler->codec_type) {
116
                codec->codec_id          = handler->codec_id;
117
                rtsp_st->dynamic_handler = handler;
118
                if (handler->open)
119
                    rtsp_st->dynamic_protocol_context = handler->open();
120
                break;
121
            }
122
        }
123
    } else {
124
        /* We are in a standard case
125
         * (from http://www.iana.org/assignments/rtp-parameters). */
126
        /* search into AVRtpPayloadTypes[] */
127
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
128
    }
129

    
130
    c = avcodec_find_decoder(codec->codec_id);
131
    if (c && c->name)
132
        c_name = c->name;
133
    else
134
        c_name = (char *) NULL;
135

    
136
    if (c_name) {
137
        get_word_sep(buf, sizeof(buf), "/", &p);
138
        i = atoi(buf);
139
        switch (codec->codec_type) {
140
        case CODEC_TYPE_AUDIO:
141
            av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
142
            codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
143
            codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
144
            if (i > 0) {
145
                codec->sample_rate = i;
146
                get_word_sep(buf, sizeof(buf), "/", &p);
147
                i = atoi(buf);
148
                if (i > 0)
149
                    codec->channels = i;
150
                // TODO: there is a bug here; if it is a mono stream, and
151
                // less than 22000Hz, faad upconverts to stereo and twice
152
                // the frequency.  No problem, but the sample rate is being
153
                // set here by the sdp line. Patch on its way. (rdm)
154
            }
155
            av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
156
                   codec->sample_rate);
157
            av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
158
                   codec->channels);
159
            break;
160
        case CODEC_TYPE_VIDEO:
161
            av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
162
            break;
163
        default:
164
            break;
165
        }
166
        return 0;
167
    }
168

    
169
    return -1;
170
}
171

    
172
/* return the length and optionally the data */
173
static int hex_to_data(uint8_t *data, const char *p)
174
{
175
    int c, len, v;
176

    
177
    len = 0;
178
    v = 1;
179
    for (;;) {
180
        skip_spaces(&p);
181
        if (*p == '\0')
182
            break;
183
        c = toupper((unsigned char) *p++);
184
        if (c >= '0' && c <= '9')
185
            c = c - '0';
186
        else if (c >= 'A' && c <= 'F')
187
            c = c - 'A' + 10;
188
        else
189
            break;
190
        v = (v << 4) | c;
191
        if (v & 0x100) {
192
            if (data)
193
                data[len] = v;
194
            len++;
195
            v = 1;
196
        }
197
    }
198
    return len;
199
}
200

    
201
static void sdp_parse_fmtp_config(AVCodecContext * codec, void *ctx,
202
                                  char *attr, char *value)
203
{
204
    switch (codec->codec_id) {
205
    case CODEC_ID_MPEG4:
206
    case CODEC_ID_AAC:
207
        if (!strcmp(attr, "config")) {
208
            /* decode the hexa encoded parameter */
209
            int len = hex_to_data(NULL, value);
210
            if (codec->extradata)
211
                av_free(codec->extradata);
212
            codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
213
            if (!codec->extradata)
214
                return;
215
            codec->extradata_size = len;
216
            hex_to_data(codec->extradata, value);
217
        }
218
        break;
219
    case CODEC_ID_VORBIS:
220
        ff_vorbis_parse_fmtp_config(codec, ctx, attr, value);
221
        break;
222
    default:
223
        break;
224
    }
225
    return;
226
}
227

    
228
typedef struct {
229
    const char *str;
230
    uint16_t    type;
231
    uint32_t    offset;
232
} AttrNameMap;
233

    
234
/* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
235
#define ATTR_NAME_TYPE_INT 0
236
#define ATTR_NAME_TYPE_STR 1
237
static const AttrNameMap attr_names[]=
238
{
239
    { "SizeLength",       ATTR_NAME_TYPE_INT,
240
      offsetof(RTPPayloadData, sizelength) },
241
    { "IndexLength",      ATTR_NAME_TYPE_INT,
242
      offsetof(RTPPayloadData, indexlength) },
243
    { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
244
      offsetof(RTPPayloadData, indexdeltalength) },
245
    { "profile-level-id", ATTR_NAME_TYPE_INT,
246
      offsetof(RTPPayloadData, profile_level_id) },
247
    { "StreamType",       ATTR_NAME_TYPE_INT,
248
      offsetof(RTPPayloadData, streamtype) },
249
    { "mode",             ATTR_NAME_TYPE_STR,
250
      offsetof(RTPPayloadData, mode) },
251
    { NULL, -1, -1 },
252
};
253

    
254
/* parse the attribute line from the fmtp a line of an sdp resonse. This
255
 * is broken out as a function because it is used in rtp_h264.c, which is
256
 * forthcoming. */
257
int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
258
                             char *value, int value_size)
259
{
260
    skip_spaces(p);
261
    if (**p) {
262
        get_word_sep(attr, attr_size, "=", p);
263
        if (**p == '=')
264
            (*p)++;
265
        get_word_sep(value, value_size, ";", p);
266
        if (**p == ';')
267
            (*p)++;
268
        return 1;
269
    }
270
    return 0;
271
}
272

    
273
/* parse a SDP line and save stream attributes */
274
static void sdp_parse_fmtp(AVStream *st, const char *p)
275
{
276
    char attr[256];
277
    /* Vorbis setup headers can be up to 12KB and are sent base64
278
     * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */
279
    char value[16384];
280
    int i;
281
    RTSPStream *rtsp_st = st->priv_data;
282
    AVCodecContext *codec = st->codec;
283
    RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
284

    
285
    /* loop on each attribute */
286
    while (rtsp_next_attr_and_value(&p, attr, sizeof(attr),
287
                                    value, sizeof(value))) {
288
        /* grab the codec extra_data from the config parameter of the fmtp
289
         * line */
290
        sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context,
291
                              attr, value);
292
        /* Looking for a known attribute */
293
        for (i = 0; attr_names[i].str; ++i) {
294
            if (!strcasecmp(attr, attr_names[i].str)) {
295
                if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
296
                    *(int *)((char *)rtp_payload_data +
297
                        attr_names[i].offset) = atoi(value);
298
                } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
299
                    *(char **)((char *)rtp_payload_data +
300
                        attr_names[i].offset) = av_strdup(value);
301
            }
302
        }
303
    }
304
}
305

    
306
/** Parse a string p in the form of Range:npt=xx-xx, and determine the start
307
 *  and end time.
308
 *  Used for seeking in the rtp stream.
309
 */
310
static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
311
{
312
    char buf[256];
313

    
314
    skip_spaces(&p);
315
    if (!av_stristart(p, "npt=", &p))
316
        return;
317

    
318
    *start = AV_NOPTS_VALUE;
319
    *end = AV_NOPTS_VALUE;
320

    
321
    get_word_sep(buf, sizeof(buf), "-", &p);
322
    *start = parse_date(buf, 1);
323
    if (*p == '-') {
324
        p++;
325
        get_word_sep(buf, sizeof(buf), "-", &p);
326
        *end = parse_date(buf, 1);
327
    }
328
//    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
329
//    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
330
}
331

    
332
typedef struct SDPParseState {
333
    /* SDP only */
334
    struct in_addr default_ip;
335
    int            default_ttl;
336
    int            skip_media;  ///< set if an unknown m= line occurs
337
} SDPParseState;
338

    
339
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
340
                           int letter, const char *buf)
341
{
342
    RTSPState *rt = s->priv_data;
343
    char buf1[64], st_type[64];
344
    const char *p;
345
    enum CodecType codec_type;
346
    int payload_type, i;
347
    AVStream *st;
348
    RTSPStream *rtsp_st;
349
    struct in_addr sdp_ip;
350
    int ttl;
351

    
352
    dprintf(s, "sdp: %c='%s'\n", letter, buf);
353

    
354
    p = buf;
355
    if (s1->skip_media && letter != 'm')
356
        return;
357
    switch (letter) {
358
    case 'c':
359
        get_word(buf1, sizeof(buf1), &p);
360
        if (strcmp(buf1, "IN") != 0)
361
            return;
362
        get_word(buf1, sizeof(buf1), &p);
363
        if (strcmp(buf1, "IP4") != 0)
364
            return;
365
        get_word_sep(buf1, sizeof(buf1), "/", &p);
366
        if (inet_aton(buf1, &sdp_ip) == 0)
367
            return;
368
        ttl = 16;
369
        if (*p == '/') {
370
            p++;
371
            get_word_sep(buf1, sizeof(buf1), "/", &p);
372
            ttl = atoi(buf1);
373
        }
374
        if (s->nb_streams == 0) {
375
            s1->default_ip = sdp_ip;
376
            s1->default_ttl = ttl;
377
        } else {
378
            st = s->streams[s->nb_streams - 1];
379
            rtsp_st = st->priv_data;
380
            rtsp_st->sdp_ip = sdp_ip;
381
            rtsp_st->sdp_ttl = ttl;
382
        }
383
        break;
384
    case 's':
385
        av_metadata_set(&s->metadata, "title", p);
386
        break;
387
    case 'i':
388
        if (s->nb_streams == 0) {
389
            av_metadata_set(&s->metadata, "comment", p);
390
            break;
391
        }
392
        break;
393
    case 'm':
394
        /* new stream */
395
        s1->skip_media = 0;
396
        get_word(st_type, sizeof(st_type), &p);
397
        if (!strcmp(st_type, "audio")) {
398
            codec_type = CODEC_TYPE_AUDIO;
399
        } else if (!strcmp(st_type, "video")) {
400
            codec_type = CODEC_TYPE_VIDEO;
401
        } else if (!strcmp(st_type, "application")) {
402
            codec_type = CODEC_TYPE_DATA;
403
        } else {
404
            s1->skip_media = 1;
405
            return;
406
        }
407
        rtsp_st = av_mallocz(sizeof(RTSPStream));
408
        if (!rtsp_st)
409
            return;
410
        rtsp_st->stream_index = -1;
411
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
412

    
413
        rtsp_st->sdp_ip = s1->default_ip;
414
        rtsp_st->sdp_ttl = s1->default_ttl;
415

    
416
        get_word(buf1, sizeof(buf1), &p); /* port */
417
        rtsp_st->sdp_port = atoi(buf1);
418

    
419
        get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
420

    
421
        /* XXX: handle list of formats */
422
        get_word(buf1, sizeof(buf1), &p); /* format list */
423
        rtsp_st->sdp_payload_type = atoi(buf1);
424

    
425
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
426
            /* no corresponding stream */
427
        } else {
428
            st = av_new_stream(s, 0);
429
            if (!st)
430
                return;
431
            st->priv_data = rtsp_st;
432
            rtsp_st->stream_index = st->index;
433
            st->codec->codec_type = codec_type;
434
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
435
                /* if standard payload type, we can find the codec right now */
436
                ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
437
            }
438
        }
439
        /* put a default control url */
440
        av_strlcpy(rtsp_st->control_url, s->filename,
441
                   sizeof(rtsp_st->control_url));
442
        break;
443
    case 'a':
444
        if (av_strstart(p, "control:", &p) && s->nb_streams > 0) {
445
            char proto[32];
446
            /* get the control url */
447
            st = s->streams[s->nb_streams - 1];
448
            rtsp_st = st->priv_data;
449

    
450
            /* XXX: may need to add full url resolution */
451
            url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
452
                      NULL, NULL, 0, p);
453
            if (proto[0] == '\0') {
454
                /* relative control URL */
455
                av_strlcat(rtsp_st->control_url, "/",
456
                           sizeof(rtsp_st->control_url));
457
                av_strlcat(rtsp_st->control_url, p,
458
                           sizeof(rtsp_st->control_url));
459
            } else
460
                av_strlcpy(rtsp_st->control_url, p,
461
                           sizeof(rtsp_st->control_url));
462
        } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
463
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
464
            get_word(buf1, sizeof(buf1), &p);
465
            payload_type = atoi(buf1);
466
            st = s->streams[s->nb_streams - 1];
467
            rtsp_st = st->priv_data;
468
            sdp_parse_rtpmap(s, st->codec, rtsp_st, payload_type, p);
469
        } else if (av_strstart(p, "fmtp:", &p)) {
470
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
471
            get_word(buf1, sizeof(buf1), &p);
472
            payload_type = atoi(buf1);
473
            for (i = 0; i < s->nb_streams; i++) {
474
                st      = s->streams[i];
475
                rtsp_st = st->priv_data;
476
                if (rtsp_st->sdp_payload_type == payload_type) {
477
                    if (!(rtsp_st->dynamic_handler &&
478
                          rtsp_st->dynamic_handler->parse_sdp_a_line &&
479
                          rtsp_st->dynamic_handler->parse_sdp_a_line(s,
480
                              i, rtsp_st->dynamic_protocol_context, buf)))
481
                        sdp_parse_fmtp(st, p);
482
                }
483
            }
484
        } else if (av_strstart(p, "framesize:", &p)) {
485
            // let dynamic protocol handlers have a stab at the line.
486
            get_word(buf1, sizeof(buf1), &p);
487
            payload_type = atoi(buf1);
488
            for (i = 0; i < s->nb_streams; i++) {
489
                st      = s->streams[i];
490
                rtsp_st = st->priv_data;
491
                if (rtsp_st->sdp_payload_type == payload_type &&
492
                    rtsp_st->dynamic_handler &&
493
                    rtsp_st->dynamic_handler->parse_sdp_a_line)
494
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
495
                        rtsp_st->dynamic_protocol_context, buf);
496
            }
497
        } else if (av_strstart(p, "range:", &p)) {
498
            int64_t start, end;
499

    
500
            // this is so that seeking on a streamed file can work.
501
            rtsp_parse_range_npt(p, &start, &end);
502
            s->start_time = start;
503
            /* AV_NOPTS_VALUE means live broadcast (and can't seek) */
504
            s->duration   = (end == AV_NOPTS_VALUE) ?
505
                            AV_NOPTS_VALUE : end - start;
506
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
507
            if (atoi(p) == 1)
508
                rt->transport = RTSP_TRANSPORT_RDT;
509
        } else {
510
            if (rt->server_type == RTSP_SERVER_WMS)
511
                ff_wms_parse_sdp_a_line(s, p);
512
            if (s->nb_streams > 0) {
513
                if (rt->server_type == RTSP_SERVER_REAL)
514
                    ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
515

    
516
                rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
517
                if (rtsp_st->dynamic_handler &&
518
                    rtsp_st->dynamic_handler->parse_sdp_a_line)
519
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
520
                        s->nb_streams - 1,
521
                        rtsp_st->dynamic_protocol_context, buf);
522
            }
523
        }
524
        break;
525
    }
526
}
527

    
528
static int sdp_parse(AVFormatContext *s, const char *content)
529
{
530
    const char *p;
531
    int letter;
532
    /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
533
     * contain long SDP lines containing complete ASF Headers (several
534
     * kB) or arrays of MDPR (RM stream descriptor) headers plus
535
     * "rulebooks" describing their properties. Therefore, the SDP line
536
     * buffer is large.
537
     *
538
     * The Vorbis FMTP line can be up to 16KB - see sdp_parse_fmtp. */
539
    char buf[16384], *q;
540
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
541

    
542
    memset(s1, 0, sizeof(SDPParseState));
543
    p = content;
544
    for (;;) {
545
        skip_spaces(&p);
546
        letter = *p;
547
        if (letter == '\0')
548
            break;
549
        p++;
550
        if (*p != '=')
551
            goto next_line;
552
        p++;
553
        /* get the content */
554
        q = buf;
555
        while (*p != '\n' && *p != '\r' && *p != '\0') {
556
            if ((q - buf) < sizeof(buf) - 1)
557
                *q++ = *p;
558
            p++;
559
        }
560
        *q = '\0';
561
        sdp_parse_line(s, s1, letter, buf);
562
    next_line:
563
        while (*p != '\n' && *p != '\0')
564
            p++;
565
        if (*p == '\n')
566
            p++;
567
    }
568
    return 0;
569
}
570

    
571
/* close and free RTSP streams */
572
static void rtsp_close_streams(RTSPState *rt)
573
{
574
    int i;
575
    RTSPStream *rtsp_st;
576

    
577
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
578
        rtsp_st = rt->rtsp_streams[i];
579
        if (rtsp_st) {
580
            if (rtsp_st->transport_priv) {
581
                if (rt->transport == RTSP_TRANSPORT_RDT)
582
                    ff_rdt_parse_close(rtsp_st->transport_priv);
583
                else
584
                    rtp_parse_close(rtsp_st->transport_priv);
585
            }
586
            if (rtsp_st->rtp_handle)
587
                url_close(rtsp_st->rtp_handle);
588
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
589
                rtsp_st->dynamic_handler->close(
590
                    rtsp_st->dynamic_protocol_context);
591
        }
592
    }
593
    av_free(rt->rtsp_streams);
594
    if (rt->asf_ctx) {
595
        av_close_input_stream (rt->asf_ctx);
596
        rt->asf_ctx = NULL;
597
    }
598
    av_freep(&rt->auth_b64);
599
}
600

    
601
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
602
{
603
    RTSPState *rt = s->priv_data;
604
    AVStream *st = NULL;
605

    
606
    /* open the RTP context */
607
    if (rtsp_st->stream_index >= 0)
608
        st = s->streams[rtsp_st->stream_index];
609
    if (!st)
610
        s->ctx_flags |= AVFMTCTX_NOHEADER;
611

    
612
    if (rt->transport == RTSP_TRANSPORT_RDT)
613
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
614
                                            rtsp_st->dynamic_protocol_context,
615
                                            rtsp_st->dynamic_handler);
616
    else
617
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
618
                                         rtsp_st->sdp_payload_type,
619
                                         &rtsp_st->rtp_payload_data);
620

    
621
    if (!rtsp_st->transport_priv) {
622
         return AVERROR(ENOMEM);
623
    } else if (rt->transport != RTSP_TRANSPORT_RDT) {
624
        if (rtsp_st->dynamic_handler) {
625
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
626
                                           rtsp_st->dynamic_protocol_context,
627
                                           rtsp_st->dynamic_handler);
628
        }
629
    }
630

    
631
    return 0;
632
}
633

    
634
#if CONFIG_RTSP_DEMUXER
635
static int rtsp_probe(AVProbeData *p)
636
{
637
    if (av_strstart(p->filename, "rtsp:", NULL))
638
        return AVPROBE_SCORE_MAX;
639
    return 0;
640
}
641

    
642
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
643
{
644
    const char *p;
645
    int v;
646

    
647
    p = *pp;
648
    skip_spaces(&p);
649
    v = strtol(p, (char **)&p, 10);
650
    if (*p == '-') {
651
        p++;
652
        *min_ptr = v;
653
        v = strtol(p, (char **)&p, 10);
654
        *max_ptr = v;
655
    } else {
656
        *min_ptr = v;
657
        *max_ptr = v;
658
    }
659
    *pp = p;
660
}
661

    
662
/* XXX: only one transport specification is parsed */
663
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
664
{
665
    char transport_protocol[16];
666
    char profile[16];
667
    char lower_transport[16];
668
    char parameter[16];
669
    RTSPTransportField *th;
670
    char buf[256];
671

    
672
    reply->nb_transports = 0;
673

    
674
    for (;;) {
675
        skip_spaces(&p);
676
        if (*p == '\0')
677
            break;
678

    
679
        th = &reply->transports[reply->nb_transports];
680

    
681
        get_word_sep(transport_protocol, sizeof(transport_protocol),
682
                     "/", &p);
683
        if (!strcasecmp (transport_protocol, "rtp")) {
684
            get_word_sep(profile, sizeof(profile), "/;,", &p);
685
            lower_transport[0] = '\0';
686
            /* rtp/avp/<protocol> */
687
            if (*p == '/') {
688
                get_word_sep(lower_transport, sizeof(lower_transport),
689
                             ";,", &p);
690
            }
691
            th->transport = RTSP_TRANSPORT_RTP;
692
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
693
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
694
            /* x-pn-tng/<protocol> */
695
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
696
            profile[0] = '\0';
697
            th->transport = RTSP_TRANSPORT_RDT;
698
        }
699
        if (!strcasecmp(lower_transport, "TCP"))
700
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
701
        else
702
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
703

    
704
        if (*p == ';')
705
            p++;
706
        /* get each parameter */
707
        while (*p != '\0' && *p != ',') {
708
            get_word_sep(parameter, sizeof(parameter), "=;,", &p);
709
            if (!strcmp(parameter, "port")) {
710
                if (*p == '=') {
711
                    p++;
712
                    rtsp_parse_range(&th->port_min, &th->port_max, &p);
713
                }
714
            } else if (!strcmp(parameter, "client_port")) {
715
                if (*p == '=') {
716
                    p++;
717
                    rtsp_parse_range(&th->client_port_min,
718
                                     &th->client_port_max, &p);
719
                }
720
            } else if (!strcmp(parameter, "server_port")) {
721
                if (*p == '=') {
722
                    p++;
723
                    rtsp_parse_range(&th->server_port_min,
724
                                     &th->server_port_max, &p);
725
                }
726
            } else if (!strcmp(parameter, "interleaved")) {
727
                if (*p == '=') {
728
                    p++;
729
                    rtsp_parse_range(&th->interleaved_min,
730
                                     &th->interleaved_max, &p);
731
                }
732
            } else if (!strcmp(parameter, "multicast")) {
733
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
734
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
735
            } else if (!strcmp(parameter, "ttl")) {
736
                if (*p == '=') {
737
                    p++;
738
                    th->ttl = strtol(p, (char **)&p, 10);
739
                }
740
            } else if (!strcmp(parameter, "destination")) {
741
                struct in_addr ipaddr;
742

    
743
                if (*p == '=') {
744
                    p++;
745
                    get_word_sep(buf, sizeof(buf), ";,", &p);
746
                    if (inet_aton(buf, &ipaddr))
747
                        th->destination = ntohl(ipaddr.s_addr);
748
                }
749
            }
750
            while (*p != ';' && *p != '\0' && *p != ',')
751
                p++;
752
            if (*p == ';')
753
                p++;
754
        }
755
        if (*p == ',')
756
            p++;
757

    
758
        reply->nb_transports++;
759
    }
760
}
761

    
762
void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
763
{
764
    const char *p;
765

    
766
    /* NOTE: we do case independent match for broken servers */
767
    p = buf;
768
    if (av_stristart(p, "Session:", &p)) {
769
        int t;
770
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
771
        if (av_stristart(p, ";timeout=", &p) &&
772
            (t = strtol(p, NULL, 10)) > 0) {
773
            reply->timeout = t;
774
        }
775
    } else if (av_stristart(p, "Content-Length:", &p)) {
776
        reply->content_length = strtol(p, NULL, 10);
777
    } else if (av_stristart(p, "Transport:", &p)) {
778
        rtsp_parse_transport(reply, p);
779
    } else if (av_stristart(p, "CSeq:", &p)) {
780
        reply->seq = strtol(p, NULL, 10);
781
    } else if (av_stristart(p, "Range:", &p)) {
782
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
783
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
784
        skip_spaces(&p);
785
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
786
    } else if (av_stristart(p, "Server:", &p)) {
787
        skip_spaces(&p);
788
        av_strlcpy(reply->server, p, sizeof(reply->server));
789
    } else if (av_stristart(p, "Notice:", &p) ||
790
               av_stristart(p, "X-Notice:", &p)) {
791
        reply->notice = strtol(p, NULL, 10);
792
    } else if (av_stristart(p, "Location:", &p)) {
793
        skip_spaces(&p);
794
        av_strlcpy(reply->location, p , sizeof(reply->location));
795
    }
796
}
797

    
798
/* skip a RTP/TCP interleaved packet */
799
static void rtsp_skip_packet(AVFormatContext *s)
800
{
801
    RTSPState *rt = s->priv_data;
802
    int ret, len, len1;
803
    uint8_t buf[1024];
804

    
805
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
806
    if (ret != 3)
807
        return;
808
    len = AV_RB16(buf + 1);
809

    
810
    dprintf(s, "skipping RTP packet len=%d\n", len);
811

    
812
    /* skip payload */
813
    while (len > 0) {
814
        len1 = len;
815
        if (len1 > sizeof(buf))
816
            len1 = sizeof(buf);
817
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
818
        if (ret != len1)
819
            return;
820
        len -= len1;
821
    }
822
}
823

    
824
/**
825
 * Read a RTSP message from the server, or prepare to read data
826
 * packets if we're reading data interleaved over the TCP/RTSP
827
 * connection as well.
828
 *
829
 * @param s RTSP demuxer context
830
 * @param reply pointer where the RTSP message header will be stored
831
 * @param content_ptr pointer where the RTSP message body, if any, will
832
 *                    be stored (length is in reply)
833
 * @param return_on_interleaved_data whether the function may return if we
834
 *                   encounter a data marker ('$'), which precedes data
835
 *                   packets over interleaved TCP/RTSP connections. If this
836
 *                   is set, this function will return 1 after encountering
837
 *                   a '$'. If it is not set, the function will skip any
838
 *                   data packets (if they are encountered), until a reply
839
 *                   has been fully parsed. If no more data is available
840
 *                   without parsing a reply, it will return an error.
841
 *
842
 * @returns 1 if a data packets is ready to be received, -1 on error,
843
 *          and 0 on success.
844
 */
845
static int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
846
                           unsigned char **content_ptr,
847
                           int return_on_interleaved_data)
848
{
849
    RTSPState *rt = s->priv_data;
850
    char buf[4096], buf1[1024], *q;
851
    unsigned char ch;
852
    const char *p;
853
    int ret, content_length, line_count = 0;
854
    unsigned char *content = NULL;
855

    
856
    memset(reply, 0, sizeof(*reply));
857

    
858
    /* parse reply (XXX: use buffers) */
859
    rt->last_reply[0] = '\0';
860
    for (;;) {
861
        q = buf;
862
        for (;;) {
863
            ret = url_read_complete(rt->rtsp_hd, &ch, 1);
864
#ifdef DEBUG_RTP_TCP
865
            dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
866
#endif
867
            if (ret != 1)
868
                return -1;
869
            if (ch == '\n')
870
                break;
871
            if (ch == '$') {
872
                /* XXX: only parse it if first char on line ? */
873
                if (return_on_interleaved_data) {
874
                    return 1;
875
                } else
876
                rtsp_skip_packet(s);
877
            } else if (ch != '\r') {
878
                if ((q - buf) < sizeof(buf) - 1)
879
                    *q++ = ch;
880
            }
881
        }
882
        *q = '\0';
883

    
884
        dprintf(s, "line='%s'\n", buf);
885

    
886
        /* test if last line */
887
        if (buf[0] == '\0')
888
            break;
889
        p = buf;
890
        if (line_count == 0) {
891
            /* get reply code */
892
            get_word(buf1, sizeof(buf1), &p);
893
            get_word(buf1, sizeof(buf1), &p);
894
            reply->status_code = atoi(buf1);
895
        } else {
896
            rtsp_parse_line(reply, p);
897
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
898
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
899
        }
900
        line_count++;
901
    }
902

    
903
    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
904
        av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
905

    
906
    content_length = reply->content_length;
907
    if (content_length > 0) {
908
        /* leave some room for a trailing '\0' (useful for simple parsing) */
909
        content = av_malloc(content_length + 1);
910
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
911
        content[content_length] = '\0';
912
    }
913
    if (content_ptr)
914
        *content_ptr = content;
915
    else
916
        av_free(content);
917

    
918
    /* EOS */
919
    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
920
        reply->notice == 2104 /* Start-of-Stream Reached */    ||
921
        reply->notice == 2306 /* Continuous Feed Terminated */) {
922
        rt->state = RTSP_STATE_IDLE;
923
    } else if (reply->notice >= 4400 && reply->notice < 5500) {
924
        return AVERROR(EIO); /* data or server error */
925
    } else if (reply->notice == 2401 /* Ticket Expired */ ||
926
             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
927
        return AVERROR(EPERM);
928

    
929
    return 0;
930
}
931

    
932
static void rtsp_send_cmd_async(AVFormatContext *s,
933
                                const char *cmd, RTSPMessageHeader *reply,
934
                                unsigned char **content_ptr)
935
{
936
    RTSPState *rt = s->priv_data;
937
    char buf[4096], buf1[1024];
938

    
939
    rt->seq++;
940
    av_strlcpy(buf, cmd, sizeof(buf));
941
    snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
942
    av_strlcat(buf, buf1, sizeof(buf));
943
    if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
944
        snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
945
        av_strlcat(buf, buf1, sizeof(buf));
946
    }
947
    if (rt->auth_b64)
948
        av_strlcatf(buf, sizeof(buf),
949
                    "Authorization: Basic %s\r\n",
950
                    rt->auth_b64);
951
    av_strlcat(buf, "\r\n", sizeof(buf));
952

    
953
    dprintf(s, "Sending:\n%s--\n", buf);
954

    
955
    url_write(rt->rtsp_hd, buf, strlen(buf));
956
    rt->last_cmd_time = av_gettime();
957
}
958

    
959
static void rtsp_send_cmd(AVFormatContext *s,
960
                          const char *cmd, RTSPMessageHeader *reply,
961
                          unsigned char **content_ptr)
962
{
963
    rtsp_send_cmd_async(s, cmd, reply, content_ptr);
964

    
965
    rtsp_read_reply(s, reply, content_ptr, 0);
966
}
967

    
968
/**
969
 * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
970
 */
971
static int make_setup_request(AVFormatContext *s, const char *host, int port,
972
                              int lower_transport, const char *real_challenge)
973
{
974
    RTSPState *rt = s->priv_data;
975
    int rtx, j, i, err, interleave = 0;
976
    RTSPStream *rtsp_st;
977
    RTSPMessageHeader reply1, *reply = &reply1;
978
    char cmd[2048];
979
    const char *trans_pref;
980

    
981
    if (rt->transport == RTSP_TRANSPORT_RDT)
982
        trans_pref = "x-pn-tng";
983
    else
984
        trans_pref = "RTP/AVP";
985

    
986
    /* default timeout: 1 minute */
987
    rt->timeout = 60;
988

    
989
    /* for each stream, make the setup request */
990
    /* XXX: we assume the same server is used for the control of each
991
     * RTSP stream */
992

    
993
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
994
        char transport[2048];
995

    
996
        /**
997
         * WMS serves all UDP data over a single connection, the RTX, which
998
         * isn't necessarily the first in the SDP but has to be the first
999
         * to be set up, else the second/third SETUP will fail with a 461.
1000
         */
1001
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
1002
             rt->server_type == RTSP_SERVER_WMS) {
1003
            if (i == 0) {
1004
                /* rtx first */
1005
                for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
1006
                    int len = strlen(rt->rtsp_streams[rtx]->control_url);
1007
                    if (len >= 4 &&
1008
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
1009
                                "/rtx"))
1010
                        break;
1011
                }
1012
                if (rtx == rt->nb_rtsp_streams)
1013
                    return -1; /* no RTX found */
1014
                rtsp_st = rt->rtsp_streams[rtx];
1015
            } else
1016
                rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
1017
        } else
1018
            rtsp_st = rt->rtsp_streams[i];
1019

    
1020
        /* RTP/UDP */
1021
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
1022
            char buf[256];
1023

    
1024
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
1025
                port = reply->transports[0].client_port_min;
1026
                goto have_port;
1027
            }
1028

    
1029
            /* first try in specified port range */
1030
            if (RTSP_RTP_PORT_MIN != 0) {
1031
                while (j <= RTSP_RTP_PORT_MAX) {
1032
                    snprintf(buf, sizeof(buf), "rtp://%s?localport=%d",
1033
                             host, j);
1034
                    /* we will use two ports per rtp stream (rtp and rtcp) */
1035
                    j += 2;
1036
                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)
1037
                        goto rtp_opened;
1038
                }
1039
            }
1040

    
1041
#if 0
1042
            /* then try on any port */
1043
            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
1044
                err = AVERROR_INVALIDDATA;
1045
                goto fail;
1046
            }
1047
#endif
1048

    
1049
        rtp_opened:
1050
            port = rtp_get_local_port(rtsp_st->rtp_handle);
1051
        have_port:
1052
            snprintf(transport, sizeof(transport) - 1,
1053
                     "%s/UDP;", trans_pref);
1054
            if (rt->server_type != RTSP_SERVER_REAL)
1055
                av_strlcat(transport, "unicast;", sizeof(transport));
1056
            av_strlcatf(transport, sizeof(transport),
1057
                     "client_port=%d", port);
1058
            if (rt->transport == RTSP_TRANSPORT_RTP &&
1059
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
1060
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1061
        }
1062

    
1063
        /* RTP/TCP */
1064
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1065
            /** For WMS streams, the application streams are only used for
1066
             * UDP. When trying to set it up for TCP streams, the server
1067
             * will return an error. Therefore, we skip those streams. */
1068
            if (rt->server_type == RTSP_SERVER_WMS &&
1069
                s->streams[rtsp_st->stream_index]->codec->codec_type ==
1070
                    CODEC_TYPE_DATA)
1071
                continue;
1072
            snprintf(transport, sizeof(transport) - 1,
1073
                     "%s/TCP;", trans_pref);
1074
            if (rt->server_type == RTSP_SERVER_WMS)
1075
                av_strlcat(transport, "unicast;", sizeof(transport));
1076
            av_strlcatf(transport, sizeof(transport),
1077
                        "interleaved=%d-%d",
1078
                        interleave, interleave + 1);
1079
            interleave += 2;
1080
        }
1081

    
1082
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1083
            snprintf(transport, sizeof(transport) - 1,
1084
                     "%s/UDP;multicast", trans_pref);
1085
        }
1086
        if (rt->server_type == RTSP_SERVER_REAL ||
1087
            rt->server_type == RTSP_SERVER_WMS)
1088
            av_strlcat(transport, ";mode=play", sizeof(transport));
1089
        snprintf(cmd, sizeof(cmd),
1090
                 "SETUP %s RTSP/1.0\r\n"
1091
                 "Transport: %s\r\n",
1092
                 rtsp_st->control_url, transport);
1093
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
1094
            char real_res[41], real_csum[9];
1095
            ff_rdt_calc_response_and_checksum(real_res, real_csum,
1096
                                              real_challenge);
1097
            av_strlcatf(cmd, sizeof(cmd),
1098
                        "If-Match: %s\r\n"
1099
                        "RealChallenge2: %s, sd=%s\r\n",
1100
                        rt->session_id, real_res, real_csum);
1101
        }
1102
        rtsp_send_cmd(s, cmd, reply, NULL);
1103
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
1104
            err = 1;
1105
            goto fail;
1106
        } else if (reply->status_code != RTSP_STATUS_OK ||
1107
                   reply->nb_transports != 1) {
1108
            err = AVERROR_INVALIDDATA;
1109
            goto fail;
1110
        }
1111

    
1112
        /* XXX: same protocol for all streams is required */
1113
        if (i > 0) {
1114
            if (reply->transports[0].lower_transport != rt->lower_transport ||
1115
                reply->transports[0].transport != rt->transport) {
1116
                err = AVERROR_INVALIDDATA;
1117
                goto fail;
1118
            }
1119
        } else {
1120
            rt->lower_transport = reply->transports[0].lower_transport;
1121
            rt->transport = reply->transports[0].transport;
1122
        }
1123

    
1124
        /* close RTP connection if not choosen */
1125
        if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
1126
            (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
1127
            url_close(rtsp_st->rtp_handle);
1128
            rtsp_st->rtp_handle = NULL;
1129
        }
1130

    
1131
        switch(reply->transports[0].lower_transport) {
1132
        case RTSP_LOWER_TRANSPORT_TCP:
1133
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
1134
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
1135
            break;
1136

    
1137
        case RTSP_LOWER_TRANSPORT_UDP: {
1138
            char url[1024];
1139

    
1140
            /* XXX: also use address if specified */
1141
            snprintf(url, sizeof(url), "rtp://%s:%d",
1142
                     host, reply->transports[0].server_port_min);
1143
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
1144
                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
1145
                err = AVERROR_INVALIDDATA;
1146
                goto fail;
1147
            }
1148
            break;
1149
        }
1150
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
1151
            char url[1024];
1152
            struct in_addr in;
1153
            int port, ttl;
1154

    
1155
            if (reply->transports[0].destination) {
1156
                in.s_addr = htonl(reply->transports[0].destination);
1157
                port      = reply->transports[0].port_min;
1158
                ttl       = reply->transports[0].ttl;
1159
            } else {
1160
                in        = rtsp_st->sdp_ip;
1161
                port      = rtsp_st->sdp_port;
1162
                ttl       = rtsp_st->sdp_ttl;
1163
            }
1164
            snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d",
1165
                     inet_ntoa(in), port, ttl);
1166
            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1167
                err = AVERROR_INVALIDDATA;
1168
                goto fail;
1169
            }
1170
            break;
1171
        }
1172
        }
1173

    
1174
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1175
            goto fail;
1176
    }
1177

    
1178
    if (reply->timeout > 0)
1179
        rt->timeout = reply->timeout;
1180

    
1181
    if (rt->server_type == RTSP_SERVER_REAL)
1182
        rt->need_subscription = 1;
1183

    
1184
    return 0;
1185

    
1186
fail:
1187
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1188
        if (rt->rtsp_streams[i]->rtp_handle) {
1189
            url_close(rt->rtsp_streams[i]->rtp_handle);
1190
            rt->rtsp_streams[i]->rtp_handle = NULL;
1191
        }
1192
    }
1193
    return err;
1194
}
1195

    
1196
static int rtsp_read_play(AVFormatContext *s)
1197
{
1198
    RTSPState *rt = s->priv_data;
1199
    RTSPMessageHeader reply1, *reply = &reply1;
1200
    char cmd[1024];
1201

    
1202
    av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
1203

    
1204
    if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
1205
        if (rt->state == RTSP_STATE_PAUSED) {
1206
            snprintf(cmd, sizeof(cmd),
1207
                     "PLAY %s RTSP/1.0\r\n",
1208
                     s->filename);
1209
        } else {
1210
            snprintf(cmd, sizeof(cmd),
1211
                     "PLAY %s RTSP/1.0\r\n"
1212
                     "Range: npt=%0.3f-\r\n",
1213
                     s->filename,
1214
                     (double)rt->seek_timestamp / AV_TIME_BASE);
1215
        }
1216
        rtsp_send_cmd(s, cmd, reply, NULL);
1217
        if (reply->status_code != RTSP_STATUS_OK) {
1218
            return -1;
1219
        }
1220
    }
1221
    rt->state = RTSP_STATE_PLAYING;
1222
    return 0;
1223
}
1224

    
1225
static int rtsp_read_header(AVFormatContext *s,
1226
                            AVFormatParameters *ap)
1227
{
1228
    RTSPState *rt = s->priv_data;
1229
    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
1230
    char *option_list, *option, *filename;
1231
    URLContext *rtsp_hd;
1232
    int port, ret, err;
1233
    RTSPMessageHeader reply1, *reply = &reply1;
1234
    unsigned char *content = NULL;
1235
    int lower_transport_mask = 0;
1236
    char real_challenge[64];
1237
redirect:
1238
    /* extract hostname and port */
1239
    url_split(NULL, 0, auth, sizeof(auth),
1240
              host, sizeof(host), &port, path, sizeof(path), s->filename);
1241
    if (*auth) {
1242
        int auth_len = strlen(auth), b64_len = ((auth_len + 2) / 3) * 4 + 1;
1243

    
1244
        if (!(rt->auth_b64 = av_malloc(b64_len)))
1245
            return AVERROR(ENOMEM);
1246
        if (!av_base64_encode(rt->auth_b64, b64_len, auth, auth_len)) {
1247
            err = AVERROR(EINVAL);
1248
            goto fail;
1249
        }
1250
    }
1251
    if (port < 0)
1252
        port = RTSP_DEFAULT_PORT;
1253

    
1254
    /* search for options */
1255
    option_list = strchr(path, '?');
1256
    if (option_list) {
1257
        filename = strchr(s->filename, '?');
1258
        while (option_list) {
1259
            /* move the option pointer */
1260
            option = ++option_list;
1261
            option_list = strchr(option_list, '&');
1262
            if (option_list)
1263
                *option_list = 0;
1264

    
1265
            /* handle the options */
1266
            if (!strcmp(option, "udp")) {
1267
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP);
1268
            } else if (!strcmp(option, "multicast")) {
1269
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1270
            } else if (!strcmp(option, "tcp")) {
1271
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_TCP);
1272
            } else {
1273
                strcpy(++filename, option);
1274
                filename += strlen(option);
1275
                if (option_list) *filename = '&';
1276
            }
1277
        }
1278
        *filename = 0;
1279
    }
1280

    
1281
    if (!lower_transport_mask)
1282
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1283

    
1284
    /* open the tcp connexion */
1285
    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
1286
    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
1287
        err = AVERROR(EIO);
1288
        goto fail;
1289
    }
1290
    rt->rtsp_hd = rtsp_hd;
1291
    rt->seq = 0;
1292

    
1293
    /* request options supported by the server; this also detects server
1294
     * type */
1295
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1296
        snprintf(cmd, sizeof(cmd),
1297
                 "OPTIONS %s RTSP/1.0\r\n", s->filename);
1298
        if (rt->server_type == RTSP_SERVER_REAL)
1299
            av_strlcat(cmd,
1300
                       /**
1301
                        * The following entries are required for proper
1302
                        * streaming from a Realmedia server. They are
1303
                        * interdependent in some way although we currently
1304
                        * don't quite understand how. Values were copied
1305
                        * from mplayer SVN r23589.
1306
                        * @param CompanyID is a 16-byte ID in base64
1307
                        * @param ClientChallenge is a 16-byte ID in hex
1308
                        */
1309
                       "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
1310
                       "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
1311
                       "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
1312
                       "GUID: 00000000-0000-0000-0000-000000000000\r\n",
1313
                       sizeof(cmd));
1314
        rtsp_send_cmd(s, cmd, reply, NULL);
1315
        if (reply->status_code != RTSP_STATUS_OK) {
1316
            err = AVERROR_INVALIDDATA;
1317
            goto fail;
1318
        }
1319

    
1320
        /* detect server type if not standard-compliant RTP */
1321
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
1322
            rt->server_type = RTSP_SERVER_REAL;
1323
            continue;
1324
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
1325
            rt->server_type = RTSP_SERVER_WMS;
1326
        } else if (rt->server_type == RTSP_SERVER_REAL)
1327
            strcpy(real_challenge, reply->real_challenge);
1328
        break;
1329
    }
1330

    
1331
    /* describe the stream */
1332
    snprintf(cmd, sizeof(cmd),
1333
             "DESCRIBE %s RTSP/1.0\r\n"
1334
             "Accept: application/sdp\r\n",
1335
             s->filename);
1336
    if (rt->server_type == RTSP_SERVER_REAL) {
1337
        /**
1338
         * The Require: attribute is needed for proper streaming from
1339
         * Realmedia servers.
1340
         */
1341
        av_strlcat(cmd,
1342
                   "Require: com.real.retain-entity-for-setup\r\n",
1343
                   sizeof(cmd));
1344
    }
1345
    rtsp_send_cmd(s, cmd, reply, &content);
1346
    if (!content) {
1347
        err = AVERROR_INVALIDDATA;
1348
        goto fail;
1349
    }
1350
    if (reply->status_code != RTSP_STATUS_OK) {
1351
        err = AVERROR_INVALIDDATA;
1352
        goto fail;
1353
    }
1354

    
1355
    /* now we got the SDP description, we parse it */
1356
    ret = sdp_parse(s, (const char *)content);
1357
    av_freep(&content);
1358
    if (ret < 0) {
1359
        err = AVERROR_INVALIDDATA;
1360
        goto fail;
1361
    }
1362

    
1363
    do {
1364
        int lower_transport = ff_log2_tab[lower_transport_mask &
1365
                                  ~(lower_transport_mask - 1)];
1366

    
1367
        err = make_setup_request(s, host, port, lower_transport,
1368
                                 rt->server_type == RTSP_SERVER_REAL ?
1369
                                     real_challenge : NULL);
1370
        if (err < 0)
1371
            goto fail;
1372
        lower_transport_mask &= ~(1 << lower_transport);
1373
        if (lower_transport_mask == 0 && err == 1) {
1374
            err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
1375
            goto fail;
1376
        }
1377
    } while (err);
1378

    
1379
    rt->state = RTSP_STATE_IDLE;
1380
    rt->seek_timestamp = 0; /* default is to start stream at position zero */
1381
    if (ap->initial_pause) {
1382
        /* do not start immediately */
1383
    } else {
1384
        if (rtsp_read_play(s) < 0) {
1385
            err = AVERROR_INVALIDDATA;
1386
            goto fail;
1387
        }
1388
    }
1389
    return 0;
1390
 fail:
1391
    rtsp_close_streams(rt);
1392
    av_freep(&content);
1393
    url_close(rt->rtsp_hd);
1394
    if (reply->status_code >=300 && reply->status_code < 400) {
1395
        av_strlcpy(s->filename, reply->location, sizeof(s->filename));
1396
        av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
1397
               reply->status_code,
1398
               s->filename);
1399
        goto redirect;
1400
    }
1401
    return err;
1402
}
1403

    
1404
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1405
                           uint8_t *buf, int buf_size)
1406
{
1407
    RTSPState *rt = s->priv_data;
1408
    RTSPStream *rtsp_st;
1409
    fd_set rfds;
1410
    int fd, fd_max, n, i, ret, tcp_fd;
1411
    struct timeval tv;
1412

    
1413
    for (;;) {
1414
        if (url_interrupt_cb())
1415
            return AVERROR(EINTR);
1416
        FD_ZERO(&rfds);
1417
        if (rt->rtsp_hd) {
1418
            tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
1419
            FD_SET(tcp_fd, &rfds);
1420
        } else {
1421
            fd_max = 0;
1422
            tcp_fd = -1;
1423
        }
1424
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
1425
            rtsp_st = rt->rtsp_streams[i];
1426
            if (rtsp_st->rtp_handle) {
1427
                /* currently, we cannot probe RTCP handle because of
1428
                 * blocking restrictions */
1429
                fd = url_get_file_handle(rtsp_st->rtp_handle);
1430
                if (fd > fd_max)
1431
                    fd_max = fd;
1432
                FD_SET(fd, &rfds);
1433
            }
1434
        }
1435
        tv.tv_sec = 0;
1436
        tv.tv_usec = 100 * 1000;
1437
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1438
        if (n > 0) {
1439
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
1440
                rtsp_st = rt->rtsp_streams[i];
1441
                if (rtsp_st->rtp_handle) {
1442
                    fd = url_get_file_handle(rtsp_st->rtp_handle);
1443
                    if (FD_ISSET(fd, &rfds)) {
1444
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1445
                        if (ret > 0) {
1446
                            *prtsp_st = rtsp_st;
1447
                            return ret;
1448
                        }
1449
                    }
1450
                }
1451
            }
1452
#if CONFIG_RTSP_DEMUXER
1453
            if (FD_ISSET(tcp_fd, &rfds)) {
1454
                RTSPMessageHeader reply;
1455

    
1456
                rtsp_read_reply(s, &reply, NULL, 0);
1457
                /* XXX: parse message */
1458
                if (rt->state != RTSP_STATE_PLAYING)
1459
                    return 0;
1460
            }
1461
#endif
1462
        }
1463
    }
1464
}
1465

    
1466
static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1467
                           uint8_t *buf, int buf_size)
1468
{
1469
    RTSPState *rt = s->priv_data;
1470
    int id, len, i, ret;
1471
    RTSPStream *rtsp_st;
1472

    
1473
#ifdef DEBUG_RTP_TCP
1474
    dprintf(s, "tcp_read_packet:\n");
1475
#endif
1476
redo:
1477
    for (;;) {
1478
        RTSPMessageHeader reply;
1479

    
1480
        ret = rtsp_read_reply(s, &reply, NULL, 1);
1481
        if (ret == -1)
1482
            return -1;
1483
        if (ret == 1) /* received '$' */
1484
            break;
1485
        /* XXX: parse message */
1486
        if (rt->state != RTSP_STATE_PLAYING)
1487
            return 0;
1488
    }
1489
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
1490
    if (ret != 3)
1491
        return -1;
1492
    id  = buf[0];
1493
    len = AV_RB16(buf + 1);
1494
#ifdef DEBUG_RTP_TCP
1495
    dprintf(s, "id=%d len=%d\n", id, len);
1496
#endif
1497
    if (len > buf_size || len < 12)
1498
        goto redo;
1499
    /* get the data */
1500
    ret = url_read_complete(rt->rtsp_hd, buf, len);
1501
    if (ret != len)
1502
        return -1;
1503
    if (rt->transport == RTSP_TRANSPORT_RDT &&
1504
        ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
1505
        return -1;
1506

    
1507
    /* find the matching stream */
1508
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1509
        rtsp_st = rt->rtsp_streams[i];
1510
        if (id >= rtsp_st->interleaved_min &&
1511
            id <= rtsp_st->interleaved_max)
1512
            goto found;
1513
    }
1514
    goto redo;
1515
found:
1516
    *prtsp_st = rtsp_st;
1517
    return len;
1518
}
1519

    
1520
static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
1521
{
1522
    RTSPState *rt = s->priv_data;
1523
    int ret, len;
1524
    uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
1525
    RTSPStream *rtsp_st;
1526

    
1527
    /* get next frames from the same RTP packet */
1528
    if (rt->cur_transport_priv) {
1529
        if (rt->transport == RTSP_TRANSPORT_RDT) {
1530
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1531
        } else
1532
            ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1533
        if (ret == 0) {
1534
            rt->cur_transport_priv = NULL;
1535
            return 0;
1536
        } else if (ret == 1) {
1537
            return 0;
1538
        } else
1539
            rt->cur_transport_priv = NULL;
1540
    }
1541

    
1542
    /* read next RTP packet */
1543
 redo:
1544
    switch(rt->lower_transport) {
1545
    default:
1546
#if CONFIG_RTSP_DEMUXER
1547
    case RTSP_LOWER_TRANSPORT_TCP:
1548
        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1549
        break;
1550
#endif
1551
    case RTSP_LOWER_TRANSPORT_UDP:
1552
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1553
        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1554
        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
1555
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
1556
        break;
1557
    }
1558
    if (len < 0)
1559
        return len;
1560
    if (len == 0)
1561
        return AVERROR_EOF;
1562
    if (rt->transport == RTSP_TRANSPORT_RDT) {
1563
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1564
    } else
1565
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1566
    if (ret < 0)
1567
        goto redo;
1568
    if (ret == 1)
1569
        /* more packets may follow, so we save the RTP context */
1570
        rt->cur_transport_priv = rtsp_st->transport_priv;
1571

    
1572
    return ret;
1573
}
1574

    
1575
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
1576
{
1577
    RTSPState *rt = s->priv_data;
1578
    int ret;
1579
    RTSPMessageHeader reply1, *reply = &reply1;
1580
    char cmd[1024];
1581

    
1582
    if (rt->server_type == RTSP_SERVER_REAL) {
1583
        int i;
1584
        enum AVDiscard cache[MAX_STREAMS];
1585

    
1586
        for (i = 0; i < s->nb_streams; i++)
1587
            cache[i] = s->streams[i]->discard;
1588

    
1589
        if (!rt->need_subscription) {
1590
            if (memcmp (cache, rt->real_setup_cache,
1591
                        sizeof(enum AVDiscard) * s->nb_streams)) {
1592
                snprintf(cmd, sizeof(cmd),
1593
                         "SET_PARAMETER %s RTSP/1.0\r\n"
1594
                         "Unsubscribe: %s\r\n",
1595
                         s->filename, rt->last_subscription);
1596
                rtsp_send_cmd(s, cmd, reply, NULL);
1597
                if (reply->status_code != RTSP_STATUS_OK)
1598
                    return AVERROR_INVALIDDATA;
1599
                rt->need_subscription = 1;
1600
            }
1601
        }
1602

    
1603
        if (rt->need_subscription) {
1604
            int r, rule_nr, first = 1;
1605

    
1606
            memcpy(rt->real_setup_cache, cache,
1607
                   sizeof(enum AVDiscard) * s->nb_streams);
1608
            rt->last_subscription[0] = 0;
1609

    
1610
            snprintf(cmd, sizeof(cmd),
1611
                     "SET_PARAMETER %s RTSP/1.0\r\n"
1612
                     "Subscribe: ",
1613
                     s->filename);
1614
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
1615
                rule_nr = 0;
1616
                for (r = 0; r < s->nb_streams; r++) {
1617
                    if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
1618
                        if (s->streams[r]->discard != AVDISCARD_ALL) {
1619
                            if (!first)
1620
                                av_strlcat(rt->last_subscription, ",",
1621
                                           sizeof(rt->last_subscription));
1622
                            ff_rdt_subscribe_rule(
1623
                                rt->last_subscription,
1624
                                sizeof(rt->last_subscription), i, rule_nr);
1625
                            first = 0;
1626
                        }
1627
                        rule_nr++;
1628
                    }
1629
                }
1630
            }
1631
            av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
1632
            rtsp_send_cmd(s, cmd, reply, NULL);
1633
            if (reply->status_code != RTSP_STATUS_OK)
1634
                return AVERROR_INVALIDDATA;
1635
            rt->need_subscription = 0;
1636

    
1637
            if (rt->state == RTSP_STATE_PLAYING)
1638
                rtsp_read_play (s);
1639
        }
1640
    }
1641

    
1642
    ret = rtsp_fetch_packet(s, pkt);
1643
    if (ret < 0)
1644
        return ret;
1645

    
1646
    /* send dummy request to keep TCP connection alive */
1647
    if ((rt->server_type == RTSP_SERVER_WMS ||
1648
         rt->server_type == RTSP_SERVER_REAL) &&
1649
        (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
1650
        if (rt->server_type == RTSP_SERVER_WMS) {
1651
            snprintf(cmd, sizeof(cmd) - 1,
1652
                     "GET_PARAMETER %s RTSP/1.0\r\n",
1653
                     s->filename);
1654
            rtsp_send_cmd_async(s, cmd, reply, NULL);
1655
        } else {
1656
            rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n",
1657
                                reply, NULL);
1658
        }
1659
    }
1660

    
1661
    return 0;
1662
}
1663

    
1664
/* pause the stream */
1665
static int rtsp_read_pause(AVFormatContext *s)
1666
{
1667
    RTSPState *rt = s->priv_data;
1668
    RTSPMessageHeader reply1, *reply = &reply1;
1669
    char cmd[1024];
1670

    
1671
    rt = s->priv_data;
1672

    
1673
    if (rt->state != RTSP_STATE_PLAYING)
1674
        return 0;
1675
    else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
1676
        snprintf(cmd, sizeof(cmd),
1677
                 "PAUSE %s RTSP/1.0\r\n",
1678
                 s->filename);
1679
        rtsp_send_cmd(s, cmd, reply, NULL);
1680
        if (reply->status_code != RTSP_STATUS_OK) {
1681
            return -1;
1682
        }
1683
    }
1684
    rt->state = RTSP_STATE_PAUSED;
1685
    return 0;
1686
}
1687

    
1688
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
1689
                          int64_t timestamp, int flags)
1690
{
1691
    RTSPState *rt = s->priv_data;
1692

    
1693
    rt->seek_timestamp = av_rescale_q(timestamp,
1694
                                      s->streams[stream_index]->time_base,
1695
                                      AV_TIME_BASE_Q);
1696
    switch(rt->state) {
1697
    default:
1698
    case RTSP_STATE_IDLE:
1699
        break;
1700
    case RTSP_STATE_PLAYING:
1701
        if (rtsp_read_pause(s) != 0)
1702
            return -1;
1703
        rt->state = RTSP_STATE_SEEKING;
1704
        if (rtsp_read_play(s) != 0)
1705
            return -1;
1706
        break;
1707
    case RTSP_STATE_PAUSED:
1708
        rt->state = RTSP_STATE_IDLE;
1709
        break;
1710
    }
1711
    return 0;
1712
}
1713

    
1714
static int rtsp_read_close(AVFormatContext *s)
1715
{
1716
    RTSPState *rt = s->priv_data;
1717
    RTSPMessageHeader reply1, *reply = &reply1;
1718
    char cmd[1024];
1719

    
1720
#if 0
1721
    /* NOTE: it is valid to flush the buffer here */
1722
    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1723
        url_fclose(&rt->rtsp_gb);
1724
    }
1725
#endif
1726
    snprintf(cmd, sizeof(cmd),
1727
             "TEARDOWN %s RTSP/1.0\r\n",
1728
             s->filename);
1729
    rtsp_send_cmd(s, cmd, reply, NULL);
1730

    
1731
    rtsp_close_streams(rt);
1732
    url_close(rt->rtsp_hd);
1733
    return 0;
1734
}
1735

    
1736
AVInputFormat rtsp_demuxer = {
1737
    "rtsp",
1738
    NULL_IF_CONFIG_SMALL("RTSP input format"),
1739
    sizeof(RTSPState),
1740
    rtsp_probe,
1741
    rtsp_read_header,
1742
    rtsp_read_packet,
1743
    rtsp_read_close,
1744
    rtsp_read_seek,
1745
    .flags = AVFMT_NOFILE,
1746
    .read_play = rtsp_read_play,
1747
    .read_pause = rtsp_read_pause,
1748
};
1749
#endif
1750

    
1751
static int sdp_probe(AVProbeData *p1)
1752
{
1753
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1754

    
1755
    /* we look for a line beginning "c=IN IP4" */
1756
    while (p < p_end && *p != '\0') {
1757
        if (p + sizeof("c=IN IP4") - 1 < p_end &&
1758
            av_strstart(p, "c=IN IP4", NULL))
1759
            return AVPROBE_SCORE_MAX / 2;
1760

    
1761
        while (p < p_end - 1 && *p != '\n') p++;
1762
        if (++p >= p_end)
1763
            break;
1764
        if (*p == '\r')
1765
            p++;
1766
    }
1767
    return 0;
1768
}
1769

    
1770
#define SDP_MAX_SIZE 8192
1771

    
1772
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1773
{
1774
    RTSPState *rt = s->priv_data;
1775
    RTSPStream *rtsp_st;
1776
    int size, i, err;
1777
    char *content;
1778
    char url[1024];
1779

    
1780
    /* read the whole sdp file */
1781
    /* XXX: better loading */
1782
    content = av_malloc(SDP_MAX_SIZE);
1783
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1784
    if (size <= 0) {
1785
        av_free(content);
1786
        return AVERROR_INVALIDDATA;
1787
    }
1788
    content[size] ='\0';
1789

    
1790
    sdp_parse(s, content);
1791
    av_free(content);
1792

    
1793
    /* open each RTP stream */
1794
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1795
        rtsp_st = rt->rtsp_streams[i];
1796

    
1797
        snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d",
1798
                 inet_ntoa(rtsp_st->sdp_ip),
1799
                 rtsp_st->sdp_port,
1800
                 rtsp_st->sdp_port,
1801
                 rtsp_st->sdp_ttl);
1802
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1803
            err = AVERROR_INVALIDDATA;
1804
            goto fail;
1805
        }
1806
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1807
            goto fail;
1808
    }
1809
    return 0;
1810
fail:
1811
    rtsp_close_streams(rt);
1812
    return err;
1813
}
1814

    
1815
static int sdp_read_close(AVFormatContext *s)
1816
{
1817
    RTSPState *rt = s->priv_data;
1818
    rtsp_close_streams(rt);
1819
    return 0;
1820
}
1821

    
1822
AVInputFormat sdp_demuxer = {
1823
    "sdp",
1824
    NULL_IF_CONFIG_SMALL("SDP"),
1825
    sizeof(RTSPState),
1826
    sdp_probe,
1827
    sdp_read_header,
1828
    rtsp_fetch_packet,
1829
    sdp_read_close,
1830
};