rtsp.c 63.0 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_formats.h"
42
#include "rtpenc_chain.h"
R
Ryan Martell 已提交
43

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

R
Reimar Döffinger 已提交
47
/* Timeout values for socket select, in ms,
48 49 50 51
 * 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
52
#define SDP_MAX_SIZE 16384
53
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
54

55 56
static void get_word_until_chars(char *buf, int buf_size,
                                 const char *sep, const char **pp)
57 58 59 60 61
{
    const char *p;
    char *q;

    p = *pp;
62
    p += strspn(p, SPACE_CHARS);
63 64 65 66 67 68 69 70 71 72 73
    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;
}

74 75
static void get_word_sep(char *buf, int buf_size, const char *sep,
                         const char **pp)
76
{
77 78 79
    if (**pp == '/') (*pp)++;
    get_word_until_chars(buf, buf_size, sep, pp);
}
80

81 82 83
static void get_word(char *buf, int buf_size, const char **pp)
{
    get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
84 85
}

M
Martin Storsjö 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/** Parse a string p in the form of Range:npt=xx-xx, and determine the start
 *  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];

    p += strspn(p, SPACE_CHARS);
    if (!av_stristart(p, "npt=", &p))
        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);
}

static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
{
    struct addrinfo hints, *ai = NULL;
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_NUMERICHOST;
    if (getaddrinfo(buf, NULL, &hints, &ai))
        return -1;
    memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen));
    freeaddrinfo(ai);
    return 0;
}

124
#if CONFIG_RTPDEC
125 126 127 128 129 130 131 132 133 134 135
static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
                             RTSPStream *rtsp_st, AVCodecContext *codec)
{
    if (!handler)
        return;
    codec->codec_id          = handler->codec_id;
    rtsp_st->dynamic_handler = handler;
    if (handler->open)
        rtsp_st->dynamic_protocol_context = handler->open();
}

136
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
137 138
static int sdp_parse_rtpmap(AVFormatContext *s,
                            AVCodecContext *codec, RTSPStream *rtsp_st,
139
                            int payload_type, const char *p)
140 141
{
    char buf[256];
R
Romain Degez 已提交
142 143
    int i;
    AVCodec *c;
144
    const char *c_name;
145

R
Romain Degez 已提交
146
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
147 148 149 150 151
     * 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 已提交
152
    if (payload_type >= RTP_PT_PRIVATE) {
153 154 155
        RTPDynamicProtocolHandler *handler =
            ff_rtp_handler_find_by_name(buf, codec->codec_type);
        init_rtp_handler(handler, rtsp_st, codec);
156 157 158 159 160 161
        /* If no dynamic handler was found, check with the list of standard
         * allocated types, if such a stream for some reason happens to
         * use a private payload type. This isn't handled in rtpdec.c, since
         * the format name from the rtpmap line never is passed into rtpdec. */
        if (!rtsp_st->dynamic_handler)
            codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
162
    } else {
163 164
        /* We are in a standard case
         * (from http://www.iana.org/assignments/rtp-parameters). */
R
Romain Degez 已提交
165
        /* search into AVRtpPayloadTypes[] */
166
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
R
Romain Degez 已提交
167 168 169 170
    }

    c = avcodec_find_decoder(codec->codec_id);
    if (c && c->name)
171
        c_name = c->name;
R
Romain Degez 已提交
172
    else
173
        c_name = "(null)";
R
Romain Degez 已提交
174

R
Ronald S. Bultje 已提交
175 176 177
    get_word_sep(buf, sizeof(buf), "/", &p);
    i = atoi(buf);
    switch (codec->codec_type) {
178
    case AVMEDIA_TYPE_AUDIO:
R
Ronald S. Bultje 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191
        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 已提交
192
        }
R
Ronald S. Bultje 已提交
193 194 195 196 197
        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;
198
    case AVMEDIA_TYPE_VIDEO:
R
Ronald S. Bultje 已提交
199 200 201 202 203 204
        av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
        break;
    default:
        break;
    }
    return 0;
205 206
}

R
Reimar Döffinger 已提交
207
/* parse the attribute line from the fmtp a line of an sdp response. This
208 209
 * is broken out as a function because it is used in rtp_h264.c, which is
 * forthcoming. */
210
int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
M
Martin Storsjö 已提交
211
                                char *value, int value_size)
212
{
213
    *p += strspn(*p, SPACE_CHARS);
214
    if (**p) {
215 216 217 218 219 220 221 222 223 224 225
        get_word_sep(attr, attr_size, "=", p);
        if (**p == '=')
            (*p)++;
        get_word_sep(value, value_size, ";", p);
        if (**p == ';')
            (*p)++;
        return 1;
    }
    return 0;
}

226 227
typedef struct SDPParseState {
    /* SDP only */
M
Martin Storsjö 已提交
228
    struct sockaddr_storage default_ip;
229 230
    int            default_ttl;
    int            skip_media;  ///< set if an unknown m= line occurs
231 232 233
} SDPParseState;

static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
234 235
                           int letter, const char *buf)
{
236
    RTSPState *rt = s->priv_data;
237 238
    char buf1[64], st_type[64];
    const char *p;
239
    enum AVMediaType codec_type;
D
Diego Pettenò 已提交
240
    int payload_type, i;
241 242
    AVStream *st;
    RTSPStream *rtsp_st;
M
Martin Storsjö 已提交
243
    struct sockaddr_storage sdp_ip;
244 245
    int ttl;

246
    dprintf(s, "sdp: %c='%s'\n", letter, buf);
247 248

    p = buf;
249 250
    if (s1->skip_media && letter != 'm')
        return;
251
    switch (letter) {
252 253 254 255 256
    case 'c':
        get_word(buf1, sizeof(buf1), &p);
        if (strcmp(buf1, "IN") != 0)
            return;
        get_word(buf1, sizeof(buf1), &p);
M
Martin Storsjö 已提交
257
        if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6"))
258 259
            return;
        get_word_sep(buf1, sizeof(buf1), "/", &p);
M
Martin Storsjö 已提交
260
        if (get_sockaddr(buf1, &sdp_ip))
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
            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;
278
    case 's':
279
        av_metadata_set2(&s->metadata, "title", p, 0);
280 281 282
        break;
    case 'i':
        if (s->nb_streams == 0) {
283
            av_metadata_set2(&s->metadata, "comment", p, 0);
284 285 286 287 288
            break;
        }
        break;
    case 'm':
        /* new stream */
289
        s1->skip_media = 0;
290 291
        get_word(st_type, sizeof(st_type), &p);
        if (!strcmp(st_type, "audio")) {
292
            codec_type = AVMEDIA_TYPE_AUDIO;
293
        } else if (!strcmp(st_type, "video")) {
294
            codec_type = AVMEDIA_TYPE_VIDEO;
295
        } else if (!strcmp(st_type, "application")) {
296
            codec_type = AVMEDIA_TYPE_DATA;
297
        } else {
298
            s1->skip_media = 1;
299 300 301 302 303
            return;
        }
        rtsp_st = av_mallocz(sizeof(RTSPStream));
        if (!rtsp_st)
            return;
304 305
        rtsp_st->stream_index = -1;
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
306 307 308 309 310 311 312 313

        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) */
314

315 316 317 318
        /* XXX: handle list of formats */
        get_word(buf1, sizeof(buf1), &p); /* format list */
        rtsp_st->sdp_payload_type = atoi(buf1);

319
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
320 321 322 323 324 325 326
            /* no corresponding stream */
        } else {
            st = av_new_stream(s, 0);
            if (!st)
                return;
            st->priv_data = rtsp_st;
            rtsp_st->stream_index = st->index;
327
            st->codec->codec_type = codec_type;
R
Romain Degez 已提交
328
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
329
                /* if standard payload type, we can find the codec right now */
330
                ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
331 332
            }
        }
