Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtsp.c @ 25f8db58

History | View | Annotate | Download (40.8 KB)

1
/*
2
 * RTSP/SDP client
3
 * Copyright (c) 2002 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
#include "avformat.h"
20

    
21
#include <unistd.h> /* for select() prototype */
22
#include <sys/time.h>
23
#include <netinet/in.h>
24
#include <sys/socket.h>
25
#ifndef __BEOS__
26
# include <arpa/inet.h>
27
#else
28
# include "barpainet.h"
29
#endif
30

    
31
//#define DEBUG
32
//#define DEBUG_RTP_TCP
33

    
34
enum RTSPClientState {
35
    RTSP_STATE_IDLE,
36
    RTSP_STATE_PLAYING,
37
    RTSP_STATE_PAUSED,
38
};
39

    
40
typedef struct RTSPState {
41
    URLContext *rtsp_hd; /* RTSP TCP connexion handle */
42
    int nb_rtsp_streams;
43
    struct RTSPStream **rtsp_streams;
44
    
45
    enum RTSPClientState state;
46
    int64_t seek_timestamp;
47
    
48
    /* XXX: currently we use unbuffered input */
49
    //    ByteIOContext rtsp_gb;
50
    int seq;        /* RTSP command sequence number */
51
    char session_id[512];
52
    enum RTSPProtocol protocol;
53
    char last_reply[2048]; /* XXX: allocate ? */
54
    RTPDemuxContext *cur_rtp;
55
} RTSPState;
56

    
57
typedef struct RTSPStream {
58
    URLContext *rtp_handle; /* RTP stream handle */
59
    RTPDemuxContext *rtp_ctx; /* RTP parse context */
60
    
61
    int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */
62
    int interleaved_min, interleaved_max;  /* interleave ids, if TCP transport */
63
    char control_url[1024]; /* url for this stream (from SDP) */
64

    
65
    int sdp_port; /* port (from SDP content - not used in RTSP) */
66
    struct in_addr sdp_ip; /* IP address  (from SDP content - not used in RTSP) */
67
    int sdp_ttl;  /* IP TTL (from SDP content - not used in RTSP) */
68
    int sdp_payload_type; /* payload type - only used in SDP */
69
    rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */
70
} RTSPStream;
71

    
72
static int rtsp_read_play(AVFormatContext *s);
73

    
74
/* XXX: currently, the only way to change the protocols consists in
75
   changing this variable */
76

    
77
int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP);
78

    
79
FFRTSPCallback *ff_rtsp_callback = NULL;
80

    
81
static int rtsp_probe(AVProbeData *p)
82
{
83
    if (strstart(p->filename, "rtsp:", NULL))
84
        return AVPROBE_SCORE_MAX;
85
    return 0;
86
}
87

    
88
static int redir_isspace(int c)
89
{
90
    return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
91
}
92

    
93
static void skip_spaces(const char **pp)
94
{
95
    const char *p;
96
    p = *pp;
97
    while (redir_isspace(*p))
98
        p++;
99
    *pp = p;
100
}
101

    
102
static void get_word_sep(char *buf, int buf_size, const char *sep, 
103
                         const char **pp)
104
{
105
    const char *p;
106
    char *q;
107

    
108
    p = *pp;
109
    if (*p == '/')
110
        p++;
111
    skip_spaces(&p);
112
    q = buf;
113
    while (!strchr(sep, *p) && *p != '\0') {
114
        if ((q - buf) < buf_size - 1)
115
            *q++ = *p;
116
        p++;
117
    }
118
    if (buf_size > 0)
119
        *q = '\0';
120
    *pp = p;
121
}
122

    
123
static void get_word(char *buf, int buf_size, const char **pp)
124
{
125
    const char *p;
126
    char *q;
127

    
128
    p = *pp;
129
    skip_spaces(&p);
130
    q = buf;
131
    while (!redir_isspace(*p) && *p != '\0') {
132
        if ((q - buf) < buf_size - 1)
133
            *q++ = *p;
134
        p++;
135
    }
136
    if (buf_size > 0)
137
        *q = '\0';
138
    *pp = p;
139
}
140

    
141
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
142
   params>] */
143
static int sdp_parse_rtpmap(AVCodecContext *codec, int payload_type, const char *p)
144
{
145
    char buf[256];
146
    int i;
147
    AVCodec *c;
148
    char *c_name;
149

    
150
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
151
       see if we can handle this kind of payload */
152
    get_word_sep(buf, sizeof(buf), "/", &p);
153
    if (payload_type >= RTP_PT_PRIVATE) {
154
        /* We are in dynmaic payload type case ... search into AVRtpDynamicPayloadTypes[] */
155
        for (i = 0; AVRtpDynamicPayloadTypes[i].codec_id != CODEC_ID_NONE; ++i)
156
            if (!strcmp(buf, AVRtpDynamicPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpDynamicPayloadTypes[i].codec_type)) {
157
                codec->codec_id = AVRtpDynamicPayloadTypes[i].codec_id;
158
                break;
159
            }
160
    } else {
161
        /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
162
        /* search into AVRtpPayloadTypes[] */
163
        for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
164
            if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){
165
                codec->codec_id = AVRtpPayloadTypes[i].codec_id;
166
                break;
167
            }
168
    }
169

    
170
    c = avcodec_find_decoder(codec->codec_id);
171
    if (c && c->name)
172
        c_name = (char *)c->name;
173
    else
174
        c_name = (char *)NULL;
175

    
176
    if (c_name) {
177
        get_word_sep(buf, sizeof(buf), "/", &p);
178
        i = atoi(buf);
179
        switch (codec->codec_type) {
180
            case CODEC_TYPE_AUDIO:
181
                av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
182
                codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
183
                codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
184
                if (i > 0) {
185
                    codec->sample_rate = i;
186
                    get_word_sep(buf, sizeof(buf), "/", &p);
187
                    i = atoi(buf);
188
                    if (i > 0)
189
                        codec->channels = i;
190
                }
191
                av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
192
                av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
193
                break;
194
            case CODEC_TYPE_VIDEO:
195
                av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
196
                break;
197
            default:
198
                break;
199
        }
200
        return 0;
201
    }
