rtsp.c 67.3 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"
25
#include "libavutil/parseutils.h"
J
Josh Allmann 已提交
26
#include "libavutil/random_seed.h"
27
#include "avformat.h"
28
#include "avio_internal.h"
29

30
#include <sys/time.h>
L
Luca Barbato 已提交
31 32
#if HAVE_POLL_H
#include <poll.h>
33
#endif
34
#include <strings.h>
35
#include "internal.h"
36
#include "network.h"
37
#include "os_support.h"
J
Josh Allmann 已提交
38
#include "http.h"
39
#include "rtsp.h"
40

41
#include "rtpdec.h"
42
#include "rdt.h"
43
#include "rtpdec_formats.h"
44
#include "rtpenc_chain.h"
R
Ryan Martell 已提交
45

46
//#define DEBUG
F
Fabrice Bellard 已提交
47
//#define DEBUG_RTP_TCP
48

L
Luca Barbato 已提交
49
/* Timeout values for socket poll, in ms,
50
 * and read_packet(), in seconds  */
L
Luca Barbato 已提交
51
#define POLL_TIMEOUT_MS 100
52
#define READ_PACKET_TIMEOUT_S 10
L
Luca Barbato 已提交
53
#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
54
#define SDP_MAX_SIZE 16384
55
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
56

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

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

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

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

M
Martin Storsjö 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/** 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);
104
    av_parse_time(start, buf, 1);
M
Martin Storsjö 已提交
105 106 107
    if (*p == '-') {
        p++;
        get_word_sep(buf, sizeof(buf), "-", &p);
108
        av_parse_time(end, buf, 1);
M
Martin Storsjö 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    }
//    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;
}

126
#if CONFIG_RTPDEC
127 128 129 130 131 132 133 134 135 136 137
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();
}

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

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

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

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

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

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

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

L
Luca Barbato 已提交
252
    av_dlog(s, "sdp: %c='%s'\n", letter, buf);
253 254

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

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

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

324
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
325 326
            /* no corresponding stream */
        } else {
327
            st = av_new_stream(s, rt->nb_rtsp_streams - 1);
328 329 330
            if (!st)
                return;
            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
                char proto[32];
                /* get the control url */
358
                rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
359

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

            // this is so that seeking on a streamed file can work.
            rtsp_parse_range_npt(p, &start, &end);
400 401 402 403
            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;
404 405 406
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
            if (atoi(p) == 1)
                rt->transport = RTSP_TRANSPORT_RDT;
407 408 409 410
        } 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);
411 412 413 414
        } 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 已提交
415 416 417
                if (rt->server_type == RTSP_SERVER_REAL)
                    ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);

418
                rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
R
Ronald S. Bultje 已提交
419 420
                if (rtsp_st->dynamic_handler &&
                    rtsp_st->dynamic_handler->parse_sdp_a_line)
421 422
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
                        s->nb_streams - 1,
R
Ronald S. Bultje 已提交
423
                        rtsp_st->dynamic_protocol_context, buf);
424
            }
425 426 427 428 429
        }
        break;
    }
}

L
Luca Barbato 已提交
430 431 432 433 434
/**
 * Parse the sdp description and allocate the rtp streams and the
 * pollfd array used for udp ones.
 */

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

451
    memset(s1, 0, sizeof(SDPParseState));
452
    p = content;
453
    for (;;) {
454
        p += strspn(p, SPACE_CHARS);
455 456 457 458 459 460 461 462 463
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
F
Fabrice Bellard 已提交
464
        while (*p != '\n' && *p != '\r' && *p != '\0') {
465 466 467 468 469
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
470
        sdp_parse_line(s, s1, letter, buf);
471 472 473 474 475 476
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
    }
L
Luca Barbato 已提交
477 478
    rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
    if (!rt->p) return AVERROR(ENOMEM);
479 480
    return 0;
}
481
#endif /* CONFIG_RTPDEC */
482

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
void ff_rtsp_undo_setup(AVFormatContext *s)
{
    RTSPState *rt = s->priv_data;
    int i;

    for (i = 0; i < rt->nb_rtsp_streams; i++) {
        RTSPStream *rtsp_st = rt->rtsp_streams[i];
        if (!rtsp_st)
            continue;
        if (rtsp_st->transport_priv) {
            if (s->oformat) {
                AVFormatContext *rtpctx = rtsp_st->transport_priv;
                av_write_trailer(rtpctx);
                if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
                    uint8_t *ptr;
                    url_close_dyn_buf(rtpctx->pb, &ptr);
                    av_free(ptr);
                } else {
                    url_fclose(rtpctx->pb);
                }
503
                avformat_free_context(rtpctx);
504 505 506 507 508 509 510 511 512 513 514 515
            } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
                ff_rdt_parse_close(rtsp_st->transport_priv);
            else if (CONFIG_RTPDEC)
                rtp_parse_close(rtsp_st->transport_priv);
        }
        rtsp_st->transport_priv = NULL;
        if (rtsp_st->rtp_handle)
            url_close(rtsp_st->rtp_handle);
        rtsp_st->rtp_handle = NULL;
    }
}

516
/* close and free RTSP streams */
517
void ff_rtsp_close_streams(AVFormatContext *s)
518
{
519
    RTSPState *rt = s->priv_data;
520 521 522
    int i;
    RTSPStream *rtsp_st;

523
    ff_rtsp_undo_setup(s);
524
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
525 526 527
        rtsp_st = rt->rtsp_streams[i];
        if (rtsp_st) {
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
528 529
                rtsp_st->dynamic_handler->close(
                    rtsp_st->dynamic_protocol_context);
530
            av_free(rtsp_st);
531 532 533 534 535 536 537
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
        av_close_input_stream (rt->asf_ctx);
        rt->asf_ctx = NULL;
    }
L
Luca Barbato 已提交
538
    av_free(rt->p);
539
    av_free(rt->recvbuf);
540 541
}