333
        /* put a default control url */
334
        av_strlcpy(rtsp_st->control_url, rt->control_uri,
335
                   sizeof(rtsp_st->control_url));
336 337
        break;
    case 'a':
338 339 340 341 342 343
        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 {
M
Martin Storsjö 已提交
344 345 346 347
                char proto[32];
                /* get the control url */
                st = s->streams[s->nb_streams - 1];
                rtsp_st = st->priv_data;
348

M
Martin Storsjö 已提交
349 350 351 352 353 354 355 356 357 358 359 360 361
                /* XXX: may need to add full url resolution */
                av_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
                             NULL, NULL, 0, p);
                if (proto[0] == '\0') {
                    /* relative control URL */
                    if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/')
                    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));
362
            }
363
        } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
364
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
365
            get_word(buf1, sizeof(buf1), &p);
366
            payload_type = atoi(buf1);
367
            st = s->streams[s->nb_streams - 1];
R
Ronald S. Bultje 已提交
368
            rtsp_st = st->priv_data;
369
            sdp_parse_rtpmap(s, st->codec, rtsp_st, payload_type, p);
370 371
        } else if (av_strstart(p, "fmtp:", &p) ||
                   av_strstart(p, "framesize:", &p)) {
372
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
373 374 375
            // let dynamic protocol handlers have a stab at the line.
            get_word(buf1, sizeof(buf1), &p);
            payload_type = atoi(buf1);
376 377
            for (i = 0; i < s->nb_streams; i++) {
                st      = s->streams[i];
378
                rtsp_st = st->priv_data;
379 380 381 382 383
                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);
384
            }
385
        } else if (av_strstart(p, "range:", &p)) {
386 387 388 389
            int64_t start, end;

            // this is so that seeking on a streamed file can work.
            rtsp_parse_range_npt(p, &start, &end);
390 391 392 393
            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;
394 395 396
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
            if (atoi(p) == 1)
                rt->transport = RTSP_TRANSPORT_RDT;
397 398 399 400
        } 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 已提交
401 402 403 404 405 406
                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)
407 408
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
                        s->nb_streams - 1,
R
Ronald S. Bultje 已提交
409
                        rtsp_st->dynamic_protocol_context, buf);
410
            }
411 412 413 414 415
        }
        break;
    }
}

416
int ff_sdp_parse(AVFormatContext *s, const char *content)
417 418 419
{
    const char *p;
    int letter;
420 421 422 423
    /* 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
424 425
     * buffer is large.
     *
426 427
     * The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line
     * in rtpdec_xiph.c. */
428
    char buf[16384], *q;
429
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
430

431
    memset(s1, 0, sizeof(SDPParseState));
432
    p = content;
433
    for (;;) {
434
        p += strspn(p, SPACE_CHARS);
435 436 437 438 439 440 441 442 443
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
F
Fabrice Bellard 已提交
444
        while (*p != '\n' && *p != '\r' && *p != '\0') {
445 446 447 448 449
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
450
        sdp_parse_line(s, s1, letter, buf);
451 452 453 454 455 456 457 458
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
    }
    return 0;
}
459
#endif /* CONFIG_RTPDEC */
460

461
/* close and free RTSP streams */
462
void ff_rtsp_close_streams(AVFormatContext *s)
463
{
464
    RTSPState *rt = s->priv_data;
465 466 467
    int i;
    RTSPStream *rtsp_st;

468
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
469 470 471
        rtsp_st = rt->rtsp_streams[i];
        if (rtsp_st) {
            if (rtsp_st->transport_priv) {
472 473 474
                if (s->oformat) {
                    AVFormatContext *rtpctx = rtsp_st->transport_priv;
                    av_write_trailer(rtpctx);
475 476 477 478 479
                    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ö 已提交
480
                        url_fclose(rtpctx->pb);
481
                    }
482 483
                    av_metadata_free(&rtpctx->streams[0]->metadata);
                    av_metadata_free(&rtpctx->metadata);
484 485
                    av_free(rtpctx->streams[0]);
                    av_free(rtpctx);
486
                } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
487
                    ff_rdt_parse_close(rtsp_st->transport_priv);
488
                else if (CONFIG_RTPDEC)
489 490 491 492 493
                    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)
494 495
                rtsp_st->dynamic_handler->close(
                    rtsp_st->dynamic_protocol_context);
496 497 498 499 500 501 502
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
        av_close_input_stream (rt->asf_ctx);
        rt->asf_ctx = NULL;
    }
503
    av_free(rt->recvbuf);
504 505
}

506
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
507 508 509 510 511 512 513 514 515 516
{
    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;

517
    if (s->oformat && CONFIG_RTSP_MUXER) {
518 519 520
        rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
                                      rtsp_st->rtp_handle,
                                      RTSP_TCP_MAX_PACKET_SIZE);
R
Reimar Döffinger 已提交
521
        /* Ownership of rtp_handle is passed to the rtp mux context */
522
        rtsp_st->rtp_handle = NULL;
523
    } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
524 525 526
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
527
    else if (CONFIG_RTPDEC)
