Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtsp.c @ bc8763cd

History | View | Annotate | Download (54.3 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/avstring.h"
26
#include "libavutil/intreadwrite.h"
27
#include "avformat.h"
28

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

    
37
#include "rtpdec.h"
38
#include "rdt.h"
39

    
40
//#define DEBUG
41
//#define DEBUG_RTP_TCP
42

    
43
static int rtsp_read_play(AVFormatContext *s);
44

    
45
/* XXX: currently, the only way to change the protocols consists in
46
   changing this variable */
47

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

    
52
static int rtsp_probe(AVProbeData *p)
53
{
54
    if (av_strstart(p->filename, "rtsp:", NULL))
55
        return AVPROBE_SCORE_MAX;
56
    return 0;
57
}
58

    
59
static int redir_isspace(int c)
60
{
61
    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
62
}
63

    
64
static void skip_spaces(const char **pp)
65
{
66
    const char *p;
67
    p = *pp;
68
    while (redir_isspace(*p))
69
        p++;
70
    *pp = p;
71
}
72

    
73
static void get_word_sep(char *buf, int buf_size, const char *sep,
74
                         const char **pp)
75
{
76
    const char *p;
77
    char *q;
78

    
79
    p = *pp;
80
    if (*p == '/')
81
        p++;
82
    skip_spaces(&p);
83
    q = buf;
84
    while (!strchr(sep, *p) && *p != '\0') {
85
        if ((q - buf) < buf_size - 1)
86
            *q++ = *p;
87
        p++;
88
    }
89
    if (buf_size > 0)
90
        *q = '\0';
91
    *pp = p;
92
}
93

    
94
static void get_word(char *buf, int buf_size, const char **pp)
95
{
96
    const char *p;
97
    char *q;
98

    
99
    p = *pp;
100
    skip_spaces(&p);
101
    q = buf;
102
    while (!redir_isspace(*p) && *p != '\0') {
103
        if ((q - buf) < buf_size - 1)
104
            *q++ = *p;
105
        p++;
106
    }
107
    if (buf_size > 0)
108
        *q = '\0';
109
    *pp = p;
110
}
111

    
112
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
113
   params>] */
114
static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
115
{
116
    char buf[256];
117
    int i;
118
    AVCodec *c;
119
    const char *c_name;
120

    
121
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
122
       see if we can handle this kind of payload */
123
    get_word_sep(buf, sizeof(buf), "/", &p);
124
    if (payload_type >= RTP_PT_PRIVATE) {
125
        RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
126
        while(handler) {
127
            if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
128
                codec->codec_id = handler->codec_id;
129
                rtsp_st->dynamic_handler= handler;
130
                if(handler->open) {
131
                    rtsp_st->dynamic_protocol_context= handler->open();
132
                }
133
                break;
134
            }
135
            handler= handler->next;
136
        }
137
    } else {
138
        /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
139
        /* search into AVRtpPayloadTypes[] */
140
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
141
    }
142

    
143
    c = avcodec_find_decoder(codec->codec_id);
144
    if (c && c->name)
145
        c_name = c->name;
146
    else
147
        c_name = (char *)NULL;
148

    
149
    if (c_name) {
150
        get_word_sep(buf, sizeof(buf), "/", &p);
151
        i = atoi(buf);
152
        switch (codec->codec_type) {
153
            case CODEC_TYPE_AUDIO:
154
                av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
155
                codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
156
                codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
157
                if (i > 0) {
158
                    codec->sample_rate = i;
159
                    get_word_sep(buf, sizeof(buf), "/", &p);
160
                    i = atoi(buf);
161
                    if (i > 0)
162
                        codec->channels = i;
163
                    // TODO: there is a bug here; if it is a mono stream, and less than 22000Hz, faad upconverts to stereo and twice the
164
                    //  frequency.  No problem, but the sample rate is being set here by the sdp line.  Upcoming patch forthcoming. (rdm)
165
                }
166
                av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
167
                av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
168
                break;
169
            case CODEC_TYPE_VIDEO:
170
                av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
171
                break;
172
            default:
173
                break;
174
        }
175
        return 0;
176
    }
177

    
178
    return -1;
179
}
180

    
181
/* return the length and optionnaly the data */
182
static int hex_to_data(uint8_t *data, const char *p)
183
{
184
    int c, len, v;
185

    
186
    len = 0;
187
    v = 1;
188
    for(;;) {
189
        skip_spaces(&p);
190
        if (p == '\0')
191
            break;
192
        c = toupper((unsigned char)*p++);
193
        if (c >= '0' && c <= '9')
194
            c = c - '0';
195
        else if (c >= 'A' && c <= 'F')
196
            c = c - 'A' + 10;
197
        else
198
            break;
199
        v = (v << 4) | c;
200
        if (v & 0x100) {
201
            if (data)
202
                data[len] = v;
203
            len++;
204
            v = 1;
205
        }
206
    }
207
    return len;
208
}
209

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

    
231
typedef struct {
232
    const char *str;
233
    uint16_t type;
234
    uint32_t offset;
235
} AttrNameMap;
236

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

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

    
270
/* parse a SDP line and save stream attributes */
271
static void sdp_parse_fmtp(AVStream *st, const char *p)
272
{
273
    char attr[256];
274
    char value[4096];
275
    int i;
276

    
277
    RTSPStream *rtsp_st = st->priv_data;
278
    AVCodecContext *codec = st->codec;
279
    RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
280

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

    
298
/** Parse a string \p in the form of Range:npt=xx-xx, and determine the start
299
 *  and end time.
300
 *  Used for seeking in the rtp stream.
301
 */
302
static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
303
{
304
    char buf[256];
305

    
306
    skip_spaces(&p);
307
    if (!av_stristart(p, "npt=", &p))
308
        return;
309

    
310
    *start = AV_NOPTS_VALUE;
311
    *end = AV_NOPTS_VALUE;
312

    
313
    get_word_sep(buf, sizeof(buf), "-", &p);
314
    *start = parse_date(buf, 1);
315
    if (*p == '-') {
316
        p++;
317
        get_word_sep(buf, sizeof(buf), "-", &p);
318
        *end = parse_date(buf, 1);
319
    }
320
//    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
321
//    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
322
}
323

    
324
typedef struct SDPParseState {
325
    /* SDP only */
326
    struct in_addr default_ip;
327
    int default_ttl;
328
    int skip_media; ///< set if an unknown m= line occurs
329
} SDPParseState;
330

    
331
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
332
                           int letter, const char *buf)