542
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
543 544 545 546 547 548 549 550 551 552
{
    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;

553
    if (s->oformat && CONFIG_RTSP_MUXER) {
554 555 556
        rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
                                      rtsp_st->rtp_handle,
                                      RTSP_TCP_MAX_PACKET_SIZE);
R
Reimar Döffinger 已提交
557
        /* Ownership of rtp_handle is passed to the rtp mux context */
558
        rtsp_st->rtp_handle = NULL;
559
    } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
560 561 562
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
563
    else if (CONFIG_RTPDEC)
564
        rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
565 566 567
                                         rtsp_st->sdp_payload_type,
            (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
            ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
568 569 570

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
571
    } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
572
        if (rtsp_st->dynamic_handler) {
573 574 575 576 577 578 579 580 581
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                           rtsp_st->dynamic_protocol_context,
                                           rtsp_st->dynamic_handler);
        }
    }

    return 0;
}

M
Martin Storsjö 已提交
582
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
583 584 585 586 587 588
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
    const char *p;
    int v;

    p = *pp;
589
    p += strspn(p, SPACE_CHARS);
590 591 592 593 594 595 596 597 598 599 600 601 602 603
    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 */
604
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
605 606 607 608 609 610 611
{
    char transport_protocol[16];
    char profile[16];
    char lower_transport[16];
    char parameter[16];
    RTSPTransportField *th;
    char buf[256];
612

613
    reply->nb_transports = 0;
614

615
    for (;;) {
616
        p += strspn(p, SPACE_CHARS);
617 618 619 620 621
        if (*p == '\0')
            break;

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

622
        get_word_sep(transport_protocol, sizeof(transport_protocol),
623
                     "/", &p);
624
        if (!strcasecmp (transport_protocol, "rtp")) {
625 626 627 628 629 630
            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);
631 632 633 634
            }
            th->transport = RTSP_TRANSPORT_RTP;
        } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
                   !strcasecmp (transport_protocol, "x-real-rdt")) {
635
            /* x-pn-tng/<protocol> */
636 637
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
            profile[0] = '\0';
638
            th->transport = RTSP_TRANSPORT_RDT;
639
        }
F
Fabrice Bellard 已提交
640
        if (!strcasecmp(lower_transport, "TCP"))
641
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
642
        else
643
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
644

645 646 647 648 649 650 651 652 653 654 655 656 657
        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++;
658
                    rtsp_parse_range(&th->client_port_min,
659 660 661 662 663
                                     &th->client_port_max, &p);
                }
            } else if (!strcmp(parameter, "server_port")) {
                if (*p == '=') {
                    p++;
664
                    rtsp_parse_range(&th->server_port_min,
665 666 667 668 669
                                     &th->server_port_max, &p);
                }
            } else if (!strcmp(parameter, "interleaved")) {
                if (*p == '=') {
                    p++;
670
                    rtsp_parse_range(&th->interleaved_min,
671 672 673
                                     &th->interleaved_max, &p);
                }
            } else if (!strcmp(parameter, "multicast")) {
674 675
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
676 677 678 679 680 681 682 683 684
            } 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ö 已提交
685
                    get_sockaddr(buf, &th->destination);
686
                }
687 688 689 690 691 692
            } else if (!strcmp(parameter, "source")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
                    av_strlcpy(th->source, buf, sizeof(th->source));
                }
693
            }
694

695 696 697 698 699 700 701 702 703 704 705 706
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

M
Martin Storsjö 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
static void handle_rtp_info(RTSPState *rt, const char *url,
                            uint32_t seq, uint32_t rtptime)
{
    int i;
    if (!rtptime || !url[0])
        return;
    if (rt->transport != RTSP_TRANSPORT_RTP)
        return;
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
        RTSPStream *rtsp_st = rt->rtsp_streams[i];
        RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
        if (!rtpctx)
            continue;
        if (!strcmp(rtsp_st->control_url, url)) {
            rtpctx->base_timestamp = rtptime;
            break;
        }
    }
}

static void rtsp_parse_rtp_info(RTSPState *rt, const char *p)
{
    int read = 0;
    char key[20], value[1024], url[1024] = "";
    uint32_t seq = 0, rtptime = 0;

    for (;;) {
        p += strspn(p, SPACE_CHARS);
        if (!*p)
            break;
        get_word_sep(key, sizeof(key), "=", &p);
        if (*p != '=')
            break;
        p++;
        get_word_sep(value, sizeof(value), ";, ", &p);
        read++;
        if (!strcmp(key, "url"))
            av_strlcpy(url, value, sizeof(url));
        else if (!strcmp(key, "seq"))
            seq = strtol(value, NULL, 10);
        else if (!strcmp(key, "rtptime"))
            rtptime = strtol(value, NULL, 10);
        if (*p == ',') {
            handle_rtp_info(rt, url, seq, rtptime);
            url[0] = '\0';
            seq = rtptime = 0;
            read = 0;
        }
        if (*p)
            p++;
    }
    if (read > 0)
        handle_rtp_info(rt, url, seq, rtptime);
}

762
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
763
                        RTSPState *rt, const char *method)
