rtsp.c 64.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
static int sdp_parse_rtpmap(AVFormatContext *s,
138
                            AVStream *st, RTSPStream *rtsp_st,
139
                            int payload_type, const char *p)
140
{
141
    AVCodecContext *codec = st->codec;
142
    char buf[256];
R
Romain Degez 已提交
143 144
    int i;
    AVCodec *c;
145
    const char *c_name;
146

R
Romain Degez 已提交
147
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
148 149 150 151 152
     * 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 已提交
153
    if (payload_type >= RTP_PT_PRIVATE) {
154 155 156
        RTPDynamicProtocolHandler *handler =
            ff_rtp_handler_find_by_name(buf, codec->codec_type);
        init_rtp_handler(handler, rtsp_st, codec);
157 158 159 160 161 162
        /* 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);
163
    } else {
164 165
        /* We are in a standard case
         * (from http://www.iana.org/assignments/rtp-parameters). */
R
Romain Degez 已提交
166
        /* search into AVRtpPayloadTypes[] */
167
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
R
Romain Degez 已提交
168 169 170 171
    }

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

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

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

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

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

250
    dprintf(s, "sdp: %c='%s'\n", letter, buf);
251 252

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

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

319 320 321 322
        /* XXX: handle list of formats */
        get_word(buf1, sizeof(buf1), &p); /* format list */
        rtsp_st->sdp_payload_type = atoi(buf1);

323
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
324 325 326 327 328 329 330
            /* no corresponding stream */
        } else {
            st = av_new_stream(s, 0);
            if (!st)
                return;
            st->priv_data = rtsp_st;
            rtsp_st->stream_index = st->index;
331
            st->codec->codec_type = codec_type;
R
Romain Degez 已提交
332
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
333
                RTPDynamicProtocolHandler *handler;
334
                /* if standard payload type, we can find the codec right now */
335
                ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
336 337
                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
                    st->codec->sample_rate > 0)
338
                    av_set_pts_info(st, 32, 1, st->codec->sample_rate);
339 340 341 342
                /* Even static payload types may need a custom depacketizer */
                handler = ff_rtp_handler_find_by_id(
                              rtsp_st->sdp_payload_type, st->codec->codec_type);
                init_rtp_handler(handler, rtsp_st, st->codec);
343 344
            }
        }
345
        /* put a default control url */
346
        av_strlcpy(rtsp_st->control_url, rt->control_uri,
347
                   sizeof(rtsp_st->control_url));
348 349
        break;
    case 'a':
350 351 352 353 354 355
        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ö 已提交
356 357 358 359
                char proto[32];
                /* get the control url */
                st = s->streams[s->nb_streams - 1];
                rtsp_st = st->priv_data;
360

M
Martin Storsjö 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373
                /* 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));
374
            }
375
        } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
376
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
377
            get_word(buf1, sizeof(buf1), &p);
378
            payload_type = atoi(buf1);
379
            st = s->streams[s->nb_streams - 1];
R
Ronald S. Bultje 已提交
380
            rtsp_st = st->priv_data;
381
            sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
382 383
        } else if (av_strstart(p, "fmtp:", &p) ||
                   av_strstart(p, "framesize:", &p)) {
384
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
385 386 387
            // let dynamic protocol handlers have a stab at the line.
            get_word(buf1, sizeof(buf1), &p);
            payload_type = atoi(buf1);
388 389
            for (i = 0; i < s->nb_streams; i++) {
                st      = s->streams[i];
390
                rtsp_st = st->priv_data;
391 392 393 394 395
                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);
396
            }
397
        } else if (av_strstart(p, "range:", &p)) {
398 399 400 401
            int64_t start, end;

            // this is so that seeking on a streamed file can work.
            rtsp_parse_range_npt(p, &start, &end);
402 403 404 405
            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;
406 407 408
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
            if (atoi(p) == 1)
                rt->transport = RTSP_TRANSPORT_RDT;
409 410 411 412
        } else if (av_strstart(p, "SampleRate:integer;", &p) &&
                   s->nb_streams > 0) {
            st = s->streams[s->nb_streams - 1];
            st->codec->sample_rate = atoi(p);
413 414 415 416
        } 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 已提交
417 418 419 420 421 422
                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)
423 424
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
                        s->nb_streams - 1,
R
Ronald S. Bultje 已提交
425
                        rtsp_st->dynamic_protocol_context, buf);
426
            }
427 428 429 430 431
        }
        break;
    }
}

432
int ff_sdp_parse(AVFormatContext *s, const char *content)
433 434 435
{
    const char *p;
    int letter;
436 437 438 439
    /* 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
440 441
     * buffer is large.
     *
442 443
     * The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line
     * in rtpdec_xiph.c. */
444
    char buf[16384], *q;
445
    SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
446

447
    memset(s1, 0, sizeof(SDPParseState));
448
    p = content;
449
    for (;;) {
450
        p += strspn(p, SPACE_CHARS);
451 452 453 454 455 456 457 458 459
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
F
Fabrice Bellard 已提交
460
        while (*p != '\n' && *p != '\r' && *p != '\0') {
461 462 463 464 465
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
466
        sdp_parse_line(s, s1, letter, buf);
467 468 469 470 471 472 473 474
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
    }
    return 0;
}
475
#endif /* CONFIG_RTPDEC */
476

