rtsp.c 72.5 KB
Newer Older
1
/*
2
 * RTSP/SDP client
3
 * Copyright (c) 2002 Fabrice Bellard
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * 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 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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
#include "libavutil/base64.h"
23
#include "libavutil/avstring.h"
24
#include "libavutil/intreadwrite.h"
J
Josh Allmann 已提交
25
#include "libavutil/random_seed.h"
26 27
#include "avformat.h"

28
#include <sys/time.h>
29
#if HAVE_SYS_SELECT_H
30
#include <sys/select.h>
31
#endif
32
#include <strings.h>
33
#include "internal.h"
34
#include "network.h"
35
#include "os_support.h"
J
Josh Allmann 已提交
36
#include "http.h"
37
#include "rtsp.h"
38

39
#include "rtpdec.h"
40
#include "rdt.h"
41
#include "rtpdec_asf.h"
R
Ryan Martell 已提交
42

43
//#define DEBUG
F
Fabrice Bellard 已提交
44
//#define DEBUG_RTP_TCP
45

R
Ronald S. Bultje 已提交
46
#if LIBAVFORMAT_VERSION_INT < (53 << 16)
47
int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
R
Ronald S. Bultje 已提交
48
#endif
F
Fabrice Bellard 已提交
49

R
Reimar Döffinger 已提交
50
/* Timeout values for socket select, in ms,
51 52 53 54 55
 * and read_packet(), in seconds  */
#define SELECT_TIMEOUT_MS 100
#define READ_PACKET_TIMEOUT_S 10
#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS

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

69 70
static void get_word_until_chars(char *buf, int buf_size,
                                 const char *sep, const char **pp)
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
{
    const char *p;
    char *q;

    p = *pp;
    skip_spaces(&p);
    q = buf;
    while (!strchr(sep, *p) && *p != '\0') {
        if ((q - buf) < buf_size - 1)
            *q++ = *p;
        p++;
    }
    if (buf_size > 0)
        *q = '\0';
    *pp = p;
}

88 89
static void get_word_sep(char *buf, int buf_size, const char *sep,
                         const char **pp)
90
{
91 92 93
    if (**pp == '/') (*pp)++;
    get_word_until_chars(buf, buf_size, sep, pp);
}
94

95 96 97
static void get_word(char *buf, int buf_size, const char **pp)
{
    get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
98 99
}

100
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
101 102
static int sdp_parse_rtpmap(AVFormatContext *s,
                            AVCodecContext *codec, RTSPStream *rtsp_st,
103
                            int payload_type, const char *p)
104 105
{
    char buf[256];
R
Romain Degez 已提交
106 107
    int i;
    AVCodec *c;
108
    const char *c_name;
109

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

    c = avcodec_find_decoder(codec->codec_id);
    if (c && c->name)
138
        c_name = c->name;
R
Romain Degez 已提交
139
    else
140
        c_name = "(null)";
R
Romain Degez 已提交
141

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

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

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

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

L
Luca Barbato 已提交
227
typedef struct {
228
    const char *str;
229 230
    uint16_t    type;
    uint32_t    offset;
L
Luca Barbato 已提交
231
} AttrNameMap;
R
Romain Degez 已提交
232

R
Reimar Döffinger 已提交
233
/* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
R
Romain Degez 已提交
234 235
#define ATTR_NAME_TYPE_INT 0
#define ATTR_NAME_TYPE_STR 1
L
Luca Barbato 已提交
236
static const AttrNameMap attr_names[]=
R
Romain Degez 已提交
237
{
238 239 240 241 242 243 244 245 246 247 248 249 250
    { "SizeLength",       ATTR_NAME_TYPE_INT,
      offsetof(RTPPayloadData, sizelength) },
    { "IndexLength",      ATTR_NAME_TYPE_INT,
      offsetof(RTPPayloadData, indexlength) },
    { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
      offsetof(RTPPayloadData, indexdeltalength) },
    { "profile-level-id", ATTR_NAME_TYPE_INT,
      offsetof(RTPPayloadData, profile_level_id) },
    { "StreamType",       ATTR_NAME_TYPE_INT,
      offsetof(RTPPayloadData, streamtype) },
    { "mode",             ATTR_NAME_TYPE_STR,
      offsetof(RTPPayloadData, mode) },
    { NULL, -1, -1 },
R
Romain Degez 已提交
251 252
};

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

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

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

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

    skip_spaces(&p);
314
    if (!av_stristart(p, "npt=", &p))
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        return;

    *start = AV_NOPTS_VALUE;
    *end = AV_NOPTS_VALUE;

    get_word_sep(buf, sizeof(buf), "-", &p);
    *start = parse_date(buf, 1);
    if (*p == '-') {
        p++;
        get_word_sep(buf, sizeof(buf), "-", &p);
        *end = parse_date(buf, 1);
    }
//    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
//    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
}

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

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

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

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

        rtsp_st->sdp_ip = s1->default_ip;
        rtsp_st->sdp_ttl = s1->default_ttl;

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

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

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

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

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

            // this is so that seeking on a streamed file can work.
            rtsp_parse_range_npt(p, &start, &end);
508 509 510 511
            s->start_time = start;
            /* AV_NOPTS_VALUE means live broadcast (and can't seek) */
            s->duration   = (end == AV_NOPTS_VALUE) ?
                            AV_NOPTS_VALUE : end - start;
512 513 514
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
            if (atoi(p) == 1)
                rt->transport = RTSP_TRANSPORT_RDT;
515 516 517 518
        } else {
            if (rt->server_type == RTSP_SERVER_WMS)
                ff_wms_parse_sdp_a_line(s, p);
            if (s->nb_streams > 0) {
R
Ronald S. Bultje 已提交
519 520 521 522 523 524
                if (rt->server_type == RTSP_SERVER_REAL)
                    ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);

                rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
                if (rtsp_st->dynamic_handler &&
                    rtsp_st->dynamic_handler->parse_sdp_a_line)
525 526
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
                        s->nb_streams - 1,
R
Ronald S. Bultje 已提交
527
                        rtsp_st->dynamic_protocol_context, buf);
528
            }
529 530 531 532 533
        }
        break;
    }
}

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

548
    memset(s1, 0, sizeof(SDPParseState));
549
    p = content;
550
    for (;;) {
551 552 553 554 555 556 557 558 559 560
        skip_spaces(&p);
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
F
Fabrice Bellard 已提交
561
        while (*p != '\n' && *p != '\r' && *p != '\0') {
562 563 564 565 566
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
567
        sdp_parse_line(s, s1, letter, buf);
568 569 570 571 572 573 574 575 576
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
    }
    return 0;
}

577
/* close and free RTSP streams */
578
void ff_rtsp_close_streams(AVFormatContext *s)
579
{
580
    RTSPState *rt = s->priv_data;
581 582 583
    int i;
    RTSPStream *rtsp_st;

584
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
585 586 587
        rtsp_st = rt->rtsp_streams[i];
        if (rtsp_st) {
            if (rtsp_st->transport_priv) {
588 589 590
                if (s->oformat) {
                    AVFormatContext *rtpctx = rtsp_st->transport_priv;
                    av_write_trailer(rtpctx);
591 592 593 594 595
                    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
                        uint8_t *ptr;
                        url_close_dyn_buf(rtpctx->pb, &ptr);
                        av_free(ptr);
                    } else {
M
Martin Storsjö 已提交
596
                        url_fclose(rtpctx->pb);
597
                    }
598 599
                    av_metadata_free(&rtpctx->streams[0]->metadata);
                    av_metadata_free(&rtpctx->metadata);
600 601 602
                    av_free(rtpctx->streams[0]);
                    av_free(rtpctx);
                } else if (rt->transport == RTSP_TRANSPORT_RDT)
603 604 605 606 607 608 609
                    ff_rdt_parse_close(rtsp_st->transport_priv);
                else
                    rtp_parse_close(rtsp_st->transport_priv);
            }
            if (rtsp_st->rtp_handle)
                url_close(rtsp_st->rtp_handle);
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
610 611
                rtsp_st->dynamic_handler->close(
                    rtsp_st->dynamic_protocol_context);
612 613 614 615 616 617 618 619 620
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
        av_close_input_stream (rt->asf_ctx);
        rt->asf_ctx = NULL;
    }
}