528
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
529 530 531
                                         rtsp_st->sdp_payload_type,
            (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
            ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
532 533 534

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
535
    } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
536
        if (rtsp_st->dynamic_handler) {
537 538 539 540 541 542 543 544 545
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                           rtsp_st->dynamic_protocol_context,
                                           rtsp_st->dynamic_handler);
        }
    }

    return 0;
}

M
Martin Storsjö 已提交
546
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
547 548 549 550 551 552
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
    const char *p;
    int v;

    p = *pp;
553
    p += strspn(p, SPACE_CHARS);
554 555 556 557 558 559 560 561 562 563 564 565 566 567
    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 */
568
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
569 570 571 572 573 574 575
{
    char transport_protocol[16];
    char profile[16];
    char lower_transport[16];
    char parameter[16];
    RTSPTransportField *th;
    char buf[256];
576

577
    reply->nb_transports = 0;
578

579
    for (;;) {
580
        p += strspn(p, SPACE_CHARS);
581 582 583 584 585
        if (*p == '\0')
            break;

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

586
        get_word_sep(transport_protocol, sizeof(transport_protocol),
587
                     "/", &p);
588
        if (!strcasecmp (transport_protocol, "rtp")) {
589 590 591 592 593 594
            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);
595 596 597 598
            }
            th->transport = RTSP_TRANSPORT_RTP;
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
599
            /* x-pn-tng/<protocol> */
600 601
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
            profile[0] = '\0';
602
            th->transport = RTSP_TRANSPORT_RDT;
603
        }
F
Fabrice Bellard 已提交
604
        if (!strcasecmp(lower_transport, "TCP"))
605
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
606
        else
607
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
608

609 610 611 612 613 614 615 616 617 618 619 620 621
        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++;
622
                    rtsp_parse_range(&th->client_port_min,
623 624 625 626 627
                                     &th->client_port_max, &p);
                }
            } else if (!strcmp(parameter, "server_port")) {
                if (*p == '=') {
                    p++;
628
                    rtsp_parse_range(&th->server_port_min,
629 630 631 632 633
                                     &th->server_port_max, &p);
                }
            } else if (!strcmp(parameter, "interleaved")) {
                if (*p == '=') {
                    p++;
634
                    rtsp_parse_range(&th->interleaved_min,
635 636 637
                                     &th->interleaved_max, &p);
                }
            } else if (!strcmp(parameter, "multicast")) {
638 639
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
640 641 642 643 644 645 646 647 648
            } else if (!strcmp(parameter, "ttl")) {
                if (*p == '=') {
                    p++;
                    th->ttl = strtol(p, (char **)&p, 10);
                }
            } else if (!strcmp(parameter, "destination")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
M
Martin Storsjö 已提交
649
                    get_sockaddr(buf, &th->destination);
650
                }
651 652 653 654 655 656
            } else if (!strcmp(parameter, "source")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
                    av_strlcpy(th->source, buf, sizeof(th->source));
                }
657
            }
658

659 660 661 662 663 664 665 666 667 668 669 670
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

671 672
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
                        HTTPAuthState *auth_state)
673 674 675 676 677
{
    const char *p;

    /* NOTE: we do case independent match for broken servers */
    p = buf;
678
    if (av_stristart(p, "Session:", &p)) {
679
        int t;
680
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
681 682 683 684
        if (av_stristart(p, ";timeout=", &p) &&
            (t = strtol(p, NULL, 10)) > 0) {
            reply->timeout = t;
        }
685
    } else if (av_stristart(p, "Content-Length:", &p)) {
686
        reply->content_length = strtol(p, NULL, 10);
687
    } else if (av_stristart(p, "Transport:", &p)) {
688
        rtsp_parse_transport(reply, p);
689
    } else if (av_stristart(p, "CSeq:", &p)) {
690
        reply->seq = strtol(p, NULL, 10);
691
    } else if (av_stristart(p, "Range:", &p)) {
692
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
693
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
694
        p += strspn(p, SPACE_CHARS);
695
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
696
    } else if (av_stristart(p, "Server:", &p)) {
697
        p += strspn(p, SPACE_CHARS);
698
        av_strlcpy(reply->server, p, sizeof(reply->server));
699 700 701
    } else if (av_stristart(p, "Notice:", &p) ||
               av_stristart(p, "X-Notice:", &p)) {
        reply->notice = strtol(p, NULL, 10);
L
Luca Barbato 已提交
702
    } else if (av_stristart(p, "Location:", &p)) {
703
        p += strspn(p, SPACE_CHARS);
L
Luca Barbato 已提交
704
        av_strlcpy(reply->location, p , sizeof(reply->location));
705
    } else if (av_stristart(p, "WWW-Authenticate:", &p) && auth_state) {
706
        p += strspn(p, SPACE_CHARS);
707 708
        ff_http_auth_handle_header(auth_state, "WWW-Authenticate", p);
    } else if (av_stristart(p, "Authentication-Info:", &p) && auth_state) {
709
        p += strspn(p, SPACE_CHARS);
710
        ff_http_auth_handle_header(auth_state, "Authentication-Info", p);
711 712 713
    } else if (av_stristart(p, "Content-Base:", &p)) {
        p += strspn(p, SPACE_CHARS);
        av_strlcpy(reply->content_base, p , sizeof(reply->content_base));
714 715 716
    }
}

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

724
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
725 726
    if (ret != 3)
        return;
727
    len = AV_RB16(buf + 1);
728 729 730

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

731 732 733 734 735
    /* skip payload */
    while (len > 0) {
        len1 = len;
        if (len1 > sizeof(buf))
            len1 = sizeof(buf);
736
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
737 738 739 740 741
        if (ret != len1)
            return;
        len -= len1;
    }
}
742

743
int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
M
Martin Storsjö 已提交
744 745
                       unsigned char **content_ptr,
                       int return_on_interleaved_data)
