rtsp.c 67.5 KB
Newer Older
1
/*
2
 * RTSP/SDP client
3
 * Copyright (c) 2002 Fabrice Bellard
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

22
#include "libavutil/base64.h"
23
#include "libavutil/avstring.h"
24
#include "libavutil/intreadwrite.h"
J
Josh Allmann 已提交
25
#include "libavutil/random_seed.h"
26 27
#include "avformat.h"

28
#include <sys/time.h>
L
Luca Barbato 已提交
29 30
#if HAVE_POLL_H
#include <poll.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

L
Luca Barbato 已提交
47
/* Timeout values for socket poll, in ms,
48
 * and read_packet(), in seconds  */
L
Luca Barbato 已提交
49
#define POLL_TIMEOUT_MS 100
50
#define READ_PACKET_TIMEOUT_S 10
L
Luca Barbato 已提交
51
#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_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;

L
Luca Barbato 已提交
250
    av_dlog(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;
    }
}

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

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

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

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
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);
                }
                av_metadata_free(&rtpctx->streams[0]->metadata);
                av_metadata_free(&rtpctx->metadata);
                av_free(rtpctx->streams[0]);
                av_free(rtpctx);
            } 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;
    }
}

521
/* close and free RTSP streams */
522
void ff_rtsp_close_streams(AVFormatContext *s)
523
{
524
    RTSPState *rt = s->priv_data;
525 526 527
    int i;
    RTSPStream *rtsp_st;

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

547
static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
548 549 550 551 552 553 554 555 556 557
{
    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;

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

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
576
    } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
577
        if (rtsp_st->dynamic_handler) {
578 579 580 581 582 583 584 585 586
            rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                           rtsp_st->dynamic_protocol_context,
                                           rtsp_st->dynamic_handler);
        }
    }

    return 0;
}

M
Martin Storsjö 已提交
587
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
588 589 590 591 592 593
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
    const char *p;
    int v;

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

618
    reply->nb_transports = 0;
619

620
    for (;;) {
621
        p += strspn(p, SPACE_CHARS);
622 623 624 625 626
        if (*p == '\0')
            break;

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

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

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

700 701 702 703 704 705 706 707 708 709 710 711
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

M
Martin Storsjö 已提交
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 762 763 764 765 766
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);
}

767
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
768
                        RTSPState *rt, const char *method)
769 770 771 772 773
{
    const char *p;

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

818
/* skip a RTP/TCP interleaved packet */
819
void ff_rtsp_skip_packet(AVFormatContext *s)
820 821 822 823 824
{
    RTSPState *rt = s->priv_data;
    int ret, len, len1;
    uint8_t buf[1024];

825
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
826 827
    if (ret != 3)
        return;
828
    len = AV_RB16(buf + 1);
829

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

832 833 834 835 836
    /* skip payload */
    while (len > 0) {
        len1 = len;
        if (len1 > sizeof(buf))
            len1 = sizeof(buf);
837
        ret = url_read_complete(rt->rtsp_hd, buf, len1);
838 839 840 841 842
        if (ret != len1)
            return;
        len -= len1;
    }
}
843

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

855
    memset(reply, 0, sizeof(*reply));
856 857 858

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

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

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

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

906 907 908 909
    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);
910
        (void)url_read_complete(rt->rtsp_hd, content, content_length);
911 912 913 914
        content[content_length] = '\0';
    }
    if (content_ptr)
        *content_ptr = content;
915 916
    else
        av_free(content);
917

918 919 920 921 922
    if (rt->seq != reply->seq) {
        av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
            rt->seq, reply->seq);
    }

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

934
    return 0;
935 936
}

937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
/**
 * 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)
955 956
{
    RTSPState *rt = s->priv_data;
J
Josh Allmann 已提交
957 958
    char buf[4096], *out_buf;
    char base64buf[AV_BASE64_SIZE(sizeof(buf))];
959

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

J
Josh Allmann 已提交
982 983 984 985 986 987
    /* 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 已提交
988
    av_dlog(s, "Sending:\n%s--\n", buf);
989

J
Josh Allmann 已提交
990 991 992 993 994 995 996
    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;
        }
997
        url_write(rt->rtsp_hd_out, send_content, send_content_length);
J
Josh Allmann 已提交
998
    }
999
    rt->last_cmd_time = av_gettime();
1000 1001

    return 0;
1002 1003
}

1004
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
M
Martin Storsjö 已提交
1005
                           const char *url, const char *headers)
1006
{
1007
    return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
1008 1009
}

1010
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
M
Martin Storsjö 已提交
1011 1012
                     const char *headers, RTSPMessageHeader *reply,
                     unsigned char **content_ptr)
1013
{
1014
    return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
M
Martin Storsjö 已提交
1015
                                         content_ptr, NULL, 0);
1016 1017
}

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

retry:
    cur_auth_type = rt->auth_state.auth_type;
1032
    if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
M
Martin Storsjö 已提交
1033 1034
                                                   send_content,
                                                   send_content_length)))
1035
        return ret;
1036

1037
    if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
1038
        return ret;
1039 1040 1041 1042

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

1044
    if (reply->status_code > 400){
L
Luca Barbato 已提交
1045
        av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
1046
               method,
L
Luca Barbato 已提交
1047 1048
               reply->status_code,
               reply->reason);
1049 1050 1051
        av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
    }

1052
    return 0;
1053 1054
}

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

1068
    if (rt->transport == RTSP_TRANSPORT_RDT)
1069 1070 1071
        trans_pref = "x-pn-tng";
    else
        trans_pref = "RTP/AVP";
1072

1073 1074 1075
    /* default timeout: 1 minute */
    rt->timeout = 60;

1076 1077
    /* for each stream, make the setup request */
    /* XXX: we assume the same server is used for the control of each
1078
     * RTSP stream */