621 622 623
static void *rtsp_rtp_mux_open(AVFormatContext *s, AVStream *st,
                               URLContext *handle)
{
624
    RTSPState *rt = s->priv_data;
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
    AVFormatContext *rtpctx;
    int ret;
    AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);

    if (!rtp_format)
        return NULL;

    /* Allocate an AVFormatContext for each output stream */
    rtpctx = avformat_alloc_context();
    if (!rtpctx)
        return NULL;

    rtpctx->oformat = rtp_format;
    if (!av_new_stream(rtpctx, 0)) {
        av_free(rtpctx);
        return NULL;
    }
    /* Copy the max delay setting; the rtp muxer reads this. */
    rtpctx->max_delay = s->max_delay;
    /* Copy other stream parameters. */
    rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio;

647 648 649
    /* Set the synchronized start time. */
    rtpctx->start_time_realtime = rt->start_time;

650 651 652 653 654 655
    /* Remove the local codec, link to the original codec
     * context instead, to give the rtp muxer access to
     * codec parameters. */
    av_free(rtpctx->streams[0]->codec);
    rtpctx->streams[0]->codec = st->codec;

656
    if (handle) {
M
Martin Storsjö 已提交
657
        url_fdopen(&rtpctx->pb, handle);
658 659
    } else
        url_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE);
660 661 662
    ret = av_write_header(rtpctx);

    if (ret) {
663
        if (handle) {
M
Martin Storsjö 已提交
664
            url_fclose(rtpctx->pb);
665 666 667 668 669
        } else {
            uint8_t *ptr;
            url_close_dyn_buf(rtpctx->pb, &ptr);
            av_free(ptr);
        }
670 671 672 673 674 675 676 677 678 679
        av_free(rtpctx->streams[0]);
        av_free(rtpctx);
        return NULL;
    }

    /* Copy the RTP AVStream timebase back to the original AVStream */
    st->time_base = rtpctx->streams[0]->time_base;
    return rtpctx;
}

680
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
681 682 683 684 685 686 687 688 689 690
{
    RTSPState *rt = s->priv_data;
    AVStream *st = NULL;

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

691 692
    if (s->oformat) {
        rtsp_st->transport_priv = rtsp_rtp_mux_open(s, st, rtsp_st->rtp_handle);
R
Reimar Döffinger 已提交
693
        /* Ownership of rtp_handle is passed to the rtp mux context */
694 695
        rtsp_st->rtp_handle = NULL;
    } else if (rt->transport == RTSP_TRANSPORT_RDT)
696 697 698 699 700 701 702 703 704 705 706
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
    else
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
                                         rtsp_st->sdp_payload_type,
                                         &rtsp_st->rtp_payload_data);

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
    } else if (rt->transport != RTSP_TRANSPORT_RDT) {
707
        if (rtsp_st->dynamic_handler) {
708 709 710 711 712 713 714 715 716
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                           rtsp_st->dynamic_protocol_context,
                                           rtsp_st->dynamic_handler);
        }
    }

    return 0;
}

M
Martin Storsjö 已提交
717
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
718 719 720 721 722 723 724
static int rtsp_probe(AVProbeData *p)
{
    if (av_strstart(p->filename, "rtsp:", NULL))
        return AVPROBE_SCORE_MAX;
    return 0;
}

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
    const char *p;
    int v;

    p = *pp;
    skip_spaces(&p);
    v = strtol(p, (char **)&p, 10);
    if (*p == '-') {
        p++;
        *min_ptr = v;
        v = strtol(p, (char **)&p, 10);
        *max_ptr = v;
    } else {
        *min_ptr = v;
        *max_ptr = v;
    }
    *pp = p;
}

/* XXX: only one transport specification is parsed */
746
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
747 748 749 750 751 752 753
{
    char transport_protocol[16];
    char profile[16];
    char lower_transport[16];
    char parameter[16];
    RTSPTransportField *th;
    char buf[256];
754

755
    reply->nb_transports = 0;
756

757
    for (;;) {
758 759 760 761 762 763
        skip_spaces(&p);
        if (*p == '\0')
            break;

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

764
        get_word_sep(transport_protocol, sizeof(transport_protocol),
765
                     "/", &p);
766
        if (!strcasecmp (transport_protocol, "rtp")) {
767 768 769 770 771 772
            get_word_sep(profile, sizeof(profile), "/;,", &p);
            lower_transport[0] = '\0';
            /* rtp/avp/<protocol> */
            if (*p == '/') {
                get_word_sep(lower_transport, sizeof(lower_transport),
                             ";,", &p);
773 774 775 776
            }
            th->transport = RTSP_TRANSPORT_RTP;
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
777
            /* x-pn-tng/<protocol> */
778 779
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
            profile[0] = '\0';
780
            th->transport = RTSP_TRANSPORT_RDT;
781
        }
F
Fabrice Bellard 已提交
782
        if (!strcasecmp(lower_transport, "TCP"))
783
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
784
        else
785
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
786

787 788 789 790 791 792 793 794 795 796 797 798 799
        if (*p == ';')
            p++;
        /* get each parameter */
        while (*p != '\0' && *p != ',') {
            get_word_sep(parameter, sizeof(parameter), "=;,", &p);
            if (!strcmp(parameter, "port")) {
                if (*p == '=') {
                    p++;
                    rtsp_parse_range(&th->port_min, &th->port_max, &p);
                }
            } else if (!strcmp(parameter, "client_port")) {
                if (*p == '=') {
                    p++;
800
                    rtsp_parse_range(&th->client_port_min,
801 802 803 804 805
                                     &th->client_port_max, &p);
                }
            } else if (!strcmp(parameter, "server_port")) {
                if (*p == '=') {
                    p++;
806
                    rtsp_parse_range(&th->server_port_min,
807 808 809 810 811
                                     &th->server_port_max, &p);
                }
            } else if (!strcmp(parameter, "interleaved")) {
                if (*p == '=') {
                    p++;
812
                    rtsp_parse_range(&th->interleaved_min,
813 814 815
                                     &th->interleaved_max, &p);
                }
            } else if (!strcmp(parameter, "multicast")) {
816 817
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
818 819 820 821 822 823 824 825 826 827 828
            } else if (!strcmp(parameter, "ttl")) {
                if (*p == '=') {
                    p++;
                    th->ttl = strtol(p, (char **)&p, 10);
                }
            } else if (!strcmp(parameter, "destination")) {
                struct in_addr ipaddr;

                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
829
                    if (ff_inet_aton(buf, &ipaddr))
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
                        th->destination = ntohl(ipaddr.s_addr);
                }
            }
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

845 846
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
                        HTTPAuthState *auth_state)
847 848 849 850 851
{
    const char *p;

    /* NOTE: we do case independent match for broken servers */
    p = buf;
852
    if (av_stristart(p, "Session:", &p)) {
853
        int t;
854
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
855 856 857 858
        if (av_stristart(p, ";timeout=", &p) &&
            (t = strtol(p, NULL, 10)) > 0) {
            reply->timeout = t;
        }
859
    } else if (av_stristart(p, "Content-Length:", &p)) {
860
        reply->content_length = strtol(p, NULL, 10);
861
    } else if (av_stristart(p, "Transport:", &p)) {
862
        rtsp_parse_transport(reply, p);
863
    } else if (av_stristart(p, "CSeq:", &p)) {
864
        reply->seq = strtol(p, NULL, 10);
865
    } else if (av_stristart(p, "Range:", &p)) {
866
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
867 868 869
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
        skip_spaces(&p);
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
870 871 872
    } else if (av_stristart(p, "Server:", &p)) {
        skip_spaces(&p);
        av_strlcpy(reply->server, p, sizeof(reply->server));
873 874 875
    } else if (av_stristart(p, "Notice:", &p) ||
               av_stristart(p, "X-Notice:", &p)) {
        reply->notice = strtol(p, NULL, 10);
L
Luca Barbato 已提交
876 877 878
    } else if (av_stristart(p, "Location:", &p)) {
        skip_spaces(&p);
        av_strlcpy(reply->location, p , sizeof(reply->location));
879 880 881 882 883 884
    } else if (av_stristart(p, "WWW-Authenticate:", &p) && auth_state) {
        skip_spaces(&p);
        ff_http_auth_handle_header(auth_state, "WWW-Authenticate", p);
    } else if (av_stristart(p, "Authentication-Info:", &p) && auth_state) {
        skip_spaces(&p);
        ff_http_auth_handle_header(auth_state, "Authentication-Info", p);
885 886 887
    }
}

888
/* skip a RTP/TCP interleaved packet */
889
void ff_rtsp_skip_packet(AVFormatContext *s)
890 891 892 893 894
{
    RTSPState *rt = s->priv_data;
    int ret, len, len1;
    uint8_t buf[1024];

895
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
896 897
    if (ret != 3)
        return;
898
    len = AV_RB16(buf + 1);
899 900 901

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

902 903 904 905 906
    /* skip payload */
    while (len > 0) {
        len1 = len;
        if (len1 > sizeof(buf))
            len1 = sizeof(buf);
907
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
908 909 910 911 912
        if (ret != len1)
            return;
        len -= len1;
    }
}
913

914
int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
M
Martin Storsjö 已提交
915 916
                       unsigned char **content_ptr,
                       int return_on_interleaved_data)