477
/* close and free RTSP streams */
478
void ff_rtsp_close_streams(AVFormatContext *s)
479
{
480
    RTSPState *rt = s->priv_data;
481 482 483
    int i;
    RTSPStream *rtsp_st;

484
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
485 486 487
        rtsp_st = rt->rtsp_streams[i];
        if (rtsp_st) {
            if (rtsp_st->transport_priv) {
488 489 490
                if (s->oformat) {
                    AVFormatContext *rtpctx = rtsp_st->transport_priv;
                    av_write_trailer(rtpctx);
491 492 493 494 495
                    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ö 已提交
496
                        url_fclose(rtpctx->pb);
497
                    }
498 499
                    av_metadata_free(&rtpctx->streams[0]->metadata);
                    av_metadata_free(&rtpctx->metadata);
500 501
                    av_free(rtpctx->streams[0]);
                    av_free(rtpctx);
502
                } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
503
                    ff_rdt_parse_close(rtsp_st->transport_priv);
504
                else if (CONFIG_RTPDEC)
505 506 507 508 509
                    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)
510 511
                rtsp_st->dynamic_handler->close(
                    rtsp_st->dynamic_protocol_context);
512 513 514 515 516 517 518
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
        av_close_input_stream (rt->asf_ctx);
        rt->asf_ctx = NULL;
    }
519
    av_free(rt->recvbuf);
520 521
}

522
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
523 524 525 526 527 528 529 530 531 532
{
    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;

533
    if (s->oformat && CONFIG_RTSP_MUXER) {
534 535 536
        rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
                                      rtsp_st->rtp_handle,
                                      RTSP_TCP_MAX_PACKET_SIZE);
R
Reimar Döffinger 已提交
537
        /* Ownership of rtp_handle is passed to the rtp mux context */
538
        rtsp_st->rtp_handle = NULL;
539
    } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
540 541 542
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
543
    else if (CONFIG_RTPDEC)
544
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
545 546 547
                                         rtsp_st->sdp_payload_type,
            (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
            ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
548 549 550

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
551
    } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
552
        if (rtsp_st->dynamic_handler) {
553 554 555 556 557 558 559 560 561
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                           rtsp_st->dynamic_protocol_context,
                                           rtsp_st->dynamic_handler);
        }
    }

    return 0;
}

M
Martin Storsjö 已提交
562
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
563 564 565 566 567 568
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
    const char *p;
    int v;

    p = *pp;
569
    p += strspn(p, SPACE_CHARS);
570 571 572 573 574 575 576 577 578 579 580 581 582 583
    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 */
584
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
585 586 587 588 589 590 591
{
    char transport_protocol[16];
    char profile[16];
    char lower_transport[16];
    char parameter[16];
    RTSPTransportField *th;
    char buf[256];
592

593
    reply->nb_transports = 0;
594

595
    for (;;) {
596
        p += strspn(p, SPACE_CHARS);
597 598 599 600 601
        if (*p == '\0')
            break;

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

602
        get_word_sep(transport_protocol, sizeof(transport_protocol),
603
                     "/", &p);
604
        if (!strcasecmp (transport_protocol, "rtp")) {
605 606 607 608 609 610
            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);
611 612 613 614
            }
            th->transport = RTSP_TRANSPORT_RTP;
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
615
            /* x-pn-tng/<protocol> */
616 617
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
            profile[0] = '\0';
618
            th->transport = RTSP_TRANSPORT_RDT;
619
        }
F
Fabrice Bellard 已提交
620
        if (!strcasecmp(lower_transport, "TCP"))
621
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
622
        else
623
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
624

625 626 627 628 629 630 631 632 633 634 635 636 637
        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++;
638
                    rtsp_parse_range(&th->client_port_min,
639 640 641 642 643
                                     &th->client_port_max, &p);
                }
            } else if (!strcmp(parameter, "server_port")) {
                if (*p == '=') {
                    p++;
644
                    rtsp_parse_range(&th->server_port_min,
645 646 647 648 649
                                     &th->server_port_max, &p);
                }
            } else if (!strcmp(parameter, "interleaved")) {
                if (*p == '=') {
                    p++;
650
                    rtsp_parse_range(&th->interleaved_min,
651 652 653
                                     &th->interleaved_max, &p);
                }
            } else if (!strcmp(parameter, "multicast")) {
654 655
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
656 657 658 659 660 661 662 663 664
            } 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ö 已提交
665
                    get_sockaddr(buf, &th->destination);
666
                }
667 668 669 670 671 672
            } else if (!strcmp(parameter, "source")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
                    av_strlcpy(th->source, buf, sizeof(th->source));
                }
673
            }
674

675 676 677 678 679 680 681 682 683 684 685 686
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

687 688
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
                        HTTPAuthState *auth_state)