746 747 748 749 750
{
    RTSPState *rt = s->priv_data;
    char buf[4096], buf1[1024], *q;
    unsigned char ch;
    const char *p;
751
    int ret, content_length, line_count = 0;
752 753
    unsigned char *content = NULL;

754
    memset(reply, 0, sizeof(*reply));
755 756 757

    /* parse reply (XXX: use buffers) */
    rt->last_reply[0] = '\0';
758
    for (;;) {
759
        q = buf;
760
        for (;;) {
761
            ret = url_read_complete(rt->rtsp_hd, &ch, 1);
762
#ifdef DEBUG_RTP_TCP
763
            dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
764 765
#endif
            if (ret != 1)
766
                return AVERROR_EOF;
767 768
            if (ch == '\n')
                break;
769 770
            if (ch == '$') {
                /* XXX: only parse it if first char on line ? */
771 772 773
                if (return_on_interleaved_data) {
                    return 1;
                } else
774
                    ff_rtsp_skip_packet(s);
775
            } else if (ch != '\r') {
776 777 778 779 780
                if ((q - buf) < sizeof(buf) - 1)
                    *q++ = ch;
            }
        }
        *q = '\0';
781 782 783

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

784 785 786 787 788 789 790 791 792
        /* 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);
L
Luca Barbato 已提交
793
            av_strlcpy(reply->reason, p, sizeof(reply->reason));
794
        } else {
795
            ff_rtsp_parse_line(reply, p, &rt->auth_state);
M
Måns Rullgård 已提交
796 797
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
798 799 800
        }
        line_count++;
    }
801

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

805 806 807 808
    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);
809
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
810 811 812 813
        content[content_length] = '\0';
    }
    if (content_ptr)
        *content_ptr = content;
814 815
    else
        av_free(content);
816

817 818 819 820 821
    if (rt->seq != reply->seq) {
        av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
            rt->seq, reply->seq);
    }

822 823 824
    /* EOS */
    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
        reply->notice == 2104 /* Start-of-Stream Reached */    ||
825
        reply->notice == 2306 /* Continuous Feed Terminated */) {
826
        rt->state = RTSP_STATE_IDLE;
827
    } else if (reply->notice >= 4400 && reply->notice < 5500) {
828
        return AVERROR(EIO); /* data or server error */
829
    } else if (reply->notice == 2401 /* Ticket Expired */ ||
830 831 832
             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
        return AVERROR(EPERM);

833
    return 0;
834 835
}

836
int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
M
Martin Storsjö 已提交
837 838 839 840
                                        const char *method, const char *url,
                                        const char *headers,
                                        const unsigned char *send_content,
                                        int send_content_length)
841 842
{
    RTSPState *rt = s->priv_data;
J
Josh Allmann 已提交
843 844
    char buf[4096], *out_buf;
    char base64buf[AV_BASE64_SIZE(sizeof(buf))];
845

J
Josh Allmann 已提交
846 847
    /* Add in RTSP headers */
    out_buf = buf;
848
    rt->seq++;
849 850 851
    snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
    if (headers)
        av_strlcat(buf, headers, sizeof(buf));
852
    av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
853 854
    if (rt->session_id[0] != '\0' && (!headers ||
        !strstr(headers, "\nIf-Match:"))) {
855
        av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
856
    }
857 858 859 860 861 862 863
    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);
    }
864 865
    if (send_content_length > 0 && send_content)
        av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
866
    av_strlcat(buf, "\r\n", sizeof(buf));
867

J
Josh Allmann 已提交
868 869 870 871 872 873
    /* base64 encode rtsp if tunneling */
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
        out_buf = base64buf;
    }

874 875
    dprintf(s, "Sending:\n%s--\n", buf);

J
Josh Allmann 已提交
876 877 878 879 880 881 882
    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;
        }
883
        url_write(rt->rtsp_hd_out, send_content, send_content_length);
J
Josh Allmann 已提交
884
    }
885
    rt->last_cmd_time = av_gettime();
886 887

    return 0;
888 889
}

890
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
M
Martin Storsjö 已提交
891
                           const char *url, const char *headers)
892
{
893
    return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
894 895
}

896
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
M
Martin Storsjö 已提交
897 898
                     const char *headers, RTSPMessageHeader *reply,
                     unsigned char **content_ptr)
899
{
900
    return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
M
Martin Storsjö 已提交
901
                                         content_ptr, NULL, 0);
902 903
}

904
int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
M
Martin Storsjö 已提交
905 906 907 908 909 910
                                  const char *method, const char *url,
                                  const char *header,
                                  RTSPMessageHeader *reply,
                                  unsigned char **content_ptr,
                                  const unsigned char *send_content,
                                  int send_content_length)
911
{
912 913
    RTSPState *rt = s->priv_data;
    HTTPAuthType cur_auth_type;
914
    int ret;
915 916 917

retry:
    cur_auth_type = rt->auth_state.auth_type;
918
    if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
M
Martin Storsjö 已提交
919 920
                                                   send_content,
                                                   send_content_length)))
921
        return ret;
922

923 924
    if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0) ) < 0)
        return ret;
925 926 927 928

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

930
    if (reply->status_code > 400){
L
Luca Barbato 已提交
931
        av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
932
               method,
L
Luca Barbato 已提交
933 934
               reply->status_code,
               reply->reason);
935 936 937
        av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
    }

938
    return 0;
939 940
}

941
/**
B
Benoit Fouet 已提交
942
 * @return 0 on success, <0 on error, 1 if protocol is unavailable.
943
 */
944 945
static int make_setup_request(AVFormatContext *s, const char *host, int port,
                              int lower_transport, const char *real_challenge)
946 947
{
    RTSPState *rt = s->priv_data;
948
    int rtx, j, i, err, interleave = 0;
949
    RTSPStream *rtsp_st;
950
    RTSPMessageHeader reply1, *reply = &reply1;
951
    char cmd[2048];
952 953
    const char *trans_pref;

954
    if (rt->transport == RTSP_TRANSPORT_RDT)
955 956 957
        trans_pref = "x-pn-tng";
    else
        trans_pref = "RTP/AVP";
958

959 960 961
    /* default timeout: 1 minute */
    rt->timeout = 60;

962 963
    /* for each stream, make the setup request */
    /* XXX: we assume the same server is used for the control of each
964
     * RTSP stream */
R
Romain Degez 已提交
965

966
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
967 968
        char transport[2048];

969 970 971 972 973 974 975 976 977 978 979 980
        /**
         * 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 &&
981 982
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
                                "/rtx"))
983 984 985 986 987 988 989 990
                        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 已提交
991
            rtsp_st = rt->rtsp_streams[i];
992 993

        /* RTP/UDP */
994
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
F
Fabrice Bellard 已提交
995 996
            char buf[256];

997 998 999 1000 1001
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
                port = reply->transports[0].client_port_min;
                goto have_port;
            }

F
Fabrice Bellard 已提交
1002
            /* first try in specified port range */