917 918 919 920 921
{
    RTSPState *rt = s->priv_data;
    char buf[4096], buf1[1024], *q;
    unsigned char ch;
    const char *p;
922
    int ret, content_length, line_count = 0;
923 924
    unsigned char *content = NULL;

925
    memset(reply, 0, sizeof(*reply));
926 927 928

    /* parse reply (XXX: use buffers) */
    rt->last_reply[0] = '\0';
929
    for (;;) {
930
        q = buf;
931
        for (;;) {
932
            ret = url_read_complete(rt->rtsp_hd, &ch, 1);
933
#ifdef DEBUG_RTP_TCP
934
            dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
935 936 937
#endif
            if (ret != 1)
                return -1;
938 939
            if (ch == '\n')
                break;
940 941
            if (ch == '$') {
                /* XXX: only parse it if first char on line ? */
942 943 944
                if (return_on_interleaved_data) {
                    return 1;
                } else
945
                    ff_rtsp_skip_packet(s);
946
            } else if (ch != '\r') {
947 948 949 950 951
                if ((q - buf) < sizeof(buf) - 1)
                    *q++ = ch;
            }
        }
        *q = '\0';
952 953 954

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

955 956 957 958 959 960 961 962 963 964
        /* test if last line */
        if (buf[0] == '\0')
            break;
        p = buf;
        if (line_count == 0) {
            /* get reply code */
            get_word(buf1, sizeof(buf1), &p);
            get_word(buf1, sizeof(buf1), &p);
            reply->status_code = atoi(buf1);
        } else {
965
            ff_rtsp_parse_line(reply, p, &rt->auth_state);
M
Måns Rullgård 已提交
966 967
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
968 969 970
        }
        line_count++;
    }
971

972
    if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
M
Måns Rullgård 已提交
973
        av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
974

975 976 977 978
    content_length = reply->content_length;
    if (content_length > 0) {
        /* leave some room for a trailing '\0' (useful for simple parsing) */
        content = av_malloc(content_length + 1);
979
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
980 981 982 983
        content[content_length] = '\0';
    }
    if (content_ptr)
        *content_ptr = content;
984 985
    else
        av_free(content);
986

987 988 989 990 991
    if (rt->seq != reply->seq) {
        av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
            rt->seq, reply->seq);
    }

992 993 994
    /* EOS */
    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
        reply->notice == 2104 /* Start-of-Stream Reached */    ||
995
        reply->notice == 2306 /* Continuous Feed Terminated */) {
996
        rt->state = RTSP_STATE_IDLE;
997
    } else if (reply->notice >= 4400 && reply->notice < 5500) {
998
        return AVERROR(EIO); /* data or server error */
999
    } else if (reply->notice == 2401 /* Ticket Expired */ ||
1000 1001 1002
             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
        return AVERROR(EPERM);

1003
    return 0;
1004 1005
}

1006
int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
M
Martin Storsjö 已提交
1007 1008 1009 1010
                                        const char *method, const char *url,
                                        const char *headers,
                                        const unsigned char *send_content,
                                        int send_content_length)
1011 1012
{
    RTSPState *rt = s->priv_data;
J
Josh Allmann 已提交
1013 1014
    char buf[4096], *out_buf;
    char base64buf[AV_BASE64_SIZE(sizeof(buf))];
1015

J
Josh Allmann 已提交
1016 1017
    /* Add in RTSP headers */
    out_buf = buf;
1018
    rt->seq++;
1019 1020 1021
    snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
    if (headers)
        av_strlcat(buf, headers, sizeof(buf));
1022
    av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
1023 1024
    if (rt->session_id[0] != '\0' && (!headers ||
        !strstr(headers, "\nIf-Match:"))) {
1025
        av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
1026
    }
1027 1028 1029 1030 1031 1032 1033
    if (rt->auth[0]) {
        char *str = ff_http_auth_create_response(&rt->auth_state,
                                                 rt->auth, url, method);
        if (str)
            av_strlcat(buf, str, sizeof(buf));
        av_free(str);
    }
1034 1035
    if (send_content_length > 0 && send_content)
        av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
1036
    av_strlcat(buf, "\r\n", sizeof(buf));
1037

J
Josh Allmann 已提交
1038 1039 1040 1041 1042 1043
    /* base64 encode rtsp if tunneling */
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
        out_buf = base64buf;
    }

1044 1045
    dprintf(s, "Sending:\n%s--\n", buf);

J
Josh Allmann 已提交
1046 1047 1048 1049 1050 1051 1052
    url_write(rt->rtsp_hd_out, out_buf, strlen(out_buf));
    if (send_content_length > 0 && send_content) {
        if (rt->control_transport == RTSP_MODE_TUNNEL) {
            av_log(s, AV_LOG_ERROR, "tunneling of RTSP requests "
                                    "with content data not supported\n");
            return AVERROR_PATCHWELCOME;
        }
1053
        url_write(rt->rtsp_hd_out, send_content, send_content_length);
J
Josh Allmann 已提交
1054
    }
1055
    rt->last_cmd_time = av_gettime();
1056 1057

    return 0;
1058 1059
}

1060
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
M
Martin Storsjö 已提交
1061
                           const char *url, const char *headers)
1062
{
1063
    return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
1064 1065
}

1066
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
M
Martin Storsjö 已提交
1067 1068
                     const char *headers, RTSPMessageHeader *reply,
                     unsigned char **content_ptr)
1069
{
1070
    return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
M
Martin Storsjö 已提交
1071
                                         content_ptr, NULL, 0);
1072 1073
}