202

    
203
    return -1;
204
}
205

    
206
/* return the length and optionnaly the data */
207
static int hex_to_data(uint8_t *data, const char *p)
208
{
209
    int c, len, v;
210

    
211
    len = 0;
212
    v = 1;
213
    for(;;) {
214
        skip_spaces(&p);
215
        if (p == '\0')
216
            break;
217
        c = toupper((unsigned char)*p++);
218
        if (c >= '0' && c <= '9')
219
            c = c - '0';
220
        else if (c >= 'A' && c <= 'F')
221
            c = c - 'A' + 10;
222
        else
223
            break;
224
        v = (v << 4) | c;
225
        if (v & 0x100) {
226
            if (data)
227
                data[len] = v;
228
            len++;
229
            v = 1;
230
        }
231
    }
232
    return len;
233
}
234

    
235
static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
236
{
237
    switch (codec->codec_id) {
238
        case CODEC_ID_MPEG4:
239
        case CODEC_ID_MPEG4AAC:
240
            if (!strcmp(attr, "config")) {
241
                /* decode the hexa encoded parameter */
242
                int len = hex_to_data(NULL, value);
243
                codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
244
                if (!codec->extradata)
245
                    return;
246
                codec->extradata_size = len;
247
                hex_to_data(codec->extradata, value);
248
            }
249
            break;
250
        default:
251
            break;
252
    }
253
    return;
254
}
255

    
256
typedef struct attrname_map
257
{
258
    char *str;
259
    uint16_t type;
260
    uint32_t offset;
261
} attrname_map_t;
262

    
263
/* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
264
#define ATTR_NAME_TYPE_INT 0
265
#define ATTR_NAME_TYPE_STR 1
266
static attrname_map_t attr_names[]=
267
{
268
    {"SizeLength",       ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)},
269
    {"IndexLength",      ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)},
270
    {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)},
271
    {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)},
272
    {"StreamType",       ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)},
273
    {"mode",             ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)},
274
    {NULL, -1, -1},
275
};
276

    
277
/* parse a SDP line and save stream attributes */
278
static void sdp_parse_fmtp(AVStream *st, const char *p)
279
{
280
    char attr[256];
281
    char value[4096];
282
    int i;
283

    
284
    RTSPStream *rtsp_st = st->priv_data;
285
    AVCodecContext *codec = st->codec;
286
    rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data;
287

    
288
    /* loop on each attribute */
289
    for(;;) {
290
        skip_spaces(&p);
291
        if (*p == '\0')
292
            break;
293
        get_word_sep(attr, sizeof(attr), "=", &p);
294
        if (*p == '=') 
295
            p++;
296
        get_word_sep(value, sizeof(value), ";", &p);
297
        if (*p == ';')
298
            p++;
299
        /* grab the codec extra_data from the config parameter of the fmtp line */
300
        sdp_parse_fmtp_config(codec, attr, value);
301
        /* Looking for a known attribute */
302
        for (i = 0; attr_names[i].str; ++i) {
303
            if (!strcasecmp(attr, attr_names[i].str)) {
304
                if (attr_names[i].type == ATTR_NAME_TYPE_INT)
305
                    *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
306
                else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
307
                    *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
308
            }
309
        }
310
    }
311
}
312

    
313
typedef struct SDPParseState {
314
    /* SDP only */
315
    struct in_addr default_ip;
316
    int default_ttl;
317
} SDPParseState;
318

    
319
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
320
                           int letter, const char *buf)
321
{
322
    RTSPState *rt = s->priv_data;
323
    char buf1[64], st_type[64];
324
    const char *p;
325
    int codec_type, payload_type, i;
326
    AVStream *st;
327
    RTSPStream *rtsp_st;
328
    struct in_addr sdp_ip;
329
    int ttl;
330

    
331
#ifdef DEBUG
332
    printf("sdp: %c='%s'\n", letter, buf);
333
#endif
334

    
335
    p = buf;
336
    switch(letter) {
337
    case 'c':
338
        get_word(buf1, sizeof(buf1), &p);
339
        if (strcmp(buf1, "IN") != 0)
340
            return;
341
        get_word(buf1, sizeof(buf1), &p);
342
        if (strcmp(buf1, "IP4") != 0)
343
            return;
344
        get_word_sep(buf1, sizeof(buf1), "/", &p);
345
        if (inet_aton(buf1, &sdp_ip) == 0)
346
            return;
347
        ttl = 16;
348
        if (*p == '/') {
349
            p++;
350
            get_word_sep(buf1, sizeof(buf1), "/", &p);
351
            ttl = atoi(buf1);
352
        }
353
        if (s->nb_streams == 0) {
354
            s1->default_ip = sdp_ip;
355
            s1->default_ttl = ttl;
356
        } else {
357
            st = s->streams[s->nb_streams - 1];
358
            rtsp_st = st->priv_data;
359
            rtsp_st->sdp_ip = sdp_ip;
360
            rtsp_st->sdp_ttl = ttl;
361
        }
362
        break;
363
    case 's':
364
        pstrcpy(s->title, sizeof(s->title), p);
365
        break;
366
    case 'i':
367
        if (s->nb_streams == 0) {
368
            pstrcpy(s->comment, sizeof(s->comment), p);
369
            break;
370
        }
371
        break;
372
    case 'm':
373
        /* new stream */
374
        get_word(st_type, sizeof(st_type), &p);
375
        if (!strcmp(st_type, "audio")) {
376
            codec_type = CODEC_TYPE_AUDIO;
377
        } else if (!strcmp(st_type, "video")) {
378
            codec_type = CODEC_TYPE_VIDEO;
379
        } else {
380
            return;
381
        }
382
        rtsp_st = av_mallocz(sizeof(RTSPStream));
383
        if (!rtsp_st)
384
            return;
385
        rtsp_st->stream_index = -1;
386
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
387

    
388
        rtsp_st->sdp_ip = s1->default_ip;
389
        rtsp_st->sdp_ttl = s1->default_ttl;
390

    
391
        get_word(buf1, sizeof(buf1), &p); /* port */
392
        rtsp_st->sdp_port = atoi(buf1);
393

    
394
        get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
395
        
396
        /* XXX: handle list of formats */
397
        get_word(buf1, sizeof(buf1), &p); /* format list */
398
        rtsp_st->sdp_payload_type = atoi(buf1);
399

    
400
        if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) {
401
            /* no corresponding stream */
402
        } else {
403
            st = av_new_stream(s, 0);
404
            if (!st)
405
                return;
406
            st->priv_data = rtsp_st;
407
            rtsp_st->stream_index = st->index;
408
            st->codec->codec_type = codec_type;
409
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
410
                /* if standard payload type, we can find the codec right now */
411
                rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
412
            }
413
        }