689 690 691 692 693
{
    const char *p;

    /* NOTE: we do case independent match for broken servers */
    p = buf;
694
    if (av_stristart(p, "Session:", &p)) {
695
        int t;
696
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
697 698 699 700
        if (av_stristart(p, ";timeout=", &p) &&
            (t = strtol(p, NULL, 10)) > 0) {
            reply->timeout = t;
        }
701
    } else if (av_stristart(p, "Content-Length:", &p)) {
702
        reply->content_length = strtol(p, NULL, 10);
703
    } else if (av_stristart(p, "Transport:", &p)) {
704
        rtsp_parse_transport(reply, p);
705
    } else if (av_stristart(p, "CSeq:", &p)) {
706
        reply->seq = strtol(p, NULL, 10);
707
    } else if (av_stristart(p, "Range:", &p)) {
708
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
709
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
710
        p += strspn(p, SPACE_CHARS);
711
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
712
    } else if (av_stristart(p, "Server:", &p)) {
713
        p += strspn(p, SPACE_CHARS);
714
        av_strlcpy(reply->server, p, sizeof(reply->server));
715 716 717
    } else if (av_stristart(p, "Notice:", &p) ||
               av_stristart(p, "X-Notice:", &p)) {
        reply->notice = strtol(p, NULL, 10);
L
Luca Barbato 已提交
718
    } else if (av_stristart(p, "Location:", &p)) {
719
        p += strspn(p, SPACE_CHARS);
L
Luca Barbato 已提交
720
        av_strlcpy(reply->location, p , sizeof(reply->location));
721
    } else if (av_stristart(p, "WWW-Authenticate:", &p) && auth_state) {
722
        p += strspn(p, SPACE_CHARS);
723 724
        ff_http_auth_handle_header(auth_state, "WWW-Authenticate", p);
    } else if (av_stristart(p, "Authentication-Info:", &p) && auth_state) {
725
        p += strspn(p, SPACE_CHARS);
726
        ff_http_auth_handle_header(auth_state, "Authentication-Info", p);
727 728 729
    } else if (av_stristart(p, "Content-Base:", &p)) {
        p += strspn(p, SPACE_CHARS);
        av_strlcpy(reply->content_base, p , sizeof(reply->content_base));
730 731 732
    }
}

733
/* skip a RTP/TCP interleaved packet */
734
void ff_rtsp_skip_packet(AVFormatContext *s)
735 736 737 738 739
{
    RTSPState *rt = s->priv_data;
    int ret, len, len1;
    uint8_t buf[1024];

740
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
741 742
    if (ret != 3)
        return;
743
    len = AV_RB16(buf + 1);
744 745 746

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

747 748 749 750 751
    /* skip payload */
    while (len > 0) {
        len1 = len;
        if (len1 > sizeof(buf))
            len1 = sizeof(buf);
752
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
753 754 755 756 757
        if (ret != len1)
            return;
        len -= len1;
    }
}
758

759
int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
M
Martin Storsjö 已提交
760 761
                       unsigned char **content_ptr,
                       int return_on_interleaved_data)
762 763 764 765 766
{
    RTSPState *rt = s->priv_data;
    char buf[4096], buf1[1024], *q;
    unsigned char ch;
    const char *p;
767
    int ret, content_length, line_count = 0;
768 769
    unsigned char *content = NULL;

770
    memset(reply, 0, sizeof(*reply));
771 772 773

    /* parse reply (XXX: use buffers) */
    rt->last_reply[0] = '\0';
774
    for (;;) {
775
        q = buf;
776
        for (;;) {
777
            ret = url_read_complete(rt->rtsp_hd, &ch, 1);
778
#ifdef DEBUG_RTP_TCP
779
            dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
780 781
#endif
            if (ret != 1)
782
                return AVERROR_EOF;
783 784
            if (ch == '\n')
                break;
785 786
            if (ch == '$') {
                /* XXX: only parse it if first char on line ? */
787 788 789
                if (return_on_interleaved_data) {
                    return 1;
                } else
790
                    ff_rtsp_skip_packet(s);
791
            } else if (ch != '\r') {
792 793 794 795 796
                if ((q - buf) < sizeof(buf) - 1)
                    *q++ = ch;
            }
        }
        *q = '\0';
797 798 799

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

800 801 802 803 804 805 806 807 808
        /* 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 已提交
809
            av_strlcpy(reply->reason, p, sizeof(reply->reason));
810
        } else {
811
            ff_rtsp_parse_line(reply, p, &rt->auth_state);
M
Måns Rullgård 已提交
812 813
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
814 815 816
        }
        line_count++;
    }
817

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

821 822 823 824
    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);
825
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
826 827 828 829
        content[content_length] = '\0';
    }
    if (content_ptr)
        *content_ptr = content;
830 831
    else
        av_free(content);
832

833 834 835 836 837
    if (rt->seq != reply->seq) {
        av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
            rt->seq, reply->seq);
    }

838 839 840
    /* EOS */
    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
        reply->notice == 2104 /* Start-of-Stream Reached */    ||
841
        reply->notice == 2306 /* Continuous Feed Terminated */) {
842
        rt->state = RTSP_STATE_IDLE;
843
    } else if (reply->notice >= 4400 && reply->notice < 5500) {
844
        return AVERROR(EIO); /* data or server error */
845
    } else if (reply->notice == 2401 /* Ticket Expired */ ||
846 847 848
             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
        return AVERROR(EPERM);

849
    return 0;
850 851
}

852
int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
M
Martin Storsjö 已提交
853 854 855 856
                                        const char *method, const char *url,
                                        const char *headers,
                                        const unsigned char *send_content,
                                        int send_content_length)