1074
int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
M
Martin Storsjö 已提交
1075 1076 1077 1078 1079 1080
                                  const char *method, const char *url,
                                  const char *header,
                                  RTSPMessageHeader *reply,
                                  unsigned char **content_ptr,
                                  const unsigned char *send_content,
                                  int send_content_length)
1081
{
1082 1083
    RTSPState *rt = s->priv_data;
    HTTPAuthType cur_auth_type;
1084
    int ret;
1085 1086 1087

retry:
    cur_auth_type = rt->auth_state.auth_type;
1088
    if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
M
Martin Storsjö 已提交
1089 1090
                                                   send_content,
                                                   send_content_length)))
1091
        return ret;
1092

1093 1094
    if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0) ) < 0)
        return ret;
1095 1096 1097 1098

    if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
        rt->auth_state.auth_type != HTTP_AUTH_NONE)
        goto retry;
1099 1100

    return 0;
1101 1102
}

1103
/**
B
Benoit Fouet 已提交
1104
 * @return 0 on success, <0 on error, 1 if protocol is unavailable.
1105
 */
1106 1107
static int make_setup_request(AVFormatContext *s, const char *host, int port,
                              int lower_transport, const char *real_challenge)
1108 1109
{
    RTSPState *rt = s->priv_data;
1110
    int rtx, j, i, err, interleave = 0;
1111
    RTSPStream *rtsp_st;
1112
    RTSPMessageHeader reply1, *reply = &reply1;
1113
    char cmd[2048];
1114 1115
    const char *trans_pref;

1116
    if (rt->transport == RTSP_TRANSPORT_RDT)
1117 1118 1119
        trans_pref = "x-pn-tng";
    else
        trans_pref = "RTP/AVP";
1120

1121 1122 1123
    /* default timeout: 1 minute */
    rt->timeout = 60;

1124 1125
    /* for each stream, make the setup request */
    /* XXX: we assume the same server is used for the control of each
1126
     * RTSP stream */
R
Romain Degez 已提交
1127

1128
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
1129 1130
        char transport[2048];

1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
        /**
         * WMS serves all UDP data over a single connection, the RTX, which
         * isn't necessarily the first in the SDP but has to be the first
         * to be set up, else the second/third SETUP will fail with a 461.
         */
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
             rt->server_type == RTSP_SERVER_WMS) {
            if (i == 0) {
                /* rtx first */
                for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
                    int len = strlen(rt->rtsp_streams[rtx]->control_url);
                    if (len >= 4 &&
1143 1144
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
                                "/rtx"))
1145 1146 1147 1148 1149 1150 1151 1152
                        break;
                }
                if (rtx == rt->nb_rtsp_streams)
                    return -1; /* no RTX found */
                rtsp_st = rt->rtsp_streams[rtx];
            } else
                rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
        } else
R
Ronald S. Bultje 已提交
1153
            rtsp_st = rt->rtsp_streams[i];
1154 1155

        /* RTP/UDP */
1156
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
F
Fabrice Bellard 已提交
1157 1158
            char buf[256];

1159 1160 1161 1162 1163
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
                port = reply->transports[0].client_port_min;
                goto have_port;
            }

F
Fabrice Bellard 已提交
1164
            /* first try in specified port range */
R
Romain Degez 已提交
1165
            if (RTSP_RTP_PORT_MIN != 0) {
1166
                while (j <= RTSP_RTP_PORT_MAX) {
1167 1168
                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
                                "?localport=%d", j);
1169 1170 1171
                    /* we will use two ports per rtp stream (rtp and rtcp) */
                    j += 2;
                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)
F
Fabrice Bellard 已提交
1172 1173
                        goto rtp_opened;
                }
1174
            }
F
Fabrice Bellard 已提交
1175

1176 1177 1178 1179 1180 1181 1182
#if 0
            /* then try on any port */
            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
#endif
F
Fabrice Bellard 已提交
1183 1184

        rtp_opened:
1185
            port = rtp_get_local_port(rtsp_st->rtp_handle);
1186
        have_port:
1187
            snprintf(transport, sizeof(transport) - 1,
1188 1189 1190 1191 1192
                     "%s/UDP;", trans_pref);
            if (rt->server_type != RTSP_SERVER_REAL)
                av_strlcat(transport, "unicast;", sizeof(transport));
            av_strlcatf(transport, sizeof(transport),
                     "client_port=%d", port);
1193 1194
            if (rt->transport == RTSP_TRANSPORT_RTP &&
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
1195
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1196 1197 1198
        }

        /* RTP/TCP */
1199
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1200 1201 1202 1203
            /** For WMS streams, the application streams are only used for
             * UDP. When trying to set it up for TCP streams, the server
             * will return an error. Therefore, we skip those streams. */
            if (rt->server_type == RTSP_SERVER_WMS &&
1204
                s->streams[rtsp_st->stream_index]->codec->codec_type ==
1205
                    AVMEDIA_TYPE_DATA)
1206
                continue;
1207
            snprintf(transport, sizeof(transport) - 1,
1208 1209 1210 1211 1212 1213 1214
                     "%s/TCP;", trans_pref);
            if (rt->server_type == RTSP_SERVER_WMS)
                av_strlcat(transport, "unicast;", sizeof(transport));
            av_strlcatf(transport, sizeof(transport),
                        "interleaved=%d-%d",
                        interleave, interleave + 1);
            interleave += 2;
1215 1216
        }

1217
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1218
            snprintf(transport, sizeof(transport) - 1,
1219
                     "%s/UDP;multicast", trans_pref);
1220
        }
1221 1222 1223
        if (s->oformat) {
            av_strlcat(transport, ";mode=receive", sizeof(transport));
        } else if (rt->server_type == RTSP_SERVER_REAL ||
1224
                   rt->server_type == RTSP_SERVER_WMS)
1225
            av_strlcat(transport, ";mode=play", sizeof(transport));
1226
        snprintf(cmd, sizeof(cmd),
F
Fabrice Bellard 已提交
1227
                 "Transport: %s\r\n",
1228
                 transport);
1229
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
1230 1231 1232 1233 1234 1235 1236 1237
            char real_res[41], real_csum[9];
            ff_rdt_calc_response_and_checksum(real_res, real_csum,
                                              real_challenge);
            av_strlcatf(cmd, sizeof(cmd),
                        "If-Match: %s\r\n"
                        "RealChallenge2: %s, sd=%s\r\n",
                        rt->session_id, real_res, real_csum);
        }
1238
        ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
1239 1240 1241
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
            err = 1;
            goto fail;
1242 1243
        } else if (reply->status_code != RTSP_STATUS_OK ||
                   reply->nb_transports != 1) {
1244 1245 1246 1247 1248 1249
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* XXX: same protocol for all streams is required */
        if (i > 0) {
1250 1251
            if (reply->transports[0].lower_transport != rt->lower_transport ||
                reply->transports[0].transport != rt->transport) {
1252 1253 1254 1255
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
        } else {
1256
            rt->lower_transport = reply->transports[0].lower_transport;
1257
            rt->transport = reply->transports[0].transport;
1258 1259 1260
        }

        /* close RTP connection if not choosen */
1261 1262
        if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
            (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
1263 1264
            url_close(rtsp_st->rtp_handle);
            rtsp_st->rtp_handle = NULL;
1265 1266
        }

1267 1268
        switch(reply->transports[0].lower_transport) {
        case RTSP_LOWER_TRANSPORT_TCP:
1269 1270 1271
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
            break;
1272

1273 1274 1275 1276
        case RTSP_LOWER_TRANSPORT_UDP: {
            char url[1024];

            /* XXX: also use address if specified */
1277 1278
            ff_url_join(url, sizeof(url), "rtp", NULL, host,
                        reply->transports[0].server_port_min, NULL);
1279 1280 1281 1282
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1283
            }
1284 1285 1286 1287
            /* Try to initialize the connection state in a
             * potential NAT router by sending dummy packets.
             * RTP/RTCP dummy packets are used for RDT, too.
             */
1288
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat)
1289
                rtp_send_punch_packets(rtsp_st->rtp_handle);
1290
            break;
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
        }
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
            char url[1024];
            struct in_addr in;
            int port, ttl;

            if (reply->transports[0].destination) {
                in.s_addr = htonl(reply->transports[0].destination);
                port      = reply->transports[0].port_min;
                ttl       = reply->transports[0].ttl;
            } else {
                in        = rtsp_st->sdp_ip;
                port      = rtsp_st->sdp_port;
                ttl       = rtsp_st->sdp_ttl;
            }
1306 1307
            ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in),
                        port, "?ttl=%d", ttl);