764 765 766 767 768
{
    const char *p;

    /* NOTE: we do case independent match for broken servers */
    p = buf;
769
    if (av_stristart(p, "Session:", &p)) {
770
        int t;
771
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
772 773 774 775
        if (av_stristart(p, ";timeout=", &p) &&
            (t = strtol(p, NULL, 10)) > 0) {
            reply->timeout = t;
        }
776
    } else if (av_stristart(p, "Content-Length:", &p)) {
777
        reply->content_length = strtol(p, NULL, 10);
778
    } else if (av_stristart(p, "Transport:", &p)) {
779
        rtsp_parse_transport(reply, p);
780
    } else if (av_stristart(p, "CSeq:", &p)) {
781
        reply->seq = strtol(p, NULL, 10);
782
    } else if (av_stristart(p, "Range:", &p)) {
783
        rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
784
    } else if (av_stristart(p, "RealChallenge1:", &p)) {
785
        p += strspn(p, SPACE_CHARS);
786
        av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
787
    } else if (av_stristart(p, "Server:", &p)) {
788
        p += strspn(p, SPACE_CHARS);
789
        av_strlcpy(reply->server, p, sizeof(reply->server));
790 791 792
    } else if (av_stristart(p, "Notice:", &p) ||
               av_stristart(p, "X-Notice:", &p)) {
        reply->notice = strtol(p, NULL, 10);
L
Luca Barbato 已提交
793
    } else if (av_stristart(p, "Location:", &p)) {
794
        p += strspn(p, SPACE_CHARS);
L
Luca Barbato 已提交
795
        av_strlcpy(reply->location, p , sizeof(reply->location));
796
    } else if (av_stristart(p, "WWW-Authenticate:", &p) && rt) {
797
        p += strspn(p, SPACE_CHARS);
798 799
        ff_http_auth_handle_header(&rt->auth_state, "WWW-Authenticate", p);
    } else if (av_stristart(p, "Authentication-Info:", &p) && rt) {
800
        p += strspn(p, SPACE_CHARS);
801
        ff_http_auth_handle_header(&rt->auth_state, "Authentication-Info", p);
802
    } else if (av_stristart(p, "Content-Base:", &p) && rt) {
803
        p += strspn(p, SPACE_CHARS);
804 805
        if (method && !strcmp(method, "DESCRIBE"))
            av_strlcpy(rt->control_uri, p , sizeof(rt->control_uri));
M
Martin Storsjö 已提交
806 807 808 809
    } else if (av_stristart(p, "RTP-Info:", &p) && rt) {
        p += strspn(p, SPACE_CHARS);
        if (method && !strcmp(method, "PLAY"))
            rtsp_parse_rtp_info(rt, p);
810 811 812
    }
}

813
/* skip a RTP/TCP interleaved packet */
814
void ff_rtsp_skip_packet(AVFormatContext *s)
815 816 817 818 819
{
    RTSPState *rt = s->priv_data;
    int ret, len, len1;
    uint8_t buf[1024];

820
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
821 822
    if (ret != 3)
        return;
823
    len = AV_RB16(buf + 1);
824

L
Luca Barbato 已提交
825
    av_dlog(s, "skipping RTP packet len=%d\n", len);
826

827 828 829 830 831
    /* skip payload */
    while (len > 0) {
        len1 = len;
        if (len1 > sizeof(buf))
            len1 = sizeof(buf);
832
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
833 834 835 836 837
        if (ret != len1)
            return;
        len -= len1;
    }
}
838

839
int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
M
Martin Storsjö 已提交
840
                       unsigned char **content_ptr,
841
                       int return_on_interleaved_data, const char *method)
842 843 844 845 846
{
    RTSPState *rt = s->priv_data;
    char buf[4096], buf1[1024], *q;
    unsigned char ch;
    const char *p;
847
    int ret, content_length, line_count = 0;
848 849
    unsigned char *content = NULL;

850
    memset(reply, 0, sizeof(*reply));
851 852 853

    /* parse reply (XXX: use buffers) */
    rt->last_reply[0] = '\0';
854
    for (;;) {
855
        q = buf;
856
        for (;;) {
857
            ret = url_read_complete(rt->rtsp_hd, &ch, 1);
858
#ifdef DEBUG_RTP_TCP
L
Luca Barbato 已提交
859
            av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
860 861
#endif
            if (ret != 1)
862
                return AVERROR_EOF;
863 864
            if (ch == '\n')
                break;
865 866
            if (ch == '$') {
                /* XXX: only parse it if first char on line ? */
867 868 869
                if (return_on_interleaved_data) {
                    return 1;
                } else
870
                    ff_rtsp_skip_packet(s);
871
            } else if (ch != '\r') {
872 873 874 875 876
                if ((q - buf) < sizeof(buf) - 1)
                    *q++ = ch;
            }
        }
        *q = '\0';
877

L
Luca Barbato 已提交
878
        av_dlog(s, "line='%s'\n", buf);
879

880 881 882 883 884 885 886 887 888
        /* 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 已提交
889
            av_strlcpy(reply->reason, p, sizeof(reply->reason));
890
        } else {
891
            ff_rtsp_parse_line(reply, p, rt, method);
M
Måns Rullgård 已提交
892 893
            av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
            av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
894 895 896
        }
        line_count++;
    }
897

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

901 902 903 904
    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);
905
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
906 907 908 909
        content[content_length] = '\0';
    }
    if (content_ptr)
        *content_ptr = content;
910 911
    else
        av_free(content);
912

913 914 915 916 917
    if (rt->seq != reply->seq) {
        av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
            rt->seq, reply->seq);
    }

918 919 920
    /* EOS */
    if (reply->notice == 2101 /* End-of-Stream Reached */      ||
        reply->notice == 2104 /* Start-of-Stream Reached */    ||
921
        reply->notice == 2306 /* Continuous Feed Terminated */) {
922
        rt->state = RTSP_STATE_IDLE;
923
    } else if (reply->notice >= 4400 && reply->notice < 5500) {
924
        return AVERROR(EIO); /* data or server error */
925
    } else if (reply->notice == 2401 /* Ticket Expired */ ||
926 927 928
             (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
        return AVERROR(EPERM);

929
    return 0;
930 931
}

932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
/**
 * Send a command to the RTSP server without waiting for the reply.
 *
 * @param s RTSP (de)muxer context
 * @param method the method for the request
 * @param url the target url for the request
 * @param headers extra header lines to include in the request
 * @param send_content if non-null, the data to send as request body content
 * @param send_content_length the length of the send_content data, or 0 if
 *                            send_content is null
 *
 * @return zero if success, nonzero otherwise
 */
static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
                                               const char *method, const char *url,
                                               const char *headers,
                                               const unsigned char *send_content,
                                               int send_content_length)
950 951
{
    RTSPState *rt = s->priv_data;
J
Josh Allmann 已提交
952 953
    char buf[4096], *out_buf;
    char base64buf[AV_BASE64_SIZE(sizeof(buf))];
954

J
Josh Allmann 已提交
955 956
    /* Add in RTSP headers */
    out_buf = buf;
957
    rt->seq++;
958 959 960
    snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
    if (headers)
        av_strlcat(buf, headers, sizeof(buf));
961
    av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
962 963
    if (rt->session_id[0] != '\0' && (!headers ||
        !strstr(headers, "\nIf-Match:"))) {
964
        av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
965
    }
966 967 968 969 970 971 972
    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);
    }
973 974
    if (send_content_length > 0 && send_content)
        av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
975
    av_strlcat(buf, "\r\n", sizeof(buf));
976

J
Josh Allmann 已提交
977 978 979 980 981 982
    /* base64 encode rtsp if tunneling */
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
        out_buf = base64buf;
    }