R
Romain Degez 已提交
1003
            if (RTSP_RTP_PORT_MIN != 0) {
1004
                while (j <= RTSP_RTP_PORT_MAX) {
1005 1006
                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
                                "?localport=%d", j);
1007 1008 1009
                    /* 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 已提交
1010 1011
                        goto rtp_opened;
                }
1012
            }
F
Fabrice Bellard 已提交
1013

1014 1015 1016 1017 1018 1019 1020
#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 已提交
1021 1022

        rtp_opened:
1023
            port = rtp_get_local_rtp_port(rtsp_st->rtp_handle);
1024
        have_port:
1025
            snprintf(transport, sizeof(transport) - 1,
1026 1027 1028 1029 1030
                     "%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);
1031 1032
            if (rt->transport == RTSP_TRANSPORT_RTP &&
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
1033
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1034 1035 1036
        }

        /* RTP/TCP */
1037
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1038 1039 1040 1041
            /** 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 &&
1042
                s->streams[rtsp_st->stream_index]->codec->codec_type ==
1043
                    AVMEDIA_TYPE_DATA)
1044
                continue;
1045
            snprintf(transport, sizeof(transport) - 1,
1046 1047 1048 1049 1050 1051 1052
                     "%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;
1053 1054
        }

1055
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1056
            snprintf(transport, sizeof(transport) - 1,
1057
                     "%s/UDP;multicast", trans_pref);
1058
        }
1059 1060 1061
        if (s->oformat) {
            av_strlcat(transport, ";mode=receive", sizeof(transport));
        } else if (rt->server_type == RTSP_SERVER_REAL ||
1062
                   rt->server_type == RTSP_SERVER_WMS)
1063
            av_strlcat(transport, ";mode=play", sizeof(transport));
1064
        snprintf(cmd, sizeof(cmd),
F
Fabrice Bellard 已提交
1065
                 "Transport: %s\r\n",
1066
                 transport);
1067
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
1068 1069 1070 1071 1072 1073 1074 1075
            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);
        }
1076
        ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
1077 1078 1079
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
            err = 1;
            goto fail;
1080 1081
        } else if (reply->status_code != RTSP_STATUS_OK ||
                   reply->nb_transports != 1) {
1082 1083 1084 1085 1086 1087
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* XXX: same protocol for all streams is required */
        if (i > 0) {
1088 1089
            if (reply->transports[0].lower_transport != rt->lower_transport ||
                reply->transports[0].transport != rt->transport) {
1090 1091 1092 1093
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
        } else {
1094
            rt->lower_transport = reply->transports[0].lower_transport;
1095
            rt->transport = reply->transports[0].transport;
1096 1097
        }

R
Reinhard Tartler 已提交
1098
        /* close RTP connection if not chosen */
1099 1100
        if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
            (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
1101 1102
            url_close(rtsp_st->rtp_handle);
            rtsp_st->rtp_handle = NULL;
1103 1104
        }

1105 1106
        switch(reply->transports[0].lower_transport) {
        case RTSP_LOWER_TRANSPORT_TCP:
1107 1108 1109
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
            break;
1110

1111 1112 1113
        case RTSP_LOWER_TRANSPORT_UDP: {
            char url[1024];

1114 1115 1116 1117 1118 1119
            /* Use source address if specified */
            if (reply->transports[0].source[0]) {
                ff_url_join(url, sizeof(url), "rtp", NULL,
                            reply->transports[0].source,
                            reply->transports[0].server_port_min, NULL);
            } else {
R
Ronald S. Bultje 已提交
1120 1121
                ff_url_join(url, sizeof(url), "rtp", NULL, host,
                            reply->transports[0].server_port_min, NULL);
1122
            }
1123 1124 1125 1126
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1127
            }
1128 1129 1130 1131
            /* Try to initialize the connection state in a
             * potential NAT router by sending dummy packets.
             * RTP/RTCP dummy packets are used for RDT, too.
             */
1132 1133
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
                CONFIG_RTPDEC)
1134
                rtp_send_punch_packets(rtsp_st->rtp_handle);
1135
            break;
1136 1137
        }
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
M
Martin Storsjö 已提交
1138 1139
            char url[1024], namebuf[50];
            struct sockaddr_storage addr;
1140 1141
            int port, ttl;

M
Martin Storsjö 已提交
1142 1143
            if (reply->transports[0].destination.ss_family) {
                addr      = reply->transports[0].destination;
1144 1145 1146
                port      = reply->transports[0].port_min;
                ttl       = reply->transports[0].ttl;
            } else {
M
Martin Storsjö 已提交
1147
                addr      = rtsp_st->sdp_ip;
1148 1149 1150
                port      = rtsp_st->sdp_port;
                ttl       = rtsp_st->sdp_ttl;
            }
M
Martin Storsjö 已提交
1151 1152 1153
            getnameinfo((struct sockaddr*) &addr, sizeof(addr),
                        namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
            ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
1154
                        port, "?ttl=%d", ttl);
1155 1156 1157
            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1158 1159 1160
            }
            break;
        }
1161
        }
R
Romain Degez 已提交
1162

1163
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1164
            goto fail;
1165 1166
    }

1167 1168 1169
    if (reply->timeout > 0)
        rt->timeout = reply->timeout;

1170
    if (rt->server_type == RTSP_SERVER_REAL)
1171 1172
        rt->need_subscription = 1;

1173 1174 1175
    return 0;

fail:
1176
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1177 1178 1179 1180 1181
        if (rt->rtsp_streams[i]->rtp_handle) {
            url_close(rt->rtsp_streams[i]->rtp_handle);
            rt->rtsp_streams[i]->rtp_handle = NULL;
        }
    }
1182 1183 1184
    return err;
}

1185 1186 1187 1188 1189
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);
1190
    rt->rtsp_hd = rt->rtsp_hd_out = NULL;
1191 1192
}

