Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtsp.c @ 1cf151e9

History | View | Annotate | Download (48.1 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 "avformat.h"
27

    
28
#include <sys/time.h>
29
#include <unistd.h> /* for select() prototype */
30
#include <strings.h>
31
#include "network.h"
32
#include "rtsp.h"
33

    
34
#include "rtp_internal.h"
35

    
36
//#define DEBUG
37
//#define DEBUG_RTP_TCP
38

    
39
enum RTSPClientState {
40
    RTSP_STATE_IDLE,
41
    RTSP_STATE_PLAYING,
42
    RTSP_STATE_PAUSED,
43
};
44

    
45
enum RTSPServerType {
46
    RTSP_SERVER_RTP, /*< Standard-compliant RTP-server */
47
    RTSP_SERVER_RDT, /*< Realmedia-style server */
48
    RTSP_SERVER_LAST
49
};
50

    
51
typedef struct RTSPState {
52
    URLContext *rtsp_hd; /* RTSP TCP connexion handle */
53
    int nb_rtsp_streams;
54
    struct RTSPStream **rtsp_streams;
55

    
56
    enum RTSPClientState state;
57
    int64_t seek_timestamp;
58

    
59
    /* XXX: currently we use unbuffered input */
60
    //    ByteIOContext rtsp_gb;
61
    int seq;        /* RTSP command sequence number */
62
    char session_id[512];
63
    enum RTSPProtocol protocol;
64
    enum RTSPServerType server_type;
65
    char last_reply[2048]; /* XXX: allocate ? */
66
    RTPDemuxContext *cur_rtp;
67
} RTSPState;
68

    
69
typedef struct RTSPStream {
70
    URLContext *rtp_handle; /* RTP stream handle */
71
    RTPDemuxContext *rtp_ctx; /* RTP parse context */
72

    
73
    int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */
74
    int interleaved_min, interleaved_max;  /* interleave ids, if TCP transport */
75
    char control_url[1024]; /* url for this stream (from SDP) */
76

    
77
    int sdp_port; /* port (from SDP content - not used in RTSP) */
78
    struct in_addr sdp_ip; /* IP address  (from SDP content - not used in RTSP) */
79
    int sdp_ttl;  /* IP TTL (from SDP content - not used in RTSP) */
80
    int sdp_payload_type; /* payload type - only used in SDP */
81
    rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */
82

    
83
    RTPDynamicProtocolHandler *dynamic_handler; ///< Only valid if it's a dynamic protocol. (This is the handler structure)
84
    void *dynamic_protocol_context; ///< Only valid if it's a dynamic protocol. (This is any private data associated with the dynamic protocol)
85
} RTSPStream;
86

    
87
static int rtsp_read_play(AVFormatContext *s);
88

    
89
/* XXX: currently, the only way to change the protocols consists in
90
   changing this variable */
91

    
92
#if LIBAVFORMAT_VERSION_INT < (53 << 16)
93
int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP);
94
#endif
95

    
96
static int rtsp_probe(AVProbeData *p)
97
{
98
    if (av_strstart(p->filename, "rtsp:", NULL))
99
        return AVPROBE_SCORE_MAX;
100
    return 0;
101
}
102

    
103
static int redir_isspace(int c)
104
{
105
    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
106
}
107

    
108
static void skip_spaces(const char **pp)
109
{
110
    const char *p;
111
    p = *pp;
112
    while (redir_isspace(*p))
113
        p++;
114
    *pp = p;
115
}
116

    
117
static void get_word_sep(char *buf, int buf_size, const char *sep,
118
                         const char **pp)
119
{
120
    const char *p;
121
    char *q;
122

    
123
    p = *pp;
124
    if (*p == '/')
125
        p++;
126
    skip_spaces(&p);
127
    q = buf;
128
    while (!strchr(sep, *p) && *p != '\0') {
129
        if ((q - buf) < buf_size - 1)
130
            *q++ = *p;
131
        p++;
132
    }
133
    if (buf_size > 0)
134
        *q = '\0';
135
    *pp = p;
136
}
137

    
138
static void get_word(char *buf, int buf_size, const char **pp)
139
{
140
    const char *p;
141
    char *q;
142

    
143
    p = *pp;
144
    skip_spaces(&p);
145
    q = buf;
146
    while (!redir_isspace(*p) && *p != '\0') {
147
        if ((q - buf) < buf_size - 1)
148
            *q++ = *p;
149
        p++;
150
    }
151
    if (buf_size > 0)
152
        *q = '\0';
153
    *pp = p;
154
}
155

    
156
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
157
   params>] */
158
static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
159
{
160
    char buf[256];
161
    int i;
162
    AVCodec *c;
163
    const char *c_name;
164

    
165
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
166
       see if we can handle this kind of payload */
167
    get_word_sep(buf, sizeof(buf), "/", &p);
168
    if (payload_type >= RTP_PT_PRIVATE) {
169
        RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
170
        while(handler) {
171
            if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
172
                codec->codec_id = handler->codec_id;
173
                rtsp_st->dynamic_handler= handler;
174
                if(handler->open) {
175
                    rtsp_st->dynamic_protocol_context= handler->open();
176
                }
177
                break;
178
            }
179
            handler= handler->next;
180
        }
181
    } else {
182
        /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
183
        /* search into AVRtpPayloadTypes[] */
184
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
185
    }
186

    
187
    c = avcodec_find_decoder(codec->codec_id);
188
    if (c && c->name)
189
        c_name = c->name;
190
    else
191
        c_name = (char *)NULL;
192

    
193
    if (c_name) {
194
        get_word_sep(buf, sizeof(buf), "/", &p);
195
        i = atoi(buf);
196
        switch (codec->codec_type) {
197
            case CODEC_TYPE_AUDIO:
198
                av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
199
                codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
200
                codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
201
                if (i > 0) {
202
                    codec->sample_rate = i;
203
                    get_word_sep(buf, sizeof(buf), "/", &p);
204
                    i = atoi(buf);
205
                    if (i > 0)
206
                        codec->channels = i;
207
                    // TODO: there is a bug here; if it is a mono stream, and less than 22000Hz, faad upconverts to stereo and twice the
208
                    //  frequency.  No problem, but the sample rate is being set here by the sdp line.  Upcoming patch forthcoming. (rdm)
209
                }
210
                av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
211
                av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
212
                break;
213
            case CODEC_TYPE_VIDEO:
214
                av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
215
                break;
216
            default:
217
                break;
218
        }
219
        return 0;
220
    }
221

    
222
    return -1;