857 858
{
    RTSPState *rt = s->priv_data;
J
Josh Allmann 已提交
859 860
    char buf[4096], *out_buf;
    char base64buf[AV_BASE64_SIZE(sizeof(buf))];
861

J
Josh Allmann 已提交
862 863
    /* Add in RTSP headers */
    out_buf = buf;
864
    rt->seq++;
865 866 867
    snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
    if (headers)
        av_strlcat(buf, headers, sizeof(buf));
868
    av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
869 870
    if (rt->session_id[0] != '\0' && (!headers ||
        !strstr(headers, "\nIf-Match:"))) {
871
        av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
872
    }
873 874 875 876 877 878 879
    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);
    }
880 881
    if (send_content_length > 0 && send_content)
        av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
882
    av_strlcat(buf, "\r\n", sizeof(buf));
883

J
Josh Allmann 已提交
884 885 886 887 888 889
    /* base64 encode rtsp if tunneling */
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
        out_buf = base64buf;
    }

890 891
    dprintf(s, "Sending:\n%s--\n", buf);

J
Josh Allmann 已提交
892 893 894 895 896 897 898
    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;
        }
899
        url_write(rt->rtsp_hd_out, send_content, send_content_length);
J
Josh Allmann 已提交
900
    }
901
    rt->last_cmd_time = av_gettime();
902 903

    return 0;
904 905
}

906
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
M
Martin Storsjö 已提交
907
                           const char *url, const char *headers)
908
{
909
    return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
910 911
}

912
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
M
Martin Storsjö 已提交
913 914
                     const char *headers, RTSPMessageHeader *reply,
                     unsigned char **content_ptr)
915
{
916
    return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
M
Martin Storsjö 已提交
917
                                         content_ptr, NULL, 0);
918 919
}

920
int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
M
Martin Storsjö 已提交
921 922 923 924 925 926
                                  const char *method, const char *url,
                                  const char *header,
                                  RTSPMessageHeader *reply,
                                  unsigned char **content_ptr,
                                  const unsigned char *send_content,
                                  int send_content_length)
927
{
928 929
    RTSPState *rt = s->priv_data;
    HTTPAuthType cur_auth_type;
930
    int ret;
931 932 933

retry:
    cur_auth_type = rt->auth_state.auth_type;
934
    if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
M
Martin Storsjö 已提交
935 936
                                                   send_content,
                                                   send_content_length)))
937
        return ret;
938

939 940
    if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0) ) < 0)
        return ret;
941 942 943 944

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

946
    if (reply->status_code > 400){
L
Luca Barbato 已提交
947
        av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
948
               method,
L
Luca Barbato 已提交
949 950
               reply->status_code,
               reply->reason);
951 952 953
        av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
    }

954
    return 0;
955 956
}

957
/**
B
Benoit Fouet 已提交
958
 * @return 0 on success, <0 on error, 1 if protocol is unavailable.
959
 */
960 961
static int make_setup_request(AVFormatContext *s, const char *host, int port,
                              int lower_transport, const char *real_challenge)
962 963
{
    RTSPState *rt = s->priv_data;
964
    int rtx, j, i, err, interleave = 0;
965
    RTSPStream *rtsp_st;
966
    RTSPMessageHeader reply1, *reply = &reply1;
967
    char cmd[2048];
968 969
    const char *trans_pref;

970
    if (rt->transport == RTSP_TRANSPORT_RDT)
971 972 973
        trans_pref = "x-pn-tng";
    else
        trans_pref = "RTP/AVP";
974

975 976 977
    /* default timeout: 1 minute */
    rt->timeout = 60;

978 979
    /* for each stream, make the setup request */
    /* XXX: we assume the same server is used for the control of each
980
     * RTSP stream */
R
Romain Degez 已提交
981

982
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
983 984
        char transport[2048];

985 986 987 988 989 990 991 992 993 994 995 996
        /**
         * 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 &&
997 998
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
                                "/rtx"))
999 1000 1001 1002 1003 1004 1005 1006
                        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 已提交
1007
            rtsp_st = rt->rtsp_streams[i];
1008 1009

        /* RTP/UDP */
1010
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
F
Fabrice Bellard 已提交
1011 1012
            char buf[256];

1013 1014 1015 1016 1017
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
                port = reply->transports[0].client_port_min;
                goto have_port;
            }

F
Fabrice Bellard 已提交
1018
            /* first try in specified port range */