414
        /* put a default control url */
415
        pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename);
416
        break;
417
    case 'a':
418
        if (strstart(p, "control:", &p) && s->nb_streams > 0) {
419
            char proto[32];
420
            /* get the control url */
421
            st = s->streams[s->nb_streams - 1];
422
            rtsp_st = st->priv_data;
423
            
424
            /* XXX: may need to add full url resolution */
425
            url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
426
            if (proto[0] == '\0') {
427
                /* relative control URL */
428
                pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
429
                pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
430
            } else {
431
                pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
432
            }
433
        } else if (strstart(p, "rtpmap:", &p)) {
434
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
435
            get_word(buf1, sizeof(buf1), &p); 
436
            payload_type = atoi(buf1);
437
            for(i = 0; i < s->nb_streams;i++) {
438
                st = s->streams[i];
439
                rtsp_st = st->priv_data;
440
                if (rtsp_st->sdp_payload_type == payload_type) {
441
                    sdp_parse_rtpmap(st->codec, payload_type, p);
442
                }
443
            }
444
        } else if (strstart(p, "fmtp:", &p)) {
445
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
446
            get_word(buf1, sizeof(buf1), &p); 
447
            payload_type = atoi(buf1);
448
            for(i = 0; i < s->nb_streams;i++) {
449
                st = s->streams[i];
450
                rtsp_st = st->priv_data;
451
                if (rtsp_st->sdp_payload_type == payload_type) {
452
                    sdp_parse_fmtp(st, p);
453
                }
454
            }
455
        }
456
        break;
457
    }
