Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtspdec.c @ b2dd842d

History | View | Annotate | Download (12.6 KB)

1 0526c6f7 Martin Storsjö
/*
2
 * RTSP demuxer
3
 * Copyright (c) 2002 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * 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
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * 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/avstring.h"
23
#include "libavutil/intreadwrite.h"
24
#include "avformat.h"
25
26
#include "internal.h"
27
#include "network.h"
28
#include "os_support.h"
29
#include "rtsp.h"
30
#include "rdt.h"
31
32
//#define DEBUG
33
//#define DEBUG_RTP_TCP
34
35
static int rtsp_read_play(AVFormatContext *s)
36
{
37
    RTSPState *rt = s->priv_data;
38
    RTSPMessageHeader reply1, *reply = &reply1;
39
    int i;
40
    char cmd[1024];
41
42
    av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
43
    rt->nb_byes = 0;
44
45
    if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
46 1726813f Martin Storsjö
        if (rt->transport == RTSP_TRANSPORT_RTP) {
47
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
48
                RTSPStream *rtsp_st = rt->rtsp_streams[i];
49
                RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
50
                if (!rtpctx)
51
                    continue;
52
                ff_rtp_reset_packet_queue(rtpctx);
53
                rtpctx->last_rtcp_ntp_time  = AV_NOPTS_VALUE;
54
                rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE;
55
                rtpctx->base_timestamp      = 0;
56
                rtpctx->rtcp_ts_offset      = 0;
57
            }
58
        }
59 0526c6f7 Martin Storsjö
        if (rt->state == RTSP_STATE_PAUSED) {
60
            cmd[0] = 0;
61
        } else {
62
            snprintf(cmd, sizeof(cmd),
63
                     "Range: npt=%0.3f-\r\n",
64
                     (double)rt->seek_timestamp / AV_TIME_BASE);
65
        }
66
        ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
67
        if (reply->status_code != RTSP_STATUS_OK) {
68
            return -1;
69
        }
70 91d96bd3 Martin Storsjö
        if (rt->transport == RTSP_TRANSPORT_RTP &&
71
            reply->range_start != AV_NOPTS_VALUE) {
72 0526c6f7 Martin Storsjö
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
73
                RTSPStream *rtsp_st = rt->rtsp_streams[i];
74
                RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
75
                AVStream *st = NULL;
76 91d96bd3 Martin Storsjö
                if (!rtpctx || rtsp_st->stream_index < 0)
77 0526c6f7 Martin Storsjö
                    continue;
78 91d96bd3 Martin Storsjö
                st = s->streams[rtsp_st->stream_index];
79 4cb06874 Martin Storsjö
                rtpctx->range_start_offset =
80
                    av_rescale_q(reply->range_start, AV_TIME_BASE_Q,
81
                                 st->time_base);
82 0526c6f7 Martin Storsjö
            }
83
        }
84
    }
85
    rt->state = RTSP_STATE_STREAMING;
86
    return 0;
87
}
88
89 e836b1b0 Martin Storsjo
/* pause the stream */
90
static int rtsp_read_pause(AVFormatContext *s)
91
{
92
    RTSPState *rt = s->priv_data;
93
    RTSPMessageHeader reply1, *reply = &reply1;
94
95
    if (rt->state != RTSP_STATE_STREAMING)
96
        return 0;
97
    else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
98
        ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
99
        if (reply->status_code != RTSP_STATUS_OK) {
100
            return -1;
101
        }
102
    }
103
    rt->state = RTSP_STATE_PAUSED;
104
    return 0;
105
}
106
107 0526c6f7 Martin Storsjö
int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
108
{
109
    RTSPState *rt = s->priv_data;
110
    char cmd[1024];
111
    unsigned char *content = NULL;
112
    int ret;
113
114
    /* describe the stream */
115
    snprintf(cmd, sizeof(cmd),
116
             "Accept: application/sdp\r\n");
117
    if (rt->server_type == RTSP_SERVER_REAL) {
118
        /**
119
         * The Require: attribute is needed for proper streaming from
120
         * Realmedia servers.
121
         */
122
        av_strlcat(cmd,
123
                   "Require: com.real.retain-entity-for-setup\r\n",
124
                   sizeof(cmd));
125
    }
126
    ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
127
    if (!content)
128
        return AVERROR_INVALIDDATA;
129
    if (reply->status_code != RTSP_STATUS_OK) {
130
        av_freep(&content);
131
        return AVERROR_INVALIDDATA;
132
    }
133
134
    av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content);
135
    /* now we got the SDP description, we parse it */
136
    ret = ff_sdp_parse(s, (const char *)content);
137
    av_freep(&content);
138
    if (ret < 0)
139 f81c7ac7 Luca Barbato
        return ret;
140 0526c6f7 Martin Storsjö
141
    return 0;