223
}
224

    
225
/* return the length and optionnaly the data */
226
static int hex_to_data(uint8_t *data, const char *p)
227
{
228
    int c, len, v;
229

    
230
    len = 0;
231
    v = 1;
232
    for(;;) {
233
        skip_spaces(&p);
234
        if (p == '\0')
235
            break;
236
        c = toupper((unsigned char)*p++);
237
        if (c >= '0' && c <= '9')
238
            c = c - '0';
239
        else if (c >= 'A' && c <= 'F')
240
            c = c - 'A' + 10;
241
        else
242
            break;
243
        v = (v << 4) | c;
244
        if (v & 0x100) {
245
            if (data)
246
                data[len] = v;
247
            len++;
248
            v = 1;
249
        }
250
    }
251
    return len;
252
}
253

    
254
static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
255
{
256
    switch (codec->codec_id) {
257
        case CODEC_ID_MPEG4:
258
        case CODEC_ID_AAC:
259
            if (!strcmp(attr, "config")) {
260
                /* decode the hexa encoded parameter */
261
                int len = hex_to_data(NULL, value);
262
                codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
263
                if (!codec->extradata)
264
                    return;
265
                codec->extradata_size = len;
266
                hex_to_data(codec->extradata, value);
267
            }
268
            break;
269
        default:
270
            break;
271
    }
272
    return;
273
}
274

    
275
typedef struct attrname_map
276
{
277
    const char *str;
278
    uint16_t type;
279
    uint32_t offset;
280
} attrname_map_t;
281

    
282
/* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
283
#define ATTR_NAME_TYPE_INT 0
284
#define ATTR_NAME_TYPE_STR 1
285
static attrname_map_t attr_names[]=
286
{
287
    {"SizeLength",       ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)},
288
    {"IndexLength",      ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)},
289
    {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)},
290
    {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)},
291
    {"StreamType",       ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)},
292
    {"mode",             ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)},
293
    {NULL, -1, -1},
294
};
295

    
296
/** parse the attribute line from the fmtp a line of an sdp resonse.  This is broken out as a function
297
* because it is used in rtp_h264.c, which is forthcoming.
298
*/
299
int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size)
300
{
301
    skip_spaces(p);
302
    if(**p)
303
    {
304
        get_word_sep(attr, attr_size, "=", p);
305
        if (**p == '=')
306
            (*p)++;
307
        get_word_sep(value, value_size, ";", p);
308
        if (**p == ';')
309
            (*p)++;
310
        return 1;
311
    }
312
    return 0;
313
}
314

    
315
/* parse a SDP line and save stream attributes */
316
static void sdp_parse_fmtp(AVStream *st, const char *p)
317
{
318
    char attr[256];
319
    char value[4096];
320
    int i;
321

    
322
    RTSPStream *rtsp_st = st->priv_data;
323
    AVCodecContext *codec = st->codec;
324
    rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data;
325

    
326
    /* loop on each attribute */
327
    while(rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value)))
328
    {
329
        /* grab the codec extra_data from the config parameter of the fmtp line */
330
        sdp_parse_fmtp_config(codec, attr, value);
331
        /* Looking for a known attribute */
332
        for (i = 0; attr_names[i].str; ++i) {
333
            if (!strcasecmp(attr, attr_names[i].str)) {
334
                if (attr_names[i].type == ATTR_NAME_TYPE_INT)
335
                    *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
336
                else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
337
                    *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
338
            }
339
        }
340
    }
341
}
342

    
343
/** Parse a string \p in the form of Range:npt=xx-xx, and determine the start
344
 *  and end time.
345
 *  Used for seeking in the rtp stream.
346
 */
347
static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
348
{
349
    char buf[256];
350

    
351
    skip_spaces(&p);
352
    if (!av_stristart(p, "npt=", &p))
353
        return;
354

    
355
    *start = AV_NOPTS_VALUE;
356
    *end = AV_NOPTS_VALUE;
357

    
358
    get_word_sep(buf, sizeof(buf), "-", &p);
359
    *start = parse_date(buf, 1);
360
    if (*p == '-') {
361
        p++;
362
        get_word_sep(buf, sizeof(buf), "-", &p);
363
        *end = parse_date(buf, 1);
364
    }
365
//    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
366
//    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
367
}
368

    
369
typedef struct SDPParseState {
370
    /* SDP only */
371
    struct in_addr default_ip;
372
    int default_ttl;
373
} SDPParseState;
374

    
375
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
376
                           int letter, const char *buf)
377
{
378
    RTSPState *rt = s->priv_data;
379
    char buf1[64], st_type[64];
380
    const char *p;
381
    int codec_type, payload_type, i;
382
    AVStream *st;
383
    RTSPStream *rtsp_st;
384
    struct in_addr sdp_ip;
385
    int ttl;
386

    
387
#ifdef DEBUG
388
    printf("sdp: %c='%s'\n", letter, buf);
389
#endif
390

    
391
    p = buf;
392
    switch(letter) {
393
    case 'c':
394
        get_word(buf1, sizeof(buf1), &p);
395
        if (strcmp(buf1, "IN") != 0)
396
            return;
397
        get_word(buf1, sizeof(buf1), &p);
398
        if (strcmp(buf1, "IP4") != 0)
399
            return;
400
        get_word_sep(buf1, sizeof(buf1), "/", &p);
401
        if (inet_aton(buf1, &sdp_ip) == 0)
402
            return;
403
        ttl = 16;
404
        if (*p == '/') {
405
            p++;
406
            get_word_sep(buf1, sizeof(buf1), "/", &p);
407
            ttl = atoi(buf1);
408
        }
409
        if (s->nb_streams == 0) {
410
            s1->default_ip = sdp_ip;
411
            s1->default_ttl = ttl;
412
        } else {
413
            st = s->streams[s->nb_streams - 1];
414
            rtsp_st = st->priv_data;
415
            rtsp_st->sdp_ip = sdp_ip;
416
            rtsp_st->sdp_ttl = ttl;
417
        }
418
        break;
419
    case 's':
420
        av_strlcpy(s->title, p, sizeof(s->title));
421
        break;
422
    case 'i':
423
        if (s->nb_streams == 0) {
424
            av_strlcpy(s->comment, p, sizeof(s->comment));
425
            break;
426
        }
427
        break;
428
    case 'm':
429
        /* new stream */
430
        get_word(st_type, sizeof(st_type), &p);
431
        if (!strcmp(st_type, "audio")) {
432
            codec_type = CODEC_TYPE_AUDIO;
433
        } else if (!strcmp(st_type, "video")) {
434
            codec_type = CODEC_TYPE_VIDEO;
435
        } else {
436
            return;
437
        }
438
        rtsp_st = av_mallocz(sizeof(RTSPStream));
439
        if (!rtsp_st)
440
            return;
441
        rtsp_st->stream_index = -1;
442
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
443

    
444
        rtsp_st->sdp_ip = s1->default_ip;
445
        rtsp_st->sdp_ttl = s1->default_ttl;
446

    
447
        get_word(buf1, sizeof(buf1), &p); /* port */
448
        rtsp_st->sdp_port = atoi(buf1);
449

    
450
        get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
451

    
452
        /* XXX: handle list of formats */
453
        get_word(buf1, sizeof(buf1), &p); /* format list */
454
        rtsp_st->sdp_payload_type = atoi(buf1);
455

    
456
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
457
            /* no corresponding stream */
458
        } else {
459
            st = av_new_stream(s, 0);
460
            if (!st)
461
                return;
462
            st->priv_data = rtsp_st;
463
            rtsp_st->stream_index = st->index;
464
            st->codec->codec_type = codec_type;
465
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
466
                /* if standard payload type, we can find the codec right now */
467
                rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
468
            }
469
        }