458
}
459

    
460
static int sdp_parse(AVFormatContext *s, const char *content)
461
{
462
    const char *p;
463
    int letter;
464
    char buf[1024], *q;
465
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
466
    
467
    memset(s1, 0, sizeof(SDPParseState));
468
    p = content;
469
    for(;;) {
470
        skip_spaces(&p);
471
        letter = *p;
472
        if (letter == '\0')
473
            break;
474
        p++;
475
        if (*p != '=')
476
            goto next_line;
477
        p++;
478
        /* get the content */
479
        q = buf;
480
        while (*p != '\n' && *p != '\r' && *p != '\0') {
481
            if ((q - buf) < sizeof(buf) - 1)
482
                *q++ = *p;
483
            p++;
484
        }
485
        *q = '\0';
486
        sdp_parse_line(s, s1, letter, buf);
487
    next_line:
488
        while (*p != '\n' && *p != '\0')
489
            p++;
490
        if (*p == '\n')
491
            p++;
492
    }
493
    return 0;
494
}
495

    
496
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
497
{
498
    const char *p;
499
    int v;
500

    
501
    p = *pp;
502
    skip_spaces(&p);
503
    v = strtol(p, (char **)&p, 10);
504
    if (*p == '-') {
505
        p++;
506
        *min_ptr = v;
507
        v = strtol(p, (char **)&p, 10);
508
        *max_ptr = v;
509
    } else {
510
        *min_ptr = v;
511
        *max_ptr = v;
512
    }
513
    *pp = p;
514
}
515

    
516
/* XXX: only one transport specification is parsed */
517
static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
518
{
519
    char transport_protocol[16];
520
    char profile[16];
521
    char lower_transport[16];
522
    char parameter[16];
523
    RTSPTransportField *th;
524
    char buf[256];
525
    
526
    reply->nb_transports = 0;
527
    
528
    for(;;) {
529
        skip_spaces(&p);
530
        if (*p == '\0')
531
            break;
532

    
533
        th = &reply->transports[reply->nb_transports];
534

    
535
        get_word_sep(transport_protocol, sizeof(transport_protocol), 
536
                     "/", &p);
537
        if (*p == '/')
538
            p++;
539
        get_word_sep(profile, sizeof(profile), "/;,", &p);
540
        lower_transport[0] = '\0';
541
        if (*p == '/') {
542
            p++;
543
            get_word_sep(lower_transport, sizeof(lower_transport), 
544
                         ";,", &p);
545
        }
546
        if (!strcasecmp(lower_transport, "TCP"))
547
            th->protocol = RTSP_PROTOCOL_RTP_TCP;
548
        else
549
            th->protocol = RTSP_PROTOCOL_RTP_UDP;
550
        
551
        if (*p == ';')
552
            p++;
553
        /* get each parameter */
554
        while (*p != '\0' && *p != ',') {
555
            get_word_sep(parameter, sizeof(parameter), "=;,", &p);
556
            if (!strcmp(parameter, "port")) {
557
                if (*p == '=') {
558
                    p++;
559
                    rtsp_parse_range(&th->port_min, &th->port_max, &p);
560
                }
561
            } else if (!strcmp(parameter, "client_port")) {
562
                if (*p == '=') {
563
                    p++;
564
                    rtsp_parse_range(&th->client_port_min, 
565
                                     &th->client_port_max, &p);
566
                }
567
            } else if (!strcmp(parameter, "server_port")) {
568
                if (*p == '=') {
569
                    p++;
570
                    rtsp_parse_range(&th->server_port_min, 
571
                                     &th->server_port_max, &p);
572
                }
573
            } else if (!strcmp(parameter, "interleaved")) {
574
                if (*p == '=') {
575
                    p++;
576
                    rtsp_parse_range(&th->interleaved_min, 
577
                                     &th->interleaved_max, &p);
578
                }
579
            } else if (!strcmp(parameter, "multicast")) {
580
                if (th->protocol == RTSP_PROTOCOL_RTP_UDP)
581
                    th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST;
582
            } else if (!strcmp(parameter, "ttl")) {
583
                if (*p == '=') {
584
                    p++;
585
                    th->ttl = strtol(p, (char **)&p, 10);
586
                }
587
            } else if (!strcmp(parameter, "destination")) {
588
                struct in_addr ipaddr;
589

    
590
                if (*p == '=') {
591
                    p++;
592
                    get_word_sep(buf, sizeof(buf), ";,", &p);
593
                    if (inet_aton(buf, &ipaddr)) 
594
                        th->destination = ntohl(ipaddr.s_addr);
595
                }
596
            }
597
            while (*p != ';' && *p != '\0' && *p != ',')
598
                p++;
599
            if (*p == ';')
600
                p++;
601
        }
602
        if (*p == ',')
603
            p++;
604

    
605
        reply->nb_transports++;
606
    }
607
}
608

    
609
static void rtsp_parse_range_npt(RTSPHeader *reply, const char *p)
610
{
611
    char buf[256];
612

    
613
    skip_spaces(&p);
614
    if (!stristart(p, "npt=", &p))
615
        return;
616

    
617
    reply->range_start = AV_NOPTS_VALUE;
618
    reply->range_end = AV_NOPTS_VALUE;
619
    
620
    get_word_sep(buf, sizeof(buf), "-", &p);
621
    reply->range_start = parse_date(buf, 1);
622
    if (*p == '-') {
623
        p++;
624
        get_word_sep(buf, sizeof(buf), "-", &p);
625
        reply->range_end = parse_date(buf, 1);
626
    }
627
}
628

    
629
void rtsp_parse_line(RTSPHeader *reply, const char *buf)
630
{
631
    const char *p;
632

    
633
    /* NOTE: we do case independent match for broken servers */
634
    p = buf;
635
    if (stristart(p, "Session:", &p)) {
636
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
637
    } else if (stristart(p, "Content-Length:", &p)) {
638
        reply->content_length = strtol(p, NULL, 10);
639
    } else if (stristart(p, "Transport:", &p)) {
640
        rtsp_parse_transport(reply, p);
641
    } else if (stristart(p, "CSeq:", &p)) {
642
        reply->seq = strtol(p, NULL, 10);
643
    } else if (stristart(p, "Range:", &p)) {
644
        rtsp_parse_range_npt(reply, p);
645
    }
646
}
647

    
648
static int url_readbuf(URLContext *h, unsigned char *buf, int size)
649
{
650
    int ret, len;
651

    
652
    len = 0;
653
    while (len < size) {
654
        ret = url_read(h, buf+len, size-len);
655
        if (ret < 1)
656
            return ret;
657
        len += ret;
658
    }
659
    return len;
660
}
661

    
662
/* skip a RTP/TCP interleaved packet */
663
static void rtsp_skip_packet(AVFormatContext *s)
664
{
665
    RTSPState *rt = s->priv_data;
666
    int ret, len, len1;
667
    uint8_t buf[1024];
668

    
669
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
670
    if (ret != 3)
671
        return;
672
    len = (buf[1] << 8) | buf[2];
673
#ifdef DEBUG
674
    printf("skipping RTP packet len=%d\n", len);
675
#endif
676
    /* skip payload */
677
    while (len > 0) {
678
        len1 = len;
679
        if (len1 > sizeof(buf))
680
            len1 = sizeof(buf);
681
        ret = url_readbuf(rt->rtsp_hd, buf, len1);
682
        if (ret != len1)
683
            return;
684
        len -= len1;
685
    }
686
}
687

    
688
static void rtsp_send_cmd(AVFormatContext *s, 
689
                          const char *cmd, RTSPHeader *reply, 
690
                          unsigned char **content_ptr)
691
{
692
    RTSPState *rt = s->priv_data;
693
    char buf[4096], buf1[1024], *q;
694
    unsigned char ch;
695
    const char *p;
696
    int content_length, line_count;
697
    unsigned char *content = NULL;
698

    
699
    memset(reply, 0, sizeof(RTSPHeader));
700

    
701
    rt->seq++;
702
    pstrcpy(buf, sizeof(buf), cmd);
703
    snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
704
    pstrcat(buf, sizeof(buf), buf1);
705
    if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
706
        snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
707
        pstrcat(buf, sizeof(buf), buf1);
708
    }
709
    pstrcat(buf, sizeof(buf), "\r\n");
710
#ifdef DEBUG
711
    printf("Sending:\n%s--\n", buf);
712
#endif
713
    url_write(rt->rtsp_hd, buf, strlen(buf));
714

    
715
    /* parse reply (XXX: use buffers) */
716
    line_count = 0;
717
    rt->last_reply[0] = '\0';