333
{
334
    RTSPState *rt = s->priv_data;
335
    char buf1[64], st_type[64];
336
    const char *p;
337
    enum CodecType codec_type;
338
    int payload_type, i;
339
    AVStream *st;
340
    RTSPStream *rtsp_st;
341
    struct in_addr sdp_ip;
342
    int ttl;
343

    
344
#ifdef DEBUG
345
    printf("sdp: %c='%s'\n", letter, buf);
346
#endif
347

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

    
407
        rtsp_st->sdp_ip = s1->default_ip;
408
        rtsp_st->sdp_ttl = s1->default_ttl;
409

    
410
        get_word(buf1, sizeof(buf1), &p); /* port */
411
        rtsp_st->sdp_port = atoi(buf1);
412

    
413
        get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
414

    
415
        /* XXX: handle list of formats */
416
        get_word(buf1, sizeof(buf1), &p); /* format list */
417
        rtsp_st->sdp_payload_type = atoi(buf1);
418

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

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

    
492
            // this is so that seeking on a streamed file can work.
493
            rtsp_parse_range_npt(p, &start, &end);
494
            s->start_time= start;
495
            s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek)
496
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
497
            if (atoi(p) == 1)
498
                rt->transport = RTSP_TRANSPORT_RDT;
499
        } else if (s->nb_streams > 0) {
500
            if (rt->server_type == RTSP_SERVER_REAL)
501
                ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
502

    
503
            rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
504
            if (rtsp_st->dynamic_handler &&
505
                rtsp_st->dynamic_handler->parse_sdp_a_line)
506
                rtsp_st->dynamic_handler->parse_sdp_a_line(s, s->nb_streams - 1,
507
                    rtsp_st->dynamic_protocol_context, buf);
508
        }
509
        break;
510
    }
511
}
512

    
513
static int sdp_parse(AVFormatContext *s, const char *content)
514
{
515
    const char *p;
516
    int letter;
517
    /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
518
     * contain long SDP lines containing complete ASF Headers (several
519
     * kB) or arrays of MDPR (RM stream descriptor) headers plus
520
     * "rulebooks" describing their properties. Therefore, the SDP line
521
     * buffer is large. */
522
    char buf[8192], *q;
523
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
524

    
525
    memset(s1, 0, sizeof(SDPParseState));
526
    p = content;
527
    for(;;) {
528
        skip_spaces(&p);
529
        letter = *p;
530
        if (letter == '\0')
531
            break;
532
        p++;
533
        if (*p != '=')
534
            goto next_line;
535
        p++;
536
        /* get the content */
537
        q = buf;
538
        while (*p != '\n' && *p != '\r' && *p != '\0') {
539
            if ((q - buf) < sizeof(buf) - 1)
540
                *q++ = *p;
541
            p++;
542
        }
543
        *q = '\0';
544
        sdp_parse_line(s, s1, letter, buf);
545
    next_line:
546
        while (*p != '\n' && *p != '\0')
547
            p++;
548
        if (*p == '\n')
549
            p++;
550
    }
551
    return 0;
552
}
553

    
554
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
555
{
556
    const char *p;
557
    int v;
558

    
559
    p = *pp;
560
    skip_spaces(&p);
561
    v = strtol(p, (char **)&p, 10);
562
    if (*p == '-') {
563
        p++;
564
        *min_ptr = v;
565
        v = strtol(p, (char **)&p, 10);
566
        *max_ptr = v;
567
    } else {
568
        *min_ptr = v;
569
        *max_ptr = v;
570
    }
571
    *pp = p;
572
}
573

    
574
/* XXX: only one transport specification is parsed */
575
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
576
{
577
    char transport_protocol[16];
578
    char profile[16];
579
    char lower_transport[16];
580
    char parameter[16];
581
    RTSPTransportField *th;
582
    char buf[256];
583

    
584
    reply->nb_transports = 0;
585

    
586
    for(;;) {
587
        skip_spaces(&p);
588
        if (*p == '\0')
589
            break;
590

    
591
        th = &reply->transports[reply->nb_transports];
592

    
593
        get_word_sep(transport_protocol, sizeof(transport_protocol),
594
                     "/", &p);
595
        if (*p == '/')
596
            p++;
597
        if (!strcasecmp (transport_protocol, "rtp")) {
598
            get_word_sep(profile, sizeof(profile), "/;,", &p);
599
            lower_transport[0] = '\0';
600
            /* rtp/avp/<protocol> */
601
            if (*p == '/') {
602
                p++;
603
                get_word_sep(lower_transport, sizeof(lower_transport),
604
                             ";,", &p);
605
            }
606
            th->transport = RTSP_TRANSPORT_RTP;
607
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
608
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
609
            /* x-pn-tng/<protocol> */
610
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
611
            profile[0] = '\0';
612
            th->transport = RTSP_TRANSPORT_RDT;
613
        }
614
        if (!strcasecmp(lower_transport, "TCP"))
615
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
616
        else
617
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
618

    
619
        if (*p == ';')
620
            p++;
621
        /* get each parameter */
622
        while (*p != '\0' && *p != ',') {
623
            get_word_sep(parameter, sizeof(parameter), "=;,", &p);
624
            if (!strcmp(parameter, "port")) {
625
                if (*p == '=') {
626
                    p++;
627
                    rtsp_parse_range(&th->port_min, &th->port_max, &p);
628
                }
629
            } else if (!strcmp(parameter, "client_port")) {
630
                if (*p == '=') {
631
                    p++;
632
                    rtsp_parse_range(&th->client_port_min,
633
                                     &th->client_port_max, &p);
634
                }
635
            } else if (!strcmp(parameter, "server_port")) {
636
                if (*p == '=') {
637
                    p++;
638
                    rtsp_parse_range(&th->server_port_min,
639
                                     &th->server_port_max, &p);
640
                }
641
            } else if (!strcmp(parameter, "interleaved")) {
642
                if (*p == '=') {
643
                    p++;
644
                    rtsp_parse_range(&th->interleaved_min,
645
                                     &th->interleaved_max, &p);
646
                }
647
            } else if (!strcmp(parameter, "multicast")) {
648
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
649
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
650
            } else if (!strcmp(parameter, "ttl")) {
651
                if (*p == '=') {
652
                    p++;
653
                    th->ttl = strtol(p, (char **)&p, 10);
654
                }
655
            } else if (!strcmp(parameter, "destination")) {
656
                struct in_addr ipaddr;
657

    
658
                if (*p == '=') {
659
                    p++;
660
                    get_word_sep(buf, sizeof(buf), ";,", &p);
661
                    if (inet_aton(buf, &ipaddr))
662
                        th->destination = ntohl(ipaddr.s_addr);
663
                }
664
            }
665
            while (*p != ';' && *p != '\0' && *p != ',')
666
                p++;
667
            if (*p == ';')
668
                p++;
669
        }
670
        if (*p == ',')
671
            p++;
672

    
673
        reply->nb_transports++;
674
    }
675
}
676

    
677
void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
678
{
679
    const char *p;
680

    
681
    /* NOTE: we do case independent match for broken servers */
682
    p = buf;
683
    if (av_stristart(p, "Session:", &p)) {
684
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
685
    } else if (av_stristart(p, "Content-Length:", &p)) {
686
        reply->content_length = strtol(p, NULL, 10);
687
    } else if (av_stristart(p, "Transport:", &p)) {
688
        rtsp_parse_transport(reply, p);
689
    } else if (av_stristart(p, "CSeq:", &p)) {
690
        reply->seq = strtol(p, NULL, 10);
691
    } else if (av_stristart(p, "Range:", &p)) {
692
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
693
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
694
        skip_spaces(&p);
695
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
696
    } else if (av_stristart(p, "Server:", &p)) {
697
        skip_spaces(&p);
698
        av_strlcpy(reply->server, p, sizeof(reply->server));
699
    }
700
}
701

    
702
static int url_readbuf(URLContext *h, unsigned char *buf, int size)
703
{
704
    int ret, len;
705

    
706
    len = 0;
707
    while (len < size) {
708
        ret = url_read(h, buf+len, size-len);
709
        if (ret < 1)
710
            return ret;
711
        len += ret;
712
    }
713
    return len;
714
}
715

    
716
/* skip a RTP/TCP interleaved packet */
717
static void rtsp_skip_packet(AVFormatContext *s)
718
{
719
    RTSPState *rt = s->priv_data;
720
    int ret, len, len1;
721
    uint8_t buf[1024];
722

    
723
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
724
    if (ret != 3)
725
        return;
726
    len = AV_RB16(buf + 1);
727
#ifdef DEBUG
728
    printf("skipping RTP packet len=%d\n", len);
729
#endif
730
    /* skip payload */
731
    while (len > 0) {
732
        len1 = len;
733
        if (len1 > sizeof(buf))
734
            len1 = sizeof(buf);
735
        ret = url_readbuf(rt->rtsp_hd, buf, len1);
736
        if (ret != len1)
737
            return;
738
        len -= len1;
739
    }
740
}
741

    
742
static void rtsp_send_cmd(AVFormatContext *s,
743
                          const char *cmd, RTSPMessageHeader *reply,
744
                          unsigned char **content_ptr)