470
        /* put a default control url */
471
        av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url));
472
        break;
473
    case 'a':
474
        if (av_strstart(p, "control:", &p) && s->nb_streams > 0) {
475
            char proto[32];
476
            /* get the control url */
477
            st = s->streams[s->nb_streams - 1];
478
            rtsp_st = st->priv_data;
479

    
480
            /* XXX: may need to add full url resolution */
481
            url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
482
            if (proto[0] == '\0') {
483
                /* relative control URL */
484
                av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url));
485
                av_strlcat(rtsp_st->control_url, p,   sizeof(rtsp_st->control_url));
486
            } else {
487
                av_strlcpy(rtsp_st->control_url, p,   sizeof(rtsp_st->control_url));
488
            }
489
        } else if (av_strstart(p, "rtpmap:", &p)) {
490
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
491
            get_word(buf1, sizeof(buf1), &p);
492
            payload_type = atoi(buf1);
493
            for(i = 0; i < s->nb_streams;i++) {
494
                st = s->streams[i];
495
                rtsp_st = st->priv_data;
496
                if (rtsp_st->sdp_payload_type == payload_type) {
497
                    sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
498
                }
499
            }
500
        } else if (av_strstart(p, "fmtp:", &p)) {
501
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
502
            get_word(buf1, sizeof(buf1), &p);
503
            payload_type = atoi(buf1);
504
            for(i = 0; i < s->nb_streams;i++) {
505
                st = s->streams[i];
506
                rtsp_st = st->priv_data;
507
                if (rtsp_st->sdp_payload_type == payload_type) {
508
                    if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
509
                        if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) {
510
                            sdp_parse_fmtp(st, p);
511
                        }
512
                    } else {
513
                        sdp_parse_fmtp(st, p);
514
                    }
515
                }
516
            }
517
        } else if(av_strstart(p, "framesize:", &p)) {
518
            // let dynamic protocol handlers have a stab at the line.
519
            get_word(buf1, sizeof(buf1), &p);
520
            payload_type = atoi(buf1);
521
            for(i = 0; i < s->nb_streams;i++) {
522
                st = s->streams[i];
523
                rtsp_st = st->priv_data;
524
                if (rtsp_st->sdp_payload_type == payload_type) {
525
                    if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
526
                        rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf);
527
                    }
528
                }
529
            }
530
        } else if(av_strstart(p, "range:", &p)) {
531
            int64_t start, end;
532

    
533
            // this is so that seeking on a streamed file can work.
534
            rtsp_parse_range_npt(p, &start, &end);
535
            s->start_time= start;
536
            s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek)
537
        } else if (s->nb_streams > 0) {
538
            rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
539
            if (rtsp_st->dynamic_handler &&
540
                rtsp_st->dynamic_handler->parse_sdp_a_line)
541
                rtsp_st->dynamic_handler->parse_sdp_a_line(s->streams[s->nb_streams - 1],
542
                    rtsp_st->dynamic_protocol_context, buf);
543
        }
544
        break;
545
    }
