rtsp.c 67.4 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 536 537 538 539 540 541
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
        av_close_input_stream (rt->asf_ctx);
        rt->asf_ctx = NULL;
    }
L
Luca Barbato 已提交
542
    av_free(rt->p);
543
    av_free(rt->recvbuf);
544 545
}

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

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

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

    return 0;
}

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

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

617
    reply->nb_transports = 0;
618

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

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

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

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

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

        reply->nb_transports++;
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

933
    return 0;
934 935
}

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

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

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

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

    return 0;
1001 1002
}

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

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

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

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

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

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

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

1051
    return 0;
1052 1053
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1293 1294 1295
    return 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1845
#if CONFIG_RTP_DEMUXER
1846 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
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;
}

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