745
{
746
    RTSPState *rt = s->priv_data;
747
    char buf[4096], buf1[1024], *q;
748
    unsigned char ch;
749
    const char *p;
750
    int content_length, line_count;
751
    unsigned char *content = NULL;
752

    
753
    memset(reply, 0, sizeof(*reply));
754

    
755
    rt->seq++;
756
    av_strlcpy(buf, cmd, sizeof(buf));
757
    snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
758
    av_strlcat(buf, buf1, sizeof(buf));
759
    if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
760
        snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
761
        av_strlcat(buf, buf1, sizeof(buf));
762
    }
763
    av_strlcat(buf, "\r\n", sizeof(buf));
764
#ifdef DEBUG
765
    printf("Sending:\n%s--\n", buf);
766
#endif
767
    url_write(rt->rtsp_hd, buf, strlen(buf));
768

    
769
    /* parse reply (XXX: use buffers) */
770
    line_count = 0;
771
    rt->last_reply[0] = '\0';
772
    for(;;) {
773
        q = buf;
774
        for(;;) {
775
            if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
776
                break;
777
            if (ch == '\n')
778
                break;
779
            if (ch == '$') {
780
                /* XXX: only parse it if first char on line ? */
781
                rtsp_skip_packet(s);
782
            } else if (ch != '\r') {
783
                if ((q - buf) < sizeof(buf) - 1)
784
                    *q++ = ch;
785
            }
786
        }
787
        *q = '\0';
788
#ifdef DEBUG
789
        printf("line='%s'\n", buf);
790
#endif
791
        /* test if last line */
792
        if (buf[0] == '\0')
793
            break;
794
        p = buf;
795
        if (line_count == 0) {
796
            /* get reply code */
797
            get_word(buf1, sizeof(buf1), &p);
798
            get_word(buf1, sizeof(buf1), &p);
799
            reply->status_code = atoi(buf1);
800
        } else {
801
            rtsp_parse_line(reply, p);
802
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
803
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
804
        }
805
        line_count++;
806
    }
807

    
808
    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
809
        av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
810

    
811
    content_length = reply->content_length;
812
    if (content_length > 0) {
813
        /* leave some room for a trailing '\0' (useful for simple parsing) */
814
        content = av_malloc(content_length + 1);
815
        (void)url_readbuf(rt->rtsp_hd, content, content_length);
816
        content[content_length] = '\0';
817
    }
818
    if (content_ptr)
819
        *content_ptr = content;
820
    else
821
        av_free(content);