R
Romain Degez 已提交
1019
            if (RTSP_RTP_PORT_MIN != 0) {
1020
                while (j <= RTSP_RTP_PORT_MAX) {
1021 1022
                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
                                "?localport=%d", j);
1023 1024 1025
                    /* 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 已提交
1026 1027
                        goto rtp_opened;
                }
1028
            }
F
Fabrice Bellard 已提交
1029

1030 1031 1032 1033 1034 1035 1036
#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 已提交
1037 1038

        rtp_opened:
1039
            port = rtp_get_local_rtp_port(rtsp_st->rtp_handle);
1040
        have_port:
1041
            snprintf(transport, sizeof(transport) - 1,
1042 1043 1044 1045 1046
                     "%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);
1047 1048
            if (rt->transport == RTSP_TRANSPORT_RTP &&
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
1049
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1050 1051 1052
        }

        /* RTP/TCP */
1053
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1054 1055 1056 1057
            /** 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 &&
1058
                s->streams[rtsp_st->stream_index]->codec->codec_type ==
1059
                    AVMEDIA_TYPE_DATA)
1060
                continue;
1061
            snprintf(transport, sizeof(transport) - 1,
1062 1063 1064 1065 1066 1067 1068
                     "%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;
1069 1070
        }

1071
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1072
            snprintf(transport, sizeof(transport) - 1,
1073
                     "%s/UDP;multicast", trans_pref);
1074
        }
1075 1076 1077
        if (s->oformat) {
            av_strlcat(transport, ";mode=receive", sizeof(transport));
        } else if (rt->server_type == RTSP_SERVER_REAL ||
1078
                   rt->server_type == RTSP_SERVER_WMS)
1079
            av_strlcat(transport, ";mode=play", sizeof(transport));
1080
        snprintf(cmd, sizeof(cmd),
F
Fabrice Bellard 已提交
1081
                 "Transport: %s\r\n",
1082
                 transport);
1083
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
1084 1085 1086 1087 1088 1089 1090 1091
            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);
        }
1092
        ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
1093 1094 1095
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
            err = 1;
            goto fail;
1096 1097
        } else if (reply->status_code != RTSP_STATUS_OK ||
                   reply->nb_transports != 1) {
1098 1099 1100 1101 1102 1103
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* XXX: same protocol for all streams is required */
        if (i > 0) {
1104 1105
            if (reply->transports[0].lower_transport != rt->lower_transport ||
                reply->transports[0].transport != rt->transport) {
1106 1107 1108 1109
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
        } else {
1110
            rt->lower_transport = reply->transports[0].lower_transport;
1111
            rt->transport = reply->transports[0].transport;
1112 1113
        }

1114 1115 1116 1117 1118 1119
        /* Fail if the server responded with another lower transport mode
         * than what we requested. */
        if (reply->transports[0].lower_transport != lower_transport) {
            av_log(s, AV_LOG_ERROR, "Nonmatching transport in server reply\n");
            err = AVERROR_INVALIDDATA;
            goto fail;
1120 1121
        }

1122 1123
        switch(reply->transports[0].lower_transport) {
        case RTSP_LOWER_TRANSPORT_TCP:
1124 1125 1126
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
            break;
1127

1128 1129 1130
        case RTSP_LOWER_TRANSPORT_UDP: {
            char url[1024];

1131 1132 1133 1134 1135 1136
            /* 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 已提交
1137 1138
                ff_url_join(url, sizeof(url), "rtp", NULL, host,
                            reply->transports[0].server_port_min, NULL);
1139
            }
1140 1141 1142 1143
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1144
            }
1145 1146 1147 1148
            /* Try to initialize the connection state in a
             * potential NAT router by sending dummy packets.
             * RTP/RTCP dummy packets are used for RDT, too.
             */
1149 1150
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
                CONFIG_RTPDEC)
1151
                rtp_send_punch_packets(rtsp_st->rtp_handle);
1152
            break;
1153 1154
        }
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
M
Martin Storsjö 已提交
1155 1156
            char url[1024], namebuf[50];
            struct sockaddr_storage addr;
1157 1158
            int port, ttl;

M
Martin Storsjö 已提交
1159 1160
            if (reply->transports[0].destination.ss_family) {
                addr      = reply->transports[0].destination;
1161 1162 1163
                port      = reply->transports[0].port_min;
                ttl       = reply->transports[0].ttl;
            } else {
M
Martin Storsjö 已提交
1164
                addr      = rtsp_st->sdp_ip;
1165 1166 1167
                port      = rtsp_st->sdp_port;
                ttl       = rtsp_st->sdp_ttl;
            }
M
Martin Storsjö 已提交
1168 1169 1170
            getnameinfo((struct sockaddr*) &addr, sizeof(addr),
                        namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
            ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
1171
                        port, "?ttl=%d", ttl);
1172 1173 1174
            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1175 1176 1177
            }
            break;
        }
1178
        }
R
Romain Degez 已提交
1179

1180
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1181
            goto fail;
1182 1183
    }

1184 1185 1186
    if (reply->timeout > 0)
        rt->timeout = reply->timeout;

1187
    if (rt->server_type == RTSP_SERVER_REAL)
1188 1189
        rt->need_subscription = 1;

1190 1191 1192
    return 0;

fail:
1193
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
1194 1195 1196 1197 1198
        if (rt->rtsp_streams[i]->rtp_handle) {
            url_close(rt->rtsp_streams[i]->rtp_handle);
            rt->rtsp_streams[i]->rtp_handle = NULL;
        }
    }
1199 1200 1201
    return err;
}

1202 1203 1204 1205 1206
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);
1207
    rt->rtsp_hd = rt->rtsp_hd_out = NULL;
1208 1209
}