142
}
143
144
static int rtsp_probe(AVProbeData *p)
145
{
146
    if (av_strstart(p->filename, "rtsp:", NULL))
147
        return AVPROBE_SCORE_MAX;
148
    return 0;
149
}
150
151
static int rtsp_read_header(AVFormatContext *s,
152
                            AVFormatParameters *ap)
153
{
154
    RTSPState *rt = s->priv_data;
155
    int ret;
156
157
    ret = ff_rtsp_connect(s);
158
    if (ret)
159
        return ret;
160
161
    rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache));
162
    if (!rt->real_setup_cache)
163
        return AVERROR(ENOMEM);
164 c77549c5 Yuriy Kaminskiy
    rt->real_setup = rt->real_setup_cache + s->nb_streams;
165 0526c6f7 Martin Storsjö
166
    if (ap->initial_pause) {
167
         /* do not start immediately */
168
    } else {
169
         if (rtsp_read_play(s) < 0) {
170
            ff_rtsp_close_streams(s);
171
            ff_rtsp_close_connections(s);
172
            return AVERROR_INVALIDDATA;
173
        }
174
    }
175
176
    return 0;
177
}
178
179
int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
180
                            uint8_t *buf, int buf_size)
181
{
182
    RTSPState *rt = s->priv_data;
183
    int id, len, i, ret;
184
    RTSPStream *rtsp_st;
185
186
#ifdef DEBUG_RTP_TCP
187 dfd2a005 Luca Barbato
    av_dlog(s, "tcp_read_packet:\n");
188 0526c6f7 Martin Storsjö
#endif
189
redo:
190
    for (;;) {
191
        RTSPMessageHeader reply;
192
193 3df54c6b Martin Storsjö
        ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL);
194 0526c6f7 Martin Storsjö
        if (ret < 0)
195
            return ret;
196
        if (ret == 1) /* received '$' */
197
            break;
198
        /* XXX: parse message */
199
        if (rt->state != RTSP_STATE_STREAMING)
200
            return 0;
201
    }
202
    ret = url_read_complete(rt->rtsp_hd, buf, 3);
203
    if (ret != 3)
204
        return -1;
205
    id  = buf[0];
206
    len = AV_RB16(buf + 1);
207
#ifdef DEBUG_RTP_TCP
208 dfd2a005 Luca Barbato
    av_dlog(s, "id=%d len=%d\n", id, len);
209 0526c6f7 Martin Storsjö
#endif
210
    if (len > buf_size || len < 12)
211
        goto redo;
212
    /* get the data */
213
    ret = url_read_complete(rt->rtsp_hd, buf, len);
214
    if (ret != len)
215
        return -1;
216
    if (rt->transport == RTSP_TRANSPORT_RDT &&
217
        ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
218
        return -1;
219
220
    /* find the matching stream */
221
    for (i = 0; i < rt->nb_rtsp_streams; i++) {
222
        rtsp_st = rt->rtsp_streams[i];
223
        if (id >= rtsp_st->interleaved_min &&
224
            id <= rtsp_st->interleaved_max)
225
            goto found;
226
    }
227
    goto redo;
228
found:
229
    *prtsp_st = rtsp_st;
230
    return len;
231
}
232 2762a7a2 Martin Storsjö
233
static int resetup_tcp(AVFormatContext *s)
234
{
235
    RTSPState *rt = s->priv_data;
236
    char host[1024];
237
    int port;
238
239
    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
240
                 s->filename);
241
    ff_rtsp_undo_setup(s);
242
    return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP,
243
                                      rt->real_challenge);
244
}
245
246 0526c6f7 Martin Storsjö
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
247
{
248
    RTSPState *rt = s->priv_data;
249
    int ret;
250
    RTSPMessageHeader reply1, *reply = &reply1;
251
    char cmd[1024];
252
253 2762a7a2 Martin Storsjö
retry:
254 0526c6f7 Martin Storsjö
    if (rt->server_type == RTSP_SERVER_REAL) {
255
        int i;
256
257
        for (i = 0; i < s->nb_streams; i++)
258
            rt->real_setup[i] = s->streams[i]->discard;
259
260
        if (!rt->need_subscription) {
261
            if (memcmp (rt->real_setup, rt->real_setup_cache,
262
                        sizeof(enum AVDiscard) * s->nb_streams)) {
263
                snprintf(cmd, sizeof(cmd),
264
                         "Unsubscribe: %s\r\n",
265
                         rt->last_subscription);
266
                ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
267
                                 cmd, reply, NULL);
268
                if (reply->status_code != RTSP_STATUS_OK)
269
                    return AVERROR_INVALIDDATA;
270
                rt->need_subscription = 1;
271
            }
272
        }
273
274
        if (rt->need_subscription) {
275
            int r, rule_nr, first = 1;
276
277
            memcpy(rt->real_setup_cache, rt->real_setup,
278
                   sizeof(enum AVDiscard) * s->nb_streams);
279
            rt->last_subscription[0] = 0;
280
281
            snprintf(cmd, sizeof(cmd),
282
                     "Subscribe: ");
283
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
284
                rule_nr = 0;
285
                for (r = 0; r < s->nb_streams; r++) {
286 b2dd842d Martin Storsjö
                    if (s->streams[r]->id == i) {
287 0526c6f7 Martin Storsjö
                        if (s->streams[r]->discard != AVDISCARD_ALL) {
288
                            if (!first)
289
                                av_strlcat(rt->last_subscription, ",",
290
                                           sizeof(rt->last_subscription));
291
                            ff_rdt_subscribe_rule(
292
                                rt->last_subscription,
293
                                sizeof(rt->last_subscription), i, rule_nr);
294
                            first = 0;
295
                        }
296
                        rule_nr++;
297
                    }
298
                }
299
            }
300
            av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
301
            ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
302
                             cmd, reply, NULL);