718
    for(;;) {
719
        q = buf;
720
        for(;;) {
721
            if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
722
                break;
723
            if (ch == '\n')
724
                break;
725
            if (ch == '$') {
726
                /* XXX: only parse it if first char on line ? */
727
                rtsp_skip_packet(s);
728
            } else if (ch != '\r') {
729
                if ((q - buf) < sizeof(buf) - 1)
730
                    *q++ = ch;
731
            }
732
        }
733
        *q = '\0';
734
#ifdef DEBUG
735
        printf("line='%s'\n", buf);
736
#endif
737
        /* test if last line */
738
        if (buf[0] == '\0')
739
            break;
740
        p = buf;
741
        if (line_count == 0) {
742
            /* get reply code */
743
            get_word(buf1, sizeof(buf1), &p);
744
            get_word(buf1, sizeof(buf1), &p);
745
            reply->status_code = atoi(buf1);
746
        } else {
747
            rtsp_parse_line(reply, p);
748
            pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
749
            pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
750
        }
751
        line_count++;
752
    }
753
    
754
    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
755
        pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
756
    
757
    content_length = reply->content_length;
758
    if (content_length > 0) {
759
        /* leave some room for a trailing '\0' (useful for simple parsing) */
760
        content = av_malloc(content_length + 1);
761
        (void)url_readbuf(rt->rtsp_hd, content, content_length);
762
        content[content_length] = '\0';
763
    }
764
    if (content_ptr)
765
        *content_ptr = content;
766
}
767

    
768
/* useful for modules: set RTSP callback function */
769

    
770
void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
771
{
772
    ff_rtsp_callback = rtsp_cb;
773
}
774

    
775

    
776
/* close and free RTSP streams */
777
static void rtsp_close_streams(RTSPState *rt)
778
{
779
    int i;
780
    RTSPStream *rtsp_st;
781

    
782
    for(i=0;i<rt->nb_rtsp_streams;i++) {
783
        rtsp_st = rt->rtsp_streams[i];
784
        if (rtsp_st) {
785
            if (rtsp_st->rtp_ctx)
786
                rtp_parse_close(rtsp_st->rtp_ctx);
787
            if (rtsp_st->rtp_handle)
788
                url_close(rtsp_st->rtp_handle);
789
        }
790
        av_free(rtsp_st);
791
    }
792
    av_free(rt->rtsp_streams);
793
}
794

    
795
static int rtsp_read_header(AVFormatContext *s,
796
                            AVFormatParameters *ap)
797
{
798
    RTSPState *rt = s->priv_data;
799
    char host[1024], path[1024], tcpname[1024], cmd[2048];
800
    URLContext *rtsp_hd;
801
    int port, i, j, ret, err;
802
    RTSPHeader reply1, *reply = &reply1;
803
    unsigned char *content = NULL;
804
    RTSPStream *rtsp_st;
805
    int protocol_mask;
806
    AVStream *st;
807

    
808
    /* extract hostname and port */
809
    url_split(NULL, 0, NULL, 0,
810
              host, sizeof(host), &port, path, sizeof(path), s->filename);
811
    if (port < 0)
812
        port = RTSP_DEFAULT_PORT;
813

    
814
    /* open the tcp connexion */
815
    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
816
    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
817
        return AVERROR_IO;
818
    rt->rtsp_hd = rtsp_hd;
819
    rt->seq = 0;
820
    
821
    /* describe the stream */
822
    snprintf(cmd, sizeof(cmd), 
823
             "DESCRIBE %s RTSP/1.0\r\n"
824
             "Accept: application/sdp\r\n",
825
             s->filename);
826
    rtsp_send_cmd(s, cmd, reply, &content);
827
    if (!content) {
828
        err = AVERROR_INVALIDDATA;
829
        goto fail;
830
    }
831
    if (reply->status_code != RTSP_STATUS_OK) {
832
        err = AVERROR_INVALIDDATA;
833
        goto fail;
834
    }
835
        
836
    /* now we got the SDP description, we parse it */
837
    ret = sdp_parse(s, (const char *)content);
838
    av_freep(&content);
839
    if (ret < 0) {
840
        err = AVERROR_INVALIDDATA;
841
        goto fail;
842
    }
843
    
844
    protocol_mask = rtsp_default_protocols;
845

    
846
    /* for each stream, make the setup request */
847
    /* XXX: we assume the same server is used for the control of each
848
       RTSP stream */
849

    
850
    for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
851
        char transport[2048];
852

    
853
        rtsp_st = rt->rtsp_streams[i];
854

    
855
        /* compute available transports */
856
        transport[0] = '\0';
857

    
858
        /* RTP/UDP */
859
        if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
860
            char buf[256];
861

    
862
            /* first try in specified port range */
863
            if (RTSP_RTP_PORT_MIN != 0) {
864
                while(j <= RTSP_RTP_PORT_MAX) {
865
                    snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
866
                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDONLY) == 0) {
867
                        j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
868
                        goto rtp_opened;
869
                    }
870
                }
871
            }
872

    
873
/*            then try on any port
874
**            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
875
**                err = AVERROR_INVALIDDATA;
876
**                goto fail;
877
**            }
878
*/
879

    
880
        rtp_opened:
881
            port = rtp_get_local_port(rtsp_st->rtp_handle);
882
            if (transport[0] != '\0')
883
                pstrcat(transport, sizeof(transport), ",");
884
            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
885
                     "RTP/AVP/UDP;unicast;client_port=%d-%d",
886
                     port, port + 1);
887
        }
888

    
889
        /* RTP/TCP */
890
        else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
891
            if (transport[0] != '\0')
892
                pstrcat(transport, sizeof(transport), ",");
893
            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
894
                     "RTP/AVP/TCP");
895
        }
896

    
897
        else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
898
            if (transport[0] != '\0')
899
                pstrcat(transport, sizeof(transport), ",");
900
            snprintf(transport + strlen(transport), 
901
                     sizeof(transport) - strlen(transport) - 1,
902
                     "RTP/AVP/UDP;multicast");
903
        }