1210
int ff_rtsp_connect(AVFormatContext *s)
1211 1212
{
    RTSPState *rt = s->priv_data;
1213 1214
    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
    char *option_list, *option, *filename;
1215
    int port, err, tcp_fd;
1216
    RTSPMessageHeader reply1 = {0}, *reply = &reply1;
1217
    int lower_transport_mask = 0;
1218
    char real_challenge[64];
1219 1220
    struct sockaddr_storage peer;
    socklen_t peer_len = sizeof(peer);
1221 1222 1223

    if (!ff_network_init())
        return AVERROR(EIO);
1224
redirect:
J
Josh Allmann 已提交
1225
    rt->control_transport = RTSP_MODE_PLAIN;
1226
    /* extract hostname and port */
M
Måns Rullgård 已提交
1227
    av_url_split(NULL, 0, auth, sizeof(auth),
M
Martin Storsjö 已提交
1228
                 host, sizeof(host), &port, path, sizeof(path), s->filename);
1229
    if (*auth) {
1230
        av_strlcpy(rt->auth, auth, sizeof(rt->auth));
1231
    }
1232 1233 1234 1235
    if (port < 0)
        port = RTSP_DEFAULT_PORT;

    /* search for options */
1236
    option_list = strrchr(path, '?');
1237
    if (option_list) {
1238 1239 1240
        /* Strip out the RTSP specific options, write out the rest of
         * the options back into the same string. */
        filename = option_list;
1241
        while (option_list) {
1242
            /* move the option pointer */
1243
            option = ++option_list;
1244 1245
            option_list = strchr(option_list, '&');
            if (option_list)
1246 1247
                *option_list = 0;

1248
            /* handle the options */
1249
            if (!strcmp(option, "udp")) {
1250
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
1251
            } else if (!strcmp(option, "multicast")) {
1252
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1253
            } else if (!strcmp(option, "tcp")) {
1254
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
J
Josh Allmann 已提交
1255 1256 1257
            } else if(!strcmp(option, "http")) {
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
                rt->control_transport = RTSP_MODE_TUNNEL;
1258
            } else {
1259 1260 1261 1262 1263
                /* 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;
1264 1265
                if (option_list) *filename = '&';
            }
1266
        }
1267
        *filename = 0;
1268 1269
    }

1270
    if (!lower_transport_mask)
1271
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1272

1273
    if (s->oformat) {
1274 1275 1276
        /* 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 已提交
1277
        if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
1278
            av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
1279
                                    "only UDP and TCP are supported for output.\n");
1280 1281 1282 1283 1284
            err = AVERROR(EINVAL);
            goto fail;
        }
    }

1285 1286 1287 1288 1289 1290
    /* 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 已提交
1291 1292 1293 1294 1295 1296
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        /* set up initial handshake for tunneling */
        char httpname[1024];
        char sessioncookie[17];
        char headers[1024];

1297
        ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
J
Josh Allmann 已提交
1298 1299 1300 1301
        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());

        /* GET requests */
1302
        if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) {
J
Josh Allmann 已提交
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
            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);
1314
        ff_http_set_headers(rt->rtsp_hd, headers);
J
Josh Allmann 已提交
1315 1316

        /* complete the connection */
1317
        if (url_connect(rt->rtsp_hd)) {
J
Josh Allmann 已提交
1318 1319 1320 1321 1322
            err = AVERROR(EIO);
            goto fail;
        }

        /* POST requests */
1323
        if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) {
J
Josh Allmann 已提交
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
            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);
1337 1338
        ff_http_set_headers(rt->rtsp_hd_out, headers);
        ff_http_set_chunked_transfer_encoding(rt->rtsp_hd_out, 0);
J
Josh Allmann 已提交
1339

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
        /* 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);

1358 1359 1360 1361 1362
        /* complete the connection */
        if (url_connect(rt->rtsp_hd_out)) {
            err = AVERROR(EIO);
            goto fail;
        }
J
Josh Allmann 已提交
1363
    } else {
1364
        /* open the tcp connection */
J
Josh Allmann 已提交
1365
        ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1366
        if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) {
J
Josh Allmann 已提交
1367 1368 1369
            err = AVERROR(EIO);
            goto fail;
        }
1370
        rt->rtsp_hd_out = rt->rtsp_hd;
J
Josh Allmann 已提交
1371
    }
1372 1373
    rt->seq = 0;

1374
    tcp_fd = url_get_file_handle(rt->rtsp_hd);
1375 1376 1377 1378 1379
    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
    }

1380 1381
    /* request options supported by the server; this also detects server
     * type */
1382
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1383
        cmd[0] = 0;
1384
        if (rt->server_type == RTSP_SERVER_REAL)
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
            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));
1400
        ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
1401 1402 1403 1404 1405 1406
        if (reply->status_code != RTSP_STATUS_OK) {
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* detect server type if not standard-compliant RTP */
1407 1408
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
            rt->server_type = RTSP_SERVER_REAL;
1409
            continue;
1410 1411
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
            rt->server_type = RTSP_SERVER_WMS;
1412
        } else if (rt->server_type == RTSP_SERVER_REAL)
1413 1414 1415 1416
            strcpy(real_challenge, reply->real_challenge);
        break;
    }