303
            if (reply->status_code != RTSP_STATUS_OK)
304
                return AVERROR_INVALIDDATA;
305
            rt->need_subscription = 0;
306
307
            if (rt->state == RTSP_STATE_STREAMING)
308
                rtsp_read_play (s);
309
        }
310
    }
311
312
    ret = ff_rtsp_fetch_packet(s, pkt);
313 2762a7a2 Martin Storsjö
    if (ret < 0) {
314
        if (ret == FF_NETERROR(ETIMEDOUT) && !rt->packets) {
315
            if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
316
                rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) {
317
                RTSPMessageHeader reply1, *reply = &reply1;
318
                av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n");
319
                if (rtsp_read_pause(s) != 0)
320
                    return -1;
321
                // TEARDOWN is required on Real-RTSP, but might make
322
                // other servers close the connection.
323
                if (rt->server_type == RTSP_SERVER_REAL)
324
                    ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL,
325
                                     reply, NULL);
326
                rt->session_id[0] = '\0';
327
                if (resetup_tcp(s) == 0) {
328
                    rt->state = RTSP_STATE_IDLE;
329
                    rt->need_subscription = 1;
330
                    if (rtsp_read_play(s) != 0)
331
                        return -1;
332
                    goto retry;
333
                }
334
            }
335
        }
336 0526c6f7 Martin Storsjö
        return ret;
337 2762a7a2 Martin Storsjö
    }
338
    rt->packets++;
339 0526c6f7 Martin Storsjö
340
    /* send dummy request to keep TCP connection alive */
341
    if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
342
        if (rt->server_type == RTSP_SERVER_WMS) {
343
            ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
344
        } else {
345
            ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
346
        }
347
    }
348
349
    return 0;
350
}
351
352
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
353
                          int64_t timestamp, int flags)
354
{
355
    RTSPState *rt = s->priv_data;
356
357
    rt->seek_timestamp = av_rescale_q(timestamp,
358
                                      s->streams[stream_index]->time_base,
359
                                      AV_TIME_BASE_Q);
360
    switch(rt->state) {
361
    default:
362
    case RTSP_STATE_IDLE:
363
        break;
364
    case RTSP_STATE_STREAMING:
365
        if (rtsp_read_pause(s) != 0)
366
            return -1;
367
        rt->state = RTSP_STATE_SEEKING;
368
        if (rtsp_read_play(s) != 0)
369
            return -1;
370
        break;
371
    case RTSP_STATE_PAUSED:
372
        rt->state = RTSP_STATE_IDLE;
373
        break;
374
    }
375
    return 0;
376
}
377
378
static int rtsp_read_close(AVFormatContext *s)
379
{
380
    RTSPState *rt = s->priv_data;
381
382
#if 0
383
    /* NOTE: it is valid to flush the buffer here */
384
    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
385
        url_fclose(&rt->rtsp_gb);
386
    }
387
#endif
388
    ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
389
390
    ff_rtsp_close_streams(s);
391
    ff_rtsp_close_connections(s);
392
    ff_network_close();
393
    rt->real_setup = NULL;
394
    av_freep(&rt->real_setup_cache);
395
    return 0;
396
}
397
398 c6610a21 Diego Elio Pettenò
AVInputFormat ff_rtsp_demuxer = {
399 0526c6f7 Martin Storsjö
    "rtsp",
400
    NULL_IF_CONFIG_SMALL("RTSP input format"),
401
    sizeof(RTSPState),
402
    rtsp_probe,
403
    rtsp_read_header,
404
    rtsp_read_packet,
405
    rtsp_read_close,
406
    rtsp_read_seek,
407
    .flags = AVFMT_NOFILE,
408
    .read_play = rtsp_read_play,
409
    .read_pause = rtsp_read_pause,
410
};