904
        snprintf(cmd, sizeof(cmd), 
905
                 "SETUP %s RTSP/1.0\r\n"
906
                 "Transport: %s\r\n",
907
                 rtsp_st->control_url, transport);
908
        rtsp_send_cmd(s, cmd, reply, NULL);
909
        if (reply->status_code != RTSP_STATUS_OK ||
910
            reply->nb_transports != 1) {
911
            err = AVERROR_INVALIDDATA;
912
            goto fail;
913
        }
914

    
915
        /* XXX: same protocol for all streams is required */
916
        if (i > 0) {
917
            if (reply->transports[0].protocol != rt->protocol) {
918
                err = AVERROR_INVALIDDATA;
919
                goto fail;
920
            }
921
        } else {
922
            rt->protocol = reply->transports[0].protocol;
923
        }
924

    
925
        /* close RTP connection if not choosen */
926
        if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
927
            (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
928
            url_close(rtsp_st->rtp_handle);
929
            rtsp_st->rtp_handle = NULL;
930
        }
931

    
932
        switch(reply->transports[0].protocol) {
933
        case RTSP_PROTOCOL_RTP_TCP:
934
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
935
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
936
            break;
937
            
938
        case RTSP_PROTOCOL_RTP_UDP:
939
            {
940
                char url[1024];
941
                
942
                /* XXX: also use address if specified */
943
                snprintf(url, sizeof(url), "rtp://%s:%d", 
944
                         host, reply->transports[0].server_port_min);
945
                if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
946
                    err = AVERROR_INVALIDDATA;
947
                    goto fail;
948
                }
949
            }
950
            break;
951
        case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
952
            {
953
                char url[1024];
954
                int ttl;
955

    
956
                ttl = reply->transports[0].ttl;
957
                if (!ttl)
958
                    ttl = 16;
959
                snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
960
                         host, 
961
                         reply->transports[0].server_port_min,
962
                         ttl);
963
                if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {
964
                    err = AVERROR_INVALIDDATA;
965
                    goto fail;
966
                }
967
            }
968
            break;
969
        }
970
        /* open the RTP context */
971
        st = NULL;
972
        if (rtsp_st->stream_index >= 0)
973
            st = s->streams[rtsp_st->stream_index];
974
        if (!st)
975
            s->ctx_flags |= AVFMTCTX_NOHEADER;
976
        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
977

    
978
        if (!rtsp_st->rtp_ctx) {
979
            err = AVERROR_NOMEM;
980
            goto fail;
981
        }
982
    }
983

    
984
    /* use callback if available to extend setup */
985
    if (ff_rtsp_callback) {
986
        if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, 
987
                             NULL, 0, rt->last_reply) < 0) {
988
            err = AVERROR_INVALIDDATA;
989
            goto fail;
990
        }
991
    }
992
                         
993

    
994
    rt->state = RTSP_STATE_IDLE;
995
    rt->seek_timestamp = 0; /* default is to start stream at position
996
                               zero */
997
    if (ap && ap->initial_pause) {
998
        /* do not start immediately */
999
    } else {
1000
        if (rtsp_read_play(s) < 0) {
1001
            err = AVERROR_INVALIDDATA;
1002
            goto fail;
1003
        }
1004
    }
1005
    return 0;
1006
 fail:
1007
    rtsp_close_streams(rt);
1008
    av_freep(&content);
1009
    url_close(rt->rtsp_hd);
1010
    return err;
1011
}
1012

    
1013
static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1014
                           uint8_t *buf, int buf_size)
1015
{
1016
    RTSPState *rt = s->priv_data;
1017
    int id, len, i, ret;
1018
    RTSPStream *rtsp_st;
1019

    
1020
#ifdef DEBUG_RTP_TCP
1021
    printf("tcp_read_packet:\n");
1022
#endif
1023
 redo:
1024
    for(;;) {
1025
        ret = url_readbuf(rt->rtsp_hd, buf, 1);
1026
#ifdef DEBUG_RTP_TCP
1027
        printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
1028
#endif
1029
        if (ret != 1)
1030
            return -1;
1031
        if (buf[0] == '$')
1032
            break;
1033
    }
1034
    ret = url_readbuf(rt->rtsp_hd, buf, 3);
1035
    if (ret != 3)
1036
        return -1;
1037
    id = buf[0];
1038
    len = (buf[1] << 8) | buf[2];
1039
#ifdef DEBUG_RTP_TCP
1040
    printf("id=%d len=%d\n", id, len);
1041
#endif
1042
    if (len > buf_size || len < 12)
1043
        goto redo;
1044
    /* get the data */
1045
    ret = url_readbuf(rt->rtsp_hd, buf, len);
1046
    if (ret != len)
1047
        return -1;
1048
        
1049
    /* find the matching stream */
1050
    for(i = 0; i < rt->nb_rtsp_streams; i++) {
1051
        rtsp_st = rt->rtsp_streams[i];
1052
        if (id >= rtsp_st->interleaved_min && 
1053
            id <= rtsp_st->interleaved_max) 
1054
            goto found;
1055
    }
1056
    goto redo;
1057
 found:
1058
    *prtsp_st = rtsp_st;
1059
    return len;
1060
}
1061

    
1062
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, 
1063
                           uint8_t *buf, int buf_size)