1417
    if (s->iformat && CONFIG_RTSP_DEMUXER)
1418
        err = ff_rtsp_setup_input_streams(s, reply);
1419
    else if (CONFIG_RTSP_MUXER)
1420
        err = ff_rtsp_setup_output_streams(s, host);
1421
    if (err)
1422 1423
        goto fail;

1424
    do {
1425 1426
        int lower_transport = ff_log2_tab[lower_transport_mask &
                                  ~(lower_transport_mask - 1)];
1427

1428
        err = make_setup_request(s, host, port, lower_transport,
1429
                                 rt->server_type == RTSP_SERVER_REAL ?
1430
                                     real_challenge : NULL);
1431
        if (err < 0)
1432
            goto fail;
1433 1434
        lower_transport_mask &= ~(1 << lower_transport);
        if (lower_transport_mask == 0 && err == 1) {
1435
            err = FF_NETERROR(EPROTONOSUPPORT);
1436 1437 1438
            goto fail;
        }
    } while (err);
1439

1440
    rt->state = RTSP_STATE_IDLE;
1441
    rt->seek_timestamp = 0; /* default is to start stream at position zero */
1442 1443
    return 0;
 fail:
1444
    ff_rtsp_close_streams(s);
1445
    ff_rtsp_close_connections(s);
1446
    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
L
Luca Barbato 已提交
1447 1448 1449 1450 1451 1452
        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;
    }
1453
    ff_network_close();
1454 1455
    return err;
}
1456
#endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */
1457

1458
#if CONFIG_RTPDEC
R
Ronald S. Bultje 已提交
1459
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1460
                           uint8_t *buf, int buf_size, int64_t wait_end)
R
Ronald S. Bultje 已提交
1461 1462 1463 1464
{
    RTSPState *rt = s->priv_data;
    RTSPStream *rtsp_st;
    fd_set rfds;
1465
    int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
R
Ronald S. Bultje 已提交
1466 1467
    struct timeval tv;

1468
    for (;;) {
R
Ronald S. Bultje 已提交
1469 1470
        if (url_interrupt_cb())
            return AVERROR(EINTR);
1471 1472
        if (wait_end && wait_end - av_gettime() < 0)
            return AVERROR(EAGAIN);
R
Ronald S. Bultje 已提交
1473 1474 1475 1476 1477 1478 1479 1480
        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;
        }
1481
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1482 1483 1484
            rtsp_st = rt->rtsp_streams[i];
            if (rtsp_st->rtp_handle) {
                fd = url_get_file_handle(rtsp_st->rtp_handle);
1485 1486 1487
                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 已提交
1488
                FD_SET(fd, &rfds);
1489
                FD_SET(fd_rtcp, &rfds);
R
Ronald S. Bultje 已提交
1490 1491 1492
            }
        }
        tv.tv_sec = 0;
1493
        tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
R
Ronald S. Bultje 已提交
1494 1495
        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
        if (n > 0) {
1496
            timeout_cnt = 0;
1497
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1498 1499 1500
                rtsp_st = rt->rtsp_streams[i];
                if (rtsp_st->rtp_handle) {
                    fd = url_get_file_handle(rtsp_st->rtp_handle);
1501 1502
                    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 已提交
1503 1504 1505 1506 1507 1508 1509 1510
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
                        if (ret > 0) {
                            *prtsp_st = rtsp_st;
                            return ret;
                        }
                    }
                }
            }
1511
#if CONFIG_RTSP_DEMUXER
1512
            if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
R
Ronald S. Bultje 已提交
1513 1514
                RTSPMessageHeader reply;

1515 1516 1517
                ret = ff_rtsp_read_reply(s, &reply, NULL, 0);
                if (ret < 0)
                    return ret;
R
Ronald S. Bultje 已提交
1518
                /* XXX: parse message */
1519
                if (rt->state != RTSP_STATE_STREAMING)
R
Ronald S. Bultje 已提交
1520 1521
                    return 0;
            }
1522
#endif
1523
        } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
1524
            return FF_NETERROR(ETIMEDOUT);
1525 1526
        } else if (n < 0 && errno != EINTR)
            return AVERROR(errno);
R
Ronald S. Bultje 已提交
1527 1528 1529
    }
}

1530
int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
R
Ronald S. Bultje 已提交
1531 1532 1533
{
    RTSPState *rt = s->priv_data;
    int ret, len;
1534 1535
    RTSPStream *rtsp_st, *first_queue_st = NULL;
    int64_t wait_end = 0;
R
Ronald S. Bultje 已提交
1536

1537 1538 1539
    if (rt->nb_byes == rt->nb_rtsp_streams)
        return AVERROR_EOF;

R
Ronald S. Bultje 已提交
1540 1541
    /* get next frames from the same RTP packet */
    if (rt->cur_transport_priv) {
1542
        if (rt->transport == RTSP_TRANSPORT_RDT) {
R
Ronald S. Bultje 已提交
1543
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1544
        } else
R
Ronald S. Bultje 已提交
1545 1546 1547 1548 1549 1550
            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;
1551
        } else
R
Ronald S. Bultje 已提交
1552 1553 1554
            rt->cur_transport_priv = NULL;
    }