546
}
547

    
548
static int sdp_parse(AVFormatContext *s, const char *content)
549
{
550
    const char *p;
551
    int letter;
552
    char buf[1024], *q;
553
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
554

    
555
    memset(s1, 0, sizeof(SDPParseState));
556
    p = content;
557
    for(;;) {
558
        skip_spaces(&p);
559
        letter = *p;
560
        if (letter == '\0')
561
            break;
562
        p++;
563
        if (*p != '=')
564
            goto next_line;
565
        p++;
566
        /* get the content */
567
        q = buf;
568
        while (*p != '\n' && *p != '\r' && *p != '\0') {
569
            if ((q - buf) < sizeof(buf) - 1)
570
                *q++ = *p;
571
            p++;
572
        }
573
        *q = '\0';
574
        sdp_parse_line(s, s1, letter, buf);
575
    next_line:
576
        while (*p != '\n' && *p != '\0')
577
            p++;
578
        if (*p == '\n')
579
            p++;
580
    }
581
    return 0;
582
}
583

    
584
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
585
{
586
    const char *p;
587
    int v;
588

    
589
    p = *pp;
590
    skip_spaces(&p);
591
    v = strtol(p, (char **)&p, 10);
592
    if (*p == '-') {
593
        p++;
594
        *min_ptr = v;
595
        v = strtol(p, (char **)&p, 10);
596
        *max_ptr = v;
597
    } else {
598
        *min_ptr = v;
599
        *max_ptr = v;
600
    }
601
    *pp = p;
602
}
603

    
604
/* XXX: only one transport specification is parsed */
605
static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
606
{
607
    char transport_protocol[16];
608
    char profile[16];
609
    char lower_transport[16];
610
    char parameter[16];
611
    RTSPTransportField *th;
612
    char buf[256];
613

    
614
    reply->nb_transports = 0;
615

    
616
    for(;;) {
617
        skip_spaces(&p);
618
        if (*p == '\0')
619
            break;
620

    
621
        th = &reply->transports[reply->nb_transports];
622

    
623
        get_word_sep(transport_protocol, sizeof(transport_protocol),
624
                     "/", &p);
625
        if (*p == '/')
626
            p++;
627
        if (!strcasecmp (transport_protocol, "rtp")) {
628
            get_word_sep(profile, sizeof(profile), "/;,", &p);
629
            lower_transport[0] = '\0';
630
            /* rtp/avp/<protocol> */
631
            if (*p == '/') {
632
                p++;
633
                get_word_sep(lower_transport, sizeof(lower_transport),
634
                             ";,", &p);
635
                }
636
        } else if (!strcasecmp (transport_protocol, "x-pn-tng")) {
637
            /* x-pn-tng/<protocol> */
638
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
639
            profile[0] = '\0';
640
        }
641
        if (!strcasecmp(lower_transport, "TCP"))
642
            th->protocol = RTSP_PROTOCOL_RTP_TCP;
643
        else
644
            th->protocol = RTSP_PROTOCOL_RTP_UDP;
645

    
646
        if (*p == ';')
647
            p++;
648
        /* get each parameter */
649
        while (*p != '\0' && *p != ',') {
650
            get_word_sep(parameter, sizeof(parameter), "=;,", &p);
651
            if (!strcmp(parameter, "port")) {
652
                if (*p == '=') {
653
                    p++;
654
                    rtsp_parse_range(&th->port_min, &th->port_max, &p);
655
                }
656
            } else if (!strcmp(parameter, "client_port")) {
657
                if (*p == '=') {
658
                    p++;
659
                    rtsp_parse_range(&th->client_port_min,
660
                                     &th->client_port_max, &p);
661
                }
662
            } else if (!strcmp(parameter, "server_port")) {
663
                if (*p == '=') {
664
                    p++;
665
                    rtsp_parse_range(&th->server_port_min,
666
                                     &th->server_port_max, &p);
667
                }
668
            } else if (!strcmp(parameter, "interleaved")) {
669
                if (*p == '=') {
670
                    p++;
671
                    rtsp_parse_range(&th->interleaved_min,
672
                                     &th->interleaved_max, &p);
673
                }
674
            } else if (!strcmp(parameter, "multicast")) {
675
                if (th->protocol == RTSP_PROTOCOL_RTP_UDP)
676
                    th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST;
677
            } else if (!strcmp(parameter, "ttl")) {
678
                if (*p == '=') {
679
                    p++;
680
                    th->ttl = strtol(p, (char **)&p, 10);
681
                }
682
            } else if (!strcmp(parameter, "destination")) {
683
                struct in_addr ipaddr;
684

    
685
                if (*p == '=') {
686
                    p++;
687
                    get_word_sep(buf, sizeof(buf), ";,", &p);
688
                    if (inet_aton(buf, &ipaddr))
689
                        th->destination = ntohl(ipaddr.s_addr);
690
                }
691
            }
692
            while (*p != ';' && *p != '\0' && *p != ',')
693
                p++;
694
            if (*p == ';')
695
                p++;
696
        }
697
        if (*p == ',')
698
            p++;
699

    
700
        reply->nb_transports++;
701
    }
702
}
703

    
704
void rtsp_parse_line(RTSPHeader *reply, const char *buf)
705
{
706
    const char *p;
707

    
708
    /* NOTE: we do case independent match for broken servers */
709
    p = buf;
710
    if (av_stristart(p, "Session:", &p)) {
711
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
712
    } else if (av_stristart(p, "Content-Length:", &p)) {
713
        reply->content_length = strtol(p, NULL, 10);
714
    } else if (av_stristart(p, "Transport:", &p)) {
715
        rtsp_parse_transport(reply, p);
716
    } else if (av_stristart(p, "CSeq:", &p)) {
717
        reply->seq = strtol(p, NULL, 10);
718
    } else if (av_stristart(p, "Range:", &p)) {
719
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
720
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
721
        skip_spaces(&p);
722
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
723
    }
724
}
725

    
726
static int url_readbuf(URLContext *h, unsigned char *buf, int size)
727
{
728
    int ret, len;
729

    
730
    len = 0;
731
    while (len < size) {
732
        ret = url_read(h, buf+len, size-len);
733
        if (ret < 1)
734
            return ret;
735
        len += ret;
736
    }
737
    return len;
738
}
739

    
740
/* skip a RTP/TCP interleaved packet */
741
static void rtsp_skip_packet(AVFormatContext *s)
742
{
743
    RTSPState *rt = s->priv_data;
744
    int ret, len, len1;
745
    uint8_t buf[1024];
746

    
747
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
748
    if (ret != 3)
749
        return;
750
    len = AV_RB16(buf + 1);
751
#ifdef DEBUG
752
    printf("skipping RTP packet len=%d\n", len);
753
#endif
754
    /* skip payload */
755
    while (len > 0) {
756
        len1 = len;
757
        if (len1 > sizeof(buf))
758
            len1 = sizeof(buf);
759
        ret = url_readbuf(rt->rtsp_hd, buf, len1);
760
        if (ret != len1)
761
            return;
762
        len -= len1;
763
    }
764
}
765

    
766
static void rtsp_send_cmd(AVFormatContext *s,
767
                          const char *cmd, RTSPHeader *reply,
768
                          unsigned char **content_ptr)
769
{
770
    RTSPState *rt = s->priv_data;
771
    char buf[4096], buf1[1024], *q;
772
    unsigned char ch;
773
    const char *p;
774
    int content_length, line_count;
775
    unsigned char *content = NULL;
776

    
777
    memset(reply, 0, sizeof(RTSPHeader));
778

    
779
    rt->seq++;
780
    av_strlcpy(buf, cmd, sizeof(buf));
781
    snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
782
    av_strlcat(buf, buf1, sizeof(buf));
783
    if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
784
        snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
785
        av_strlcat(buf, buf1, sizeof(buf));
786
    }
787
    av_strlcat(buf, "\r\n", sizeof(buf));
788
#ifdef DEBUG
789
    printf("Sending:\n%s--\n", buf);
790
#endif
791
    url_write(rt->rtsp_hd, buf, strlen(buf));
792

    
793
    /* parse reply (XXX: use buffers) */
794
    line_count = 0;
795
    rt->last_reply[0] = '\0';
796
    for(;;) {
797
        q = buf;
798
        for(;;) {
799
            if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
800
                break;
801
            if (ch == '\n')
802
                break;
803
            if (ch == '$') {
804
                /* XXX: only parse it if first char on line ? */
805
                rtsp_skip_packet(s);
806
            } else if (ch != '\r') {
807
                if ((q - buf) < sizeof(buf) - 1)
808
                    *q++ = ch;
809
            }
810
        }
811
        *q = '\0';
812
#ifdef DEBUG
813
        printf("line='%s'\n", buf);
814
#endif
815
        /* test if last line */
816
        if (buf[0] == '\0')
817
            break;
818
        p = buf;
819
        if (line_count == 0) {
820
            /* get reply code */
821
            get_word(buf1, sizeof(buf1), &p);
822
            get_word(buf1, sizeof(buf1), &p);
823
            reply->status_code = atoi(buf1);
824
        } else {
825
            rtsp_parse_line(reply, p);
826
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
827
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
828
        }
829
        line_count++;
830
    }