1308 1309 1310
            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1311 1312 1313
            }
            break;
        }
1314
        }
R
Romain Degez 已提交
1315

1316
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1317
            goto fail;
1318 1319
    }

1320 1321 1322
    if (reply->timeout > 0)
        rt->timeout = reply->timeout;

1323
    if (rt->server_type == RTSP_SERVER_REAL)
1324 1325
        rt->need_subscription = 1;

1326 1327 1328
    return 0;

fail:
1329
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1330 1331 1332 1333 1334
        if (rt->rtsp_streams[i]->rtp_handle) {
            url_close(rt->rtsp_streams[i]->rtp_handle);
            rt->rtsp_streams[i]->rtp_handle = NULL;
        }
    }
1335 1336 1337
    return err;
}

1338 1339 1340 1341
static int rtsp_read_play(AVFormatContext *s)
{
    RTSPState *rt = s->priv_data;
    RTSPMessageHeader reply1, *reply = &reply1;
1342
    int i;
1343 1344 1345 1346 1347 1348
    char cmd[1024];

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

    if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
        if (rt->state == RTSP_STATE_PAUSED) {
1349
            cmd[0] = 0;
1350 1351 1352 1353 1354
        } else {
            snprintf(cmd, sizeof(cmd),
                     "Range: npt=%0.3f-\r\n",
                     (double)rt->seek_timestamp / AV_TIME_BASE);
        }
1355
        ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
1356 1357 1358
        if (reply->status_code != RTSP_STATUS_OK) {
            return -1;
        }
1359 1360 1361 1362 1363 1364
        if (reply->range_start != AV_NOPTS_VALUE &&
            rt->transport == RTSP_TRANSPORT_RTP) {
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
                RTSPStream *rtsp_st = rt->rtsp_streams[i];
                RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
                AVStream *st = NULL;
1365 1366
                if (!rtpctx)
                    continue;
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
                if (rtsp_st->stream_index >= 0)
                    st = s->streams[rtsp_st->stream_index];
                rtpctx->last_rtcp_ntp_time  = AV_NOPTS_VALUE;
                rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE;
                if (st)
                    rtpctx->range_start_offset = av_rescale_q(reply->range_start,
                                                              AV_TIME_BASE_Q,
                                                              st->time_base);
            }
        }
1377
    }
1378
    rt->state = RTSP_STATE_STREAMING;
1379 1380 1381
    return 0;
}

1382
static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
1383 1384 1385 1386 1387 1388 1389 1390
{
    RTSPState *rt = s->priv_data;
    char cmd[1024];
    unsigned char *content = NULL;
    int ret;

    /* describe the stream */
    snprintf(cmd, sizeof(cmd),
1391
             "Accept: application/sdp\r\n");
1392 1393 1394 1395 1396 1397 1398 1399 1400
    if (rt->server_type == RTSP_SERVER_REAL) {
        /**
         * The Require: attribute is needed for proper streaming from
         * Realmedia servers.
         */
        av_strlcat(cmd,
                   "Require: com.real.retain-entity-for-setup\r\n",
                   sizeof(cmd));
    }
1401
    ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
    if (!content)
        return AVERROR_INVALIDDATA;
    if (reply->status_code != RTSP_STATUS_OK) {
        av_freep(&content);
        return AVERROR_INVALIDDATA;
    }

    /* now we got the SDP description, we parse it */
    ret = sdp_parse(s, (const char *)content);
    av_freep(&content);
    if (ret < 0)
        return AVERROR_INVALIDDATA;

    return 0;
}

1418
static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
1419 1420 1421 1422 1423
{
    RTSPState *rt = s->priv_data;
    RTSPMessageHeader reply1, *reply = &reply1;
    int i;
    char *sdp;
1424
    AVFormatContext sdp_ctx, *ctx_array[1];
1425 1426

    rt->start_time = av_gettime();
1427 1428 1429 1430 1431

    /* Announce the stream */
    sdp = av_mallocz(8192);
    if (sdp == NULL)
        return AVERROR(ENOMEM);
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
    /* We create the SDP based on the RTSP AVFormatContext where we
     * aren't allowed to change the filename field. (We create the SDP
     * based on the RTSP context since the contexts for the RTP streams
     * don't exist yet.) In order to specify a custom URL with the actual
     * peer IP instead of the originally specified hostname, we create
     * a temporary copy of the AVFormatContext, where the custom URL is set.
     *
     * FIXME: Create the SDP without copying the AVFormatContext.
     * This either requires setting up the RTP stream AVFormatContexts
     * already here (complicating things immensely) or getting a more
     * flexible SDP creation interface.
     */
    sdp_ctx = *s;
    ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename),
                "rtsp", NULL, addr, -1, NULL);
    ctx_array[0] = &sdp_ctx;
    if (avf_sdp_create(ctx_array, 1, sdp, 8192)) {
1449 1450 1451 1452
        av_free(sdp);
        return AVERROR_INVALIDDATA;
    }
    av_log(s, AV_LOG_INFO, "SDP:\n%s\n", sdp);
1453 1454 1455
    ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri,
                                  "Content-Type: application/sdp\r\n",
                                  reply, NULL, sdp, strlen(sdp));
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
    av_free(sdp);
    if (reply->status_code != RTSP_STATUS_OK)
        return AVERROR_INVALIDDATA;

    /* Set up the RTSPStreams for each AVStream */
    for (i = 0; i < s->nb_streams; i++) {
        RTSPStream *rtsp_st;
        AVStream *st = s->streams[i];

        rtsp_st = av_mallocz(sizeof(RTSPStream));
        if (!rtsp_st)
            return AVERROR(ENOMEM);
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);

        st->priv_data = rtsp_st;
        rtsp_st->stream_index = i;

1473
        av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url));
1474 1475 1476 1477 1478 1479 1480 1481
        /* Note, this must match the relative uri set in the sdp content */
        av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url),
                    "/streamid=%d", i);
    }

    return 0;
}

1482 1483 1484 1485 1486 1487 1488
void ff_rtsp_close_connections(AVFormatContext *s)
{
    RTSPState *rt = s->priv_data;
    if (rt->rtsp_hd_out != rt->rtsp_hd) url_close(rt->rtsp_hd_out);
    url_close(rt->rtsp_hd);
}

