rtsp.c 78.1 KB
Newer Older
1
/*
2
 * RTSP/SDP client
3
 * Copyright (c) 2002 Fabrice Bellard
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav 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
 * Libav 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 Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

22
#include "libavutil/base64.h"
23
#include "libavutil/avstring.h"
24
#include "libavutil/intreadwrite.h"
25
#include "libavutil/mathematics.h"
26
#include "libavutil/parseutils.h"
Josh Allmann's avatar
Josh Allmann committed
27
#include "libavutil/random_seed.h"
28
#include "libavutil/dict.h"
29
#include "libavutil/opt.h"
30
#include "libavutil/time.h"
31
#include "avformat.h"
32
#include "avio_internal.h"
33

Luca Barbato's avatar
Luca Barbato committed
34 35
#if HAVE_POLL_H
#include <poll.h>
36
#endif
37
#include "internal.h"
38
#include "network.h"
39
#include "os_support.h"
Josh Allmann's avatar
Josh Allmann committed
40
#include "http.h"
41
#include "rtsp.h"
42

43
#include "rtpdec.h"
44
#include "rdt.h"
45
#include "rtpdec_formats.h"
46
#include "rtpenc_chain.h"
Anton Khirnov's avatar
Anton Khirnov committed
47
#include "url.h"
48
#include "rtpenc.h"
49
#include "mpegts.h"
Ryan Martell's avatar
Ryan Martell committed
50

51 52
//#define DEBUG

Luca Barbato's avatar
Luca Barbato committed
53
/* Timeout values for socket poll, in ms,
54
 * and read_packet(), in seconds  */
Luca Barbato's avatar
Luca Barbato committed
55
#define POLL_TIMEOUT_MS 100
56
#define READ_PACKET_TIMEOUT_S 10
Luca Barbato's avatar
Luca Barbato committed
57
#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
58
#define SDP_MAX_SIZE 16384
59
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
60
#define DEFAULT_REORDERING_DELAY 100000
61

62 63
#define OFFSET(x) offsetof(RTSPState, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
64
#define ENC AV_OPT_FLAG_ENCODING_PARAM
65 66