L
Luca Barbato 已提交
983
    av_dlog(s, "Sending:\n%s--\n", buf);
984

J
Josh Allmann 已提交
985 986 987 988 989 990 991
    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;
        }
992
        url_write(rt->rtsp_hd_out, send_content, send_content_length);
J
Josh Allmann 已提交
993
    }
994
    rt->last_cmd_time = av_gettime();
995 996

    return 0;
997 998
}

999
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
M
Martin Storsjö 已提交
1000
                           const char *url, const char *headers)
1001
{
1002
    return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
1003 1004
}

1005
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
M
Martin Storsjö 已提交
1006 1007
                     const char *headers, RTSPMessageHeader *reply,
                     unsigned char **content_ptr)
1008
{
1009
    return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
M
Martin Storsjö 已提交
1010
                                         content_ptr, NULL, 0);
1011 1012
}

1013
int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
M
Martin Storsjö 已提交
1014 1015 1016 1017 1018 1019
                                  const char *method, const char *url,
                                  const char *header,
                                  RTSPMessageHeader *reply,
                                  unsigned char **content_ptr,
                                  const unsigned char *send_content,
                                  int send_content_length)
1020
{
1021 1022
    RTSPState *rt = s->priv_data;
    HTTPAuthType cur_auth_type;
1023
    int ret;
1024 1025 1026

retry:
    cur_auth_type = rt->auth_state.auth_type;
1027
    if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
M
Martin Storsjö 已提交
1028 1029
                                                   send_content,
                                                   send_content_length)))
1030
        return ret;
1031

1032
    if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
1033
        return ret;
1034 1035 1036 1037

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

1039
    if (reply->status_code > 400){
L
Luca Barbato 已提交
1040
        av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
1041
               method,
L
Luca Barbato 已提交
1042 1043
               reply->status_code,
               reply->reason);
1044 1045 1046
        av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
    }

1047
    return 0;
1048 1049
}

1050
/**
B
Benoit Fouet 已提交
1051
 * @return 0 on success, <0 on error, 1 if protocol is unavailable.
1052
 */
1053
int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
1054
                              int lower_transport, const char *real_challenge)
1055 1056
{
    RTSPState *rt = s->priv_data;
1057
    int rtx, j, i, err, interleave = 0;
1058
    RTSPStream *rtsp_st;
1059
    RTSPMessageHeader reply1, *reply = &reply1;
1060
    char cmd[2048];
1061 1062
    const char *trans_pref;

1063
    if (rt->transport == RTSP_TRANSPORT_RDT)
1064 1065 1066
        trans_pref = "x-pn-tng";
    else
        trans_pref = "RTP/AVP";
1067

1068 1069 1070
    /* default timeout: 1 minute */
    rt->timeout = 60;

1071 1072
    /* for each stream, make the setup request */
    /* XXX: we assume the same server is used for the control of each
1073
     * RTSP stream */
R
Romain Degez 已提交
1074

1075
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
1076 1077
        char transport[2048];

1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
        /**
         * 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 &&
1090 1091
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
                                "/rtx"))
1092 1093 1094 1095 1096 1097 1098 1099
                        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 已提交
1100
            rtsp_st = rt->rtsp_streams[i];
1101 1102

        /* RTP/UDP */
1103
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
F
Fabrice Bellard 已提交
1104 1105
            char buf[256];

1106 1107 1108 1109 1110
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
                port = reply->transports[0].client_port_min;
                goto have_port;
            }

F
Fabrice Bellard 已提交
1111
            /* first try in specified port range */