831

    
832
    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
833
        av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
834

    
835
    content_length = reply->content_length;
836
    if (content_length > 0) {
837
        /* leave some room for a trailing '\0' (useful for simple parsing) */
838
        content = av_malloc(content_length + 1);
839
        (void)url_readbuf(rt->rtsp_hd, content, content_length);
840
        content[content_length] = '\0';
841
    }
842
    if (content_ptr)
843
        *content_ptr = content;
844
    else
845
        av_free(content);
846
}
847

    
848

    
849
/* close and free RTSP streams */
850
static void rtsp_close_streams(RTSPState *rt)
851
{
852
    int i;
853
    RTSPStream *rtsp_st;
854

    
855
    for(i=0;i<rt->nb_rtsp_streams;i++) {
856
        rtsp_st = rt->rtsp_streams[i];
857
        if (rtsp_st) {
858
            if (rtsp_st->rtp_ctx)
859
                rtp_parse_close(rtsp_st->rtp_ctx);
860
            if (rtsp_st->rtp_handle)
861
                url_close(rtsp_st->rtp_handle);
862
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
863
                rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
864
        }
865
    }
866
    av_free(rt->rtsp_streams);
867
}
868

    
869
/**
870
 * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
871
 */
872
static int
873
make_setup_request (AVFormatContext *s, const char *host, int port, int protocol)
874
{
875
    RTSPState *rt = s->priv_data;
876
    int j, i, err;
877
    RTSPStream *rtsp_st;
878
    AVStream *st;
879
    RTSPHeader reply1, *reply = &reply1;
880
    char cmd[2048];
881

    
882
    /* for each stream, make the setup request */
883
    /* XXX: we assume the same server is used for the control of each
884
       RTSP stream */
885

    
886
    for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
887
        char transport[2048];
888

    
889
        rtsp_st = rt->rtsp_streams[i];
890

    
891
        /* compute available transports */
892
        transport[0] = '\0';
893

    
894
        /* RTP/UDP */
895
        if (protocol == RTSP_PROTOCOL_RTP_UDP) {
896
            char buf[256];
897

    
898
            /* first try in specified port range */
899
            if (RTSP_RTP_PORT_MIN != 0) {
900
                while(j <= RTSP_RTP_PORT_MAX) {
901
                    snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j);
902
                    j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
903
                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
904
                        goto rtp_opened;
905
                    }
906
                }
907
            }
908

    
909
/*            then try on any port
910
**            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
911
**                err = AVERROR_INVALIDDATA;
912
**                goto fail;
913
**            }
914
*/
915

    
916
        rtp_opened:
917
            port = rtp_get_local_port(rtsp_st->rtp_handle);
918
            if (transport[0] != '\0')
919
                av_strlcat(transport, ",", sizeof(transport));
920
            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
921
                     "RTP/AVP/UDP;unicast;client_port=%d-%d",
922
                     port, port + 1);
923
        }
924

    
925
        /* RTP/TCP */
926
        else if (protocol == RTSP_PROTOCOL_RTP_TCP) {
927
            if (transport[0] != '\0')
928
                av_strlcat(transport, ",", sizeof(transport));
929
            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
930
                     "RTP/AVP/TCP");
931
        }
932

    
933
        else if (protocol == RTSP_PROTOCOL_RTP_UDP_MULTICAST) {
934
            if (transport[0] != '\0')
935
                av_strlcat(transport, ",", sizeof(transport));
936
            snprintf(transport + strlen(transport),
937
                     sizeof(transport) - strlen(transport) - 1,
938
                     "RTP/AVP/UDP;multicast");
939
        }
940
        snprintf(cmd, sizeof(cmd),
941
                 "SETUP %s RTSP/1.0\r\n"
942
                 "Transport: %s\r\n",
943
                 rtsp_st->control_url, transport);
944
        rtsp_send_cmd(s, cmd, reply, NULL);
945
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
946
            err = 1;
947
            goto fail;
948
        } else if (reply->status_code != RTSP_STATUS_OK ||
949
                   reply->nb_transports != 1) {
950
            err = AVERROR_INVALIDDATA;
951
            goto fail;
952
        }
953

    
954
        /* XXX: same protocol for all streams is required */
955
        if (i > 0) {
956
            if (reply->transports[0].protocol != rt->protocol) {
957
                err = AVERROR_INVALIDDATA;
958
                goto fail;
959
            }
960
        } else {
961
            rt->protocol = reply->transports[0].protocol;
962
        }
963

    
964
        /* close RTP connection if not choosen */
965
        if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
966
            (protocol == RTSP_PROTOCOL_RTP_UDP)) {
967
            url_close(rtsp_st->rtp_handle);
968
            rtsp_st->rtp_handle = NULL;
969
        }
970

    
971
        switch(reply->transports[0].protocol) {
972
        case RTSP_PROTOCOL_RTP_TCP:
973
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
974
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
975
            break;
976

    
977
        case RTSP_PROTOCOL_RTP_UDP:
978
            {
979
                char url[1024];
980

    
981
                /* XXX: also use address if specified */
982
                snprintf(url, sizeof(url), "rtp://%s:%d",
983
                         host, reply->transports[0].server_port_min);
984
                if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
985
                    err = AVERROR_INVALIDDATA;
986
                    goto fail;
987
                }
988
            }
989
            break;
990
        case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
991
            {
992
                char url[1024];
993
                struct in_addr in;
994

    
995
                in.s_addr = htonl(reply->transports[0].destination);
996
                snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d",
997
                         inet_ntoa(in),
998
                         reply->transports[0].port_min,
999
                         reply->transports[0].ttl);
1000
                if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1001
                    err = AVERROR_INVALIDDATA;
1002
                    goto fail;
1003
                }
1004
            }
1005
            break;
1006
        }
1007
        /* open the RTP context */
1008
        st = NULL;
1009
        if (rtsp_st->stream_index >= 0)
1010
            st = s->streams[rtsp_st->stream_index];
1011
        if (!st)
1012
            s->ctx_flags |= AVFMTCTX_NOHEADER;
1013
        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
1014

    
1015
        if (!rtsp_st->rtp_ctx) {
1016
            err = AVERROR(ENOMEM);
1017
            goto fail;
1018
        } else {
1019
            if(rtsp_st->dynamic_handler) {
1020
                rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
1021
                rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
1022
            }
1023
        }
1024
    }
1025

    
1026
    return 0;