1193
int ff_rtsp_connect(AVFormatContext *s)
1194 1195
{
    RTSPState *rt = s->priv_data;
1196 1197
    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
    char *option_list, *option, *filename;
1198
    int port, err, tcp_fd;
1199
    RTSPMessageHeader reply1 = {0}, *reply = &reply1;
1200
    int lower_transport_mask = 0;
1201
    char real_challenge[64];
1202 1203
    struct sockaddr_storage peer;
    socklen_t peer_len = sizeof(peer);
1204 1205 1206

    if (!ff_network_init())
        return AVERROR(EIO);
1207
redirect:
J
Josh Allmann 已提交
1208
    rt->control_transport = RTSP_MODE_PLAIN;
1209
    /* extract hostname and port */
M
Måns Rullgård 已提交
1210
    av_url_split(NULL, 0, auth, sizeof(auth),
M
Martin Storsjö 已提交
1211
                 host, sizeof(host), &port, path, sizeof(path), s->filename);
1212
    if (*auth) {
1213
        av_strlcpy(rt->auth, auth, sizeof(rt->auth));
1214
    }
1215 1216 1217 1218
    if (port < 0)
        port = RTSP_DEFAULT_PORT;

    /* search for options */
1219
    option_list = strrchr(path, '?');
1220
    if (option_list) {
1221 1222 1223
        /* Strip out the RTSP specific options, write out the rest of
         * the options back into the same string. */
        filename = option_list;
1224
        while (option_list) {
1225
            /* move the option pointer */
1226
            option = ++option_list;
1227 1228
            option_list = strchr(option_list, '&');
            if (option_list)
1229 1230
                *option_list = 0;

1231
            /* handle the options */
1232
            if (!strcmp(option, "udp")) {
1233
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
1234
            } else if (!strcmp(option, "multicast")) {
1235
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1236
            } else if (!strcmp(option, "tcp")) {
1237
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
J
Josh Allmann 已提交
1238 1239 1240
            } else if(!strcmp(option, "http")) {
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
                rt->control_transport = RTSP_MODE_TUNNEL;
1241
            } else {
1242 1243 1244 1245 1246
                /* 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;
1247 1248
                if (option_list) *filename = '&';
            }
1249
        }
1250
        *filename = 0;
1251 1252
    }

1253
    if (!lower_transport_mask)
1254
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1255

1256
    if (s->oformat) {
1257 1258 1259
        /* 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 已提交
1260
        if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
1261
            av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
1262
                                    "only UDP and TCP are supported for output.\n");
1263 1264 1265 1266 1267
            err = AVERROR(EINVAL);
            goto fail;
        }
    }

1268 1269 1270 1271 1272 1273
    /* 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 已提交
1274 1275 1276 1277 1278 1279
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        /* set up initial handshake for tunneling */
        char httpname[1024];
        char sessioncookie[17];
        char headers[1024];

1280
        ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
J
Josh Allmann 已提交
1281 1282 1283 1284
        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());

        /* GET requests */
1285
        if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) {
J
Josh Allmann 已提交
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
            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);
1297
        ff_http_set_headers(rt->rtsp_hd, headers);
J
Josh Allmann 已提交
1298 1299

        /* complete the connection */
1300
        if (url_connect(rt->rtsp_hd)) {
J
Josh Allmann 已提交
1301 1302 1303 1304 1305
            err = AVERROR(EIO);
            goto fail;
        }

        /* POST requests */
1306
        if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) {
J
Josh Allmann 已提交
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
            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);
1320 1321
        ff_http_set_headers(rt->rtsp_hd_out, headers);
        ff_http_set_chunked_transfer_encoding(rt->rtsp_hd_out, 0);
J
Josh Allmann 已提交
1322

1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
        /* Initialize the authentication state for the POST session. The HTTP
         * protocol implementation doesn't properly handle multi-pass
         * authentication for POST requests, since it would require one of
         * the following:
         * - implementing Expect: 100-continue, which many HTTP servers
         *   don't support anyway, even less the RTSP servers that do HTTP
         *   tunneling
         * - sending the whole POST data until getting a 401 reply specifying
         *   what authentication method to use, then resending all that data
         * - waiting for potential 401 replies directly after sending the
         *   POST header (waiting for some unspecified time)
         * Therefore, we copy the full auth state, which works for both basic
         * and digest. (For digest, we would have to synchronize the nonce
         * count variable between the two sessions, if we'd do more requests
         * with the original session, though.)
         */
        ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd);

1341 1342 1343 1344 1345
        /* complete the connection */
        if (url_connect(rt->rtsp_hd_out)) {
            err = AVERROR(EIO);
            goto fail;
        }
J
Josh Allmann 已提交
1346
    } else {
1347
        /* open the tcp connection */
J
Josh Allmann 已提交
1348
        ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1349
        if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) {
J
Josh Allmann 已提交
1350 1351 1352
            err = AVERROR(EIO);
            goto fail;
        }
1353
        rt->rtsp_hd_out = rt->rtsp_hd;
J
Josh Allmann 已提交
1354
    }
1355 1356
    rt->seq = 0;

1357
    tcp_fd = url_get_file_handle(rt->rtsp_hd);
1358 1359 1360 1361 1362
    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
    }

1363 1364
    /* request options supported by the server; this also detects server
     * type */
1365
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1366
        cmd[0] = 0;
1367
        if (rt->server_type == RTSP_SERVER_REAL)
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
            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));
1383
        ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
1384 1385 1386 1387 1388 1389
        if (reply->status_code != RTSP_STATUS_OK) {
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* detect server type if not standard-compliant RTP */
1390 1391
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
            rt->server_type = RTSP_SERVER_REAL;
1392
            continue;
1393 1394
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
            rt->server_type = RTSP_SERVER_WMS;
1395
        } else if (rt->server_type == RTSP_SERVER_REAL)
1396 1397 1398 1399
            strcpy(real_challenge, reply->real_challenge);
        break;
    }

1400
    if (s->iformat && CONFIG_RTSP_DEMUXER)
1401
        err = ff_rtsp_setup_input_streams(s, reply);
1402
    else if (CONFIG_RTSP_MUXER)
1403
        err = ff_rtsp_setup_output_streams(s, host);
1404
    if (err)
1405 1406
        goto fail;

1407
    do {
1408 1409
        int lower_transport = ff_log2_tab[lower_transport_mask &
                                  ~(lower_transport_mask - 1)];
1410

1411
        err = make_setup_request(s, host, port, lower_transport,
1412
                                 rt->server_type == RTSP_SERVER_REAL ?
1413
                                     real_challenge : NULL);
1414
        if (err < 0)
1415
            goto fail;
1416 1417
        lower_transport_mask &= ~(1 << lower_transport);
        if (lower_transport_mask == 0 && err == 1) {
1418
            err = FF_NETERROR(EPROTONOSUPPORT);
1419 1420 1421
            goto fail;
        }
    } while (err);
1422

1423
    rt->state = RTSP_STATE_IDLE;
1424
    rt->seek_timestamp = 0; /* default is to start stream at position zero */