R
Romain Degez 已提交
1112
            if (RTSP_RTP_PORT_MIN != 0) {
1113
                while (j <= RTSP_RTP_PORT_MAX) {
1114 1115
                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
                                "?localport=%d", j);
1116 1117 1118
                    /* 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 已提交
1119 1120
                        goto rtp_opened;
                }
1121
            }
F
Fabrice Bellard 已提交
1122

1123 1124 1125 1126 1127 1128
#if 0
            /* then try on any port */
            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
1129 1130 1131 1132
#else
            av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
            err = AVERROR(EIO);
            goto fail;
1133
#endif
F
Fabrice Bellard 已提交
1134 1135

        rtp_opened:
1136
            port = rtp_get_local_rtp_port(rtsp_st->rtp_handle);
1137
        have_port:
1138
            snprintf(transport, sizeof(transport) - 1,
1139 1140 1141 1142 1143
                     "%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);
1144 1145
            if (rt->transport == RTSP_TRANSPORT_RTP &&
                !(rt->server_type == RTSP_SERVER_WMS && i > 0))
1146
                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
1147 1148 1149
        }

        /* RTP/TCP */
1150
        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1151 1152 1153 1154
            /** 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 &&
1155
                s->streams[rtsp_st->stream_index]->codec->codec_type ==
1156
                    AVMEDIA_TYPE_DATA)
1157
                continue;
1158
            snprintf(transport, sizeof(transport) - 1,
1159 1160 1161 1162 1163 1164 1165
                     "%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;
1166 1167
        }

1168
        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1169
            snprintf(transport, sizeof(transport) - 1,
1170
                     "%s/UDP;multicast", trans_pref);
1171
        }
1172 1173 1174
        if (s->oformat) {
            av_strlcat(transport, ";mode=receive", sizeof(transport));
        } else if (rt->server_type == RTSP_SERVER_REAL ||
1175
                   rt->server_type == RTSP_SERVER_WMS)
1176
            av_strlcat(transport, ";mode=play", sizeof(transport));
1177
        snprintf(cmd, sizeof(cmd),
F
Fabrice Bellard 已提交
1178
                 "Transport: %s\r\n",
1179
                 transport);
1180
        if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
1181 1182 1183 1184 1185 1186 1187 1188
            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);
        }
1189
        ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
1190 1191 1192
        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
            err = 1;
            goto fail;
1193 1194
        } else if (reply->status_code != RTSP_STATUS_OK ||
                   reply->nb_transports != 1) {
1195 1196 1197 1198 1199 1200
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* XXX: same protocol for all streams is required */
        if (i > 0) {
1201 1202
            if (reply->transports[0].lower_transport != rt->lower_transport ||
                reply->transports[0].transport != rt->transport) {
1203 1204 1205 1206
                err = AVERROR_INVALIDDATA;
                goto fail;
            }
        } else {
1207
            rt->lower_transport = reply->transports[0].lower_transport;
1208
            rt->transport = reply->transports[0].transport;
1209 1210
        }

1211 1212 1213 1214 1215 1216
        /* 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;
1217 1218
        }

1219 1220
        switch(reply->transports[0].lower_transport) {
        case RTSP_LOWER_TRANSPORT_TCP:
1221 1222 1223
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
            break;
1224

1225
        case RTSP_LOWER_TRANSPORT_UDP: {
1226
            char url[1024], options[30] = "";
1227

1228 1229
            if (rt->filter_source)
                av_strlcpy(options, "?connect=1", sizeof(options));
1230 1231 1232 1233
            /* Use source address if specified */
            if (reply->transports[0].source[0]) {
                ff_url_join(url, sizeof(url), "rtp", NULL,
                            reply->transports[0].source,
1234
                            reply->transports[0].server_port_min, options);
1235
            } else {
R
Ronald S. Bultje 已提交
1236
                ff_url_join(url, sizeof(url), "rtp", NULL, host,
1237
                            reply->transports[0].server_port_min, options);
1238
            }
1239 1240 1241 1242
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1243
            }
1244 1245 1246 1247
            /* Try to initialize the connection state in a
             * potential NAT router by sending dummy packets.
             * RTP/RTCP dummy packets are used for RDT, too.
             */
1248 1249
            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
                CONFIG_RTPDEC)
1250
                rtp_send_punch_packets(rtsp_st->rtp_handle);
1251
            break;
1252 1253
        }
        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
M
Martin Storsjö 已提交
1254 1255
            char url[1024], namebuf[50];
            struct sockaddr_storage addr;
1256 1257
            int port, ttl;

M
Martin Storsjö 已提交
1258 1259
            if (reply->transports[0].destination.ss_family) {
                addr      = reply->transports[0].destination;
1260 1261 1262
                port      = reply->transports[0].port_min;
                ttl       = reply->transports[0].ttl;
            } else {
M
Martin Storsjö 已提交
1263
                addr      = rtsp_st->sdp_ip;
1264 1265 1266
                port      = rtsp_st->sdp_port;
                ttl       = rtsp_st->sdp_ttl;
            }
M
Martin Storsjö 已提交
1267 1268 1269
            getnameinfo((struct sockaddr*) &addr, sizeof(addr),
                        namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
            ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
1270
                        port, "?ttl=%d", ttl);
1271 1272 1273
            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
                err = AVERROR_INVALIDDATA;
                goto fail;
1274 1275 1276
            }
            break;
        }
1277
        }
R
Romain Degez 已提交
1278

1279
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1280
            goto fail;
1281 1282
    }

1283 1284 1285
    if (reply->timeout > 0)
        rt->timeout = reply->timeout;

1286
    if (rt->server_type == RTSP_SERVER_REAL)
1287 1288
        rt->need_subscription = 1;

1289 1290 1291
    return 0;

fail:
1292
    ff_rtsp_undo_setup(s);
1293 1294 1295
    return err;
}

1296 1297 1298 1299 1300
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);
1301
    rt->rtsp_hd = rt->rtsp_hd_out = NULL;
1302 1303
}