1489
int ff_rtsp_connect(AVFormatContext *s)
1490 1491
{
    RTSPState *rt = s->priv_data;
1492 1493
    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
    char *option_list, *option, *filename;
1494
    URLContext *rtsp_hd, *rtsp_hd_out;
1495
    int port, err, tcp_fd;
1496
    RTSPMessageHeader reply1 = {}, *reply = &reply1;
1497
    int lower_transport_mask = 0;
1498
    char real_challenge[64];
1499 1500
    struct sockaddr_storage peer;
    socklen_t peer_len = sizeof(peer);
1501 1502 1503

    if (!ff_network_init())
        return AVERROR(EIO);
1504
redirect:
J
Josh Allmann 已提交
1505
    rt->control_transport = RTSP_MODE_PLAIN;
1506
    /* extract hostname and port */
1507
    ff_url_split(NULL, 0, auth, sizeof(auth),
M
Martin Storsjö 已提交
1508
                 host, sizeof(host), &port, path, sizeof(path), s->filename);
1509
    if (*auth) {
1510
        av_strlcpy(rt->auth, auth, sizeof(rt->auth));
1511
    }
1512 1513 1514 1515
    if (port < 0)
        port = RTSP_DEFAULT_PORT;

    /* search for options */
1516
    option_list = strrchr(path, '?');
1517
    if (option_list) {
1518 1519 1520
        /* Strip out the RTSP specific options, write out the rest of
         * the options back into the same string. */
        filename = option_list;
1521
        while (option_list) {
1522
            /* move the option pointer */
1523
            option = ++option_list;
1524 1525
            option_list = strchr(option_list, '&');
            if (option_list)
1526 1527
                *option_list = 0;

1528
            /* handle the options */
1529
            if (!strcmp(option, "udp")) {
1530
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
1531
            } else if (!strcmp(option, "multicast")) {
1532
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1533
            } else if (!strcmp(option, "tcp")) {
1534
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
J
Josh Allmann 已提交
1535 1536 1537
            } else if(!strcmp(option, "http")) {
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
                rt->control_transport = RTSP_MODE_TUNNEL;
1538
            } else {
1539 1540 1541 1542 1543
                /* Write options back into the buffer, using memmove instead
                 * of strcpy since the strings may overlap. */
                int len = strlen(option);
                memmove(++filename, option, len);
                filename += len;
1544 1545
                if (option_list) *filename = '&';
            }
1546
        }
1547
        *filename = 0;
1548 1549
    }

1550
    if (!lower_transport_mask)
1551
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1552

1553
    if (s->oformat) {
1554 1555 1556
        /* Only UDP or TCP - UDP multicast isn't supported. */
        lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |
                                (1 << RTSP_LOWER_TRANSPORT_TCP);
J
Josh Allmann 已提交
1557
        if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
1558
            av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
1559
                                    "only UDP and TCP are supported for output.\n");
1560 1561 1562 1563 1564
            err = AVERROR(EINVAL);
            goto fail;
        }
    }

1565 1566 1567 1568 1569 1570
    /* Construct the URI used in request; this is similar to s->filename,
     * but with authentication credentials removed and RTSP specific options
     * stripped out. */
    ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,
                host, port, "%s", path);

J
Josh Allmann 已提交
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        /* set up initial handshake for tunneling */
        char httpname[1024];
        char sessioncookie[17];
        char headers[1024];

        ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path);
        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());

        /* GET requests */
        if (url_open(&rtsp_hd, httpname, URL_RDONLY) < 0) {
            err = AVERROR(EIO);
            goto fail;
        }

        /* generate GET headers */
        snprintf(headers, sizeof(headers),
                 "x-sessioncookie: %s\r\n"
                 "Accept: application/x-rtsp-tunnelled\r\n"
                 "Pragma: no-cache\r\n"
                 "Cache-Control: no-cache\r\n",
                 sessioncookie);
        ff_http_set_headers(rtsp_hd, headers);

        /* complete the connection */
        if (url_read(rtsp_hd, NULL, 0)) {
            err = AVERROR(EIO);
            goto fail;
        }

        /* POST requests */
        if (url_open(&rtsp_hd_out, httpname, URL_WRONLY) < 0 ) {
            err = AVERROR(EIO);
            goto fail;
        }

        /* generate POST headers */
        snprintf(headers, sizeof(headers),
                 "x-sessioncookie: %s\r\n"
                 "Content-Type: application/x-rtsp-tunnelled\r\n"
                 "Pragma: no-cache\r\n"
                 "Cache-Control: no-cache\r\n"
                 "Content-Length: 32767\r\n"
                 "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n",
                 sessioncookie);
        ff_http_set_headers(rtsp_hd_out, headers);
        ff_http_set_chunked_transfer_encoding(rtsp_hd_out, 0);

    } else {
1621
    /* open the tcp connexion */
1622
    ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1623 1624 1625 1626
    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
        err = AVERROR(EIO);
        goto fail;
    }
1627
    rtsp_hd_out = rtsp_hd;
J
Josh Allmann 已提交
1628
    }
1629
    rt->rtsp_hd = rtsp_hd;
1630
    rt->rtsp_hd_out = rtsp_hd_out;
1631 1632
    rt->seq = 0;

1633 1634 1635 1636 1637 1638
    tcp_fd = url_get_file_handle(rtsp_hd);
    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
    }

1639 1640
    /* request options supported by the server; this also detects server
     * type */
1641
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1642
        cmd[0] = 0;
1643
        if (rt->server_type == RTSP_SERVER_REAL)
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
            av_strlcat(cmd,
                       /**
                        * The following entries are required for proper
                        * streaming from a Realmedia server. They are
                        * interdependent in some way although we currently
                        * don't quite understand how. Values were copied
                        * from mplayer SVN r23589.
                        * @param CompanyID is a 16-byte ID in base64
                        * @param ClientChallenge is a 16-byte ID in hex
                        */
                       "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
                       "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
                       "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
                       "GUID: 00000000-0000-0000-0000-000000000000\r\n",
                       sizeof(cmd));
1659
        ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
1660 1661 1662 1663 1664 1665
        if (reply->status_code != RTSP_STATUS_OK) {
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* detect server type if not standard-compliant RTP */
1666 1667
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
            rt->server_type = RTSP_SERVER_REAL;
1668
            continue;
1669 1670
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
            rt->server_type = RTSP_SERVER_WMS;
1671
        } else if (rt->server_type == RTSP_SERVER_REAL)
1672 1673 1674 1675
            strcpy(real_challenge, reply->real_challenge);
        break;
    }

1676
    if (s->iformat)
1677
        err = rtsp_setup_input_streams(s, reply);
1678
    else
1679
        err = rtsp_setup_output_streams(s, host);
1680
    if (err)
1681 1682
        goto fail;

1683
    do {
1684 1685
        int lower_transport = ff_log2_tab[lower_transport_mask &
                                  ~(lower_transport_mask - 1)];
1686

1687
        err = make_setup_request(s, host, port, lower_transport,
1688
                                 rt->server_type == RTSP_SERVER_REAL ?
1689
                                     real_challenge : NULL);
1690
        if (err < 0)
1691
            goto fail;
1692 1693
        lower_transport_mask &= ~(1 << lower_transport);
        if (lower_transport_mask == 0 && err == 1) {
1694
            err = FF_NETERROR(EPROTONOSUPPORT);
1695 1696 1697
            goto fail;
        }
    } while (err);
1698

1699
    rt->state = RTSP_STATE_IDLE;
1700
    rt->seek_timestamp = 0; /* default is to start stream at position zero */
1701 1702
    return 0;
 fail:
1703
    ff_rtsp_close_streams(s);
1704
    ff_rtsp_close_connections(s);
1705
    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
L
Luca Barbato 已提交
1706 1707 1708 1709 1710 1711
        av_strlcpy(s->filename, reply->location, sizeof(s->filename));
        av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
               reply->status_code,
               s->filename);
        goto redirect;
    }
1712
    ff_network_close();
1713 1714
    return err;
}
M
Martin Storsjö 已提交
1715
#endif
1716