822
}
823

    
824

    
825
/* close and free RTSP streams */
826
static void rtsp_close_streams(RTSPState *rt)
827
{
828
    int i;
829
    RTSPStream *rtsp_st;
830

    
831
    for(i=0;i<rt->nb_rtsp_streams;i++) {
832
        rtsp_st = rt->rtsp_streams[i];
833
        if (rtsp_st) {
834
            if (rtsp_st->transport_priv) {
835
                if (rt->transport == RTSP_TRANSPORT_RDT)
836
                    ff_rdt_parse_close(rtsp_st->transport_priv);
837
                else
838
                    rtp_parse_close(rtsp_st->transport_priv);
839
            }
840
            if (rtsp_st->rtp_handle)
841
                url_close(rtsp_st->rtp_handle);
842
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
843
                rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
844
        }
845
    }
846
    av_free(rt->rtsp_streams);
847
}
848

    
849
static int
850
rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
851
{
852
    RTSPState *rt = s->priv_data;
853
    AVStream *st = NULL;
854

    
855
    /* open the RTP context */
856
    if (rtsp_st->stream_index >= 0)
857
        st = s->streams[rtsp_st->stream_index];
858
    if (!st)
859
        s->ctx_flags |= AVFMTCTX_NOHEADER;
860

    
861
    if (rt->transport == RTSP_TRANSPORT_RDT)
862
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
863
                                            rtsp_st->dynamic_protocol_context,
864
                                            rtsp_st->dynamic_handler);
865
    else
866
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
867
                                         rtsp_st->sdp_payload_type,
868
                                         &rtsp_st->rtp_payload_data);
869

    
870
    if (!rtsp_st->transport_priv) {
871
         return AVERROR(ENOMEM);
872
    } else if (rt->transport != RTSP_TRANSPORT_RDT) {
873
        if(rtsp_st->dynamic_handler) {
874
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
875
                                           rtsp_st->dynamic_protocol_context,
876
                                           rtsp_st->dynamic_handler);
877
        }
878
    }
879

    
880
    return 0;
881
}
882

    
883
/**
884
 * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
885
 */
886
static int
887
make_setup_request (AVFormatContext *s, const char *host, int port,
888
                    int lower_transport, const char *real_challenge)
889
{
890
    RTSPState *rt = s->priv_data;
891
    int rtx, j, i, err, interleave = 0;
892
    RTSPStream *rtsp_st;
893
    RTSPMessageHeader reply1, *reply = &reply1;
894
    char cmd[2048];
895
    const char *trans_pref;
896

    
897
    if (rt->transport == RTSP_TRANSPORT_RDT)
898
        trans_pref = "x-pn-tng";
899
    else
900
        trans_pref = "RTP/AVP";
901

    
902
    /* for each stream, make the setup request */
903
    /* XXX: we assume the same server is used for the control of each
904
       RTSP stream */
905

    
906
    for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
907
        char transport[2048];
908

    
909
        /**
910
         * WMS serves all UDP data over a single connection, the RTX, which
911
         * isn't necessarily the first in the SDP but has to be the first
912
         * to be set up, else the second/third SETUP will fail with a 461.
913
         */
914
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
915
             rt->server_type == RTSP_SERVER_WMS) {
916
            if (i == 0) {
917
                /* rtx first */
918
                for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
919
                    int len = strlen(rt->rtsp_streams[rtx]->control_url);
920
                    if (len >= 4 &&
921
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4, "/rtx"))
922
                        break;
923
                }
924
                if (rtx == rt->nb_rtsp_streams)
925
                    return -1; /* no RTX found */
926
                rtsp_st = rt->rtsp_streams[rtx];
927
            } else
928
                rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
929
        } else
930
            rtsp_st = rt->rtsp_streams[i];
931

    
932
        /* RTP/UDP */
933
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
934
            char buf[256];
935

    
936
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
937
                port = reply->transports[0].client_port_min;
938
                goto have_port;
939
            }
940

    
941
            /* first try in specified port range */
942
            if (RTSP_RTP_PORT_MIN != 0) {
943
                while(j <= RTSP_RTP_PORT_MAX) {
944
                    snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j);
945
                    j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
946
                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
947
                        goto rtp_opened;
948
                    }
949
                }
950
            }
951

    
952
/*            then try on any port
953
**            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
954
**                err = AVERROR_INVALIDDATA;
955
**                goto fail;
956
**            }
957
*/
958

    
959
        rtp_opened:
960
            port = rtp_get_local_port(rtsp_st->rtp_handle);
961
        have_port:
962
            snprintf(transport, sizeof(transport) - 1,
963
                     "%s/UDP;", trans_pref);
964
            if (rt->server_type != RTSP_SERVER_REAL)
965
                av_strlcat(transport, "unicast;", sizeof(transport));
966
            av_strlcatf(transport, sizeof(transport),
967
                     "client_port=%d", port);
968
            if (rt->transport == RTSP_TRANSPORT_RTP &&
969
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
970
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
971
        }
972

    
973
        /* RTP/TCP */
974
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
975
            /** For WMS streams, the application streams are only used for
976
             * UDP. When trying to set it up for TCP streams, the server
977
             * will return an error. Therefore, we skip those streams. */
978
            if (rt->server_type == RTSP_SERVER_WMS &&
979
                s->streams[rtsp_st->stream_index]->codec->codec_type == CODEC_TYPE_DATA)
980
                continue;
981
            snprintf(transport, sizeof(transport) - 1,
982
                     "%s/TCP;", trans_pref);
983
            if (rt->server_type == RTSP_SERVER_WMS)
984
                av_strlcat(transport, "unicast;", sizeof(transport));
985
            av_strlcatf(transport, sizeof(transport),
986
                        "interleaved=%d-%d",
987
                        interleave, interleave + 1);
988
            interleave += 2;
989
        }
990

    
991
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
992
            snprintf(transport, sizeof(transport) - 1,
993
                     "%s/UDP;multicast", trans_pref);
994
        }
995
        if (rt->server_type == RTSP_SERVER_REAL ||
996
            rt->server_type == RTSP_SERVER_WMS)
997
            av_strlcat(transport, ";mode=play", sizeof(transport));
998
        snprintf(cmd, sizeof(cmd),
999
                 "SETUP %s RTSP/1.0\r\n"
1000
                 "Transport: %s\r\n",
1001
                 rtsp_st->control_url, transport);
1002
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
1003
            char real_res[41], real_csum[9];
1004
            ff_rdt_calc_response_and_checksum(real_res, real_csum,
1005
                                              real_challenge);
1006
            av_strlcatf(cmd, sizeof(cmd),
1007
                        "If-Match: %s\r\n"
1008
                        "RealChallenge2: %s, sd=%s\r\n",
1009
                        rt->session_id, real_res, real_csum);
1010
        }
1011
        rtsp_send_cmd(s, cmd, reply, NULL);
1012
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
1013
            err = 1;
1014
            goto fail;