1027

    
1028
fail:
1029
    for (i=0; i<rt->nb_rtsp_streams; i++) {
1030
        if (rt->rtsp_streams[i]->rtp_handle) {
1031
            url_close(rt->rtsp_streams[i]->rtp_handle);
1032
            rt->rtsp_streams[i]->rtp_handle = NULL;
1033
        }
1034
    }
1035
    return err;
1036
}
1037

    
1038
static int rtsp_read_header(AVFormatContext *s,
1039
                            AVFormatParameters *ap)
1040
{
1041
    RTSPState *rt = s->priv_data;
1042
    char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
1043
    URLContext *rtsp_hd;
1044
    int port, ret, err;
1045
    RTSPHeader reply1, *reply = &reply1;
1046
    unsigned char *content = NULL;
1047
    int protocol_mask = 0;
1048
    char real_challenge[64];
1049

    
1050
    /* extract hostname and port */
1051
    url_split(NULL, 0, NULL, 0,
1052
              host, sizeof(host), &port, path, sizeof(path), s->filename);
1053
    if (port < 0)
1054
        port = RTSP_DEFAULT_PORT;
1055

    
1056
    /* search for options */
1057
    option_list = strchr(path, '?');
1058
    if (option_list) {
1059
        /* remove the options from the path */
1060
        *option_list++ = 0;
1061
        while(option_list) {
1062
            /* move the option pointer */
1063
            option = option_list;
1064
            option_list = strchr(option_list, '&');
1065
            if (option_list)
1066
                *(option_list++) = 0;
1067
            /* handle the options */
1068
            if (strcmp(option, "udp") == 0)
1069
                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP);
1070
            else if (strcmp(option, "multicast") == 0)
1071
                protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST);
1072
            else if (strcmp(option, "tcp") == 0)
1073
                protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP);
1074
        }
1075
    }
1076

    
1077
    if (!protocol_mask)
1078
        protocol_mask = (1 << RTSP_PROTOCOL_RTP_LAST) - 1;
1079

    
1080
    /* open the tcp connexion */
1081
    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
1082
    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
1083
        return AVERROR(EIO);
1084
    rt->rtsp_hd = rtsp_hd;
1085
    rt->seq = 0;
1086

    
1087
    /* request options supported by the server; this also detects server type */
1088
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1089
        snprintf(cmd, sizeof(cmd),
1090
                 "OPTIONS %s RTSP/1.0\r\n", s->filename);
1091
        if (rt->server_type == RTSP_SERVER_RDT)
1092
            av_strlcat(cmd,
1093
                       /**
1094
                        * The following entries are required for proper
1095
                        * streaming from a Realmedia server. They are
1096
                        * interdependent in some way although we currently
1097
                        * don't quite understand how. Values were copied
1098
                        * from mplayer SVN r23589.
1099
                        * @param CompanyID is a 16-byte ID in base64
1100
                        * @param ClientChallenge is a 16-byte ID in hex
1101
                        */
1102
                       "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
1103
                       "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
1104
                       "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
1105
                       "GUID: 00000000-0000-0000-0000-000000000000\r\n",
1106
                       sizeof(cmd));
1107
        rtsp_send_cmd(s, cmd, reply, NULL);
1108
        if (reply->status_code != RTSP_STATUS_OK) {
1109
            err = AVERROR_INVALIDDATA;
1110
            goto fail;
1111
        }
1112

    
1113
        /* detect server type if not standard-compliant RTP */
1114
        if (rt->server_type != RTSP_SERVER_RDT && reply->real_challenge[0]) {
1115
            rt->server_type = RTSP_SERVER_RDT;
1116
            continue;
1117
        } else if (rt->server_type == RTSP_SERVER_RDT) {
1118
            strcpy(real_challenge, reply->real_challenge);
1119
        }
1120
        break;
1121
    }
1122

    
1123
    /* describe the stream */
1124
    snprintf(cmd, sizeof(cmd),
1125
             "DESCRIBE %s RTSP/1.0\r\n"
1126
             "Accept: application/sdp\r\n",
1127
             s->filename);
1128
    rtsp_send_cmd(s, cmd, reply, &content);
1129
    if (!content) {
1130
        err = AVERROR_INVALIDDATA;
1131
        goto fail;
1132
    }
1133
    if (reply->status_code != RTSP_STATUS_OK) {
1134
        err = AVERROR_INVALIDDATA;
1135
        goto fail;
1136
    }
1137

    
1138
    /* now we got the SDP description, we parse it */
1139
    ret = sdp_parse(s, (const char *)content);
1140
    av_freep(&content);
1141
    if (ret < 0) {
1142
        err = AVERROR_INVALIDDATA;
1143
        goto fail;
1144
    }
1145

    
1146
    do {
1147
        int protocol = ff_log2_tab[protocol_mask & ~(protocol_mask - 1)];
1148

    
1149
        err = make_setup_request(s, host, port, protocol);
1150
        if (err < 0)
1151
            goto fail;
1152
        protocol_mask &= ~(1 << protocol);
1153
        if (protocol_mask == 0 && err == 1) {
1154
            err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
1155
            goto fail;
1156
        }
1157
    } while (err);
1158

    
1159
    rt->state = RTSP_STATE_IDLE;
1160
    rt->seek_timestamp = 0; /* default is to start stream at position
1161
                               zero */
1162
    if (ap->initial_pause) {
1163
        /* do not start immediately */
1164
    } else {
1165
        if (rtsp_read_play(s) < 0) {
1166
            err = AVERROR_INVALIDDATA;
1167
            goto fail;
1168
        }
1169
    }
1170
    return 0;
1171
 fail:
1172
    rtsp_close_streams(rt);
1173
    av_freep(&content);
1174
    url_close(rt->rtsp_hd);
1175
    return err;
1176
}
1177

    
1178
static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1179
                           uint8_t *buf, int buf_size)
1180
{
1181
    RTSPState *rt = s->priv_data;
1182
    int id, len, i, ret;
1183
    RTSPStream *rtsp_st;
1184

    
1185
#ifdef DEBUG_RTP_TCP
1186
    printf("tcp_read_packet:\n");
1187
#endif
1188
 redo:
1189
    for(;;) {
1190
        ret = url_readbuf(rt->rtsp_hd, buf, 1);
1191
#ifdef DEBUG_RTP_TCP
1192
        printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
1193
#endif
1194
        if (ret != 1)
1195
            return -1;
1196
        if (buf[0] == '$')
1197
            break;
1198
    }
1199
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
1200
    if (ret != 3)
1201
        return -1;
1202
    id = buf[0];
1203
    len = AV_RB16(buf + 1);
1204
#ifdef DEBUG_RTP_TCP
1205
    printf("id=%d len=%d\n", id, len);
1206
#endif
1207
    if (len > buf_size || len < 12)
1208
        goto redo;
1209
    /* get the data */
1210
    ret = url_readbuf(rt->rtsp_hd, buf, len);
1211
    if (ret != len)
1212
        return -1;
1213

    
1214
    /* find the matching stream */
1215
    for(i = 0; i < rt->nb_rtsp_streams; i++) {
1216
        rtsp_st = rt->rtsp_streams[i];
1217
        if (id >= rtsp_st->interleaved_min &&
1218
            id <= rtsp_st->interleaved_max)
1219
            goto found;
1220
    }
1221
    goto redo;
1222
 found:
1223
    *prtsp_st = rtsp_st;
1224
    return len;
1225
}
1226

    
1227
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1228
                           uint8_t *buf, int buf_size)