1304
int ff_rtsp_connect(AVFormatContext *s)
1305 1306
{
    RTSPState *rt = s->priv_data;
1307 1308
    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
    char *option_list, *option, *filename;
1309
    int port, err, tcp_fd;
1310
    RTSPMessageHeader reply1 = {0}, *reply = &reply1;
1311
    int lower_transport_mask = 0;
1312
    char real_challenge[64] = "";
1313 1314
    struct sockaddr_storage peer;
    socklen_t peer_len = sizeof(peer);
1315 1316 1317

    if (!ff_network_init())
        return AVERROR(EIO);
1318
redirect:
J
Josh Allmann 已提交
1319
    rt->control_transport = RTSP_MODE_PLAIN;
1320
    /* extract hostname and port */
M
Måns Rullgård 已提交
1321
    av_url_split(NULL, 0, auth, sizeof(auth),
M
Martin Storsjö 已提交
1322
                 host, sizeof(host), &port, path, sizeof(path), s->filename);
1323
    if (*auth) {
1324
        av_strlcpy(rt->auth, auth, sizeof(rt->auth));
1325
    }
1326 1327 1328 1329
    if (port < 0)
        port = RTSP_DEFAULT_PORT;

    /* search for options */
1330
    option_list = strrchr(path, '?');
1331
    if (option_list) {
1332 1333 1334
        /* Strip out the RTSP specific options, write out the rest of
         * the options back into the same string. */
        filename = option_list;
1335
        while (option_list) {
1336
            /* move the option pointer */
1337
            option = ++option_list;
1338 1339
            option_list = strchr(option_list, '&');
            if (option_list)
1340 1341
                *option_list = 0;

1342
            /* handle the options */
1343
            if (!strcmp(option, "udp")) {
1344
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
1345
            } else if (!strcmp(option, "multicast")) {
1346
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
1347
            } else if (!strcmp(option, "tcp")) {
1348
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
J
Josh Allmann 已提交
1349 1350 1351
            } else if(!strcmp(option, "http")) {
                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
                rt->control_transport = RTSP_MODE_TUNNEL;
1352 1353
            } else if (!strcmp(option, "filter_src")) {
                rt->filter_source = 1;
1354
            } else {
1355 1356 1357 1358 1359
                /* 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;
1360 1361
                if (option_list) *filename = '&';
            }
1362
        }
1363
        *filename = 0;
1364 1365
    }

1366
    if (!lower_transport_mask)
1367
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1368

1369
    if (s->oformat) {
1370 1371 1372
        /* 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 已提交
1373
        if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
1374
            av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
1375
                                    "only UDP and TCP are supported for output.\n");
1376 1377 1378 1379 1380
            err = AVERROR(EINVAL);
            goto fail;
        }
    }

1381 1382 1383 1384 1385 1386
    /* 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 已提交
1387 1388 1389 1390 1391 1392
    if (rt->control_transport == RTSP_MODE_TUNNEL) {
        /* set up initial handshake for tunneling */
        char httpname[1024];
        char sessioncookie[17];
        char headers[1024];

1393
        ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
J
Josh Allmann 已提交
1394 1395 1396 1397
        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());

        /* GET requests */
1398
        if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) {
J
Josh Allmann 已提交
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
            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);
1410
        ff_http_set_headers(rt->rtsp_hd, headers);
J
Josh Allmann 已提交
1411 1412

        /* complete the connection */
1413
        if (url_connect(rt->rtsp_hd)) {
J
Josh Allmann 已提交
1414 1415 1416 1417 1418
            err = AVERROR(EIO);
            goto fail;
        }

        /* POST requests */
1419
        if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) {
J
Josh Allmann 已提交
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
            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);
1433 1434
        ff_http_set_headers(rt->rtsp_hd_out, headers);
        ff_http_set_chunked_transfer_encoding(rt->rtsp_hd_out, 0);
J
Josh Allmann 已提交
1435

1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
        /* 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);

1454 1455 1456 1457 1458
        /* complete the connection */
        if (url_connect(rt->rtsp_hd_out)) {
            err = AVERROR(EIO);
            goto fail;
        }
J
Josh Allmann 已提交
1459
    } else {
1460
        /* open the tcp connection */
J
Josh Allmann 已提交
1461
        ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1462
        if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) {
J
Josh Allmann 已提交
1463 1464 1465
            err = AVERROR(EIO);
            goto fail;
        }
1466
        rt->rtsp_hd_out = rt->rtsp_hd;
J
Josh Allmann 已提交
1467
    }
1468 1469
    rt->seq = 0;

1470
    tcp_fd = url_get_file_handle(rt->rtsp_hd);
1471 1472 1473 1474 1475
    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
    }

1476 1477
    /* request options supported by the server; this also detects server
     * type */
1478
    for (rt->server_type = RTSP_SERVER_RTP;;) {
1479
        cmd[0] = 0;
1480
        if (rt->server_type == RTSP_SERVER_REAL)
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
            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));
1496
        ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
1497 1498 1499 1500 1501 1502
        if (reply->status_code != RTSP_STATUS_OK) {
            err = AVERROR_INVALIDDATA;
            goto fail;
        }

        /* detect server type if not standard-compliant RTP */
1503 1504
        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
            rt->server_type = RTSP_SERVER_REAL;
1505
            continue;
1506 1507
        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
            rt->server_type = RTSP_SERVER_WMS;
1508
        } else if (rt->server_type == RTSP_SERVER_REAL)
1509 1510 1511 1512
            strcpy(real_challenge, reply->real_challenge);
        break;
    }

1513
    if (s->iformat && CONFIG_RTSP_DEMUXER)
1514
        err = ff_rtsp_setup_input_streams(s, reply);
1515
    else if (CONFIG_RTSP_MUXER)
1516
        err = ff_rtsp_setup_output_streams(s, host);
1517
    if (err)
1518 1519
        goto fail;

1520
    do {
1521 1522
        int lower_transport = ff_log2_tab[lower_transport_mask &
                                  ~(lower_transport_mask - 1)];
1523

1524
        err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
1525
                                 rt->server_type == RTSP_SERVER_REAL ?
1526
                                     real_challenge : NULL);
1527
        if (err < 0)
1528
            goto fail;
1529 1530
        lower_transport_mask &= ~(1 << lower_transport);
        if (lower_transport_mask == 0 && err == 1) {
1531
            err = AVERROR(EPROTONOSUPPORT);
1532 1533 1534
            goto fail;
        }
    } while (err);