M
Martin Storsjö 已提交
1717
#if CONFIG_RTSP_DEMUXER
1718 1719 1720 1721 1722
static int rtsp_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
{
    int ret;

1723
    ret = ff_rtsp_connect(s);
1724 1725 1726 1727 1728 1729 1730
    if (ret)
        return ret;

    if (ap->initial_pause) {
         /* do not start immediately */
    } else {
         if (rtsp_read_play(s) < 0) {
1731
            ff_rtsp_close_streams(s);
1732
            ff_rtsp_close_connections(s);
1733 1734 1735 1736 1737 1738 1739
            return AVERROR_INVALIDDATA;
        }
    }

    return 0;
}

R
Ronald S. Bultje 已提交
1740 1741 1742 1743 1744 1745
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
                           uint8_t *buf, int buf_size)
{
    RTSPState *rt = s->priv_data;
    RTSPStream *rtsp_st;
    fd_set rfds;
1746
    int fd, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
R
Ronald S. Bultje 已提交
1747 1748
    struct timeval tv;

1749
    for (;;) {
R
Ronald S. Bultje 已提交
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
        if (url_interrupt_cb())
            return AVERROR(EINTR);
        FD_ZERO(&rfds);
        if (rt->rtsp_hd) {
            tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
            FD_SET(tcp_fd, &rfds);
        } else {
            fd_max = 0;
            tcp_fd = -1;
        }
1760
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
            rtsp_st = rt->rtsp_streams[i];
            if (rtsp_st->rtp_handle) {
                /* currently, we cannot probe RTCP handle because of
                 * blocking restrictions */
                fd = url_get_file_handle(rtsp_st->rtp_handle);
                if (fd > fd_max)
                    fd_max = fd;
                FD_SET(fd, &rfds);
            }
        }
        tv.tv_sec = 0;
1772
        tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
R
Ronald S. Bultje 已提交
1773 1774
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
        if (n > 0) {
1775
            timeout_cnt = 0;
1776
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789
                rtsp_st = rt->rtsp_streams[i];
                if (rtsp_st->rtp_handle) {
                    fd = url_get_file_handle(rtsp_st->rtp_handle);
                    if (FD_ISSET(fd, &rfds)) {
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
                        if (ret > 0) {
                            *prtsp_st = rtsp_st;
                            return ret;
                        }
                    }
                }
            }
#if CONFIG_RTSP_DEMUXER
1790
            if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
R
Ronald S. Bultje 已提交
1791 1792
                RTSPMessageHeader reply;

1793 1794 1795
                ret = ff_rtsp_read_reply(s, &reply, NULL, 0);
                if (ret < 0)
                    return ret;
R
Ronald S. Bultje 已提交
1796
                /* XXX: parse message */
1797
                if (rt->state != RTSP_STATE_STREAMING)
R
Ronald S. Bultje 已提交
1798 1799 1800
                    return 0;
            }
#endif
1801
        } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
1802
            return FF_NETERROR(ETIMEDOUT);
1803 1804
        } else if (n < 0 && errno != EINTR)
            return AVERROR(errno);
R
Ronald S. Bultje 已提交
1805 1806 1807
    }
}

1808 1809
static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
                           uint8_t *buf, int buf_size)
1810 1811
{
    RTSPState *rt = s->priv_data;
F
Fabrice Bellard 已提交
1812
    int id, len, i, ret;
1813 1814
    RTSPStream *rtsp_st;

F
Fabrice Bellard 已提交
1815
#ifdef DEBUG_RTP_TCP
1816
    dprintf(s, "tcp_read_packet:\n");
F
Fabrice Bellard 已提交
1817
#endif
1818 1819
redo:
    for (;;) {
1820 1821
        RTSPMessageHeader reply;

1822
        ret = ff_rtsp_read_reply(s, &reply, NULL, 1);
1823
        if (ret == -1)
1824
            return -1;
1825
        if (ret == 1) /* received '$' */
1826
            break;
1827
        /* XXX: parse message */
1828
        if (rt->state != RTSP_STATE_STREAMING)
1829
            return 0;
1830
    }
1831
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
F
Fabrice Bellard 已提交
1832
    if (ret != 3)
1833
        return -1;
1834
    id  = buf[0];
1835
    len = AV_RB16(buf + 1);
F
Fabrice Bellard 已提交
1836
#ifdef DEBUG_RTP_TCP
1837
    dprintf(s, "id=%d len=%d\n", id, len);
F
Fabrice Bellard 已提交
1838
#endif
1839
    if (len > buf_size || len < 12)
1840 1841
        goto redo;
    /* get the data */
1842
    ret = url_read_complete(rt->rtsp_hd, buf, len);
F
Fabrice Bellard 已提交
1843
    if (ret != len)
1844
        return -1;
1845
    if (rt->transport == RTSP_TRANSPORT_RDT &&
1846
        ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
1847
        return -1;
1848

1849
    /* find the matching stream */
1850
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1851
        rtsp_st = rt->rtsp_streams[i];
1852 1853
        if (id >= rtsp_st->interleaved_min &&
            id <= rtsp_st->interleaved_max)
1854 1855 1856
            goto found;
    }
    goto redo;
1857
found:
1858 1859
    *prtsp_st = rtsp_st;
    return len;
1860 1861
}

R
Ronald S. Bultje 已提交
1862 1863 1864 1865 1866 1867 1868 1869 1870
static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
{
    RTSPState *rt = s->priv_data;
    int ret, len;
    uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
    RTSPStream *rtsp_st;

    /* get next frames from the same RTP packet */
    if (rt->cur_transport_priv) {
1871
        if (rt->transport == RTSP_TRANSPORT_RDT) {
R
Ronald S. Bultje 已提交
1872
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1873
        } else
R
Ronald S. Bultje 已提交
1874 1875 1876 1877 1878 1879
            ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
        if (ret == 0) {
            rt->cur_transport_priv = NULL;
            return 0;
        } else if (ret == 1) {
            return 0;
1880
        } else
R
Ronald S. Bultje 已提交
1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
            rt->cur_transport_priv = NULL;
    }

    /* read next RTP packet */
 redo:
    switch(rt->lower_transport) {
    default:
#if CONFIG_RTSP_DEMUXER
    case RTSP_LOWER_TRANSPORT_TCP:
        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
        break;
#endif
    case RTSP_LOWER_TRANSPORT_UDP:
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
        break;
    }
    if (len < 0)
        return len;
    if (len == 0)
        return AVERROR_EOF;
1904
    if (rt->transport == RTSP_TRANSPORT_RDT) {
R
Ronald S. Bultje 已提交
1905
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1906
    } else {
R
Ronald S. Bultje 已提交
1907
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926
        if (ret < 0) {
            /* Either bad packet, or a RTCP packet. Check if the
             * first_rtcp_ntp_time field was initialized. */
            RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
            if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) {
                /* first_rtcp_ntp_time has been initialized for this stream,
                 * copy the same value to all other uninitialized streams,
                 * in order to map their timestamp origin to the same ntp time
                 * as this one. */
                int i;
                for (i = 0; i < rt->nb_rtsp_streams; i++) {
                    RTPDemuxContext *rtpctx2 = rtsp_st->transport_priv;
                    if (rtpctx2 &&
                        rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE)
                        rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
                }
            }
        }
    }
R
Ronald S. Bultje 已提交
1927 1928
    if (ret < 0)
        goto redo;
1929
    if (ret == 1)
R
Ronald S. Bultje 已提交
1930 1931 1932 1933 1934 1935
        /* more packets may follow, so we save the RTP context */
        rt->cur_transport_priv = rtsp_st->transport_priv;

    return ret;
}