1229
{
1230
    RTSPState *rt = s->priv_data;
1231
    RTSPStream *rtsp_st;
1232
    fd_set rfds;
1233
    int fd1, fd2, fd_max, n, i, ret;
1234
    struct timeval tv;
1235

    
1236
    for(;;) {
1237
        if (url_interrupt_cb())
1238
            return AVERROR(EINTR);
1239
        FD_ZERO(&rfds);
1240
        fd_max = -1;
1241
        for(i = 0; i < rt->nb_rtsp_streams; i++) {
1242
            rtsp_st = rt->rtsp_streams[i];
1243
            /* currently, we cannot probe RTCP handle because of blocking restrictions */
1244
            rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
1245
            if (fd1 > fd_max)
1246
                fd_max = fd1;
1247
            FD_SET(fd1, &rfds);
1248
        }
1249
        tv.tv_sec = 0;
1250
        tv.tv_usec = 100 * 1000;
1251
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1252
        if (n > 0) {
1253
            for(i = 0; i < rt->nb_rtsp_streams; i++) {
1254
                rtsp_st = rt->rtsp_streams[i];
1255
                rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
1256
                if (FD_ISSET(fd1, &rfds)) {
1257
                    ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1258
                    if (ret > 0) {
1259
                        *prtsp_st = rtsp_st;
1260
                        return ret;
1261
                    }
1262
                }
1263
            }
1264
        }
1265
    }
1266
}
1267

    
1268
static int rtsp_read_packet(AVFormatContext *s,
1269
                            AVPacket *pkt)
1270
{
1271
    RTSPState *rt = s->priv_data;
1272
    RTSPStream *rtsp_st;
1273
    int ret, len;
1274
    uint8_t buf[RTP_MAX_PACKET_LENGTH];
1275

    
1276
    /* get next frames from the same RTP packet */
1277
    if (rt->cur_rtp) {
1278
        ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);
1279
        if (ret == 0) {
1280
            rt->cur_rtp = NULL;
1281
            return 0;
1282
        } else if (ret == 1) {
1283
            return 0;
1284
        } else {
1285
            rt->cur_rtp = NULL;
1286
        }
1287
    }
1288

    
1289
    /* read next RTP packet */
1290
 redo:
1291
    switch(rt->protocol) {
1292
    default:
1293
    case RTSP_PROTOCOL_RTP_TCP:
1294
        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1295
        break;
1296
    case RTSP_PROTOCOL_RTP_UDP:
1297
    case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
1298
        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1299
        if (len >=0 && rtsp_st->rtp_ctx)
1300
            rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len);
1301
        break;
1302
    }
1303
    if (len < 0)
1304
        return len;
1305
    ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
1306
    if (ret < 0)
1307
        goto redo;
1308
    if (ret == 1) {
1309
        /* more packets may follow, so we save the RTP context */
1310
        rt->cur_rtp = rtsp_st->rtp_ctx;
1311
    }
1312
    return 0;
1313
}
1314

    
1315
static int rtsp_read_play(AVFormatContext *s)
1316
{
1317
    RTSPState *rt = s->priv_data;
1318
    RTSPHeader reply1, *reply = &reply1;
1319
    char cmd[1024];
1320

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

    
1323
    if (rt->state == RTSP_STATE_PAUSED) {
1324
        snprintf(cmd, sizeof(cmd),
1325
                 "PLAY %s RTSP/1.0\r\n",
1326
                 s->filename);
1327
    } else {
1328
        snprintf(cmd, sizeof(cmd),
1329
                 "PLAY %s RTSP/1.0\r\n"
1330
                 "Range: npt=%0.3f-\r\n",
1331
                 s->filename,
1332
                 (double)rt->seek_timestamp / AV_TIME_BASE);
1333
    }
1334
    rtsp_send_cmd(s, cmd, reply, NULL);
1335
    if (reply->status_code != RTSP_STATUS_OK) {
1336
        return -1;
1337
    } else {
1338
        rt->state = RTSP_STATE_PLAYING;
1339
        return 0;
1340
    }
1341
}
1342

    
1343
/* pause the stream */
1344
static int rtsp_read_pause(AVFormatContext *s)
1345
{
1346
    RTSPState *rt = s->priv_data;
1347
    RTSPHeader reply1, *reply = &reply1;
1348
    char cmd[1024];
1349

    
1350
    rt = s->priv_data;
1351

    
1352
    if (rt->state != RTSP_STATE_PLAYING)
1353
        return 0;
1354

    
1355
    snprintf(cmd, sizeof(cmd),
1356
             "PAUSE %s RTSP/1.0\r\n",
1357
             s->filename);
1358
    rtsp_send_cmd(s, cmd, reply, NULL);
1359
    if (reply->status_code != RTSP_STATUS_OK) {
1360
        return -1;
1361
    } else {
1362
        rt->state = RTSP_STATE_PAUSED;
1363
        return 0;
1364
    }
1365
}
1366

    
1367
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
1368
                          int64_t timestamp, int flags)
1369
{
1370
    RTSPState *rt = s->priv_data;
1371

    
1372
    rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q);
1373
    switch(rt->state) {
1374
    default:
1375
    case RTSP_STATE_IDLE:
1376
        break;
1377
    case RTSP_STATE_PLAYING:
1378
        if (rtsp_read_play(s) != 0)
1379
            return -1;
1380
        break;
1381
    case RTSP_STATE_PAUSED:
1382
        rt->state = RTSP_STATE_IDLE;
1383
        break;
1384
    }
1385
    return 0;
1386
}
1387

    
1388
static int rtsp_read_close(AVFormatContext *s)
1389
{
1390
    RTSPState *rt = s->priv_data;
1391
    RTSPHeader reply1, *reply = &reply1;
1392
    char cmd[1024];
1393

    
1394
#if 0
1395
    /* NOTE: it is valid to flush the buffer here */
1396
    if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
1397
        url_fclose(&rt->rtsp_gb);
1398
    }