1535

1536 1537
    rt->lower_transport_mask = lower_transport_mask;
    av_strlcpy(rt->real_challenge, real_challenge, sizeof(rt->real_challenge));
1538
    rt->state = RTSP_STATE_IDLE;
1539
    rt->seek_timestamp = 0; /* default is to start stream at position zero */
1540 1541
    return 0;
 fail:
1542
    ff_rtsp_close_streams(s);
1543
    ff_rtsp_close_connections(s);
1544
    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
L
Luca Barbato 已提交
1545 1546 1547 1548 1549 1550
        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;
    }
1551
    ff_network_close();
1552 1553
    return err;
}
1554
#endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */
1555

1556
#if CONFIG_RTPDEC
R
Ronald S. Bultje 已提交
1557
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1558
                           uint8_t *buf, int buf_size, int64_t wait_end)
R
Ronald S. Bultje 已提交
1559 1560 1561
{
    RTSPState *rt = s->priv_data;
    RTSPStream *rtsp_st;
L
Luca Barbato 已提交
1562 1563 1564
    int n, i, ret, tcp_fd, timeout_cnt = 0;
    int max_p = 0;
    struct pollfd *p = rt->p;
R
Ronald S. Bultje 已提交
1565

1566
    for (;;) {
R
Ronald S. Bultje 已提交
1567 1568
        if (url_interrupt_cb())
            return AVERROR(EINTR);
1569 1570
        if (wait_end && wait_end - av_gettime() < 0)
            return AVERROR(EAGAIN);
L
Luca Barbato 已提交
1571
        max_p = 0;
R
Ronald S. Bultje 已提交
1572
        if (rt->rtsp_hd) {
L
Luca Barbato 已提交
1573 1574 1575
            tcp_fd = url_get_file_handle(rt->rtsp_hd);
            p[max_p].fd = tcp_fd;
            p[max_p++].events = POLLIN;
R
Ronald S. Bultje 已提交
1576 1577 1578
        } else {
            tcp_fd = -1;
        }
1579
        for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1580 1581
            rtsp_st = rt->rtsp_streams[i];
            if (rtsp_st->rtp_handle) {
L
Luca Barbato 已提交
1582 1583 1584 1585
                p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle);
                p[max_p++].events = POLLIN;
                p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
                p[max_p++].events = POLLIN;
R
Ronald S. Bultje 已提交
1586 1587
            }
        }
L
Luca Barbato 已提交
1588
        n = poll(p, max_p, POLL_TIMEOUT_MS);
R
Ronald S. Bultje 已提交
1589
        if (n > 0) {
L
Luca Barbato 已提交
1590
            int j = 1 - (tcp_fd == -1);
1591
            timeout_cnt = 0;
1592
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
R
Ronald S. Bultje 已提交
1593 1594
                rtsp_st = rt->rtsp_streams[i];
                if (rtsp_st->rtp_handle) {
L
Luca Barbato 已提交
1595
                    if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
R
Ronald S. Bultje 已提交
1596 1597 1598 1599 1600 1601
                        ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
                        if (ret > 0) {
                            *prtsp_st = rtsp_st;
                            return ret;
                        }
                    }
L
Luca Barbato 已提交
1602
                    j+=2;
R
Ronald S. Bultje 已提交
1603 1604
                }
            }
1605
#if CONFIG_RTSP_DEMUXER
L
Luca Barbato 已提交
1606
            if (tcp_fd != -1 && p[0].revents & POLLIN) {
R
Ronald S. Bultje 已提交
1607 1608
                RTSPMessageHeader reply;

1609
                ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
1610 1611
                if (ret < 0)
                    return ret;
R
Ronald S. Bultje 已提交
1612
                /* XXX: parse message */
1613
                if (rt->state != RTSP_STATE_STREAMING)
R
Ronald S. Bultje 已提交
1614 1615
                    return 0;
            }
1616
#endif
1617
        } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
1618
            return AVERROR(ETIMEDOUT);
1619 1620
        } else if (n < 0 && errno != EINTR)
            return AVERROR(errno);
R
Ronald S. Bultje 已提交
1621 1622 1623
    }
}

1624
int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
R
Ronald S. Bultje 已提交
1625 1626 1627
{
    RTSPState *rt = s->priv_data;
    int ret, len;
1628 1629
    RTSPStream *rtsp_st, *first_queue_st = NULL;
    int64_t wait_end = 0;
R
Ronald S. Bultje 已提交
1630

1631 1632 1633
    if (rt->nb_byes == rt->nb_rtsp_streams)
        return AVERROR_EOF;

R
Ronald S. Bultje 已提交
1634 1635
    /* get next frames from the same RTP packet */
    if (rt->cur_transport_priv) {
1636
        if (rt->transport == RTSP_TRANSPORT_RDT) {
R
Ronald S. Bultje 已提交
1637
            ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
1638
        } else
R
Ronald S. Bultje 已提交
1639 1640 1641 1642 1643 1644
            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;
1645
        } else
R
Ronald S. Bultje 已提交
1646 1647 1648
            rt->cur_transport_priv = NULL;
    }

1649 1650 1651 1652 1653
    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;
1654 1655 1656 1657
            int64_t queue_time;
            if (!rtpctx)
                continue;
            queue_time = ff_rtp_queued_packet_time(rtpctx);
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667
            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 已提交
1668 1669
    /* read next RTP packet */
 redo:
1670 1671 1672 1673 1674 1675
    if (!rt->recvbuf) {
        rt->recvbuf = av_malloc(RECVBUF_SIZE);
        if (!rt->recvbuf)
            return AVERROR(ENOMEM);
    }