1015
        } else if (reply->status_code != RTSP_STATUS_OK ||
1016
                   reply->nb_transports != 1) {
1017
            err = AVERROR_INVALIDDATA;
1018
            goto fail;
1019
        }
1020

    
1021
        /* XXX: same protocol for all streams is required */
1022
        if (i > 0) {
1023
            if (reply->transports[0].lower_transport != rt->lower_transport ||
1024
                reply->transports[0].transport != rt->transport) {
1025
                err = AVERROR_INVALIDDATA;
1026
                goto fail;
1027
            }
1028
        } else {
1029
            rt->lower_transport = reply->transports[0].lower_transport;
1030
            rt->transport = reply->transports[0].transport;
1031
        }
1032

    
1033
        /* close RTP connection if not choosen */
1034
        if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
1035
            (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
1036
            url_close(rtsp_st->rtp_handle);
1037
            rtsp_st->rtp_handle = NULL;
1038
        }
1039

    
1040
        switch(reply->transports[0].lower_transport) {
1041
        case RTSP_LOWER_TRANSPORT_TCP:
1042
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
1043
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
1044
            break;
1045

    
1046
        case RTSP_LOWER_TRANSPORT_UDP:
1047
            {
1048
                char url[1024];
1049

    
1050
                /* XXX: also use address if specified */
1051
                snprintf(url, sizeof(url), "rtp://%s:%d",
1052
                         host, reply->transports[0].server_port_min);
1053
                if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
1054
                    rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
1055
                    err = AVERROR_INVALIDDATA;
1056
                    goto fail;
1057
                }
1058
            }
1059
            break;
1060
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1061
            {
1062
                char url[1024];
1063
                struct in_addr in;
1064

    
1065
                in.s_addr = htonl(reply->transports[0].destination);
1066
                snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d",
1067
                         inet_ntoa(in),
1068
                         reply->transports[0].port_min,
1069
                         reply->transports[0].ttl);
1070
                if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1071
                    err = AVERROR_INVALIDDATA;
1072
                    goto fail;
1073
                }
1074
            }
1075
            break;
1076
        }
1077

    
1078
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1079
            goto fail;
1080
    }
1081

    
1082
    if (rt->server_type == RTSP_SERVER_REAL)
1083
        rt->need_subscription = 1;
1084

    
1085
    return 0;
1086

    
1087
fail:
1088
    for (i=0; i<rt->nb_rtsp_streams; i++) {
1089
        if (rt->rtsp_streams[i]->rtp_handle) {
1090
            url_close(rt->rtsp_streams[i]->rtp_handle);
1091
            rt->rtsp_streams[i]->rtp_handle = NULL;
1092
        }
1093
    }
1094
    return err;
1095
}
1096

    
1097
static int rtsp_read_header(AVFormatContext *s,
1098
                            AVFormatParameters *ap)
1099
{
1100
    RTSPState *rt = s->priv_data;
1101
    char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
1102
    URLContext *rtsp_hd;
1103
    int port, ret, err;
1104
    RTSPMessageHeader reply1, *reply = &reply1;
1105
    unsigned char *content = NULL;
1106
    int lower_transport_mask = 0;
1107
    char real_challenge[64];
1108

    
1109
    /* extract hostname and port */
1110
    url_split(NULL, 0, NULL, 0,
1111
              host, sizeof(host), &port, path, sizeof(path), s->filename);
1112
    if (port < 0)
1113
        port = RTSP_DEFAULT_PORT;
1114

    
1115
    /* search for options */
1116
    option_list = strchr(path, '?');
1117
    if (option_list) {
1118
        /* remove the options from the path */
1119
        *option_list++ = 0;
1120
        while(option_list) {
1121
            /* move the option pointer */
1122
            option = option_list;
1123
            option_list = strchr(option_list, '&');
1124
            if (option_list)
1125
                *(option_list++) = 0;
1126
            /* handle the options */
1127
            if (strcmp(option, "udp") == 0)
1128
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP);
1129
            else if (strcmp(option, "multicast") == 0)
1130
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1131
            else if (strcmp(option, "tcp") == 0)
1132
                lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_TCP);
1133
        }
1134
    }
1135

    
1136
    if (!lower_transport_mask)
1137
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1138

    
1139
    /* open the tcp connexion */
1140
    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
1141
    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
1142
        return AVERROR(EIO);
1143
    rt->rtsp_hd = rtsp_hd;
1144
    rt->seq = 0;
1145

    
1146
    /* request options supported by the server; this also detects server type */
1147
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1148
        snprintf(cmd, sizeof(cmd),
1149
                 "OPTIONS %s RTSP/1.0\r\n", s->filename);
1150
        if (rt->server_type == RTSP_SERVER_REAL)
1151
            av_strlcat(cmd,
1152
                       /**
1153
                        * The following entries are required for proper
1154
                        * streaming from a Realmedia server. They are
1155
                        * interdependent in some way although we currently
1156
                        * don't quite understand how. Values were copied
1157
                        * from mplayer SVN r23589.
1158
                        * @param CompanyID is a 16-byte ID in base64
1159
                        * @param ClientChallenge is a 16-byte ID in hex
1160
                        */
1161
                       "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
1162
                       "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
1163
                       "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
1164
                       "GUID: 00000000-0000-0000-0000-000000000000\r\n",
1165
                       sizeof(cmd));
1166
        rtsp_send_cmd(s, cmd, reply, NULL);
1167
        if (reply->status_code != RTSP_STATUS_OK) {
1168
            err = AVERROR_INVALIDDATA;
1169
            goto fail;
1170
        }
1171

    
1172
        /* detect server type if not standard-compliant RTP */
1173
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
1174
            rt->server_type = RTSP_SERVER_REAL;
1175
            continue;
1176
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
1177
            rt->server_type = RTSP_SERVER_WMS;
1178
        } else if (rt->server_type == RTSP_SERVER_REAL) {
1179
            strcpy(real_challenge, reply->real_challenge);
1180
        }
1181
        break;
1182
    }
1183

    
1184
    /* describe the stream */
1185
    snprintf(cmd, sizeof(cmd),
1186
             "DESCRIBE %s RTSP/1.0\r\n"
1187
             "Accept: application/sdp\r\n",
1188
             s->filename);