1399
#endif
1400
    snprintf(cmd, sizeof(cmd),
1401
             "TEARDOWN %s RTSP/1.0\r\n",
1402
             s->filename);
1403
    rtsp_send_cmd(s, cmd, reply, NULL);
1404

    
1405
    rtsp_close_streams(rt);
1406
    url_close(rt->rtsp_hd);
1407
    return 0;
1408
}
1409

    
1410
#ifdef CONFIG_RTSP_DEMUXER
1411
AVInputFormat rtsp_demuxer = {
1412
    "rtsp",
1413
    NULL_IF_CONFIG_SMALL("RTSP input format"),
1414
    sizeof(RTSPState),
1415
    rtsp_probe,
1416
    rtsp_read_header,
1417
    rtsp_read_packet,
1418
    rtsp_read_close,
1419
    rtsp_read_seek,
1420
    .flags = AVFMT_NOFILE,
1421
    .read_play = rtsp_read_play,
1422
    .read_pause = rtsp_read_pause,
1423
};
1424
#endif
1425

    
1426
static int sdp_probe(AVProbeData *p1)
1427
{
1428
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1429

    
1430
    /* we look for a line beginning "c=IN IP4" */
1431
    while (p < p_end && *p != '\0') {
1432
        if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL))
1433
            return AVPROBE_SCORE_MAX / 2;
1434

    
1435
        while(p < p_end - 1 && *p != '\n') p++;
1436
        if (++p >= p_end)
1437
            break;
1438
        if (*p == '\r')
1439
            p++;
1440
    }
1441
    return 0;
1442
}
1443

    
1444
#define SDP_MAX_SIZE 8192
1445

    
1446
static int sdp_read_header(AVFormatContext *s,
1447
                           AVFormatParameters *ap)
1448
{
1449
    RTSPState *rt = s->priv_data;
1450
    RTSPStream *rtsp_st;
1451
    int size, i, err;
1452
    char *content;
1453
    char url[1024];
1454
    AVStream *st;
1455

    
1456
    /* read the whole sdp file */
1457
    /* XXX: better loading */
1458
    content = av_malloc(SDP_MAX_SIZE);
1459
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1460
    if (size <= 0) {
1461
        av_free(content);
1462
        return AVERROR_INVALIDDATA;
1463
    }
1464
    content[size] ='\0';
1465

    
1466
    sdp_parse(s, content);
1467
    av_free(content);
1468

    
1469
    /* open each RTP stream */
1470
    for(i=0;i<rt->nb_rtsp_streams;i++) {
1471
        rtsp_st = rt->rtsp_streams[i];
1472

    
1473
        snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d",
1474
                 inet_ntoa(rtsp_st->sdp_ip),
1475
                 rtsp_st->sdp_port,
1476
                 rtsp_st->sdp_port,
1477
                 rtsp_st->sdp_ttl);
1478
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1479
            err = AVERROR_INVALIDDATA;
1480
            goto fail;
1481
        }
1482
        /* open the RTP context */
1483
        st = NULL;
1484
        if (rtsp_st->stream_index >= 0)
1485
            st = s->streams[rtsp_st->stream_index];
1486
        if (!st)
1487
            s->ctx_flags |= AVFMTCTX_NOHEADER;
1488
        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
1489
        if (!rtsp_st->rtp_ctx) {
1490
            err = AVERROR(ENOMEM);
1491
            goto fail;
1492
        } else {
1493
            if(rtsp_st->dynamic_handler) {
1494
                rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
1495
                rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
1496
            }
1497
        }
1498
    }
1499
    return 0;
1500
 fail:
1501
    rtsp_close_streams(rt);
1502
    return err;
1503
}
1504

    
1505
static int sdp_read_packet(AVFormatContext *s,
1506
                            AVPacket *pkt)
1507
{
1508
    return rtsp_read_packet(s, pkt);
1509
}
1510

    
1511
static int sdp_read_close(AVFormatContext *s)
1512
{
1513
    RTSPState *rt = s->priv_data;
1514
    rtsp_close_streams(rt);
1515
    return 0;
1516
}
1517

    
1518
#ifdef CONFIG_SDP_DEMUXER
1519
AVInputFormat sdp_demuxer = {
1520
    "sdp",
1521
    NULL_IF_CONFIG_SMALL("SDP"),
1522
    sizeof(RTSPState),
1523
    sdp_probe,
1524
    sdp_read_header,
1525
    sdp_read_packet,
1526
    sdp_read_close,
1527
};
1528
#endif
1529

    
1530
#ifdef CONFIG_REDIR_DEMUXER
1531
/* dummy redirector format (used directly in av_open_input_file now) */
1532
static int redir_probe(AVProbeData *pd)
1533
{
1534
    const char *p;
1535
    p = pd->buf;
1536
    while (redir_isspace(*p))
1537
        p++;
1538
    if (av_strstart(p, "http://", NULL) ||
1539
        av_strstart(p, "rtsp://", NULL))
1540
        return AVPROBE_SCORE_MAX;
1541
    return 0;
1542
}
1543

    
1544
static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap)
1545
{
1546
    char buf[4096], *q;
1547
    int c;
1548
    AVFormatContext *ic = NULL;
1549
    ByteIOContext *f = s->pb;
1550

    
1551
    /* parse each URL and try to open it */
1552
    c = url_fgetc(f);
1553
    while (c != URL_EOF) {
1554
        /* skip spaces */
1555
        for(;;) {
1556
            if (!redir_isspace(c))
1557
                break;
1558
            c = url_fgetc(f);
1559
        }
1560
        if (c == URL_EOF)
1561
            break;
1562
        /* record url */
1563
        q = buf;
1564
        for(;;) {
1565
            if (c == URL_EOF || redir_isspace(c))
1566
                break;
1567
            if ((q - buf) < sizeof(buf) - 1)
1568
                *q++ = c;
1569
            c = url_fgetc(f);
1570
        }
1571
        *q = '\0';
1572
        //printf("URL='%s'\n", buf);
1573
        /* try to open the media file */
1574
        if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1575
            break;
1576
    }
1577
    if (!ic)
1578
        return AVERROR(EIO);
1579

    
1580
    *s = *ic;
1581
    url_fclose(f);
1582

    
1583
    return 0;
1584
}
1585

    
1586
AVInputFormat redir_demuxer = {
1587
    "redir",
1588
    NULL_IF_CONFIG_SMALL("Redirector format"),
1589
    0,
1590
    redir_probe,
1591
    redir_read_header,
1592
    NULL,
1593
    NULL,
1594
};
1595
#endif