R
Romain Degez 已提交
1079

1080
    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
1081 1082
        char transport[2048];

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

        /* RTP/UDP */
1108
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
F
Fabrice Bellard 已提交
1109 1110
            char buf[256];

1111 1112 1113 1114 1115
            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
                port = reply->transports[0].client_port_min;
                goto have_port;
            }

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

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

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

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

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

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

1216 1217 1218 1219 1220 1221
        /* 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;
1222 1223
        }

1224 1225
        switch(reply->transports[0].lower_transport) {
        case RTSP_LOWER_TRANSPORT_TCP:
1226 1227 1228
            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
            break;
1229

1230
        case RTSP_LOWER_TRANSPORT_UDP: {
1231
            char url[1024], options[30] = "";
1232

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

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

1284
        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1285
            goto fail;
1286 1287
    }

1288 1289 1290
    if (reply->timeout > 0)
        rt->timeout = reply->timeout;

1291
    if (rt->server_type == RTSP_SERVER_REAL)
1292 1293
        rt->need_subscription = 1;

1294 1295 1296
    return 0;

fail:
1297
    ff_rtsp_undo_setup(s);
1298 1299 1300
    return err;
}

1301 1302 1303 1304 1305
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);
1306
    rt->rtsp_hd = rt->rtsp_hd_out = NULL;
1307 1308
}

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

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

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

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

1371
    if (!lower_transport_mask)
1372
        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1373

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

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

1398
        ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
J
Josh Allmann 已提交
1399 1400 1401 1402
        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());

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

        /* complete the connection */
1418
        if (url_connect(rt->rtsp_hd)) {
J
Josh Allmann 已提交
1419 1420 1421 1422 1423
            err = AVERROR(EIO);
            goto fail;
        }

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

1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
        /* 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);

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

1475
    tcp_fd = url_get_file_handle(rt->rtsp_hd);
1476 1477 1478 1479 1480
    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
    }

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

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

1518
    if (s->iformat && CONFIG_RTSP_DEMUXER)
1519
        err = ff_rtsp_setup_input_streams(s, reply);
1520
    else if (CONFIG_RTSP_MUXER)
1521
        err = ff_rtsp_setup_output_streams(s, host);
1522
    if (err)
1523 1524
        goto fail;

1525
    do {
1526 1527
        int lower_transport = ff_log2_tab[lower_transport_mask &
                                  ~(lower_transport_mask - 1)];
1528

1529
        err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
1530
                                 rt->server_type == RTSP_SERVER_REAL ?
1531
                                     real_challenge : NULL);
1532
        if (err < 0)
1533
            goto fail;
1534 1535
        lower_transport_mask &= ~(1 << lower_transport);
        if (lower_transport_mask == 0 && err == 1) {
1536
            err = FF_NETERROR(EPROTONOSUPPORT);
1537 1538 1539
            goto fail;
        }
    } while (err);
1540

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

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

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

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

1629
int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
R
Ronald S. Bultje 已提交
1630 1631 1632
{
    RTSPState *rt = s->priv_data;
    int ret, len;
1633 1634
    RTSPStream *rtsp_st, *first_queue_st = NULL;
    int64_t wait_end = 0;
R
Ronald S. Bultje 已提交
1635

1636 1637 1638
    if (rt->nb_byes == rt->nb_rtsp_streams)
        return AVERROR_EOF;

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

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

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

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

1758
#if CONFIG_SDP_DEMUXER
1759
static int sdp_probe(AVProbeData *p1)
1760
{
1761
    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
1762

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

1769
        while (p < p_end - 1 && *p != '\n') p++;
1770
        if (++p >= p_end)
1771 1772 1773 1774
            break;
        if (*p == '\r')
            p++;
    }
1775 1776 1777
    return 0;
}

1778
static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1779
{
1780
    RTSPState *rt = s->priv_data;
1781 1782 1783 1784 1785
    RTSPStream *rtsp_st;
    int size, i, err;
    char *content;
    char url[1024];

1786 1787 1788
    if (!ff_network_init())
        return AVERROR(EIO);

1789 1790 1791
    /* read the whole sdp file */
    /* XXX: better loading */
    content = av_malloc(SDP_MAX_SIZE);
1792
    size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1793 1794 1795 1796 1797 1798
    if (size <= 0) {
        av_free(content);
        return AVERROR_INVALIDDATA;
    }
    content[size] ='\0';

1799
    err = ff_sdp_parse(s, content);
1800
    av_free(content);
1801
    if (err) goto fail;
1802 1803

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

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

static int sdp_read_close(AVFormatContext *s)
{
1830
    ff_rtsp_close_streams(s);
1831
    ff_network_close();
1832 1833 1834
    return 0;
}

1835
AVInputFormat ff_sdp_demuxer = {
1836
    "sdp",
1837
    NULL_IF_CONFIG_SMALL("SDP"),
1838 1839 1840
    sizeof(RTSPState),
    sdp_probe,
    sdp_read_header,
1841
    ff_rtsp_fetch_packet,
1842 1843
    sdp_read_close,
};
1844
#endif /* CONFIG_SDP_DEMUXER */
1845

1846
#if CONFIG_RTP_DEMUXER
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 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 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938
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;
}

1939
AVInputFormat ff_rtp_demuxer = {
1940 1941 1942 1943 1944
    "rtp",
    NULL_IF_CONFIG_SMALL("RTP input format"),
    sizeof(RTSPState),
    rtp_probe,
    rtp_read_header,
1945
    ff_rtsp_fetch_packet,
1946 1947 1948
    sdp_read_close,
    .flags = AVFMT_NOFILE,
};
1949
#endif /* CONFIG_RTP_DEMUXER */
1950