1064
{
1065
    RTSPState *rt = s->priv_data;
1066
    RTSPStream *rtsp_st;
1067
    fd_set rfds;
1068
    int fd1, fd2, fd_max, n, i, ret;
1069
    struct timeval tv;
1070

    
1071
    for(;;) {
1072
        if (url_interrupt_cb())
1073
            return -1;
1074
        FD_ZERO(&rfds);
1075
        fd_max = -1;
1076
        for(i = 0; i < rt->nb_rtsp_streams; i++) {
1077
            rtsp_st = rt->rtsp_streams[i];
1078
            /* currently, we cannot probe RTCP handle because of blocking restrictions */
1079
            rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
1080
            if (fd1 > fd_max)
1081
                fd_max = fd1;
1082
            FD_SET(fd1, &rfds);
1083
        }
1084
        tv.tv_sec = 0;
1085
        tv.tv_usec = 100 * 1000;
1086
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1087
        if (n > 0) {
1088
            for(i = 0; i < rt->nb_rtsp_streams; i++) {
1089
                rtsp_st = rt->rtsp_streams[i];
1090
                rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
1091
                if (FD_ISSET(fd1, &rfds)) {
1092
                    ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1093
                    if (ret > 0) {
1094
                        *prtsp_st = rtsp_st;
1095
                        return ret;
1096
                    }
1097
                }
1098
            }
1099
        }
1100
    }
1101
}
1102

    
1103
static int rtsp_read_packet(AVFormatContext *s,
1104
                            AVPacket *pkt)
1105
{
1106
    RTSPState *rt = s->priv_data;
1107
    RTSPStream *rtsp_st;
1108
    int ret, len;
1109
    uint8_t buf[RTP_MAX_PACKET_LENGTH];
1110

    
1111
    /* get next frames from the same RTP packet */
1112
    if (rt->cur_rtp) {
1113
        ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);
1114
        if (ret == 0) {
1115
            rt->cur_rtp = NULL;
1116
            return 0;
1117
        } else if (ret == 1) {
1118
            return 0;
1119
        } else {
1120
            rt->cur_rtp = NULL;
1121
        }
1122
    }
1123

    
1124
    /* read next RTP packet */
1125
 redo:
1126
    switch(rt->protocol) {
1127
    default:
1128
    case RTSP_PROTOCOL_RTP_TCP:
1129
        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1130
        break;
1131
    case RTSP_PROTOCOL_RTP_UDP:
1132
    case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
1133
        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
1134
        break;
1135
    }
1136
    if (len < 0)
1137
        return AVERROR_IO;
1138
    ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
1139
    if (ret < 0)
1140
        goto redo;
1141
    if (ret == 1) {
1142
        /* more packets may follow, so we save the RTP context */
1143
        rt->cur_rtp = rtsp_st->rtp_ctx;
1144
    }
1145
    return 0;
1146
}
1147

    
1148
static int rtsp_read_play(AVFormatContext *s)
1149
{
1150
    RTSPState *rt = s->priv_data;
1151
    RTSPHeader reply1, *reply = &reply1;
1152
    char cmd[1024];
1153

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

    
1156
    if (rt->state == RTSP_STATE_PAUSED) {
1157
        snprintf(cmd, sizeof(cmd), 
1158
                 "PLAY %s RTSP/1.0\r\n",
1159
                 s->filename);
1160
    } else {
1161
        snprintf(cmd, sizeof(cmd), 
1162
                 "PLAY %s RTSP/1.0\r\n"
1163
                 "Range: npt=%0.3f-\r\n",
1164
                 s->filename,
1165
                 (double)rt->seek_timestamp / AV_TIME_BASE);
1166
    }
1167
    rtsp_send_cmd(s, cmd, reply, NULL);
1168
    if (reply->status_code != RTSP_STATUS_OK) {
1169
        return -1;
1170
    } else {
1171
        rt->state = RTSP_STATE_PLAYING;
1172
        return 0;
1173
    }
1174
}
1175

    
1176
/* pause the stream */
1177
static int rtsp_read_pause(AVFormatContext *s)
1178
{
1179
    RTSPState *rt = s->priv_data;
1180
    RTSPHeader reply1, *reply = &reply1;
1181
    char cmd[1024];
1182

    
1183
    rt = s->priv_data;
1184
    
1185
    if (rt->state != RTSP_STATE_PLAYING)
1186
        return 0;
1187

    
1188
    snprintf(cmd, sizeof(cmd), 
1189
             "PAUSE %s RTSP/1.0\r\n",
1190
             s->filename);
1191
    rtsp_send_cmd(s, cmd, reply, NULL);
1192
    if (reply->status_code != RTSP_STATUS_OK) {
1193
        return -1;
1194
    } else {
1195
        rt->state = RTSP_STATE_PAUSED;
1196
        return 0;
1197
    }
1198
}
1199

    
1200
static int rtsp_read_seek(AVFormatContext *s, int stream_index, 
1201
                          int64_t timestamp, int flags)
1202
{
1203
    RTSPState *rt = s->priv_data;
1204
    
1205
    rt->seek_timestamp = timestamp;
1206
    switch(rt->state) {
1207
    default:
1208
    case RTSP_STATE_IDLE:
1209
        break;
1210
    case RTSP_STATE_PLAYING:
1211
        if (rtsp_read_play(s) != 0)
1212
            return -1;
1213
        break;
1214
    case RTSP_STATE_PAUSED:
1215
        rt->state = RTSP_STATE_IDLE;
1216
        break;
1217
    }
1218
    return 0;
1219
}
1220

    
1221
static int rtsp_read_close(AVFormatContext *s)
1222
{
1223
    RTSPState *rt = s->priv_data;
1224
    RTSPHeader reply1, *reply = &reply1;
1225
    char cmd[1024];
1226

    
1227
#if 0
1228
    /* NOTE: it is valid to flush the buffer here */
1229
    if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
1230
        url_fclose(&rt->rtsp_gb);
1231
    }
1232
#endif
1233
    snprintf(cmd, sizeof(cmd), 
1234
             "TEARDOWN %s RTSP/1.0\r\n",
1235
             s->filename);
1236
    rtsp_send_cmd(s, cmd, reply, NULL);
1237

    
1238
    if (ff_rtsp_callback) {
1239
        ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, 
1240
                         NULL, 0, NULL);
1241
    }
1242

    
1243
    rtsp_close_streams(rt);
1244
    url_close(rt->rtsp_hd);
1245
    return 0;