1189
    if (rt->server_type == RTSP_SERVER_REAL) {
1190
        /**
1191
         * The Require: attribute is needed for proper streaming from
1192
         * Realmedia servers.
1193
         */
1194
        av_strlcat(cmd,
1195
                   "Require: com.real.retain-entity-for-setup\r\n",
1196
                   sizeof(cmd));
1197
    }
1198
    rtsp_send_cmd(s, cmd, reply, &content);
1199
    if (!content) {
1200
        err = AVERROR_INVALIDDATA;
1201
        goto fail;
1202
    }
1203
    if (reply->status_code != RTSP_STATUS_OK) {
1204
        err = AVERROR_INVALIDDATA;
1205
        goto fail;
1206
    }
1207

    
1208
    /* now we got the SDP description, we parse it */
1209
    ret = sdp_parse(s, (const char *)content);
1210
    av_freep(&content);
1211
    if (ret < 0) {
1212
        err = AVERROR_INVALIDDATA;
1213
        goto fail;
1214
    }
1215

    
1216
    do {
1217
        int lower_transport = ff_log2_tab[lower_transport_mask & ~(lower_transport_mask - 1)];
1218

    
1219
        err = make_setup_request(s, host, port, lower_transport,
1220
                                 rt->server_type == RTSP_SERVER_REAL ?
1221
                                     real_challenge : NULL);
1222
        if (err < 0)
1223
            goto fail;
1224
        lower_transport_mask &= ~(1 << lower_transport);
1225
        if (lower_transport_mask == 0 && err == 1) {
1226
            err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
1227
            goto fail;
1228
        }
1229
    } while (err);
1230

    
1231
    rt->state = RTSP_STATE_IDLE;
1232
    rt->seek_timestamp = 0; /* default is to start stream at position
1233
                               zero */
1234
    if (ap->initial_pause) {
1235
        /* do not start immediately */
1236
    } else {
1237
        if (rtsp_read_play(s) < 0) {
1238
            err = AVERROR_INVALIDDATA;
1239
            goto fail;
1240
        }
1241
    }
1242
    return 0;
1243
 fail:
1244
    rtsp_close_streams(rt);
1245
    av_freep(&content);
1246
    url_close(rt->rtsp_hd);
1247
    return err;
1248
}
1249

    
1250
static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1251
                           uint8_t *buf, int buf_size)
1252
{
1253
    RTSPState *rt = s->priv_data;
1254
    int id, len, i, ret;
1255
    RTSPStream *rtsp_st;
1256

    
1257
#ifdef DEBUG_RTP_TCP
1258
    printf("tcp_read_packet:\n");
1259
#endif
1260
 redo:
1261
    for(;;) {
1262
        ret = url_readbuf(rt->rtsp_hd, buf, 1);
1263
#ifdef DEBUG_RTP_TCP
1264
        printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
1265
#endif
1266
        if (ret != 1)
1267
            return -1;
1268
        if (buf[0] == '$')
1269
            break;
1270
    }
1271
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
1272
    if (ret != 3)
1273
        return -1;
1274
    id = buf[0];
1275
    len = AV_RB16(buf + 1);
1276
#ifdef DEBUG_RTP_TCP
1277
    printf("id=%d len=%d\n", id, len);
1278
#endif
1279
    if (len > buf_size || len < 12)
1280
        goto redo;
1281
    /* get the data */
1282
    ret = url_readbuf(rt->rtsp_hd, buf, len);
1283
    if (ret != len)
1284
        return -1;
1285
    if (rt->transport == RTSP_TRANSPORT_RDT &&
1286
        ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
1287
        return -1;
1288

    
1289
    /* find the matching stream */
1290
    for(i = 0; i < rt->nb_rtsp_streams; i++) {
1291
        rtsp_st = rt->rtsp_streams[i];
1292
        if (id >= rtsp_st->interleaved_min &&
1293
            id <= rtsp_st->interleaved_max)
1294
            goto found;
1295
    }
1296
    goto redo;
1297
 found:
1298
    *prtsp_st = rtsp_st;
1299
    return len;
1300
}
1301

    
1302
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1303
                           uint8_t *buf, int buf_size)
1304
{
1305
    RTSPState *rt = s->priv_data;
1306
    RTSPStream *rtsp_st;
1307
    fd_set rfds;
1308
    int fd, fd_max, n, i, ret;
1309
    struct timeval tv;
1310

    
1311
    for(;;) {
1312
        if (url_interrupt_cb())
1313
            return AVERROR(EINTR);
1314
        FD_ZERO(&rfds);
1315
        fd_max = -1;
1316
        for(i = 0; i < rt->nb_rtsp_streams; i++) {
1317
            rtsp_st = rt->rtsp_streams[i];
1318
            if (rtsp_st->rtp_handle) {
1319
                /* currently, we cannot probe RTCP handle because of
1320
                 * blocking restrictions */
1321
                fd = url_get_file_handle(rtsp_st->rtp_handle);
1322
                if (fd > fd_max)
1323
                    fd_max = fd;
1324
                FD_SET(fd, &rfds);
1325
            }
1326
        }
1327
        tv.tv_sec = 0;
1328
        tv.tv_usec = 100 * 1000;
1329
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1330
        if (n > 0) {
1331
            for(i = 0; i < rt->nb_rtsp_streams; i++) {
1332
                rtsp_st = rt->rtsp_streams[i];
1333
                if (rtsp_st->rtp_handle) {
1334
                    fd = url_get_file_handle(rtsp_st->rtp_handle);
1335
                    if (FD_ISSET(fd, &rfds)) {
1336
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1337
                        if (ret > 0) {
1338
                            *prtsp_st = rtsp_st;
1339
                            return ret;
1340
                        }
1341
                    }
1342
                }
1343
            }
1344
        }
1345
    }
1346
}
1347

    
1348
static int rtsp_read_packet(AVFormatContext *s,
1349
                            AVPacket *pkt)