R
Ronald S. Bultje 已提交
1676 1677
    switch(rt->lower_transport) {
    default:
1678
#if CONFIG_RTSP_DEMUXER
R
Ronald S. Bultje 已提交
1679
    case RTSP_LOWER_TRANSPORT_TCP:
1680
        len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE);
R
Ronald S. Bultje 已提交
1681
        break;
1682
#endif
R
Ronald S. Bultje 已提交
1683 1684
    case RTSP_LOWER_TRANSPORT_UDP:
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
1685
        len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end);
1686
        if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
R
Ronald S. Bultje 已提交
1687 1688 1689
            rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
        break;
    }
1690 1691 1692 1693 1694 1695
    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 已提交
1696 1697 1698 1699
    if (len < 0)
        return len;
    if (len == 0)
        return AVERROR_EOF;
1700
    if (rt->transport == RTSP_TRANSPORT_RDT) {
1701
        ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1702
    } else {
1703
        ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
        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;
1714 1715 1716
                AVStream *st = NULL;
                if (rtsp_st->stream_index >= 0)
                    st = s->streams[rtsp_st->stream_index];
1717
                for (i = 0; i < rt->nb_rtsp_streams; i++) {
1718
                    RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_priv;
1719 1720 1721 1722 1723
                    AVStream *st2 = NULL;
                    if (rt->rtsp_streams[i]->stream_index >= 0)
                        st2 = s->streams[rt->rtsp_streams[i]->stream_index];
                    if (rtpctx2 && st && st2 &&
                        rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE) {
1724
                        rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
1725 1726 1727 1728
                        rtpctx2->rtcp_ts_offset = av_rescale_q(
                            rtpctx->rtcp_ts_offset, st->time_base,
                            st2->time_base);
                    }
1729 1730
                }
            }
1731 1732 1733 1734 1735 1736 1737 1738 1739
            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;
            }
1740 1741
        }
    }
1742
end:
R
Ronald S. Bultje 已提交
1743 1744
    if (ret < 0)
        goto redo;
1745
    if (ret == 1)
R
Ronald S. Bultje 已提交
1746 1747 1748 1749 1750
        /* more packets may follow, so we save the RTP context */
        rt->cur_transport_priv = rtsp_st->transport_priv;

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

1753
#if CONFIG_SDP_DEMUXER
1754
static int sdp_probe(AVProbeData *p1)
1755
{
1756
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1757

M
Martin Storsjö 已提交
1758
    /* we look for a line beginning "c=IN IP" */
1759
    while (p < p_end && *p != '\0') {
M
Martin Storsjö 已提交
1760 1761
        if (p + sizeof("c=IN IP") - 1 < p_end &&
            av_strstart(p, "c=IN IP", NULL))
1762
            return AVPROBE_SCORE_MAX / 2;
1763

1764
        while (p < p_end - 1 && *p != '\n') p++;
1765
        if (++p >= p_end)
1766 1767 1768 1769
            break;
        if (*p == '\r')
            p++;
    }
1770 1771 1772
    return 0;
}

1773
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1774
{
1775
    RTSPState *rt = s->priv_data;
1776 1777 1778 1779 1780
    RTSPStream *rtsp_st;
    int size, i, err;
    char *content;
    char url[1024];

1781 1782 1783
    if (!ff_network_init())
        return AVERROR(EIO);

1784 1785 1786
    /* read the whole sdp file */
    /* XXX: better loading */
    content = av_malloc(SDP_MAX_SIZE);
1787
    size = avio_read(s->pb, content, SDP_MAX_SIZE - 1);
1788 1789 1790 1791 1792 1793
    if (size <= 0) {
        av_free(content);
        return AVERROR_INVALIDDATA;
    }
    content[size] ='\0';

1794
    err = ff_sdp_parse(s, content);
1795
    av_free(content);
1796
    if (err) goto fail;
1797 1798

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

M
Martin Storsjö 已提交
1803 1804
        getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
                    namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
1805
        ff_url_join(url, sizeof(url), "rtp", NULL,
M
Martin Storsjö 已提交
1806
                    namebuf, rtsp_st->sdp_port,
1807 1808
                    "?localport=%d&ttl=%d", rtsp_st->sdp_port,
                    rtsp_st->sdp_ttl);
1809
        if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1810 1811 1812
            err = AVERROR_INVALIDDATA;
            goto fail;
        }
1813
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1814
            goto fail;
1815 1816
    }
    return 0;
1817
fail:
1818
    ff_rtsp_close_streams(s);
1819
    ff_network_close();
1820 1821 1822 1823 1824
    return err;
}

static int sdp_read_close(AVFormatContext *s)
{
1825
    ff_rtsp_close_streams(s);
1826
    ff_network_close();
1827 1828 1829
    return 0;
}

1830
AVInputFormat ff_sdp_demuxer = {
1831
    "sdp",
1832
    NULL_IF_CONFIG_SMALL("SDP"),
1833 1834 1835
    sizeof(RTSPState),
    sdp_probe,
    sdp_read_header,
1836
    ff_rtsp_fetch_packet,
1837 1838
    sdp_read_close,
};
1839
#endif /* CONFIG_SDP_DEMUXER */
1840

1841
#if CONFIG_RTP_DEMUXER
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858
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;
1859
    AVIOContext pb;
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916
    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);

1917
    ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
    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;
}

1934
AVInputFormat ff_rtp_demuxer = {
1935 1936 1937 1938 1939
    "rtp",
    NULL_IF_CONFIG_SMALL("RTP input format"),
    sizeof(RTSPState),
    rtp_probe,
    rtp_read_header,
1940
    ff_rtsp_fetch_packet,
1941 1942 1943
    sdp_read_close,
    .flags = AVFMT_NOFILE,
};
1944
#endif /* CONFIG_RTP_DEMUXER */
1945