Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtspdec.c @ e836b1b0

History | View | Annotate | Download (11.2 KB)

1
/*
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
        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
        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
        if (rt->transport == RTSP_TRANSPORT_RTP &&
71
            reply->range_start != AV_NOPTS_VALUE) {
72
            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
                if (!rtpctx || rtsp_st->stream_index < 0)
77
                    continue;
78
                st = s->streams[rtsp_st->stream_index];
79
                rtpctx->range_start_offset =
80
                    av_rescale_q(reply->range_start, AV_TIME_BASE_Q,
81
                                 st->time_base);
82
            }
83
        }
84
    }
85
    rt->state = RTSP_STATE_STREAMING;
86
    return 0;
87
}
88

    
89
/* 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
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
        return AVERROR_INVALIDDATA;
140

    
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
    rt->real_setup = rt->real_setup_cache + s->nb_streams;
165

    
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
    dprintf(s, "tcp_read_packet:\n");
188
#endif
189
redo:
190
    for (;;) {
191
        RTSPMessageHeader reply;
192

    
193
        ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL);
194
        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
    dprintf(s, "id=%d len=%d\n", id, len);
209
#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
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
233
{
234
    RTSPState *rt = s->priv_data;
235
    int ret;
236
    RTSPMessageHeader reply1, *reply = &reply1;
237
    char cmd[1024];
238

    
239
    if (rt->server_type == RTSP_SERVER_REAL) {
240
        int i;
241

    
242
        for (i = 0; i < s->nb_streams; i++)
243
            rt->real_setup[i] = s->streams[i]->discard;
244

    
245
        if (!rt->need_subscription) {
246
            if (memcmp (rt->real_setup, rt->real_setup_cache,
247
                        sizeof(enum AVDiscard) * s->nb_streams)) {
248
                snprintf(cmd, sizeof(cmd),
249
                         "Unsubscribe: %s\r\n",
250
                         rt->last_subscription);
251
                ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
252
                                 cmd, reply, NULL);
253
                if (reply->status_code != RTSP_STATUS_OK)
254
                    return AVERROR_INVALIDDATA;
255
                rt->need_subscription = 1;
256
            }
257
        }
258

    
259
        if (rt->need_subscription) {
260
            int r, rule_nr, first = 1;
261

    
262
            memcpy(rt->real_setup_cache, rt->real_setup,
263
                   sizeof(enum AVDiscard) * s->nb_streams);
264
            rt->last_subscription[0] = 0;
265

    
266
            snprintf(cmd, sizeof(cmd),
267
                     "Subscribe: ");
268
            for (i = 0; i < rt->nb_rtsp_streams; i++) {
269
                rule_nr = 0;
270
                for (r = 0; r < s->nb_streams; r++) {
271
                    if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
272
                        if (s->streams[r]->discard != AVDISCARD_ALL) {
273
                            if (!first)
274
                                av_strlcat(rt->last_subscription, ",",
275
                                           sizeof(rt->last_subscription));
276
                            ff_rdt_subscribe_rule(
277
                                rt->last_subscription,
278
                                sizeof(rt->last_subscription), i, rule_nr);
279
                            first = 0;
280
                        }
281
                        rule_nr++;
282
                    }
283
                }
284
            }
285
            av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
286
            ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
287
                             cmd, reply, NULL);
288
            if (reply->status_code != RTSP_STATUS_OK)
289
                return AVERROR_INVALIDDATA;
290
            rt->need_subscription = 0;
291

    
292
            if (rt->state == RTSP_STATE_STREAMING)
293
                rtsp_read_play (s);
294
        }
295
    }
296

    
297
    ret = ff_rtsp_fetch_packet(s, pkt);
298
    if (ret < 0)
299
        return ret;
300

    
301
    /* send dummy request to keep TCP connection alive */
302
    if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
303
        if (rt->server_type == RTSP_SERVER_WMS) {
304
            ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
305
        } else {
306
            ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
307
        }
308
    }
309

    
310
    return 0;
311
}
312

    
313
static int rtsp_read_seek(AVFormatContext *s, int stream_index,
314
                          int64_t timestamp, int flags)
315
{
316
    RTSPState *rt = s->priv_data;
317

    
318
    rt->seek_timestamp = av_rescale_q(timestamp,
319
                                      s->streams[stream_index]->time_base,
320
                                      AV_TIME_BASE_Q);
321
    switch(rt->state) {
322
    default:
323
    case RTSP_STATE_IDLE:
324
        break;
325
    case RTSP_STATE_STREAMING:
326
        if (rtsp_read_pause(s) != 0)
327
            return -1;
328
        rt->state = RTSP_STATE_SEEKING;
329
        if (rtsp_read_play(s) != 0)
330
            return -1;
331
        break;
332
    case RTSP_STATE_PAUSED:
333
        rt->state = RTSP_STATE_IDLE;
334
        break;
335
    }
336
    return 0;
337
}
338

    
339
static int rtsp_read_close(AVFormatContext *s)
340
{
341
    RTSPState *rt = s->priv_data;
342

    
343
#if 0
344
    /* NOTE: it is valid to flush the buffer here */
345
    if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
346
        url_fclose(&rt->rtsp_gb);
347
    }
348
#endif
349
    ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
350

    
351
    ff_rtsp_close_streams(s);
352
    ff_rtsp_close_connections(s);
353
    ff_network_close();
354
    rt->real_setup = NULL;
355
    av_freep(&rt->real_setup_cache);
356
    return 0;
357
}
358

    
359
AVInputFormat rtsp_demuxer = {
360
    "rtsp",
361
    NULL_IF_CONFIG_SMALL("RTSP input format"),
362
    sizeof(RTSPState),
363
    rtsp_probe,
364
    rtsp_read_header,
365
    rtsp_read_packet,
366
    rtsp_read_close,
367
    rtsp_read_seek,
368
    .flags = AVFMT_NOFILE,
369
    .read_play = rtsp_read_play,
370
    .read_pause = rtsp_read_pause,
371
};