#define RTSP_FLAG_OPTS(name, longname) \
67
    { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
68 69
    { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \
    { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }
70

71
#define RTSP_MEDIATYPE_OPTS(name, longname) \
72
    { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { .i64 = (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
73 74 75
    { "video", "Video", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_VIDEO}, 0, 0, DEC, "allowed_media_types" }, \
    { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \
    { "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
76

77 78 79
#define RTSP_REORDERING_OPTS() \
    { "reorder_queue_size", "Number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }

80
const AVOption ff_rtsp_options[] = {
81
    { "initial_pause",  "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
82
    FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
83
    { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
84 85 86 87
    { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
    { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
    { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
    { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {.i64 = (1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
88
    RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"),
89
    RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
90 91 92
    { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
    { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
    { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC },
93
    RTSP_REORDERING_OPTS(),
94 95 96
    { NULL },
};

97 98
static const AVOption sdp_options[] = {
    RTSP_FLAG_OPTS("sdp_flags", "SDP flags"),
99
    RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
100
    RTSP_REORDERING_OPTS(),
101 102 103 104 105
    { NULL },
};

static const AVOption rtp_options[] = {
    RTSP_FLAG_OPTS("rtp_flags", "RTP flags"),
106
    RTSP_REORDERING_OPTS(),
107 108 109
    { NULL },
};

110 111
static void get_word_until_chars(char *buf, int buf_size,
                                 const char *sep, const char **pp)
112 113 114 115 116
{
    const char *p;
    char *q;

    p = *pp;
117
    p += strspn(p, SPACE_CHARS);
118 119 120 121 122 123 124 125 126 127 128
    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;
}

129 130
static void get_word_sep(char *buf, int buf_size, const char *sep,
                         const char **pp)
131
{
132 133 134
    if (**pp == '/') (*pp)++;
    get_word_until_chars(buf, buf_size, sep, pp);
}
135

136 137 138
static void get_word(char *buf, int buf_size, const char **pp)
{
    get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
139 140
}

Martin Storsjö's avatar
Martin Storsjö committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/** 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);
157
    av_parse_time(start, buf, 1);
Martin Storsjö's avatar
Martin Storsjö committed
158 159 160
    if (*p == '-') {
        p++;
        get_word_sep(buf, sizeof(buf), "-", &p);
161
        av_parse_time(end, buf, 1);
Martin Storsjö's avatar
Martin Storsjö committed
162 163 164 165 166
    }
}

static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
{
167
    struct addrinfo hints = { 0 }, *ai = NULL;
Martin Storsjö's avatar
Martin Storsjö committed
168 169 170 171 172 173 174 175
    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;
}

176
#if CONFIG_RTPDEC
177 178 179 180 181 182 183
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;
184
    if (handler->alloc) {
185
        rtsp_st->dynamic_protocol_context = handler->alloc();
186 187 188
        if (!rtsp_st->dynamic_protocol_context)
            rtsp_st->dynamic_handler = NULL;
    }
189 190
}

191
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
192
static int sdp_parse_rtpmap(AVFormatContext *s,
193
                            AVStream *st, RTSPStream *rtsp_st,
194
                            int payload_type, const char *p)
195
{
196
    AVCodecContext *codec = st->codec;
197
    char buf[256];
Romain Degez's avatar
Romain Degez committed
198 199
    int i;
    AVCodec *c;
200
    const char *c_name;
201

Romain Degez's avatar
Romain Degez committed
202
    /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
203 204 205 206 207
     * 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);
208 209 210 211 212 213 214
    if (payload_type < RTP_PT_PRIVATE) {
        /* We are in a standard case
         * (from http://www.iana.org/assignments/rtp-parameters). */
        /* search into AVRtpPayloadTypes[] */
        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
    }

215
    if (codec->codec_id == AV_CODEC_ID_NONE) {
216 217 218
        RTPDynamicProtocolHandler *handler =
            ff_rtp_handler_find_by_name(buf, codec->codec_type);
        init_rtp_handler(handler, rtsp_st, codec);
219 220 221 222 223 224
        /* 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);
Romain Degez's avatar
Romain Degez committed
225 226 227 228
    }

    c = avcodec_find_decoder(codec->codec_id);
    if (c && c->name)
229
        c_name = c->name;
Romain Degez's avatar
Romain Degez committed
230
    else
231
        c_name = "(null)";
Romain Degez's avatar
Romain Degez committed
232

Ronald S. Bultje's avatar
Ronald S. Bultje committed
233 234 235
    get_word_sep(buf, sizeof(buf), "/", &p);
    i = atoi(buf);
    switch (codec->codec_type) {
236
    case AVMEDIA_TYPE_AUDIO:
Ronald S. Bultje's avatar
Ronald S. Bultje committed
237 238 239 240 241
        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;
242
            avpriv_set_pts_info(st, 32, 1, codec->sample_rate);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
243 244 245 246 247 248 249 250
            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)
Romain Degez's avatar
Romain Degez committed
251
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
252 253 254 255 256
        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;
257
    case AVMEDIA_TYPE_VIDEO:
Ronald S. Bultje's avatar
Ronald S. Bultje committed
258
        av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
259
        if (i > 0)
260
            avpriv_set_pts_info(st, 32, 1, i);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
261 262 263 264
        break;
    default:
        break;
    }
265 266 267
    if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->init)
        rtsp_st->dynamic_handler->init(s, st->index,
                                       rtsp_st->dynamic_protocol_context);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
268
    return 0;
269 270
}

Reimar Döffinger's avatar
Reimar Döffinger committed
271
/* parse the attribute line from the fmtp a line of an sdp response. This
272 273
 * is broken out as a function because it is used in rtp_h264.c, which is
 * forthcoming. */
274
int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
Martin Storsjö's avatar
Martin Storsjö committed
275
                                char *value, int value_size)
276
{
277
    *p += strspn(*p, SPACE_CHARS);
278
    if (**p) {
279 280 281 282 283 284 285 286 287 288 289
        get_word_sep(attr, attr_size, "=", p);
        if (**p == '=')
            (*p)++;
        get_word_sep(value, value_size, ";", p);
        if (**p == ';')
            (*p)++;
        return 1;
    }
    return 0;
}

290 291
typedef struct SDPParseState {
    /* SDP only */
292
    struct sockaddr_storage default_ip;
293 294
    int            default_ttl;
    int            skip_media;  ///< set if an unknown m= line occurs
295 296 297
} SDPParseState;

static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
298 299
                           int letter, const char *buf)
{
300
    RTSPState *rt = s->priv_data;
301 302
    char buf1[64], st_type[64];
    const char *p;
303
    enum AVMediaType codec_type;
304
    int payload_type, i;
305 306
    AVStream *st;
    RTSPStream *rtsp_st;
307
    struct sockaddr_storage sdp_ip;
308 309
    int ttl;

Luca Barbato's avatar
Luca Barbato committed
310
    av_dlog(s, "sdp: %c='%s'\n", letter, buf);
311 312

    p = buf;
313 314
    if (s1->skip_media && letter != 'm')
        return;
315
    switch (letter) {
316 317 318 319 320
    case 'c':
        get_word(buf1, sizeof(buf1), &p);
        if (strcmp(buf1, "IN") != 0)
            return;
        get_word(buf1, sizeof(buf1), &p);
321
        if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6"))
322 323
            return;
        get_word_sep(buf1, sizeof(buf1), "/", &p);
324
        if (get_sockaddr(buf1, &sdp_ip))
325 326 327 328 329 330 331 332 333 334 335
            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 {
336
            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
337 338 339 340
            rtsp_st->sdp_ip = sdp_ip;
            rtsp_st->sdp_ttl = ttl;
        }
        break;
341
    case 's':
342
        av_dict_set(&s->metadata, "title", p, 0);
343 344 345
        break;
    case 'i':
        if (s->nb_streams == 0) {
346
            av_dict_set(&s->metadata, "comment", p, 0);
347 348 349 350 351
            break;
        }
        break;
    case 'm':
        /* new stream */
352
        s1->skip_media = 0;
353
        codec_type = AVMEDIA_TYPE_UNKNOWN;
354 355
        get_word(st_type, sizeof(st_type), &p);
        if (!strcmp(st_type, "audio")) {
356
            codec_type = AVMEDIA_TYPE_AUDIO;
357
        } else if (!strcmp(st_type, "video")) {
358
            codec_type = AVMEDIA_TYPE_VIDEO;
359
        } else if (!strcmp(st_type, "application")) {
360
            codec_type = AVMEDIA_TYPE_DATA;
361 362
        }
        if (codec_type == AVMEDIA_TYPE_UNKNOWN || !(rt->media_type_mask & (1 << codec_type))) {
363
            s1->skip_media = 1;
364 365 366 367 368
            return;
        }
        rtsp_st = av_mallocz(sizeof(RTSPStream));
        if (!rtsp_st)
            return;
369 370
        rtsp_st->stream_index = -1;
        dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
371 372 373 374 375 376 377

        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);

378 379 380
        get_word(buf1, sizeof(buf1), &p); /* protocol */
        if (!strcmp(buf1, "udp"))
            rt->transport = RTSP_TRANSPORT_RAW;
381

382 383 384 385
        /* XXX: handle list of formats */
        get_word(buf1, sizeof(buf1), &p); /* format list */
        rtsp_st->sdp_payload_type = atoi(buf1);

386
        if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
387
            /* no corresponding stream */
388 389
            if (rt->transport == RTSP_TRANSPORT_RAW && !rt->ts && CONFIG_RTPDEC)
                rt->ts = ff_mpegts_parse_open(s);
390 391 392 393
        } else if (rt->server_type == RTSP_SERVER_WMS &&
                   codec_type == AVMEDIA_TYPE_DATA) {
            /* RTX stream, a stream that carries all the other actual
             * audio/video streams. Don't expose this to the callers. */
394
        } else {
395
            st = avformat_new_stream(s, NULL);
396 397
            if (!st)
                return;
398
            st->id = rt->nb_rtsp_streams - 1;
399
            rtsp_st->stream_index = st->index;
400
            st->codec->codec_type = codec_type;
Romain Degez's avatar
Romain Degez committed
401
            if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
402
                RTPDynamicProtocolHandler *handler;
403
                /* if standard payload type, we can find the codec right now */
404
                ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
405 406
                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
                    st->codec->sample_rate > 0)
407
                    avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
408 409 410 411
                /* 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);
412 413 414
                if (handler && handler->init)
                    handler->init(s, st->index,
                                  rtsp_st->dynamic_protocol_context);
415 416
            }
        }
417
        /* put a default control url */
418
        av_strlcpy(rtsp_st->control_url, rt->control_uri,
419
                   sizeof(rtsp_st->control_url));
420 421
        break;
    case 'a':
422 423 424 425 426 427
        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 {
428 429
                char proto[32];
                /* get the control url */
430
                rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
431

432 433 434 435 436 437 438 439 440 441 442 443 444
                /* 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));
445
            }
446
        } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
447
            /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
448
            get_word(buf1, sizeof(buf1), &p);
449
            payload_type = atoi(buf1);
450
            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
451 452 453 454
            if (rtsp_st->stream_index >= 0) {
                st = s->streams[rtsp_st->stream_index];
                sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
            }
455 456
        } else if (av_strstart(p, "fmtp:", &p) ||
                   av_strstart(p, "framesize:", &p)) {
457
            /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
458 459 460
            // let dynamic protocol handlers have a stab at the line.
            get_word(buf1, sizeof(buf1), &p);
            payload_type = atoi(buf1);
461 462
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
                rtsp_st = rt->rtsp_streams[i];
463 464 465 466 467
                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);
468
            }
469
        } else if (av_strstart(p, "range:", &p)) {
470 471 472 473
            int64_t start, end;

            // this is so that seeking on a streamed file can work.
            rtsp_parse_range_npt(p, &start, &end);
474 475 476 477
            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;
478 479 480
        } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
            if (atoi(p) == 1)
                rt->transport = RTSP_TRANSPORT_RDT;
481 482 483 484
        } 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);
485 486 487 488
        } else {
            if (rt->server_type == RTSP_SERVER_WMS)
                ff_wms_parse_sdp_a_line(s, p);
            if (s->nb_streams > 0) {
489 490
                rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];

Ronald S. Bultje's avatar
Ronald S. Bultje committed
491
                if (rt->server_type == RTSP_SERVER_REAL)
492
                    ff_real_parse_sdp_a_line(s, rtsp_st->stream_index, p);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
493 494 495

                if (rtsp_st->dynamic_handler &&
                    rtsp_st->dynamic_handler->parse_sdp_a_line)
496
                    rtsp_st->dynamic_handler->parse_sdp_a_line(s,
497
                        rtsp_st->stream_index,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
498
                        rtsp_st->dynamic_protocol_context, buf);
499
            }
500 501 502 503 504
        }
        break;
    }
}

505
int ff_sdp_parse(AVFormatContext *s, const char *content)
506
{
Luca Barbato's avatar
Luca Barbato committed
507
    RTSPState *rt = s->priv_data;
508 509
    const char *p;
    int letter;
510 511 512 513
    /* 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
514 515
     * buffer is large.
     *
516 517
     * The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line
     * in rtpdec_xiph.c. */
518
    char buf[16384], *q;
519
    SDPParseState sdp_parse_state = { { 0 } }, *s1 = &sdp_parse_state;
520

521
    p = content;
522
    for (;;) {
523
        p += strspn(p, SPACE_CHARS);
524 525 526 527 528 529 530 531 532
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
Fabrice Bellard's avatar
Fabrice Bellard committed
533
        while (*p != '\n' && *p != '\r' && *p != '\0') {
534 535 536 537 538
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
539
        sdp_parse_line(s, s1, letter, buf);
540 541 542 543 544 545
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
    }
Luca Barbato's avatar
Luca Barbato committed
546 547
    rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
    if (!rt->p) return AVERROR(ENOMEM);
548 549
    return 0;
}
550
#endif /* CONFIG_RTPDEC */
551

552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
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;
567
                    avio_close_dyn_buf(rtpctx->pb, &ptr);
568 569
                    av_free(ptr);
                } else {
570
                    avio_close(rtpctx->pb);
571
                }
572
                avformat_free_context(rtpctx);
573 574
            } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
                ff_rdt_parse_close(rtsp_st->transport_priv);
575
            else if (rt->transport == RTSP_TRANSPORT_RTP && CONFIG_RTPDEC)
576
                ff_rtp_parse_close(rtsp_st->transport_priv);
577 578 579
        }
        rtsp_st->transport_priv = NULL;
        if (rtsp_st->rtp_handle)
580
            ffurl_close(rtsp_st->rtp_handle);
581 582 583 584
        rtsp_st->rtp_handle = NULL;
    }
}

585
/* close and free RTSP streams */
586
void ff_rtsp_close_streams(AVFormatContext *s)
587
{
588
    RTSPState *rt = s->priv_data;
589 590 591
    int i;
    RTSPStream *rtsp_st;

592
    ff_rtsp_undo_setup(s);
593
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
594 595 596
        rtsp_st = rt->rtsp_streams[i];
        if (rtsp_st) {
            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
597
                rtsp_st->dynamic_handler->free(
598
                    rtsp_st->dynamic_protocol_context);
599
            av_free(rtsp_st);
600 601 602 603
        }
    }
    av_free(rt->rtsp_streams);
    if (rt->asf_ctx) {
604
        avformat_close_input(&rt->asf_ctx);
605
    }
606 607
    if (rt->ts && CONFIG_RTPDEC)
        ff_mpegts_parse_close(rt->ts);
Luca Barbato's avatar
Luca Barbato committed
608
    av_free(rt->p);
609
    av_free(rt->recvbuf);
610 611
}

612
int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
613 614 615
{
    RTSPState *rt = s->priv_data;
    AVStream *st = NULL;
616 617 618 619 620 621 622
    int reordering_queue_size = rt->reordering_queue_size;
    if (reordering_queue_size < 0) {
        if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
            reordering_queue_size = 0;
        else
            reordering_queue_size = RTP_REORDER_QUEUE_DEFAULT_SIZE;
    }
623 624 625 626 627 628 629

    /* open the RTP context */
    if (rtsp_st->stream_index >= 0)
        st = s->streams[rtsp_st->stream_index];
    if (!st)
        s->ctx_flags |= AVFMTCTX_NOHEADER;

630
    if (s->oformat && CONFIG_RTSP_MUXER) {
631 632 633
        int ret = ff_rtp_chain_mux_open(&rtsp_st->transport_priv, s, st,
                                        rtsp_st->rtp_handle,
                                        RTSP_TCP_MAX_PACKET_SIZE);
Reimar Döffinger's avatar
Reimar Döffinger committed
634
        /* Ownership of rtp_handle is passed to the rtp mux context */
635
        rtsp_st->rtp_handle = NULL;
636 637
        if (ret < 0)
            return ret;
638 639
    } else if (rt->transport == RTSP_TRANSPORT_RAW) {
        return 0; // Don't need to open any parser here
640
    } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
641 642 643
        rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
                                            rtsp_st->dynamic_protocol_context,
                                            rtsp_st->dynamic_handler);
644
    else if (CONFIG_RTPDEC)
645
        rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->rtp_handle,
646
                                         rtsp_st->sdp_payload_type,
647
                                         reordering_queue_size);
648 649 650

    if (!rtsp_st->transport_priv) {
         return AVERROR(ENOMEM);
651
    } else if (rt->transport == RTSP_TRANSPORT_RTP && CONFIG_RTPDEC) {
652
        if (rtsp_st->dynamic_handler) {
653 654 655
            ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                              rtsp_st->dynamic_protocol_context,
                                              rtsp_st->dynamic_handler);
656 657 658 659 660 661
        }
    }

    return 0;
}

Martin Storsjö's avatar
Martin Storsjö committed
662
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
663 664
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
665 666
    const char *q;
    char *p;
667 668
    int v;

669 670 671
    q = *pp;
    q += strspn(q, SPACE_CHARS);
    v = strtol(q, &p, 10);
672 673 674
    if (*p == '-') {
        p++;
        *min_ptr = v;
675
        v = strtol(p, &p, 10);
676 677 678 679 680 681 682 683 684
        *max_ptr = v;
    } else {
        *min_ptr = v;
        *max_ptr = v;
    }
    *pp = p;
}

/* XXX: only one transport specification is parsed */
685
static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
686 687 688 689 690 691 692
{
    char transport_protocol[16];
    char profile[16];
    char lower_transport[16];
    char parameter[16];
    RTSPTransportField *th;
    char buf[256];
693

694
    reply->nb_transports = 0;
695

696
    for (;;) {
697
        p += strspn(p, SPACE_CHARS);
698 699 700 701 702
        if (*p == '\0')
            break;

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

703
        get_word_sep(transport_protocol, sizeof(transport_protocol),
704
                     "/", &p);
705
        if (!av_strcasecmp (transport_protocol, "rtp")) {
706 707 708 709 710 711
            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);
712 713
            }
            th->transport = RTSP_TRANSPORT_RTP;
714 715
        } else if (!av_strcasecmp (transport_protocol, "x-pn-tng") ||
                   !av_strcasecmp (transport_protocol, "x-real-rdt")) {
716
            /* x-pn-tng/<protocol> */
717 718
            get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
            profile[0] = '\0';
719
            th->transport = RTSP_TRANSPORT_RDT;
720 721 722 723 724 725 726 727 728
        } else if (!av_strcasecmp(transport_protocol, "raw")) {
            get_word_sep(profile, sizeof(profile), "/;,", &p);
            lower_transport[0] = '\0';
            /* raw/raw/<protocol> */
            if (*p == '/') {
                get_word_sep(lower_transport, sizeof(lower_transport),
                             ";,", &p);
            }
            th->transport = RTSP_TRANSPORT_RAW;
729
        }
730
        if (!av_strcasecmp(lower_transport, "TCP"))
731
            th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
732
        else
733
            th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
734

735 736 737 738 739 740 741 742 743 744 745 746 747
        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++;
748
                    rtsp_parse_range(&th->client_port_min,
749 750 751 752 753
                                     &th->client_port_max, &p);
                }
            } else if (!strcmp(parameter, "server_port")) {
                if (*p == '=') {
                    p++;
754
                    rtsp_parse_range(&th->server_port_min,
755 756 757 758 759
                                     &th->server_port_max, &p);
                }
            } else if (!strcmp(parameter, "interleaved")) {
                if (*p == '=') {
                    p++;
760
                    rtsp_parse_range(&th->interleaved_min,
761 762 763
                                     &th->interleaved_max, &p);
                }
            } else if (!strcmp(parameter, "multicast")) {
764 765
                if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
                    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
766 767
            } else if (!strcmp(parameter, "ttl")) {
                if (*p == '=') {
768
                    char *end;
769
                    p++;
770 771
                    th->ttl = strtol(p, &end, 10);
                    p = end;
772 773 774 775 776
                }
            } else if (!strcmp(parameter, "destination")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
Martin Storsjö's avatar
Martin Storsjö committed
777
                    get_sockaddr(buf, &th->destination);
778
                }
779 780 781 782 783 784
            } else if (!strcmp(parameter, "source")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";,", &p);
                    av_strlcpy(th->source, buf, sizeof(th->source));
                }
785 786 787 788 789 790 791 792
            } else if (!strcmp(parameter, "mode")) {
                if (*p == '=') {
                    p++;
                    get_word_sep(buf, sizeof(buf), ";, ", &p);
                    if (!strcmp(buf, "record") ||
                        !strcmp(buf, "receive"))
                        th->mode_record = 1;
                }
793
            }
794

795 796 797 798 799 800 801 802 803 804 805 806
            while (*p != ';' && *p != '\0' && *p != ',')
                p++;
            if (*p == ';')
                p++;
        }
        if (*p == ',')
            p++;

        reply->nb_transports++;
    }
}

Martin Storsjö's avatar
Martin Storsjö committed
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831