1555 1556 1557 1558 1559
    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;
1560 1561 1562 1563
            int64_t queue_time;
            if (!rtpctx)
                continue;
            queue_time = ff_rtp_queued_packet_time(rtpctx);
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
            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 已提交
1574 1575
    /* read next RTP packet */
 redo:
1576 1577 1578 1579 1580 1581
    if (!rt->recvbuf) {
        rt->recvbuf = av_malloc(RECVBUF_SIZE);
        if (!rt->recvbuf)
            return AVERROR(ENOMEM);
    }

R
Ronald S. Bultje 已提交
1582 1583
    switch(rt->lower_transport) {
    default:
1584
#if CONFIG_RTSP_DEMUXER
R
Ronald S. Bultje 已提交
1585
    case RTSP_LOWER_TRANSPORT_TCP:
1586
        len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE);
R
Ronald S. Bultje 已提交
1587
        break;
1588
#endif
R
Ronald S. Bultje 已提交
1589 1590
    case RTSP_LOWER_TRANSPORT_UDP:
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1591
        len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end);
R
Ronald S. Bultje 已提交
1592 1593 1594 1595
        if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
        break;
    }
1596 1597 1598 1599 1600 1601
    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 已提交
1602 1603 1604 1605
    if (len < 0)
        return len;
    if (len == 0)
        return AVERROR_EOF;
1606
    if (rt->transport == RTSP_TRANSPORT_RDT) {
1607
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1608
    } else {
1609
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
        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++) {
1621
                    RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_priv;
1622 1623 1624 1625 1626
                    if (rtpctx2 &&
                        rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE)
                        rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
                }
            }
1627 1628 1629 1630 1631 1632 1633 1634 1635
            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;
            }
1636 1637
        }
    }
1638
end:
R
Ronald S. Bultje 已提交
1639 1640
    if (ret < 0)
        goto redo;
1641
    if (ret == 1)
R
Ronald S. Bultje 已提交
1642 1643 1644 1645 1646
        /* more packets may follow, so we save the RTP context */
        rt->cur_transport_priv = rtsp_st->transport_priv;

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

1649
#if CONFIG_SDP_DEMUXER
1650
static int sdp_probe(AVProbeData *p1)
1651
{
1652
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1653

M
Martin Storsjö 已提交
1654
    /* we look for a line beginning "c=IN IP" */
1655
    while (p < p_end && *p != '\0') {
M
Martin Storsjö 已提交
1656 1657
        if (p + sizeof("c=IN IP") - 1 < p_end &&
            av_strstart(p, "c=IN IP", NULL))
1658
            return AVPROBE_SCORE_MAX / 2;
1659

1660
        while (p < p_end - 1 && *p != '\n') p++;
1661
        if (++p >= p_end)
1662 1663 1664 1665
            break;
        if (*p == '\r')
            p++;
    }
1666 1667 1668
    return 0;
}

1669
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1670
{
1671
    RTSPState *rt = s->priv_data;
1672 1673 1674 1675 1676
    RTSPStream *rtsp_st;
    int size, i, err;
    char *content;
    char url[1024];

1677 1678 1679
    if (!ff_network_init())
        return AVERROR(EIO);

1680 1681 1682
    /* read the whole sdp file */
    /* XXX: better loading */
    content = av_malloc(SDP_MAX_SIZE);
1683
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1684 1685 1686 1687 1688 1689
    if (size <= 0) {
        av_free(content);
        return AVERROR_INVALIDDATA;
    }
    content[size] ='\0';

1690
    ff_sdp_parse(s, content);
1691 1692 1693
    av_free(content);

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

M
Martin Storsjö 已提交
1698 1699
        getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
                    namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
1700
        ff_url_join(url, sizeof(url), "rtp", NULL,
M
Martin Storsjö 已提交
1701
                    namebuf, rtsp_st->sdp_port,
1702 1703
                    "?localport=%d&ttl=%d", rtsp_st->sdp_port,
                    rtsp_st->sdp_ttl);
1704
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1705 1706 1707
            err = AVERROR_INVALIDDATA;
            goto fail;
        }
1708
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1709
            goto fail;
1710 1711
    }
    return 0;
1712
fail:
1713
    ff_rtsp_close_streams(s);
1714
    ff_network_close();
1715 1716 1717 1718 1719
    return err;
}

static int sdp_read_close(AVFormatContext *s)
{
1720
    ff_rtsp_close_streams(s);
1721
    ff_network_close();
1722 1723 1724
    return 0;
}

1725
AVInputFormat sdp_demuxer = {
1726
    "sdp",
1727
    NULL_IF_CONFIG_SMALL("SDP"),
1728 1729 1730
    sizeof(RTSPState),
    sdp_probe,
    sdp_read_header,
1731
    ff_rtsp_fetch_packet,
1732 1733
    sdp_read_close,
};
1734
#endif /* CONFIG_SDP_DEMUXER */
1735

1736
#if CONFIG_RTP_DEMUXER
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 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834
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,
1835
    ff_rtsp_fetch_packet,
1836 1837 1838
    sdp_read_close,
    .flags = AVFMT_NOFILE,
};
1839
#endif /* CONFIG_RTP_DEMUXER */
1840