1350
{
1351
    RTSPState *rt = s->priv_data;
1352
    RTSPStream *rtsp_st;
1353
    int ret, len;
1354
    uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
1355

    
1356
    if (rt->server_type == RTSP_SERVER_REAL) {
1357
        int i;
1358
        RTSPMessageHeader reply1, *reply = &reply1;
1359
        enum AVDiscard cache[MAX_STREAMS];
1360
        char cmd[1024];
1361

    
1362
        for (i = 0; i < s->nb_streams; i++)
1363
            cache[i] = s->streams[i]->discard;
1364

    
1365
        if (!rt->need_subscription) {
1366
            if (memcmp (cache, rt->real_setup_cache,
1367
                        sizeof(enum AVDiscard) * s->nb_streams)) {
1368
                av_strlcatf(cmd, sizeof(cmd),
1369
                            "SET_PARAMETER %s RTSP/1.0\r\n"
1370
                            "Unsubscribe: %s\r\n",
1371
                            s->filename, rt->last_subscription);
1372
                rtsp_send_cmd(s, cmd, reply, NULL);
1373
                if (reply->status_code != RTSP_STATUS_OK)
1374
                    return AVERROR_INVALIDDATA;
1375
                rt->need_subscription = 1;
1376
            }
1377
        }
1378

    
1379
        if (rt->need_subscription) {
1380
            int r, rule_nr, first = 1;
1381

    
1382
            memcpy(rt->real_setup_cache, cache,
1383
                   sizeof(enum AVDiscard) * s->nb_streams);
1384
            rt->last_subscription[0] = 0;
1385

    
1386
            snprintf(cmd, sizeof(cmd),
1387
                     "SET_PARAMETER %s RTSP/1.0\r\n"
1388
                     "Subscribe: ",
1389
                     s->filename);
1390
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
1391
                rule_nr = 0;
1392
                for (r = 0; r < s->nb_streams; r++) {
1393
                    if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
1394
                        if (s->streams[r]->discard != AVDISCARD_ALL) {
1395
                            if (!first)
1396
                                av_strlcat(rt->last_subscription, ",",
1397
                                           sizeof(rt->last_subscription));
1398
                            ff_rdt_subscribe_rule(
1399
                                rt->last_subscription,
1400
                                sizeof(rt->last_subscription), i, rule_nr);
1401
                            first = 0;
1402
                        }
1403
                        rule_nr++;
1404
                    }
1405
                }
1406
            }
1407
            av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
1408
            rtsp_send_cmd(s, cmd, reply, NULL);
1409
            if (reply->status_code != RTSP_STATUS_OK)
1410
                return AVERROR_INVALIDDATA;
1411
            rt->need_subscription = 0;
1412

    
1413
            if (rt->state == RTSP_STATE_PLAYING)
1414
                rtsp_read_play (s);
1415
        }
1416
    }
1417

    
1418
    /* get next frames from the same RTP packet */
1419
    if (rt->cur_transport_priv) {
1420
        if (rt->transport == RTSP_TRANSPORT_RDT)
1421
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1422
        else
1423
            ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1424
        if (ret == 0) {
1425
            rt->cur_transport_priv = NULL;
1426
            return 0;
1427
        } else if (ret == 1) {
1428
            return 0;
1429
        } else {
1430
            rt->cur_transport_priv = NULL;
1431
        }
1432
    }
1433

    
1434
    /* read next RTP packet */
1435
 redo:
1436
    switch(rt->lower_transport) {
1437
    default:
1438
    case RTSP_LOWER_TRANSPORT_TCP:
1439
        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1440
        break;
1441
    case RTSP_LOWER_TRANSPORT_UDP:
1442
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1443
        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1444
        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
1445
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
1446
        break;
1447
    }
1448
    if (len < 0)
1449
        return len;
1450
    if (rt->transport == RTSP_TRANSPORT_RDT)
1451
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1452
    else
1453
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1454
    if (ret < 0)
1455
        goto redo;
1456
    if (ret == 1) {
1457
        /* more packets may follow, so we save the RTP context */
1458
        rt->cur_transport_priv = rtsp_st->transport_priv;
1459
    }
1460
    return 0;
1461
}
1462

    
1463
static int rtsp_read_play(AVFormatContext *s)
1464
{
1465
    RTSPState *rt = s->priv_data;
1466
    RTSPMessageHeader reply1, *reply = &reply1;
1467
    char cmd[1024];
1468

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

    
1471
    if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
1472
        if (rt->state == RTSP_STATE_PAUSED) {
1473
            snprintf(cmd, sizeof(cmd),
1474
                     "PLAY %s RTSP/1.0\r\n",
1475
                     s->filename);
1476
        } else {
1477
            snprintf(cmd, sizeof(cmd),
1478
                     "PLAY %s RTSP/1.0\r\n"
1479
                     "Range: npt=%0.3f-\r\n",
1480
                     s->filename,
1481
                     (double)rt->seek_timestamp / AV_TIME_BASE);
1482
        }
1483
        rtsp_send_cmd(s, cmd, reply, NULL);
1484
        if (reply->status_code != RTSP_STATUS_OK) {
1485
            return -1;
1486
        }
1487
    }
1488
    rt->state = RTSP_STATE_PLAYING;
1489
    return 0;
1490
}
1491

    
1492
/* pause the stream */
1493
static int rtsp_read_pause(AVFormatContext *s)
1494
{
1495
    RTSPState *rt = s->priv_data;
1496
    RTSPMessageHeader reply1, *reply = &reply1;
1497
    char cmd[1024];
1498

    
1499
    rt = s->priv_data;
1500

    
1501
    if (rt->state != RTSP_STATE_PLAYING)
1502
        return 0;
1503
    else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
1504
        snprintf(cmd, sizeof(cmd),
1505
                 "PAUSE %s RTSP/1.0\r\n",
1506
                 s->filename);
1507
        rtsp_send_cmd(s, cmd, reply, NULL);
1508
        if (reply->status_code != RTSP_STATUS_OK) {
1509
            return -1;
1510
        }
1511
    }
1512
    rt->state = RTSP_STATE_PAUSED;
1513
    return 0;
1514
}
1515

    
1516
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
1517
                          int64_t timestamp, int flags)
1518
{
1519
    RTSPState *rt = s->priv_data;
1520

    
1521
    rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q);
1522
    switch(rt->state) {
1523
    default:
1524
    case RTSP_STATE_IDLE:
1525
        break;
1526
    case RTSP_STATE_PLAYING:
1527
        if (rtsp_read_play(s) != 0)
1528
            return -1;
1529
        break;
1530
    case RTSP_STATE_PAUSED:
1531
        rt->state = RTSP_STATE_IDLE;
1532
        break;
1533
    }
1534
    return 0;