1936
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
1937 1938
{
    RTSPState *rt = s->priv_data;
1939
    int ret;
1940 1941
    RTSPMessageHeader reply1, *reply = &reply1;
    char cmd[1024];
1942

1943
    if (rt->server_type == RTSP_SERVER_REAL) {
1944
        int i;
1945
        enum AVDiscard cache[MAX_STREAMS];
1946

1947 1948 1949 1950 1951 1952
        for (i = 0; i < s->nb_streams; i++)
            cache[i] = s->streams[i]->discard;

        if (!rt->need_subscription) {
            if (memcmp (cache, rt->real_setup_cache,
                        sizeof(enum AVDiscard) * s->nb_streams)) {
1953
                snprintf(cmd, sizeof(cmd),
R
Ronald S. Bultje 已提交
1954
                         "Unsubscribe: %s\r\n",
1955 1956 1957
                         rt->last_subscription);
                ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
                                 cmd, reply, NULL);
1958 1959 1960 1961
                if (reply->status_code != RTSP_STATUS_OK)
                    return AVERROR_INVALIDDATA;
                rt->need_subscription = 1;
            }
1962 1963
        }

1964 1965 1966 1967 1968 1969 1970 1971
        if (rt->need_subscription) {
            int r, rule_nr, first = 1;

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

            snprintf(cmd, sizeof(cmd),
1972
                     "Subscribe: ");
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
                rule_nr = 0;
                for (r = 0; r < s->nb_streams; r++) {
                    if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
                        if (s->streams[r]->discard != AVDISCARD_ALL) {
                            if (!first)
                                av_strlcat(rt->last_subscription, ",",
                                           sizeof(rt->last_subscription));
                            ff_rdt_subscribe_rule(
                                rt->last_subscription,
                                sizeof(rt->last_subscription), i, rule_nr);
                            first = 0;
                        }
                        rule_nr++;
                    }
                }
            }
            av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
1991 1992
            ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
                             cmd, reply, NULL);
1993 1994 1995 1996
            if (reply->status_code != RTSP_STATUS_OK)
                return AVERROR_INVALIDDATA;
            rt->need_subscription = 0;

1997
            if (rt->state == RTSP_STATE_STREAMING)
1998 1999
                rtsp_read_play (s);
        }
2000 2001
    }

L
Luca Barbato 已提交
2002
    ret = rtsp_fetch_packet(s, pkt);
2003
    if (ret < 0)
2004
        return ret;
2005 2006 2007 2008 2009 2010

    /* send dummy request to keep TCP connection alive */
    if ((rt->server_type == RTSP_SERVER_WMS ||
         rt->server_type == RTSP_SERVER_REAL) &&
        (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
        if (rt->server_type == RTSP_SERVER_WMS) {
2011
            ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
2012
        } else {
2013
            ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
2014 2015 2016
        }
    }

2017
    return 0;
2018 2019
}

2020 2021
/* pause the stream */
static int rtsp_read_pause(AVFormatContext *s)
2022
{
2023
    RTSPState *rt = s->priv_data;
2024
    RTSPMessageHeader reply1, *reply = &reply1;
2025

2026
    if (rt->state != RTSP_STATE_STREAMING)
2027
        return 0;
2028
    else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
2029
        ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
2030 2031 2032
        if (reply->status_code != RTSP_STATUS_OK) {
            return -1;
        }
2033
    }
2034 2035
    rt->state = RTSP_STATE_PAUSED;
    return 0;
2036 2037
}

2038
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
2039
                          int64_t timestamp, int flags)
2040 2041
{
    RTSPState *rt = s->priv_data;
2042

2043 2044 2045
    rt->seek_timestamp = av_rescale_q(timestamp,
                                      s->streams[stream_index]->time_base,
                                      AV_TIME_BASE_Q);
2046 2047 2048 2049
    switch(rt->state) {
    default:
    case RTSP_STATE_IDLE:
        break;
2050
    case RTSP_STATE_STREAMING:
2051 2052 2053
        if (rtsp_read_pause(s) != 0)
            return -1;
        rt->state = RTSP_STATE_SEEKING;
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
        if (rtsp_read_play(s) != 0)
            return -1;
        break;
    case RTSP_STATE_PAUSED:
        rt->state = RTSP_STATE_IDLE;
        break;
    }
    return 0;
}

2064 2065 2066 2067
static int rtsp_read_close(AVFormatContext *s)
{
    RTSPState *rt = s->priv_data;

F
Fabrice Bellard 已提交
2068
#if 0
2069
    /* NOTE: it is valid to flush the buffer here */
2070
    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
2071 2072
        url_fclose(&rt->rtsp_gb);
    }
F
Fabrice Bellard 已提交
2073
#endif
2074
    ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
2075

2076
    ff_rtsp_close_streams(s);
2077
    ff_rtsp_close_connections(s);
2078
    ff_network_close();
2079 2080 2081
    return 0;
}

2082
AVInputFormat rtsp_demuxer = {
2083
    "rtsp",
2084
    NULL_IF_CONFIG_SMALL("RTSP input format"),
2085 2086 2087 2088 2089
    sizeof(RTSPState),
    rtsp_probe,
    rtsp_read_header,
    rtsp_read_packet,
    rtsp_read_close,
2090
    rtsp_read_seek,
2091
    .flags = AVFMT_NOFILE,
2092 2093
    .read_play = rtsp_read_play,
    .read_pause = rtsp_read_pause,
2094
};
2095
#endif
2096

2097
static int sdp_probe(AVProbeData *p1)
2098
{
2099
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
2100 2101

    /* we look for a line beginning "c=IN IP4" */
2102
    while (p < p_end && *p != '\0') {
2103 2104
        if (p + sizeof("c=IN IP4") - 1 < p_end &&
            av_strstart(p, "c=IN IP4", NULL))
2105
            return AVPROBE_SCORE_MAX / 2;
2106

2107
        while (p < p_end - 1 && *p != '\n') p++;
2108
        if (++p >= p_end)
2109 2110 2111 2112
            break;
        if (*p == '\r')
            p++;
    }
2113 2114 2115 2116 2117
    return 0;
}

#define SDP_MAX_SIZE 8192

2118
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
2119
{
2120
    RTSPState *rt = s->priv_data;
2121 2122 2123 2124 2125
    RTSPStream *rtsp_st;
    int size, i, err;
    char *content;
    char url[1024];

2126 2127 2128
    if (!ff_network_init())
        return AVERROR(EIO);

2129 2130 2131
    /* read the whole sdp file */
    /* XXX: better loading */
    content = av_malloc(SDP_MAX_SIZE);
2132
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142
    if (size <= 0) {
        av_free(content);
        return AVERROR_INVALIDDATA;
    }
    content[size] ='\0';

    sdp_parse(s, content);
    av_free(content);

    /* open each RTP stream */
2143
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
2144
        rtsp_st = rt->rtsp_streams[i];
2145

2146 2147 2148 2149
        ff_url_join(url, sizeof(url), "rtp", NULL,
                    inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port,
                    "?localport=%d&ttl=%d", rtsp_st->sdp_port,
                    rtsp_st->sdp_ttl);
2150
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
2151 2152 2153
            err = AVERROR_INVALIDDATA;
            goto fail;
        }
2154
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
2155
            goto fail;
2156 2157
    }
    return 0;
2158
fail:
2159
    ff_rtsp_close_streams(s);
2160
    ff_network_close();
2161 2162 2163 2164 2165
    return err;
}

static int sdp_read_close(AVFormatContext *s)
{
2166
    ff_rtsp_close_streams(s);
2167
    ff_network_close();
2168 2169 2170
    return 0;
}

2171
AVInputFormat sdp_demuxer = {
2172
    "sdp",
2173
    NULL_IF_CONFIG_SMALL("SDP"),
2174 2175 2176
    sizeof(RTSPState),
    sdp_probe,
    sdp_read_header,
L
Luca Barbato 已提交
2177
    rtsp_fetch_packet,
2178 2179
    sdp_read_close,
};