1425 1426
    return 0;
 fail:
1427
    ff_rtsp_close_streams(s);
1428
    ff_rtsp_close_connections(s);
1429
    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
L
Luca Barbato 已提交
1430 1431 1432 1433 1434 1435
        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;
    }
1436
    ff_network_close();
1437 1438
    return err;
}
1439
#endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */
1440

1441
#if CONFIG_RTPDEC
R
Ronald S. Bultje 已提交
1442
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1443
                           uint8_t *buf, int buf_size, int64_t wait_end)
R
Ronald S. Bultje 已提交
1444 1445 1446 1447
{
    RTSPState *rt = s->priv_data;
    RTSPStream *rtsp_st;
    fd_set rfds;
1448
    int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
R
Ronald S. Bultje 已提交
1449 1450
    struct timeval tv;

1451
    for (;;) {
R
Ronald S. Bultje 已提交
1452 1453
        if (url_interrupt_cb())
            return AVERROR(EINTR);
1454 1455
        if (wait_end && wait_end - av_gettime() < 0)
            return AVERROR(EAGAIN);
R
Ronald S. Bultje 已提交
1456 1457 1458 1459 1460 1461 1462 1463
        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;
        }
1464
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1465 1466 1467
            rtsp_st = rt->rtsp_streams[i];
            if (rtsp_st->rtp_handle) {
                fd = url_get_file_handle(rtsp_st->rtp_handle);
1468 1469 1470
                fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
                if (FFMAX(fd, fd_rtcp) > fd_max)
                    fd_max = FFMAX(fd, fd_rtcp);
R
Ronald S. Bultje 已提交
1471
                FD_SET(fd, &rfds);
1472
                FD_SET(fd_rtcp, &rfds);
R
Ronald S. Bultje 已提交
1473 1474 1475
            }
        }
        tv.tv_sec = 0;
1476
        tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
R
Ronald S. Bultje 已提交
1477 1478
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
        if (n > 0) {
1479
            timeout_cnt = 0;
1480
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1481 1482 1483
                rtsp_st = rt->rtsp_streams[i];
                if (rtsp_st->rtp_handle) {
                    fd = url_get_file_handle(rtsp_st->rtp_handle);
1484 1485
                    fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
                    if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) {
R
Ronald S. Bultje 已提交
1486 1487 1488 1489 1490 1491 1492 1493
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
                        if (ret > 0) {
                            *prtsp_st = rtsp_st;
                            return ret;
                        }
                    }
                }
            }
1494
#if CONFIG_RTSP_DEMUXER
1495
            if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
R
Ronald S. Bultje 已提交
1496 1497
                RTSPMessageHeader reply;

1498 1499 1500
                ret = ff_rtsp_read_reply(s, &reply, NULL, 0);
                if (ret < 0)
                    return ret;
R
Ronald S. Bultje 已提交
1501
                /* XXX: parse message */
1502
                if (rt->state != RTSP_STATE_STREAMING)
R
Ronald S. Bultje 已提交
1503 1504
                    return 0;
            }
1505
#endif
1506
        } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
1507
            return FF_NETERROR(ETIMEDOUT);
1508 1509
        } else if (n < 0 && errno != EINTR)
            return AVERROR(errno);
R
Ronald S. Bultje 已提交
1510 1511 1512
    }
}

1513
int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
R
Ronald S. Bultje 已提交
1514 1515 1516
{
    RTSPState *rt = s->priv_data;
    int ret, len;
1517 1518
    RTSPStream *rtsp_st, *first_queue_st = NULL;
    int64_t wait_end = 0;
R
Ronald S. Bultje 已提交
1519

1520 1521 1522
    if (rt->nb_byes == rt->nb_rtsp_streams)
        return AVERROR_EOF;

R
Ronald S. Bultje 已提交
1523 1524
    /* get next frames from the same RTP packet */
    if (rt->cur_transport_priv) {
1525
        if (rt->transport == RTSP_TRANSPORT_RDT) {
R
Ronald S. Bultje 已提交
1526
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1527
        } else
R
Ronald S. Bultje 已提交
1528 1529 1530 1531 1532 1533
            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;
1534
        } else
R
Ronald S. Bultje 已提交
1535 1536 1537
            rt->cur_transport_priv = NULL;
    }

1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
    if (rt->transport == RTSP_TRANSPORT_RTP) {
        int i;
        int64_t first_queue_time = 0;
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
            RTPDemuxContext *rtpctx = rt->rtsp_streams[i]->transport_priv;
            int64_t queue_time = ff_rtp_queued_packet_time(rtpctx);
            if (queue_time && (queue_time - first_queue_time < 0 ||
                               !first_queue_time)) {
                first_queue_time = queue_time;
                first_queue_st   = rt->rtsp_streams[i];
            }
        }
        if (first_queue_time)
            wait_end = first_queue_time + s->max_delay;
    }

R
Ronald S. Bultje 已提交
1554 1555
    /* read next RTP packet */
 redo:
1556 1557 1558 1559 1560 1561
    if (!rt->recvbuf) {
        rt->recvbuf = av_malloc(RECVBUF_SIZE);
        if (!rt->recvbuf)
            return AVERROR(ENOMEM);
    }

R
Ronald S. Bultje 已提交
1562 1563
    switch(rt->lower_transport) {
    default:
1564
#if CONFIG_RTSP_DEMUXER
R
Ronald S. Bultje 已提交
1565
    case RTSP_LOWER_TRANSPORT_TCP:
1566
        len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE);
R
Ronald S. Bultje 已提交
1567
        break;
1568
#endif
R
Ronald S. Bultje 已提交
1569 1570
    case RTSP_LOWER_TRANSPORT_UDP:
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1571
        len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end);
R
Ronald S. Bultje 已提交
1572 1573 1574 1575
        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
        break;
    }
1576 1577 1578 1579 1580 1581
    if (len == AVERROR(EAGAIN) && first_queue_st &&
        rt->transport == RTSP_TRANSPORT_RTP) {
        rtsp_st = first_queue_st;
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0);
        goto end;
    }
R
Ronald S. Bultje 已提交
1582 1583 1584 1585
    if (len < 0)
        return len;
    if (len == 0)
        return AVERROR_EOF;
1586
    if (rt->transport == RTSP_TRANSPORT_RDT) {
1587
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1588
    } else {
1589
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600
        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++) {
1601
                    RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_priv;
1602 1603 1604 1605 1606
                    if (rtpctx2 &&
                        rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE)
                        rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
                }
            }