1535
}
1536

    
1537
static int rtsp_read_close(AVFormatContext *s)
1538
{
1539
    RTSPState *rt = s->priv_data;
1540
    RTSPMessageHeader reply1, *reply = &reply1;
1541
    char cmd[1024];
1542

    
1543
#if 0
1544
    /* NOTE: it is valid to flush the buffer here */
1545
    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1546
        url_fclose(&rt->rtsp_gb);
1547
    }
1548
#endif
1549
    snprintf(cmd, sizeof(cmd),
1550
             "TEARDOWN %s RTSP/1.0\r\n",
1551
             s->filename);
1552
    rtsp_send_cmd(s, cmd, reply, NULL);
1553

    
1554
    rtsp_close_streams(rt);
1555
    url_close(rt->rtsp_hd);
1556
    return 0;
1557
}
1558

    
1559
#if CONFIG_RTSP_DEMUXER
1560
AVInputFormat rtsp_demuxer = {
1561
    "rtsp",
1562
    NULL_IF_CONFIG_SMALL("RTSP input format"),
1563
    sizeof(RTSPState),
1564
    rtsp_probe,
1565
    rtsp_read_header,
1566
    rtsp_read_packet,
1567
    rtsp_read_close,
1568
    rtsp_read_seek,
1569
    .flags = AVFMT_NOFILE,
1570
    .read_play = rtsp_read_play,
1571
    .read_pause = rtsp_read_pause,
1572
};
1573
#endif
1574

    
1575
static int sdp_probe(AVProbeData *p1)
1576
{
1577
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1578

    
1579
    /* we look for a line beginning "c=IN IP4" */
1580
    while (p < p_end && *p != '\0') {
1581
        if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL))
1582
            return AVPROBE_SCORE_MAX / 2;
1583

    
1584
        while(p < p_end - 1 && *p != '\n') p++;
1585
        if (++p >= p_end)
1586
            break;
1587
        if (*p == '\r')
1588
            p++;
1589
    }
1590
    return 0;
1591
}
1592

    
1593
#define SDP_MAX_SIZE 8192
1594

    
1595
static int sdp_read_header(AVFormatContext *s,
1596
                           AVFormatParameters *ap)
1597
{
1598
    RTSPState *rt = s->priv_data;
1599
    RTSPStream *rtsp_st;
1600
    int size, i, err;
1601
    char *content;
1602
    char url[1024];
1603

    
1604
    /* read the whole sdp file */
1605
    /* XXX: better loading */
1606
    content = av_malloc(SDP_MAX_SIZE);
1607
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1608
    if (size <= 0) {
1609
        av_free(content);
1610
        return AVERROR_INVALIDDATA;
1611
    }
1612
    content[size] ='\0';
1613

    
1614
    sdp_parse(s, content);
1615
    av_free(content);
1616

    
1617
    /* open each RTP stream */
1618
    for(i=0;i<rt->nb_rtsp_streams;i++) {
1619
        rtsp_st = rt->rtsp_streams[i];
1620

    
1621
        snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d",
1622
                 inet_ntoa(rtsp_st->sdp_ip),
1623
                 rtsp_st->sdp_port,
1624
                 rtsp_st->sdp_port,
1625
                 rtsp_st->sdp_ttl);
1626
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1627
            err = AVERROR_INVALIDDATA;
1628
            goto fail;
1629
        }
1630
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1631
            goto fail;
1632
    }
1633
    return 0;
1634
 fail:
1635
    rtsp_close_streams(rt);
1636
    return err;
1637
}
1638

    
1639
static int sdp_read_packet(AVFormatContext *s,
1640
                            AVPacket *pkt)
1641
{
1642
    return rtsp_read_packet(s, pkt);
1643
}
1644

    
1645
static int sdp_read_close(AVFormatContext *s)
1646
{
1647
    RTSPState *rt = s->priv_data;
1648
    rtsp_close_streams(rt);
1649
    return 0;
1650
}
1651

    
1652
#if CONFIG_SDP_DEMUXER
1653
AVInputFormat sdp_demuxer = {
1654
    "sdp",
1655
    NULL_IF_CONFIG_SMALL("SDP"),
1656
    sizeof(RTSPState),
1657
    sdp_probe,
1658
    sdp_read_header,
1659
    sdp_read_packet,
1660
    sdp_read_close,
1661
};
1662
#endif
1663

    
1664
#if CONFIG_REDIR_DEMUXER
1665
/* dummy redirector format (used directly in av_open_input_file now) */
1666
static int redir_probe(AVProbeData *pd)
1667
{
1668
    const char *p;
1669
    p = pd->buf;
1670
    while (redir_isspace(*p))
1671
        p++;
1672
    if (av_strstart(p, "http://", NULL) ||
1673
        av_strstart(p, "rtsp://", NULL))
1674
        return AVPROBE_SCORE_MAX;
1675
    return 0;
1676
}
1677

    
1678
static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap)
1679
{
1680
    char buf[4096], *q;
1681
    int c;
1682
    AVFormatContext *ic = NULL;
1683
    ByteIOContext *f = s->pb;
1684

    
1685
    /* parse each URL and try to open it */
1686
    c = url_fgetc(f);
1687
    while (c != URL_EOF) {
1688
        /* skip spaces */
1689
        for(;;) {
1690
            if (!redir_isspace(c))
1691
                break;
1692
            c = url_fgetc(f);
1693
        }
1694
        if (c == URL_EOF)
1695
            break;
1696
        /* record url */
1697
        q = buf;
1698
        for(;;) {
1699
            if (c == URL_EOF || redir_isspace(c))
1700
                break;
1701
            if ((q - buf) < sizeof(buf) - 1)
1702
                *q++ = c;
1703
            c = url_fgetc(f);
1704
        }
1705
        *q = '\0';
1706
        //printf("URL='%s'\n", buf);
1707
        /* try to open the media file */
1708
        if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1709
            break;
1710
    }
1711
    if (!ic)
1712
        return AVERROR(EIO);
1713

    
1714
    *s = *ic;
1715
    url_fclose(f);
1716

    
1717
    return 0;
1718
}
1719

    
1720
AVInputFormat redir_demuxer = {
1721
    "redir",
1722
    NULL_IF_CONFIG_SMALL("Redirector format"),
1723
    0,
1724
    redir_probe,
1725
    redir_read_header,
1726
    NULL,
1727
    NULL,
1728
};
1729
#endif