1246
}
1247

    
1248
AVInputFormat rtsp_demux = {
1249
    "rtsp",
1250
    "RTSP input format",
1251
    sizeof(RTSPState),
1252
    rtsp_probe,
1253
    rtsp_read_header,
1254
    rtsp_read_packet,
1255
    rtsp_read_close,
1256
    rtsp_read_seek,
1257
    .flags = AVFMT_NOFILE,
1258
    .read_play = rtsp_read_play,
1259
    .read_pause = rtsp_read_pause,
1260
};
1261

    
1262
static int sdp_probe(AVProbeData *p1)
1263
{
1264
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1265

    
1266
    /* we look for a line beginning "c=IN IP4" */
1267
    while (p < p_end && *p != '\0') {
1268
        if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL))
1269
            return AVPROBE_SCORE_MAX / 2;
1270

    
1271
        while(p < p_end - 1 && *p != '\n') p++;
1272
        if (++p >= p_end)
1273
            break;
1274
        if (*p == '\r')
1275
            p++;
1276
    }
1277
    return 0;
1278
}
1279

    
1280
#define SDP_MAX_SIZE 8192
1281

    
1282
static int sdp_read_header(AVFormatContext *s,
1283
                           AVFormatParameters *ap)
1284
{
1285
    RTSPState *rt = s->priv_data;
1286
    RTSPStream *rtsp_st;
1287
    int size, i, err;
1288
    char *content;
1289
    char url[1024];
1290
    AVStream *st;
1291

    
1292
    /* read the whole sdp file */
1293
    /* XXX: better loading */
1294
    content = av_malloc(SDP_MAX_SIZE);
1295
    size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);
1296
    if (size <= 0) {
1297
        av_free(content);
1298
        return AVERROR_INVALIDDATA;
1299
    }
1300
    content[size] ='\0';
1301

    
1302
    sdp_parse(s, content);
1303
    av_free(content);
1304

    
1305
    /* open each RTP stream */
1306
    for(i=0;i<rt->nb_rtsp_streams;i++) {
1307
        rtsp_st = rt->rtsp_streams[i];
1308
        
1309
        snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
1310
                 inet_ntoa(rtsp_st->sdp_ip), 
1311
                 rtsp_st->sdp_port,
1312
                 rtsp_st->sdp_ttl);
1313
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {
1314
            err = AVERROR_INVALIDDATA;
1315
            goto fail;
1316
        }
1317
        /* open the RTP context */
1318
        st = NULL;
1319
        if (rtsp_st->stream_index >= 0)
1320
            st = s->streams[rtsp_st->stream_index];
1321
        if (!st)
1322
            s->ctx_flags |= AVFMTCTX_NOHEADER;
1323
        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
1324
        if (!rtsp_st->rtp_ctx) {
1325
            err = AVERROR_NOMEM;
1326
            goto fail;
1327
        }
1328
    }
1329
    return 0;
1330
 fail:
1331
    rtsp_close_streams(rt);
1332
    return err;
1333
}
1334

    
1335
static int sdp_read_packet(AVFormatContext *s,
1336
                            AVPacket *pkt)
1337
{
1338
    return rtsp_read_packet(s, pkt);
1339
}
1340

    
1341
static int sdp_read_close(AVFormatContext *s)
1342
{
1343
    RTSPState *rt = s->priv_data;
1344
    rtsp_close_streams(rt);
1345
    return 0;
1346
}
1347

    
1348

    
1349
static AVInputFormat sdp_demux = {
1350
    "sdp",
1351
    "SDP",
1352
    sizeof(RTSPState),
1353
    sdp_probe,
1354
    sdp_read_header,
1355
    sdp_read_packet,
1356
    sdp_read_close,
1357
};
1358

    
1359

    
1360
/* dummy redirector format (used directly in av_open_input_file now) */
1361
static int redir_probe(AVProbeData *pd)
1362
{
1363
    const char *p;
1364
    p = pd->buf;
1365
    while (redir_isspace(*p))
1366
        p++;
1367
    if (strstart(p, "http://", NULL) ||
1368
        strstart(p, "rtsp://", NULL))
1369
        return AVPROBE_SCORE_MAX;
1370
    return 0;
1371
}
1372

    
1373
/* called from utils.c */
1374
int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
1375
{
1376
    char buf[4096], *q;
1377
    int c;
1378
    AVFormatContext *ic = NULL;
1379

    
1380
    /* parse each URL and try to open it */
1381
    c = url_fgetc(f);
1382
    while (c != URL_EOF) {
1383
        /* skip spaces */
1384
        for(;;) {
1385
            if (!redir_isspace(c))
1386
                break;
1387
            c = url_fgetc(f);
1388
        }
1389
        if (c == URL_EOF)
1390
            break;
1391
        /* record url */
1392
        q = buf;
1393
        for(;;) {
1394
            if (c == URL_EOF || redir_isspace(c))
1395
                break;
1396
            if ((q - buf) < sizeof(buf) - 1)
1397
                *q++ = c;
1398
            c = url_fgetc(f);
1399
        }
1400
        *q = '\0';
1401
        //printf("URL='%s'\n", buf);
1402
        /* try to open the media file */
1403
        if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
1404
            break;
1405
    }
1406
    *ic_ptr = ic;
1407
    if (!ic)
1408
        return AVERROR_IO;
1409
    else
1410
        return 0;
1411
}
1412

    
1413
AVInputFormat redir_demux = {
1414
    "redir",
1415
    "Redirector format",
1416
    0,
1417
    redir_probe,
1418
    NULL,
1419
    NULL,
1420
    NULL,
1421
};
1422

    
1423
int rtsp_init(void)
1424
{
1425
    av_register_input_format(&rtsp_demux);
1426
    av_register_input_format(&redir_demux);
1427
    av_register_input_format(&sdp_demux);
1428
    return 0;
1429
}