1607 1608 1609 1610 1611 1612 1613 1614 1615
            if (ret == -RTCP_BYE) {
                rt->nb_byes++;

                av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n",
                       rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams);

                if (rt->nb_byes == rt->nb_rtsp_streams)
                    return AVERROR_EOF;
            }
1616 1617
        }
    }
1618
end:
R
Ronald S. Bultje 已提交
1619 1620
    if (ret < 0)
        goto redo;
1621
    if (ret == 1)
R
Ronald S. Bultje 已提交
1622 1623 1624 1625 1626
        /* more packets may follow, so we save the RTP context */
        rt->cur_transport_priv = rtsp_st->transport_priv;

    return ret;
}
1627
#endif /* CONFIG_RTPDEC */
R
Ronald S. Bultje 已提交
1628

1629
#if CONFIG_SDP_DEMUXER
1630
static int sdp_probe(AVProbeData *p1)
1631
{
1632
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1633

M
Martin Storsjö 已提交
1634
    /* we look for a line beginning "c=IN IP" */
1635
    while (p < p_end && *p != '\0') {
M
Martin Storsjö 已提交
1636 1637
        if (p + sizeof("c=IN IP") - 1 < p_end &&
            av_strstart(p, "c=IN IP", NULL))
1638
            return AVPROBE_SCORE_MAX / 2;
1639

1640
        while (p < p_end - 1 && *p != '\n') p++;
1641
        if (++p >= p_end)
1642 1643 1644 1645
            break;
        if (*p == '\r')
            p++;
    }
1646 1647 1648
    return 0;
}

1649
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1650
{
1651
    RTSPState *rt = s->priv_data;
1652 1653 1654 1655 1656
    RTSPStream *rtsp_st;
    int size, i, err;
    char *content;
    char url[1024];

1657 1658 1659
    if (!ff_network_init())
        return AVERROR(EIO);

1660 1661 1662
    /* read the whole sdp file */
    /* XXX: better loading */
    content = av_malloc(SDP_MAX_SIZE);
1663
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1664 1665 1666 1667 1668 1669
    if (size <= 0) {
        av_free(content);
        return AVERROR_INVALIDDATA;
    }
    content[size] ='\0';

1670
    ff_sdp_parse(s, content);
1671 1672 1673
    av_free(content);

    /* open each RTP stream */
1674
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
M
Martin Storsjö 已提交
1675
        char namebuf[50];
1676
        rtsp_st = rt->rtsp_streams[i];
1677

M
Martin Storsjö 已提交
1678 1679
        getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
                    namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
1680
        ff_url_join(url, sizeof(url), "rtp", NULL,
M
Martin Storsjö 已提交
1681
                    namebuf, rtsp_st->sdp_port,
1682 1683
                    "?localport=%d&ttl=%d", rtsp_st->sdp_port,
                    rtsp_st->sdp_ttl);
1684
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1685 1686 1687
            err = AVERROR_INVALIDDATA;
            goto fail;
        }
1688
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1689
            goto fail;
1690 1691
    }
    return 0;
1692
fail:
1693
    ff_rtsp_close_streams(s);
1694
    ff_network_close();
1695 1696 1697 1698 1699
    return err;
}

static int sdp_read_close(AVFormatContext *s)
{
1700
    ff_rtsp_close_streams(s);
1701
    ff_network_close();
1702 1703 1704
    return 0;
}

1705
AVInputFormat sdp_demuxer = {
1706
    "sdp",
1707
    NULL_IF_CONFIG_SMALL("SDP"),
1708 1709 1710
    sizeof(RTSPState),
    sdp_probe,
    sdp_read_header,
1711
    ff_rtsp_fetch_packet,
1712 1713
    sdp_read_close,
};
1714
#endif /* CONFIG_SDP_DEMUXER */
1715

1716
#if CONFIG_RTP_DEMUXER
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
static int rtp_probe(AVProbeData *p)
{
    if (av_strstart(p->filename, "rtp:", NULL))
        return AVPROBE_SCORE_MAX;
    return 0;
}

static int rtp_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
    uint8_t recvbuf[1500];
    char host[500], sdp[500];
    int ret, port;
    URLContext* in = NULL;
    int payload_type;
    AVCodecContext codec;
    struct sockaddr_storage addr;
    ByteIOContext pb;
    socklen_t addrlen = sizeof(addr);

    if (!ff_network_init())
        return AVERROR(EIO);

    ret = url_open(&in, s->filename, URL_RDONLY);
    if (ret)
        goto fail;

    while (1) {
        ret = url_read(in, recvbuf, sizeof(recvbuf));
        if (ret == AVERROR(EAGAIN))
            continue;
        if (ret < 0)
            goto fail;
        if (ret < 12) {
            av_log(s, AV_LOG_WARNING, "Received too short packet\n");
            continue;
        }

        if ((recvbuf[0] & 0xc0) != 0x80) {
            av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
                                      "received\n");
            continue;
        }

        payload_type = recvbuf[1] & 0x7f;
        break;
    }
    getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
    url_close(in);
    in = NULL;

    memset(&codec, 0, sizeof(codec));
    if (ff_rtp_get_codec_info(&codec, payload_type)) {
        av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
                                "without an SDP file describing it\n",
                                 payload_type);
        goto fail;
    }
    if (codec.codec_type != AVMEDIA_TYPE_DATA) {
        av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
                                  "properly you need an SDP file "
                                  "describing it\n");
    }

    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
                 NULL, 0, s->filename);

    snprintf(sdp, sizeof(sdp),
             "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
             addr.ss_family == AF_INET ? 4 : 6, host,
             codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" :
             codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
             port, payload_type);
    av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);

    init_put_byte(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
    s->pb = &pb;

    /* sdp_read_header initializes this again */
    ff_network_close();

    ret = sdp_read_header(s, ap);
    s->pb = NULL;
    return ret;

fail:
    if (in)
        url_close(in);
    ff_network_close();
    return ret;
}

AVInputFormat rtp_demuxer = {
    "rtp",
    NULL_IF_CONFIG_SMALL("RTP input format"),
    sizeof(RTSPState),
    rtp_probe,
    rtp_read_header,
1815
    ff_rtsp_fetch_packet,
1816 1817 1818
    sdp_read_close,
    .flags = AVFMT_NOFILE,
};
1819
#endif /* CONFIG_RTP_DEMUXER */
1820