Mercurial > libavformat.hg
annotate rtsp.c @ 3877:3e0c7ad2a675 libavformat
Remove unused code that used to handle protocol concatenation, i.e. trying
multiple protocols at the same time. We now cycle protocols individually
to autodetect, making this code no longer needed, and thus the support code
for it in make_setup_request() can be removed. See "[PATCH] remove transport
concatenation dead code" on mailinglist.
author | rbultje |
---|---|
date | Wed, 03 Sep 2008 04:47:44 +0000 |
parents | 1026953d4ffe |
children | aeb79f68ba7e |
rev | line source |
---|---|
0 | 1 /* |
2 * RTSP/SDP client | |
3 * Copyright (c) 2002 Fabrice Bellard. | |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
3286 | 21 |
3722
68749aaea50f
ensure we get explicit definition of various _XOPEN_SOURCE functions we use
aurel
parents:
3714
diff
changeset
|
22 /* needed by inet_aton() */ |
68749aaea50f
ensure we get explicit definition of various _XOPEN_SOURCE functions we use
aurel
parents:
3714
diff
changeset
|
23 #define _SVID_SOURCE |
68749aaea50f
ensure we get explicit definition of various _XOPEN_SOURCE functions we use
aurel
parents:
3714
diff
changeset
|
24 |
3286 | 25 #include "libavutil/avstring.h" |
0 | 26 #include "avformat.h" |
27 | |
1808
572ce77d7333
Fix compilation on Mac OS X, patch by Marc Hoffman, mmh pleasantst com.
diego
parents:
1754
diff
changeset
|
28 #include <sys/time.h> |
182 | 29 #include <unistd.h> /* for select() prototype */ |
3714 | 30 #include <strings.h> |
1754 | 31 #include "network.h" |
2681
6037eb4919fb
Remove the inclusion of rtsp.h and rtp.h from avformat.h, and
lucabe
parents:
2408
diff
changeset
|
32 #include "rtsp.h" |
0 | 33 |
1419 | 34 #include "rtp_internal.h" |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
35 #include "rdt.h" |
1419 | 36 |
0 | 37 //#define DEBUG |
172 | 38 //#define DEBUG_RTP_TCP |
0 | 39 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
40 enum RTSPClientState { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
41 RTSP_STATE_IDLE, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
42 RTSP_STATE_PLAYING, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
43 RTSP_STATE_PAUSED, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
44 }; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
45 |
3854
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
46 enum RTSPServerType { |
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
47 RTSP_SERVER_RTP, /*< Standard-compliant RTP-server */ |
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
48 RTSP_SERVER_RDT, /*< Realmedia-style server */ |
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
49 RTSP_SERVER_LAST |
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
50 }; |
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
51 |
0 | 52 typedef struct RTSPState { |
53 URLContext *rtsp_hd; /* RTSP TCP connexion handle */ | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
54 int nb_rtsp_streams; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
55 struct RTSPStream **rtsp_streams; |
885 | 56 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
57 enum RTSPClientState state; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
58 int64_t seek_timestamp; |
885 | 59 |
172 | 60 /* XXX: currently we use unbuffered input */ |
61 // ByteIOContext rtsp_gb; | |
0 | 62 int seq; /* RTSP command sequence number */ |
63 char session_id[512]; | |
64 enum RTSPProtocol protocol; | |
3854
8b2b84b5ef74
Implement RTSPServerType enum as a way to identify the flavour of RTSP that
rbultje
parents:
3853
diff
changeset
|
65 enum RTSPServerType server_type; |
0 | 66 char last_reply[2048]; /* XXX: allocate ? */ |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
67 RTPDemuxContext *cur_rtp; |
0 | 68 } RTSPState; |
69 | |
70 typedef struct RTSPStream { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
71 URLContext *rtp_handle; /* RTP stream handle */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
72 RTPDemuxContext *rtp_ctx; /* RTP parse context */ |
885 | 73 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
74 int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */ |
0 | 75 int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */ |
76 char control_url[1024]; /* url for this stream (from SDP) */ | |
77 | |
78 int sdp_port; /* port (from SDP content - not used in RTSP) */ | |
79 struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */ | |
80 int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */ | |
81 int sdp_payload_type; /* payload type - only used in SDP */ | |
774 | 82 rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */ |
1419 | 83 |
84 RTPDynamicProtocolHandler *dynamic_handler; ///< Only valid if it's a dynamic protocol. (This is the handler structure) | |
85 void *dynamic_protocol_context; ///< Only valid if it's a dynamic protocol. (This is any private data associated with the dynamic protocol) | |
0 | 86 } RTSPStream; |
87 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
88 static int rtsp_read_play(AVFormatContext *s); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
89 |
0 | 90 /* XXX: currently, the only way to change the protocols consists in |
91 changing this variable */ | |
92 | |
2884 | 93 #if LIBAVFORMAT_VERSION_INT < (53 << 16) |
774 | 94 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP); |
2884 | 95 #endif |
0 | 96 |
97 static int rtsp_probe(AVProbeData *p) | |
98 { | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
99 if (av_strstart(p->filename, "rtsp:", NULL)) |
0 | 100 return AVPROBE_SCORE_MAX; |
101 return 0; | |
102 } | |
103 | |
104 static int redir_isspace(int c) | |
105 { | |
3278 | 106 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; |
0 | 107 } |
108 | |
109 static void skip_spaces(const char **pp) | |
110 { | |
111 const char *p; | |
112 p = *pp; | |
113 while (redir_isspace(*p)) | |
114 p++; | |
115 *pp = p; | |
116 } | |
117 | |
885 | 118 static void get_word_sep(char *buf, int buf_size, const char *sep, |
0 | 119 const char **pp) |
120 { | |
121 const char *p; | |
122 char *q; | |
123 | |
124 p = *pp; | |
774 | 125 if (*p == '/') |
126 p++; | |
0 | 127 skip_spaces(&p); |
128 q = buf; | |
129 while (!strchr(sep, *p) && *p != '\0') { | |
130 if ((q - buf) < buf_size - 1) | |
131 *q++ = *p; | |
132 p++; | |
133 } | |
134 if (buf_size > 0) | |
135 *q = '\0'; | |
136 *pp = p; | |
137 } | |
138 | |
139 static void get_word(char *buf, int buf_size, const char **pp) | |
140 { | |
141 const char *p; | |
142 char *q; | |
143 | |
144 p = *pp; | |
145 skip_spaces(&p); | |
146 q = buf; | |
147 while (!redir_isspace(*p) && *p != '\0') { | |
148 if ((q - buf) < buf_size - 1) | |
149 *q++ = *p; | |
150 p++; | |
151 } | |
152 if (buf_size > 0) | |
153 *q = '\0'; | |
154 *pp = p; | |
155 } | |
156 | |
157 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other | |
158 params>] */ | |
1419 | 159 static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p) |
0 | 160 { |
161 char buf[256]; | |
774 | 162 int i; |
163 AVCodec *c; | |
1124
d3aff2c607f9
Add const to (mostly) char* and make some functions static, which aren't used
diego
parents:
1003
diff
changeset
|
164 const char *c_name; |
0 | 165 |
774 | 166 /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and |
167 see if we can handle this kind of payload */ | |
0 | 168 get_word_sep(buf, sizeof(buf), "/", &p); |
774 | 169 if (payload_type >= RTP_PT_PRIVATE) { |
1419 | 170 RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler; |
171 while(handler) { | |
172 if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) { | |
173 codec->codec_id = handler->codec_id; | |
174 rtsp_st->dynamic_handler= handler; | |
175 if(handler->open) { | |
176 rtsp_st->dynamic_protocol_context= handler->open(); | |
177 } | |
774 | 178 break; |
179 } | |
1419 | 180 handler= handler->next; |
181 } | |
774 | 182 } else { |
183 /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */ | |
184 /* search into AVRtpPayloadTypes[] */ | |
2759
b252e318023a
Remove the "AVRtpPayloadTypes[i].pt == i" assumption from RTP and RTSP
lucabe
parents:
2711
diff
changeset
|
185 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type); |
774 | 186 } |
187 | |
188 c = avcodec_find_decoder(codec->codec_id); | |
189 if (c && c->name) | |
1124
d3aff2c607f9
Add const to (mostly) char* and make some functions static, which aren't used
diego
parents:
1003
diff
changeset
|
190 c_name = c->name; |
774 | 191 else |
192 c_name = (char *)NULL; | |
193 | |
194 if (c_name) { | |
195 get_word_sep(buf, sizeof(buf), "/", &p); | |
196 i = atoi(buf); | |
197 switch (codec->codec_type) { | |
198 case CODEC_TYPE_AUDIO: | |
199 av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name); | |
200 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE; | |
201 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS; | |
202 if (i > 0) { | |
203 codec->sample_rate = i; | |
204 get_word_sep(buf, sizeof(buf), "/", &p); | |
205 i = atoi(buf); | |
206 if (i > 0) | |
207 codec->channels = i; | |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
208 // TODO: there is a bug here; if it is a mono stream, and less than 22000Hz, faad upconverts to stereo and twice the |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
209 // frequency. No problem, but the sample rate is being set here by the sdp line. Upcoming patch forthcoming. (rdm) |
774 | 210 } |
211 av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate); | |
212 av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels); | |
213 break; | |
214 case CODEC_TYPE_VIDEO: | |
215 av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name); | |
216 break; | |
217 default: | |
218 break; | |
219 } | |
0 | 220 return 0; |
221 } | |
774 | 222 |
223 return -1; | |
0 | 224 } |
225 | |
226 /* return the length and optionnaly the data */ | |
227 static int hex_to_data(uint8_t *data, const char *p) | |
228 { | |
229 int c, len, v; | |
230 | |
231 len = 0; | |
232 v = 1; | |
233 for(;;) { | |
234 skip_spaces(&p); | |
235 if (p == '\0') | |
236 break; | |
237 c = toupper((unsigned char)*p++); | |
238 if (c >= '0' && c <= '9') | |
239 c = c - '0'; | |
240 else if (c >= 'A' && c <= 'F') | |
241 c = c - 'A' + 10; | |
242 else | |
243 break; | |
244 v = (v << 4) | c; | |
245 if (v & 0x100) { | |
246 if (data) | |
247 data[len] = v; | |
248 len++; | |
249 v = 1; | |
250 } | |
251 } | |
252 return len; | |
253 } | |
254 | |
774 | 255 static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value) |
256 { | |
257 switch (codec->codec_id) { | |
258 case CODEC_ID_MPEG4: | |
1472
49d5a5ca2987
get rid of CODEC_ID_MPEG4AAC after next version bump, and change it to CODEC_ID_AAC where used
bcoudurier
parents:
1453
diff
changeset
|
259 case CODEC_ID_AAC: |
774 | 260 if (!strcmp(attr, "config")) { |
261 /* decode the hexa encoded parameter */ | |
262 int len = hex_to_data(NULL, value); | |
263 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); | |
264 if (!codec->extradata) | |
265 return; | |
266 codec->extradata_size = len; | |
267 hex_to_data(codec->extradata, value); | |
268 } | |
269 break; | |
270 default: | |
271 break; | |
272 } | |
273 return; | |
274 } | |
275 | |
276 typedef struct attrname_map | |
277 { | |
1124
d3aff2c607f9
Add const to (mostly) char* and make some functions static, which aren't used
diego
parents:
1003
diff
changeset
|
278 const char *str; |
774 | 279 uint16_t type; |
280 uint32_t offset; | |
281 } attrname_map_t; | |
282 | |
283 /* All known fmtp parmeters and the corresping RTPAttrTypeEnum */ | |
284 #define ATTR_NAME_TYPE_INT 0 | |
285 #define ATTR_NAME_TYPE_STR 1 | |
286 static attrname_map_t attr_names[]= | |
287 { | |
288 {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)}, | |
289 {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)}, | |
290 {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)}, | |
291 {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)}, | |
292 {"StreamType", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)}, | |
293 {"mode", ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)}, | |
294 {NULL, -1, -1}, | |
295 }; | |
296 | |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
297 /** parse the attribute line from the fmtp a line of an sdp resonse. This is broken out as a function |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
298 * because it is used in rtp_h264.c, which is forthcoming. |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
299 */ |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
300 int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size) |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
301 { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
302 skip_spaces(p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
303 if(**p) |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
304 { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
305 get_word_sep(attr, attr_size, "=", p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
306 if (**p == '=') |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
307 (*p)++; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
308 get_word_sep(value, value_size, ";", p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
309 if (**p == ';') |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
310 (*p)++; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
311 return 1; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
312 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
313 return 0; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
314 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
315 |
774 | 316 /* parse a SDP line and save stream attributes */ |
317 static void sdp_parse_fmtp(AVStream *st, const char *p) | |
0 | 318 { |
319 char attr[256]; | |
320 char value[4096]; | |
774 | 321 int i; |
322 | |
323 RTSPStream *rtsp_st = st->priv_data; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
774
diff
changeset
|
324 AVCodecContext *codec = st->codec; |
774 | 325 rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data; |
0 | 326 |
327 /* loop on each attribute */ | |
1514
958decd51c1f
remove duplicate code, patch by Ryan Martell rdm4 A martellventures P com
gpoirier
parents:
1472
diff
changeset
|
328 while(rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value))) |
958decd51c1f
remove duplicate code, patch by Ryan Martell rdm4 A martellventures P com
gpoirier
parents:
1472
diff
changeset
|
329 { |
887 | 330 /* grab the codec extra_data from the config parameter of the fmtp line */ |
774 | 331 sdp_parse_fmtp_config(codec, attr, value); |
332 /* Looking for a known attribute */ | |
333 for (i = 0; attr_names[i].str; ++i) { | |
334 if (!strcasecmp(attr, attr_names[i].str)) { | |
335 if (attr_names[i].type == ATTR_NAME_TYPE_INT) | |
336 *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value); | |
337 else if (attr_names[i].type == ATTR_NAME_TYPE_STR) | |
338 *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value); | |
887 | 339 } |
0 | 340 } |
341 } | |
342 } | |
343 | |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
344 /** Parse a string \p in the form of Range:npt=xx-xx, and determine the start |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
345 * and end time. |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
346 * Used for seeking in the rtp stream. |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
347 */ |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
348 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
349 { |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
350 char buf[256]; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
351 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
352 skip_spaces(&p); |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
353 if (!av_stristart(p, "npt=", &p)) |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
354 return; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
355 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
356 *start = AV_NOPTS_VALUE; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
357 *end = AV_NOPTS_VALUE; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
358 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
359 get_word_sep(buf, sizeof(buf), "-", &p); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
360 *start = parse_date(buf, 1); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
361 if (*p == '-') { |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
362 p++; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
363 get_word_sep(buf, sizeof(buf), "-", &p); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
364 *end = parse_date(buf, 1); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
365 } |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
366 // av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
367 // av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
368 } |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
369 |
0 | 370 typedef struct SDPParseState { |
371 /* SDP only */ | |
372 struct in_addr default_ip; | |
373 int default_ttl; | |
374 } SDPParseState; | |
375 | |
376 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | |
377 int letter, const char *buf) | |
378 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
379 RTSPState *rt = s->priv_data; |
0 | 380 char buf1[64], st_type[64]; |
381 const char *p; | |
382 int codec_type, payload_type, i; | |
383 AVStream *st; | |
384 RTSPStream *rtsp_st; | |
385 struct in_addr sdp_ip; | |
386 int ttl; | |
387 | |
388 #ifdef DEBUG | |
389 printf("sdp: %c='%s'\n", letter, buf); | |
390 #endif | |
391 | |
392 p = buf; | |
393 switch(letter) { | |
394 case 'c': | |
395 get_word(buf1, sizeof(buf1), &p); | |
396 if (strcmp(buf1, "IN") != 0) | |
397 return; | |
398 get_word(buf1, sizeof(buf1), &p); | |
399 if (strcmp(buf1, "IP4") != 0) | |
400 return; | |
401 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
402 if (inet_aton(buf1, &sdp_ip) == 0) | |
403 return; | |
404 ttl = 16; | |
405 if (*p == '/') { | |
406 p++; | |
407 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
408 ttl = atoi(buf1); | |
409 } | |
410 if (s->nb_streams == 0) { | |
411 s1->default_ip = sdp_ip; | |
412 s1->default_ttl = ttl; | |
413 } else { | |
414 st = s->streams[s->nb_streams - 1]; | |
415 rtsp_st = st->priv_data; | |
416 rtsp_st->sdp_ip = sdp_ip; | |
417 rtsp_st->sdp_ttl = ttl; | |
418 } | |
419 break; | |
420 case 's': | |
2189 | 421 av_strlcpy(s->title, p, sizeof(s->title)); |
0 | 422 break; |
423 case 'i': | |
424 if (s->nb_streams == 0) { | |
2189 | 425 av_strlcpy(s->comment, p, sizeof(s->comment)); |
0 | 426 break; |
427 } | |
428 break; | |
429 case 'm': | |
430 /* new stream */ | |
431 get_word(st_type, sizeof(st_type), &p); | |
432 if (!strcmp(st_type, "audio")) { | |
433 codec_type = CODEC_TYPE_AUDIO; | |
434 } else if (!strcmp(st_type, "video")) { | |
435 codec_type = CODEC_TYPE_VIDEO; | |
436 } else { | |
437 return; | |
438 } | |
439 rtsp_st = av_mallocz(sizeof(RTSPStream)); | |
440 if (!rtsp_st) | |
441 return; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
442 rtsp_st->stream_index = -1; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
443 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); |
0 | 444 |
445 rtsp_st->sdp_ip = s1->default_ip; | |
446 rtsp_st->sdp_ttl = s1->default_ttl; | |
447 | |
448 get_word(buf1, sizeof(buf1), &p); /* port */ | |
449 rtsp_st->sdp_port = atoi(buf1); | |
450 | |
451 get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */ | |
885 | 452 |
0 | 453 /* XXX: handle list of formats */ |
454 get_word(buf1, sizeof(buf1), &p); /* format list */ | |
455 rtsp_st->sdp_payload_type = atoi(buf1); | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
456 |
2759
b252e318023a
Remove the "AVRtpPayloadTypes[i].pt == i" assumption from RTP and RTSP
lucabe
parents:
2711
diff
changeset
|
457 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
458 /* no corresponding stream */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
459 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
460 st = av_new_stream(s, 0); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
461 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
462 return; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
463 st->priv_data = rtsp_st; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
464 rtsp_st->stream_index = st->index; |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
774
diff
changeset
|
465 st->codec->codec_type = codec_type; |
774 | 466 if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
467 /* if standard payload type, we can find the codec right now */ |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
774
diff
changeset
|
468 rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type); |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
469 } |
0 | 470 } |
471 /* put a default control url */ | |
2189 | 472 av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url)); |
0 | 473 break; |
474 case 'a': | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
475 if (av_strstart(p, "control:", &p) && s->nb_streams > 0) { |
0 | 476 char proto[32]; |
477 /* get the control url */ | |
478 st = s->streams[s->nb_streams - 1]; | |
479 rtsp_st = st->priv_data; | |
885 | 480 |
0 | 481 /* XXX: may need to add full url resolution */ |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
391
diff
changeset
|
482 url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p); |
0 | 483 if (proto[0] == '\0') { |
484 /* relative control URL */ | |
2189 | 485 av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url)); |
486 av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); | |
0 | 487 } else { |
2189 | 488 av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); |
0 | 489 } |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
490 } else if (av_strstart(p, "rtpmap:", &p)) { |
0 | 491 /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ |
885 | 492 get_word(buf1, sizeof(buf1), &p); |
0 | 493 payload_type = atoi(buf1); |
494 for(i = 0; i < s->nb_streams;i++) { | |
495 st = s->streams[i]; | |
496 rtsp_st = st->priv_data; | |
497 if (rtsp_st->sdp_payload_type == payload_type) { | |
1419 | 498 sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p); |
0 | 499 } |
500 } | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
501 } else if (av_strstart(p, "fmtp:", &p)) { |
0 | 502 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ |
885 | 503 get_word(buf1, sizeof(buf1), &p); |
0 | 504 payload_type = atoi(buf1); |
505 for(i = 0; i < s->nb_streams;i++) { | |
506 st = s->streams[i]; | |
507 rtsp_st = st->priv_data; | |
508 if (rtsp_st->sdp_payload_type == payload_type) { | |
1419 | 509 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { |
510 if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) { | |
511 sdp_parse_fmtp(st, p); | |
512 } | |
513 } else { | |
1424
1c39ce5c6a5d
indentation fix, patch by Ryan Martell % rdm4 A martellventures P com %
gpoirier
parents:
1419
diff
changeset
|
514 sdp_parse_fmtp(st, p); |
1419 | 515 } |
0 | 516 } |
517 } | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
518 } else if(av_strstart(p, "framesize:", &p)) { |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
519 // let dynamic protocol handlers have a stab at the line. |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
520 get_word(buf1, sizeof(buf1), &p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
521 payload_type = atoi(buf1); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
522 for(i = 0; i < s->nb_streams;i++) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
523 st = s->streams[i]; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
524 rtsp_st = st->priv_data; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
525 if (rtsp_st->sdp_payload_type == payload_type) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
526 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
527 rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
528 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
529 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
530 } |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
531 } else if(av_strstart(p, "range:", &p)) { |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
532 int64_t start, end; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
533 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
534 // this is so that seeking on a streamed file can work. |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
535 rtsp_parse_range_npt(p, &start, &end); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
536 s->start_time= start; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
537 s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek) |
3784
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
538 } else if (s->nb_streams > 0) { |
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
539 rtsp_st = s->streams[s->nb_streams - 1]->priv_data; |
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
540 if (rtsp_st->dynamic_handler && |
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
541 rtsp_st->dynamic_handler->parse_sdp_a_line) |
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
542 rtsp_st->dynamic_handler->parse_sdp_a_line(s->streams[s->nb_streams - 1], |
d370d80ad1df
Use RTPDynamicProtocol parse_sdp_a_line() handlers in case of unknown SDP
rbultje
parents:
3722
diff
changeset
|
543 rtsp_st->dynamic_protocol_context, buf); |
0 | 544 } |
545 break; | |
546 } | |
547 } | |
548 | |
64 | 549 static int sdp_parse(AVFormatContext *s, const char *content) |
0 | 550 { |
551 const char *p; | |
552 int letter; | |
3860
d8fce96bb3ab
Some RTSP streams use SDP lines longer than 1024 bytes, so the SDP line
rbultje
parents:
3859
diff
changeset
|
553 char buf[2048], *q; |
0 | 554 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state; |
885 | 555 |
0 | 556 memset(s1, 0, sizeof(SDPParseState)); |
557 p = content; | |
558 for(;;) { | |
559 skip_spaces(&p); | |
560 letter = *p; | |
561 if (letter == '\0') | |
562 break; | |
563 p++; | |
564 if (*p != '=') | |
565 goto next_line; | |
566 p++; | |
567 /* get the content */ | |
568 q = buf; | |
172 | 569 while (*p != '\n' && *p != '\r' && *p != '\0') { |
0 | 570 if ((q - buf) < sizeof(buf) - 1) |
571 *q++ = *p; | |
572 p++; | |
573 } | |
574 *q = '\0'; | |
575 sdp_parse_line(s, s1, letter, buf); | |
576 next_line: | |
577 while (*p != '\n' && *p != '\0') | |
578 p++; | |
579 if (*p == '\n') | |
580 p++; | |
581 } | |
582 return 0; | |
583 } | |
584 | |
585 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) | |
586 { | |
587 const char *p; | |
588 int v; | |
589 | |
590 p = *pp; | |
591 skip_spaces(&p); | |
592 v = strtol(p, (char **)&p, 10); | |
593 if (*p == '-') { | |
594 p++; | |
595 *min_ptr = v; | |
596 v = strtol(p, (char **)&p, 10); | |
597 *max_ptr = v; | |
598 } else { | |
599 *min_ptr = v; | |
600 *max_ptr = v; | |
601 } | |
602 *pp = p; | |
603 } | |
604 | |
605 /* XXX: only one transport specification is parsed */ | |
606 static void rtsp_parse_transport(RTSPHeader *reply, const char *p) | |
607 { | |
608 char transport_protocol[16]; | |
609 char profile[16]; | |
610 char lower_transport[16]; | |
611 char parameter[16]; | |
612 RTSPTransportField *th; | |
613 char buf[256]; | |
885 | 614 |
0 | 615 reply->nb_transports = 0; |
885 | 616 |
0 | 617 for(;;) { |
618 skip_spaces(&p); | |
619 if (*p == '\0') | |
620 break; | |
621 | |
622 th = &reply->transports[reply->nb_transports]; | |
623 | |
885 | 624 get_word_sep(transport_protocol, sizeof(transport_protocol), |
0 | 625 "/", &p); |
626 if (*p == '/') | |
627 p++; | |
2865
51aa1054528c
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 2 x-pn-tng support
lu_zero
parents:
2864
diff
changeset
|
628 if (!strcasecmp (transport_protocol, "rtp")) { |
2866
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
629 get_word_sep(profile, sizeof(profile), "/;,", &p); |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
630 lower_transport[0] = '\0'; |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
631 /* rtp/avp/<protocol> */ |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
632 if (*p == '/') { |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
633 p++; |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
634 get_word_sep(lower_transport, sizeof(lower_transport), |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
635 ";,", &p); |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
636 } |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
637 } else if (!strcasecmp (transport_protocol, "x-pn-tng")) { |
ccbca87ccd5e
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 3 Reindent
lu_zero
parents:
2865
diff
changeset
|
638 /* x-pn-tng/<protocol> */ |
2865
51aa1054528c
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 2 x-pn-tng support
lu_zero
parents:
2864
diff
changeset
|
639 get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p); |
51aa1054528c
Real RTSP support, from Ronald S. Bultje rsbultje gmail - part 2 x-pn-tng support
lu_zero
parents:
2864
diff
changeset
|
640 profile[0] = '\0'; |
0 | 641 } |
172 | 642 if (!strcasecmp(lower_transport, "TCP")) |
0 | 643 th->protocol = RTSP_PROTOCOL_RTP_TCP; |
644 else | |
645 th->protocol = RTSP_PROTOCOL_RTP_UDP; | |
885 | 646 |
0 | 647 if (*p == ';') |
648 p++; | |
649 /* get each parameter */ | |
650 while (*p != '\0' && *p != ',') { | |
651 get_word_sep(parameter, sizeof(parameter), "=;,", &p); | |
652 if (!strcmp(parameter, "port")) { | |
653 if (*p == '=') { | |
654 p++; | |
655 rtsp_parse_range(&th->port_min, &th->port_max, &p); | |
656 } | |
657 } else if (!strcmp(parameter, "client_port")) { | |
658 if (*p == '=') { | |
659 p++; | |
885 | 660 rtsp_parse_range(&th->client_port_min, |
0 | 661 &th->client_port_max, &p); |
662 } | |
663 } else if (!strcmp(parameter, "server_port")) { | |
664 if (*p == '=') { | |
665 p++; | |
885 | 666 rtsp_parse_range(&th->server_port_min, |
0 | 667 &th->server_port_max, &p); |
668 } | |
669 } else if (!strcmp(parameter, "interleaved")) { | |
670 if (*p == '=') { | |
671 p++; | |
885 | 672 rtsp_parse_range(&th->interleaved_min, |
0 | 673 &th->interleaved_max, &p); |
674 } | |
675 } else if (!strcmp(parameter, "multicast")) { | |
676 if (th->protocol == RTSP_PROTOCOL_RTP_UDP) | |
677 th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST; | |
678 } else if (!strcmp(parameter, "ttl")) { | |
679 if (*p == '=') { | |
680 p++; | |
681 th->ttl = strtol(p, (char **)&p, 10); | |
682 } | |
683 } else if (!strcmp(parameter, "destination")) { | |
684 struct in_addr ipaddr; | |
685 | |
686 if (*p == '=') { | |
687 p++; | |
688 get_word_sep(buf, sizeof(buf), ";,", &p); | |
885 | 689 if (inet_aton(buf, &ipaddr)) |
0 | 690 th->destination = ntohl(ipaddr.s_addr); |
691 } | |
692 } | |
693 while (*p != ';' && *p != '\0' && *p != ',') | |
694 p++; | |
695 if (*p == ';') | |
696 p++; | |
697 } | |
698 if (*p == ',') | |
699 p++; | |
700 | |
701 reply->nb_transports++; | |
702 } | |
703 } | |
704 | |
705 void rtsp_parse_line(RTSPHeader *reply, const char *buf) | |
706 { | |
707 const char *p; | |
708 | |
709 /* NOTE: we do case independent match for broken servers */ | |
710 p = buf; | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
711 if (av_stristart(p, "Session:", &p)) { |
0 | 712 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
713 } else if (av_stristart(p, "Content-Length:", &p)) { |
0 | 714 reply->content_length = strtol(p, NULL, 10); |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
715 } else if (av_stristart(p, "Transport:", &p)) { |
0 | 716 rtsp_parse_transport(reply, p); |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
717 } else if (av_stristart(p, "CSeq:", &p)) { |
0 | 718 reply->seq = strtol(p, NULL, 10); |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
719 } else if (av_stristart(p, "Range:", &p)) { |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
720 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end); |
3855 | 721 } else if (av_stristart(p, "RealChallenge1:", &p)) { |
722 skip_spaces(&p); | |
723 av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge)); | |
0 | 724 } |
725 } | |
726 | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
727 static int url_readbuf(URLContext *h, unsigned char *buf, int size) |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
728 { |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
729 int ret, len; |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
730 |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
731 len = 0; |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
732 while (len < size) { |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
733 ret = url_read(h, buf+len, size-len); |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
734 if (ret < 1) |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
735 return ret; |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
736 len += ret; |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
737 } |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
738 return len; |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
739 } |
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
740 |
179 | 741 /* skip a RTP/TCP interleaved packet */ |
742 static void rtsp_skip_packet(AVFormatContext *s) | |
743 { | |
744 RTSPState *rt = s->priv_data; | |
745 int ret, len, len1; | |
746 uint8_t buf[1024]; | |
747 | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
748 ret = url_readbuf(rt->rtsp_hd, buf, 3); |
179 | 749 if (ret != 3) |
750 return; | |
2222 | 751 len = AV_RB16(buf + 1); |
179 | 752 #ifdef DEBUG |
753 printf("skipping RTP packet len=%d\n", len); | |
754 #endif | |
755 /* skip payload */ | |
756 while (len > 0) { | |
757 len1 = len; | |
758 if (len1 > sizeof(buf)) | |
759 len1 = sizeof(buf); | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
760 ret = url_readbuf(rt->rtsp_hd, buf, len1); |
179 | 761 if (ret != len1) |
762 return; | |
763 len -= len1; | |
764 } | |
765 } | |
0 | 766 |
885 | 767 static void rtsp_send_cmd(AVFormatContext *s, |
768 const char *cmd, RTSPHeader *reply, | |
0 | 769 unsigned char **content_ptr) |
770 { | |
771 RTSPState *rt = s->priv_data; | |
772 char buf[4096], buf1[1024], *q; | |
773 unsigned char ch; | |
774 const char *p; | |
775 int content_length, line_count; | |
776 unsigned char *content = NULL; | |
777 | |
778 memset(reply, 0, sizeof(RTSPHeader)); | |
779 | |
780 rt->seq++; | |
2189 | 781 av_strlcpy(buf, cmd, sizeof(buf)); |
172 | 782 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); |
2189 | 783 av_strlcat(buf, buf1, sizeof(buf)); |
0 | 784 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { |
172 | 785 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); |
2189 | 786 av_strlcat(buf, buf1, sizeof(buf)); |
0 | 787 } |
2189 | 788 av_strlcat(buf, "\r\n", sizeof(buf)); |
0 | 789 #ifdef DEBUG |
790 printf("Sending:\n%s--\n", buf); | |
791 #endif | |
792 url_write(rt->rtsp_hd, buf, strlen(buf)); | |
793 | |
794 /* parse reply (XXX: use buffers) */ | |
795 line_count = 0; | |
796 rt->last_reply[0] = '\0'; | |
797 for(;;) { | |
798 q = buf; | |
799 for(;;) { | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
800 if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1) |
0 | 801 break; |
802 if (ch == '\n') | |
803 break; | |
179 | 804 if (ch == '$') { |
805 /* XXX: only parse it if first char on line ? */ | |
806 rtsp_skip_packet(s); | |
807 } else if (ch != '\r') { | |
0 | 808 if ((q - buf) < sizeof(buf) - 1) |
809 *q++ = ch; | |
810 } | |
811 } | |
812 *q = '\0'; | |
813 #ifdef DEBUG | |
814 printf("line='%s'\n", buf); | |
815 #endif | |
816 /* test if last line */ | |
817 if (buf[0] == '\0') | |
818 break; | |
819 p = buf; | |
820 if (line_count == 0) { | |
821 /* get reply code */ | |
822 get_word(buf1, sizeof(buf1), &p); | |
823 get_word(buf1, sizeof(buf1), &p); | |
824 reply->status_code = atoi(buf1); | |
825 } else { | |
826 rtsp_parse_line(reply, p); | |
2189 | 827 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); |
828 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply)); | |
0 | 829 } |
830 line_count++; | |
831 } | |
885 | 832 |
0 | 833 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') |
2189 | 834 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id)); |
885 | 835 |
0 | 836 content_length = reply->content_length; |
837 if (content_length > 0) { | |
838 /* leave some room for a trailing '\0' (useful for simple parsing) */ | |
839 content = av_malloc(content_length + 1); | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
840 (void)url_readbuf(rt->rtsp_hd, content, content_length); |
0 | 841 content[content_length] = '\0'; |
842 } | |
843 if (content_ptr) | |
844 *content_ptr = content; | |
2263 | 845 else |
846 av_free(content); | |
0 | 847 } |
848 | |
849 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
850 /* close and free RTSP streams */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
851 static void rtsp_close_streams(RTSPState *rt) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
852 { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
853 int i; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
854 RTSPStream *rtsp_st; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
855 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
856 for(i=0;i<rt->nb_rtsp_streams;i++) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
857 rtsp_st = rt->rtsp_streams[i]; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
858 if (rtsp_st) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
859 if (rtsp_st->rtp_ctx) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
860 rtp_parse_close(rtsp_st->rtp_ctx); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
861 if (rtsp_st->rtp_handle) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
862 url_close(rtsp_st->rtp_handle); |
1419 | 863 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) |
864 rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context); | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
865 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
866 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
867 av_free(rt->rtsp_streams); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
868 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
869 |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
870 /** |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
871 * @returns 0 on success, <0 on error, 1 if protocol is unavailable. |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
872 */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
873 static int |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
874 make_setup_request (AVFormatContext *s, const char *host, int port, |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
875 int protocol, const char *real_challenge) |
0 | 876 { |
877 RTSPState *rt = s->priv_data; | |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
878 int j, i, err; |
0 | 879 RTSPStream *rtsp_st; |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
880 AVStream *st; |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
881 RTSPHeader reply1, *reply = &reply1; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
882 char cmd[2048]; |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
883 const char *trans_pref; |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
884 |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
885 if (rt->server_type == RTSP_SERVER_RDT) |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
886 trans_pref = "x-pn-tng"; |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
887 else |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
888 trans_pref = "RTP/AVP"; |
885 | 889 |
0 | 890 /* for each stream, make the setup request */ |
891 /* XXX: we assume the same server is used for the control of each | |
892 RTSP stream */ | |
774 | 893 |
894 for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) { | |
0 | 895 char transport[2048]; |
896 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
897 rtsp_st = rt->rtsp_streams[i]; |
0 | 898 |
899 /* RTP/UDP */ | |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
900 if (protocol == RTSP_PROTOCOL_RTP_UDP) { |
0 | 901 char buf[256]; |
902 | |
903 /* first try in specified port range */ | |
774 | 904 if (RTSP_RTP_PORT_MIN != 0) { |
905 while(j <= RTSP_RTP_PORT_MAX) { | |
2711
0ff7c5289e68
Specify the server address when opening an rtp:// URL in rtsp.c, so
lucabe
parents:
2684
diff
changeset
|
906 snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j); |
2684
3dd4b622f4e3
If local port n is not available, try n + 2 instead of continuing to bind
lucabe
parents:
2681
diff
changeset
|
907 j += 2; /* we will use two port by rtp stream (rtp and rtcp) */ |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
908 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) { |
0 | 909 goto rtp_opened; |
774 | 910 } |
0 | 911 } |
912 } | |
913 | |
774 | 914 /* then try on any port |
915 ** if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { | |
916 ** err = AVERROR_INVALIDDATA; | |
917 ** goto fail; | |
918 ** } | |
919 */ | |
0 | 920 |
921 rtp_opened: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
922 port = rtp_get_local_port(rtsp_st->rtp_handle); |
3877
3e0c7ad2a675
Remove unused code that used to handle protocol concatenation, i.e. trying
rbultje
parents:
3876
diff
changeset
|
923 snprintf(transport, sizeof(transport) - 1, |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
924 "%s/UDP;unicast;client_port=%d", |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
925 trans_pref, port); |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
926 if (rt->server_type == RTSP_SERVER_RTP) |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
927 av_strlcatf(transport, sizeof(transport), "-%d", port + 1); |
0 | 928 } |
929 | |
930 /* RTP/TCP */ | |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
931 else if (protocol == RTSP_PROTOCOL_RTP_TCP) { |
3877
3e0c7ad2a675
Remove unused code that used to handle protocol concatenation, i.e. trying
rbultje
parents:
3876
diff
changeset
|
932 snprintf(transport, sizeof(transport) - 1, |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
933 "%s/TCP", trans_pref); |
0 | 934 } |
935 | |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
936 else if (protocol == RTSP_PROTOCOL_RTP_UDP_MULTICAST) { |
3877
3e0c7ad2a675
Remove unused code that used to handle protocol concatenation, i.e. trying
rbultje
parents:
3876
diff
changeset
|
937 snprintf(transport, sizeof(transport) - 1, |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
938 "%s/UDP;multicast", trans_pref); |
0 | 939 } |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
940 if (rt->server_type == RTSP_SERVER_RDT) |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
941 av_strlcat(transport, ";mode=play", sizeof(transport)); |
885 | 942 snprintf(cmd, sizeof(cmd), |
172 | 943 "SETUP %s RTSP/1.0\r\n" |
944 "Transport: %s\r\n", | |
0 | 945 rtsp_st->control_url, transport); |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
946 if (i == 0 && rt->server_type == RTSP_SERVER_RDT) { |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
947 char real_res[41], real_csum[9]; |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
948 ff_rdt_calc_response_and_checksum(real_res, real_csum, |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
949 real_challenge); |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
950 av_strlcatf(cmd, sizeof(cmd), |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
951 "If-Match: %s\r\n" |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
952 "RealChallenge2: %s, sd=%s\r\n", |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
953 rt->session_id, real_res, real_csum); |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
954 } |
0 | 955 rtsp_send_cmd(s, cmd, reply, NULL); |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
956 if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) { |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
957 err = 1; |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
958 goto fail; |
3151 | 959 } else if (reply->status_code != RTSP_STATUS_OK || |
960 reply->nb_transports != 1) { | |
0 | 961 err = AVERROR_INVALIDDATA; |
962 goto fail; | |
963 } | |
964 | |
965 /* XXX: same protocol for all streams is required */ | |
966 if (i > 0) { | |
967 if (reply->transports[0].protocol != rt->protocol) { | |
968 err = AVERROR_INVALIDDATA; | |
969 goto fail; | |
970 } | |
971 } else { | |
972 rt->protocol = reply->transports[0].protocol; | |
973 } | |
974 | |
975 /* close RTP connection if not choosen */ | |
976 if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP && | |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
977 (protocol == RTSP_PROTOCOL_RTP_UDP)) { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
978 url_close(rtsp_st->rtp_handle); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
979 rtsp_st->rtp_handle = NULL; |
0 | 980 } |
981 | |
982 switch(reply->transports[0].protocol) { | |
983 case RTSP_PROTOCOL_RTP_TCP: | |
984 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; | |
985 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; | |
986 break; | |
885 | 987 |
0 | 988 case RTSP_PROTOCOL_RTP_UDP: |
989 { | |
990 char url[1024]; | |
885 | 991 |
0 | 992 /* XXX: also use address if specified */ |
885 | 993 snprintf(url, sizeof(url), "rtp://%s:%d", |
0 | 994 host, reply->transports[0].server_port_min); |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
995 if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { |
0 | 996 err = AVERROR_INVALIDDATA; |
997 goto fail; | |
998 } | |
999 } | |
1000 break; | |
1001 case RTSP_PROTOCOL_RTP_UDP_MULTICAST: | |
1002 { | |
1003 char url[1024]; | |
2246
6dade35dc9b3
rtsp multicast fix by Thijs Vermeir $1$2@gmail.com
lu_zero
parents:
2222
diff
changeset
|
1004 struct in_addr in; |
0 | 1005 |
2246
6dade35dc9b3
rtsp multicast fix by Thijs Vermeir $1$2@gmail.com
lu_zero
parents:
2222
diff
changeset
|
1006 in.s_addr = htonl(reply->transports[0].destination); |
3221 | 1007 snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d", |
2246
6dade35dc9b3
rtsp multicast fix by Thijs Vermeir $1$2@gmail.com
lu_zero
parents:
2222
diff
changeset
|
1008 inet_ntoa(in), |
6dade35dc9b3
rtsp multicast fix by Thijs Vermeir $1$2@gmail.com
lu_zero
parents:
2222
diff
changeset
|
1009 reply->transports[0].port_min, |
6dade35dc9b3
rtsp multicast fix by Thijs Vermeir $1$2@gmail.com
lu_zero
parents:
2222
diff
changeset
|
1010 reply->transports[0].ttl); |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1011 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
0 | 1012 err = AVERROR_INVALIDDATA; |
1013 goto fail; | |
1014 } | |
1015 } | |
1016 break; | |
1017 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1018 /* open the RTP context */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1019 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1020 if (rtsp_st->stream_index >= 0) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1021 st = s->streams[rtsp_st->stream_index]; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1022 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1023 s->ctx_flags |= AVFMTCTX_NOHEADER; |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1024 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); |
774 | 1025 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1026 if (!rtsp_st->rtp_ctx) { |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2263
diff
changeset
|
1027 err = AVERROR(ENOMEM); |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1028 goto fail; |
1419 | 1029 } else { |
1030 if(rtsp_st->dynamic_handler) { | |
1031 rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context; | |
1032 rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet; | |
1033 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1034 } |
0 | 1035 } |
1036 | |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1037 return 0; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1038 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1039 fail: |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1040 for (i=0; i<rt->nb_rtsp_streams; i++) { |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1041 if (rt->rtsp_streams[i]->rtp_handle) { |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1042 url_close(rt->rtsp_streams[i]->rtp_handle); |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1043 rt->rtsp_streams[i]->rtp_handle = NULL; |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1044 } |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1045 } |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1046 return err; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1047 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1048 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1049 static int rtsp_read_header(AVFormatContext *s, |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1050 AVFormatParameters *ap) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1051 { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1052 RTSPState *rt = s->priv_data; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1053 char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1054 URLContext *rtsp_hd; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1055 int port, ret, err; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1056 RTSPHeader reply1, *reply = &reply1; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1057 unsigned char *content = NULL; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1058 int protocol_mask = 0; |
3856 | 1059 char real_challenge[64]; |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1060 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1061 /* extract hostname and port */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1062 url_split(NULL, 0, NULL, 0, |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1063 host, sizeof(host), &port, path, sizeof(path), s->filename); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1064 if (port < 0) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1065 port = RTSP_DEFAULT_PORT; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1066 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1067 /* search for options */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1068 option_list = strchr(path, '?'); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1069 if (option_list) { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1070 /* remove the options from the path */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1071 *option_list++ = 0; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1072 while(option_list) { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1073 /* move the option pointer */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1074 option = option_list; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1075 option_list = strchr(option_list, '&'); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1076 if (option_list) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1077 *(option_list++) = 0; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1078 /* handle the options */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1079 if (strcmp(option, "udp") == 0) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1080 protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1081 else if (strcmp(option, "multicast") == 0) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1082 protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1083 else if (strcmp(option, "tcp") == 0) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1084 protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1085 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1086 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1087 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1088 if (!protocol_mask) |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1089 protocol_mask = (1 << RTSP_PROTOCOL_RTP_LAST) - 1; |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1090 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1091 /* open the tcp connexion */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1092 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1093 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1094 return AVERROR(EIO); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1095 rt->rtsp_hd = rtsp_hd; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1096 rt->seq = 0; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1097 |
3856 | 1098 /* request options supported by the server; this also detects server type */ |
1099 for (rt->server_type = RTSP_SERVER_RTP;;) { | |
1100 snprintf(cmd, sizeof(cmd), | |
1101 "OPTIONS %s RTSP/1.0\r\n", s->filename); | |
1102 if (rt->server_type == RTSP_SERVER_RDT) | |
1103 av_strlcat(cmd, | |
1104 /** | |
1105 * The following entries are required for proper | |
1106 * streaming from a Realmedia server. They are | |
1107 * interdependent in some way although we currently | |
1108 * don't quite understand how. Values were copied | |
1109 * from mplayer SVN r23589. | |
1110 * @param CompanyID is a 16-byte ID in base64 | |
1111 * @param ClientChallenge is a 16-byte ID in hex | |
1112 */ | |
1113 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n" | |
1114 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n" | |
1115 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n" | |
1116 "GUID: 00000000-0000-0000-0000-000000000000\r\n", | |
1117 sizeof(cmd)); | |
1118 rtsp_send_cmd(s, cmd, reply, NULL); | |
1119 if (reply->status_code != RTSP_STATUS_OK) { | |
1120 err = AVERROR_INVALIDDATA; | |
1121 goto fail; | |
1122 } | |
1123 | |
1124 /* detect server type if not standard-compliant RTP */ | |
1125 if (rt->server_type != RTSP_SERVER_RDT && reply->real_challenge[0]) { | |
1126 rt->server_type = RTSP_SERVER_RDT; | |
1127 continue; | |
1128 } else if (rt->server_type == RTSP_SERVER_RDT) { | |
1129 strcpy(real_challenge, reply->real_challenge); | |
1130 } | |
1131 break; | |
1132 } | |
1133 | |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1134 /* describe the stream */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1135 snprintf(cmd, sizeof(cmd), |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1136 "DESCRIBE %s RTSP/1.0\r\n" |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1137 "Accept: application/sdp\r\n", |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1138 s->filename); |
3859 | 1139 if (rt->server_type == RTSP_SERVER_RDT) { |
1140 /** | |
1141 * The Require: attribute is needed for proper streaming from | |
1142 * Realmedia servers. | |
1143 */ | |
1144 av_strlcat(cmd, | |
1145 "Require: com.real.retain-entity-for-setup\r\n", | |
1146 sizeof(cmd)); | |
1147 } | |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1148 rtsp_send_cmd(s, cmd, reply, &content); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1149 if (!content) { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1150 err = AVERROR_INVALIDDATA; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1151 goto fail; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1152 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1153 if (reply->status_code != RTSP_STATUS_OK) { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1154 err = AVERROR_INVALIDDATA; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1155 goto fail; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1156 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1157 |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1158 /* now we got the SDP description, we parse it */ |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1159 ret = sdp_parse(s, (const char *)content); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1160 av_freep(&content); |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1161 if (ret < 0) { |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1162 err = AVERROR_INVALIDDATA; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1163 goto fail; |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1164 } |
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1165 |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1166 do { |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
1167 int protocol = ff_log2_tab[protocol_mask & ~(protocol_mask - 1)]; |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1168 |
3876
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
1169 err = make_setup_request(s, host, port, protocol, |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
1170 rt->server_type == RTSP_SERVER_RDT ? |
1026953d4ffe
Implement Realmedia/RTSP-compatible SETUP command. This includes calculation
rbultje
parents:
3861
diff
changeset
|
1171 real_challenge : NULL); |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1172 if (err < 0) |
3151 | 1173 goto fail; |
3150
095003bbe73e
Change protocol_mask into protocol, since we always just try a single one per
rbultje
parents:
3149
diff
changeset
|
1174 protocol_mask &= ~(1 << protocol); |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1175 if (protocol_mask == 0 && err == 1) { |
3202
98e633b72d38
use FF_NETERROR to make winsock happy, patch from prossATxvidDoTorg
lu_zero
parents:
3151
diff
changeset
|
1176 err = AVERROR(FF_NETERROR(EPROTONOSUPPORT)); |
3149
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1177 goto fail; |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1178 } |
5a7a7406ab1f
Allow cycling between different protocols (TCP, UDP or multicast) so that if
rbultje
parents:
3147
diff
changeset
|
1179 } while (err); |
3147
91d65fdf91e1
Split the SETUP request into a separate function, as a prelude into allowing
rbultje
parents:
2884
diff
changeset
|
1180 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1181 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1182 rt->seek_timestamp = 0; /* default is to start stream at position |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1183 zero */ |
1003 | 1184 if (ap->initial_pause) { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1185 /* do not start immediately */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1186 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1187 if (rtsp_read_play(s) < 0) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1188 err = AVERROR_INVALIDDATA; |
0 | 1189 goto fail; |
1190 } | |
1191 } | |
1192 return 0; | |
1193 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1194 rtsp_close_streams(rt); |
0 | 1195 av_freep(&content); |
1196 url_close(rt->rtsp_hd); | |
1197 return err; | |
1198 } | |
1199 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1200 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1201 uint8_t *buf, int buf_size) |
0 | 1202 { |
1203 RTSPState *rt = s->priv_data; | |
172 | 1204 int id, len, i, ret; |
0 | 1205 RTSPStream *rtsp_st; |
1206 | |
172 | 1207 #ifdef DEBUG_RTP_TCP |
1208 printf("tcp_read_packet:\n"); | |
1209 #endif | |
0 | 1210 redo: |
1211 for(;;) { | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
1212 ret = url_readbuf(rt->rtsp_hd, buf, 1); |
172 | 1213 #ifdef DEBUG_RTP_TCP |
1214 printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]); | |
1215 #endif | |
1216 if (ret != 1) | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1217 return -1; |
172 | 1218 if (buf[0] == '$') |
0 | 1219 break; |
1220 } | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
1221 ret = url_readbuf(rt->rtsp_hd, buf, 3); |
172 | 1222 if (ret != 3) |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1223 return -1; |
172 | 1224 id = buf[0]; |
2222 | 1225 len = AV_RB16(buf + 1); |
172 | 1226 #ifdef DEBUG_RTP_TCP |
1227 printf("id=%d len=%d\n", id, len); | |
1228 #endif | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1229 if (len > buf_size || len < 12) |
0 | 1230 goto redo; |
1231 /* get the data */ | |
391
1cf22651d33b
support url_read which reads less then requested patch by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
370
diff
changeset
|
1232 ret = url_readbuf(rt->rtsp_hd, buf, len); |
172 | 1233 if (ret != len) |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1234 return -1; |
885 | 1235 |
0 | 1236 /* find the matching stream */ |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1237 for(i = 0; i < rt->nb_rtsp_streams; i++) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1238 rtsp_st = rt->rtsp_streams[i]; |
885 | 1239 if (id >= rtsp_st->interleaved_min && |
1240 id <= rtsp_st->interleaved_max) | |
0 | 1241 goto found; |
1242 } | |
1243 goto redo; | |
1244 found: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1245 *prtsp_st = rtsp_st; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1246 return len; |
0 | 1247 } |
1248 | |
885 | 1249 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1250 uint8_t *buf, int buf_size) |
0 | 1251 { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1252 RTSPState *rt = s->priv_data; |
0 | 1253 RTSPStream *rtsp_st; |
1254 fd_set rfds; | |
1255 int fd1, fd2, fd_max, n, i, ret; | |
1256 struct timeval tv; | |
1257 | |
1258 for(;;) { | |
179 | 1259 if (url_interrupt_cb()) |
2772
b43dc2901f83
Make av_read_frame with rtsp client return EINTR on interrupt
lu_zero
parents:
2771
diff
changeset
|
1260 return AVERROR(EINTR); |
0 | 1261 FD_ZERO(&rfds); |
1262 fd_max = -1; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1263 for(i = 0; i < rt->nb_rtsp_streams; i++) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1264 rtsp_st = rt->rtsp_streams[i]; |
0 | 1265 /* currently, we cannot probe RTCP handle because of blocking restrictions */ |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1266 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 1267 if (fd1 > fd_max) |
1268 fd_max = fd1; | |
1269 FD_SET(fd1, &rfds); | |
1270 } | |
1271 tv.tv_sec = 0; | |
179 | 1272 tv.tv_usec = 100 * 1000; |
0 | 1273 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
1274 if (n > 0) { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1275 for(i = 0; i < rt->nb_rtsp_streams; i++) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1276 rtsp_st = rt->rtsp_streams[i]; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1277 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 1278 if (FD_ISSET(fd1, &rfds)) { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1279 ret = url_read(rtsp_st->rtp_handle, buf, buf_size); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1280 if (ret > 0) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1281 *prtsp_st = rtsp_st; |
0 | 1282 return ret; |
1283 } | |
1284 } | |
1285 } | |
1286 } | |
1287 } | |
1288 } | |
1289 | |
1290 static int rtsp_read_packet(AVFormatContext *s, | |
1291 AVPacket *pkt) | |
1292 { | |
1293 RTSPState *rt = s->priv_data; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1294 RTSPStream *rtsp_st; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1295 int ret, len; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1296 uint8_t buf[RTP_MAX_PACKET_LENGTH]; |
0 | 1297 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1298 /* get next frames from the same RTP packet */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1299 if (rt->cur_rtp) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1300 ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1301 if (ret == 0) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1302 rt->cur_rtp = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1303 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1304 } else if (ret == 1) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1305 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1306 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1307 rt->cur_rtp = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1308 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1309 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1310 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1311 /* read next RTP packet */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1312 redo: |
0 | 1313 switch(rt->protocol) { |
1314 default: | |
1315 case RTSP_PROTOCOL_RTP_TCP: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1316 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
0 | 1317 break; |
1318 case RTSP_PROTOCOL_RTP_UDP: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1319 case RTSP_PROTOCOL_RTP_UDP_MULTICAST: |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1320 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
2219
fa6c59a5ab0d
check udp_read_packet return value not to access uninitialized memory
benoit
parents:
2193
diff
changeset
|
1321 if (len >=0 && rtsp_st->rtp_ctx) |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1322 rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len); |
0 | 1323 break; |
1324 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1325 if (len < 0) |
2775
1301147d9450
Make av_read_frame with rtsp client return EINTR on interrupt
lu_zero
parents:
2772
diff
changeset
|
1326 return len; |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1327 ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1328 if (ret < 0) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1329 goto redo; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1330 if (ret == 1) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1331 /* more packets may follow, so we save the RTP context */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1332 rt->cur_rtp = rtsp_st->rtp_ctx; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1333 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1334 return 0; |
0 | 1335 } |
1336 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1337 static int rtsp_read_play(AVFormatContext *s) |
179 | 1338 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1339 RTSPState *rt = s->priv_data; |
179 | 1340 RTSPHeader reply1, *reply = &reply1; |
1341 char cmd[1024]; | |
1342 | |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
304
diff
changeset
|
1343 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1344 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1345 if (rt->state == RTSP_STATE_PAUSED) { |
885 | 1346 snprintf(cmd, sizeof(cmd), |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1347 "PLAY %s RTSP/1.0\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1348 s->filename); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1349 } else { |
885 | 1350 snprintf(cmd, sizeof(cmd), |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1351 "PLAY %s RTSP/1.0\r\n" |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1352 "Range: npt=%0.3f-\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1353 s->filename, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1354 (double)rt->seek_timestamp / AV_TIME_BASE); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1355 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1356 rtsp_send_cmd(s, cmd, reply, NULL); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1357 if (reply->status_code != RTSP_STATUS_OK) { |
179 | 1358 return -1; |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1359 } |
3861
a0098594ab90
Remove useless "else" case in if X { A; return }; else { B }. See discussion
rbultje
parents:
3860
diff
changeset
|
1360 rt->state = RTSP_STATE_PLAYING; |
a0098594ab90
Remove useless "else" case in if X { A; return }; else { B }. See discussion
rbultje
parents:
3860
diff
changeset
|
1361 return 0; |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1362 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1363 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1364 /* pause the stream */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1365 static int rtsp_read_pause(AVFormatContext *s) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1366 { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1367 RTSPState *rt = s->priv_data; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1368 RTSPHeader reply1, *reply = &reply1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1369 char cmd[1024]; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1370 |
179 | 1371 rt = s->priv_data; |
885 | 1372 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1373 if (rt->state != RTSP_STATE_PLAYING) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1374 return 0; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1375 |
885 | 1376 snprintf(cmd, sizeof(cmd), |
179 | 1377 "PAUSE %s RTSP/1.0\r\n", |
1378 s->filename); | |
1379 rtsp_send_cmd(s, cmd, reply, NULL); | |
1380 if (reply->status_code != RTSP_STATUS_OK) { | |
1381 return -1; | |
1382 } | |
3861
a0098594ab90
Remove useless "else" case in if X { A; return }; else { B }. See discussion
rbultje
parents:
3860
diff
changeset
|
1383 rt->state = RTSP_STATE_PAUSED; |
a0098594ab90
Remove useless "else" case in if X { A; return }; else { B }. See discussion
rbultje
parents:
3860
diff
changeset
|
1384 return 0; |
179 | 1385 } |
1386 | |
885 | 1387 static int rtsp_read_seek(AVFormatContext *s, int stream_index, |
558 | 1388 int64_t timestamp, int flags) |
179 | 1389 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1390 RTSPState *rt = s->priv_data; |
885 | 1391 |
2408 | 1392 rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q); |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1393 switch(rt->state) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1394 default: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1395 case RTSP_STATE_IDLE: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1396 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1397 case RTSP_STATE_PLAYING: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1398 if (rtsp_read_play(s) != 0) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1399 return -1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1400 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1401 case RTSP_STATE_PAUSED: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1402 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1403 break; |
179 | 1404 } |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1405 return 0; |
179 | 1406 } |
1407 | |
0 | 1408 static int rtsp_read_close(AVFormatContext *s) |
1409 { | |
1410 RTSPState *rt = s->priv_data; | |
1411 RTSPHeader reply1, *reply = &reply1; | |
1412 char cmd[1024]; | |
1413 | |
172 | 1414 #if 0 |
0 | 1415 /* NOTE: it is valid to flush the buffer here */ |
1416 if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { | |
1417 url_fclose(&rt->rtsp_gb); | |
1418 } | |
172 | 1419 #endif |
885 | 1420 snprintf(cmd, sizeof(cmd), |
172 | 1421 "TEARDOWN %s RTSP/1.0\r\n", |
0 | 1422 s->filename); |
1423 rtsp_send_cmd(s, cmd, reply, NULL); | |
1424 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1425 rtsp_close_streams(rt); |
0 | 1426 url_close(rt->rtsp_hd); |
1427 return 0; | |
1428 } | |
1429 | |
2054 | 1430 #ifdef CONFIG_RTSP_DEMUXER |
1167 | 1431 AVInputFormat rtsp_demuxer = { |
0 | 1432 "rtsp", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
1433 NULL_IF_CONFIG_SMALL("RTSP input format"), |
0 | 1434 sizeof(RTSPState), |
1435 rtsp_probe, | |
1436 rtsp_read_header, | |
1437 rtsp_read_packet, | |
1438 rtsp_read_close, | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1439 rtsp_read_seek, |
0 | 1440 .flags = AVFMT_NOFILE, |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1441 .read_play = rtsp_read_play, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1442 .read_pause = rtsp_read_pause, |
0 | 1443 }; |
2054 | 1444 #endif |
0 | 1445 |
1446 static int sdp_probe(AVProbeData *p1) | |
1447 { | |
706
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1448 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; |
0 | 1449 |
1450 /* we look for a line beginning "c=IN IP4" */ | |
706
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1451 while (p < p_end && *p != '\0') { |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
1452 if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL)) |
0 | 1453 return AVPROBE_SCORE_MAX / 2; |
706
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1454 |
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1455 while(p < p_end - 1 && *p != '\n') p++; |
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1456 if (++p >= p_end) |
0 | 1457 break; |
1458 if (*p == '\r') | |
1459 p++; | |
1460 } | |
1461 return 0; | |
1462 } | |
1463 | |
1464 #define SDP_MAX_SIZE 8192 | |
1465 | |
1466 static int sdp_read_header(AVFormatContext *s, | |
1467 AVFormatParameters *ap) | |
1468 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1469 RTSPState *rt = s->priv_data; |
0 | 1470 RTSPStream *rtsp_st; |
1471 int size, i, err; | |
1472 char *content; | |
1473 char url[1024]; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1474 AVStream *st; |
0 | 1475 |
1476 /* read the whole sdp file */ | |
1477 /* XXX: better loading */ | |
1478 content = av_malloc(SDP_MAX_SIZE); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2759
diff
changeset
|
1479 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1); |
0 | 1480 if (size <= 0) { |
1481 av_free(content); | |
1482 return AVERROR_INVALIDDATA; | |
1483 } | |
1484 content[size] ='\0'; | |
1485 | |
1486 sdp_parse(s, content); | |
1487 av_free(content); | |
1488 | |
1489 /* open each RTP stream */ | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1490 for(i=0;i<rt->nb_rtsp_streams;i++) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1491 rtsp_st = rt->rtsp_streams[i]; |
885 | 1492 |
3222 | 1493 snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d", |
885 | 1494 inet_ntoa(rtsp_st->sdp_ip), |
0 | 1495 rtsp_st->sdp_port, |
3222 | 1496 rtsp_st->sdp_port, |
0 | 1497 rtsp_st->sdp_ttl); |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1498 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
0 | 1499 err = AVERROR_INVALIDDATA; |
1500 goto fail; | |
1501 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1502 /* open the RTP context */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1503 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1504 if (rtsp_st->stream_index >= 0) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1505 st = s->streams[rtsp_st->stream_index]; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1506 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1507 s->ctx_flags |= AVFMTCTX_NOHEADER; |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1508 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1509 if (!rtsp_st->rtp_ctx) { |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2263
diff
changeset
|
1510 err = AVERROR(ENOMEM); |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1511 goto fail; |
1419 | 1512 } else { |
1513 if(rtsp_st->dynamic_handler) { | |
1514 rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context; | |
1515 rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet; | |
1516 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1517 } |
0 | 1518 } |
1519 return 0; | |
1520 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1521 rtsp_close_streams(rt); |
0 | 1522 return err; |
1523 } | |
1524 | |
1525 static int sdp_read_packet(AVFormatContext *s, | |
1526 AVPacket *pkt) | |
1527 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1528 return rtsp_read_packet(s, pkt); |
0 | 1529 } |
1530 | |
1531 static int sdp_read_close(AVFormatContext *s) | |
1532 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1533 RTSPState *rt = s->priv_data; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1534 rtsp_close_streams(rt); |
0 | 1535 return 0; |
1536 } | |
1537 | |
1169 | 1538 #ifdef CONFIG_SDP_DEMUXER |
1539 AVInputFormat sdp_demuxer = { | |
0 | 1540 "sdp", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
1541 NULL_IF_CONFIG_SMALL("SDP"), |
0 | 1542 sizeof(RTSPState), |
1543 sdp_probe, | |
1544 sdp_read_header, | |
1545 sdp_read_packet, | |
1546 sdp_read_close, | |
1547 }; | |
1169 | 1548 #endif |
0 | 1549 |
2053 | 1550 #ifdef CONFIG_REDIR_DEMUXER |
0 | 1551 /* dummy redirector format (used directly in av_open_input_file now) */ |
1552 static int redir_probe(AVProbeData *pd) | |
1553 { | |
1554 const char *p; | |
1555 p = pd->buf; | |
1556 while (redir_isspace(*p)) | |
1557 p++; | |
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
1558 if (av_strstart(p, "http://", NULL) || |
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2189
diff
changeset
|
1559 av_strstart(p, "rtsp://", NULL)) |
0 | 1560 return AVPROBE_SCORE_MAX; |
1561 return 0; | |
1562 } | |
1563 | |
2785
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1564 static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap) |
0 | 1565 { |
1566 char buf[4096], *q; | |
1567 int c; | |
1568 AVFormatContext *ic = NULL; | |
2785
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1569 ByteIOContext *f = s->pb; |
0 | 1570 |
1571 /* parse each URL and try to open it */ | |
1572 c = url_fgetc(f); | |
1573 while (c != URL_EOF) { | |
1574 /* skip spaces */ | |
1575 for(;;) { | |
1576 if (!redir_isspace(c)) | |
1577 break; | |
1578 c = url_fgetc(f); | |
1579 } | |
1580 if (c == URL_EOF) | |
1581 break; | |
1582 /* record url */ | |
1583 q = buf; | |
1584 for(;;) { | |
1585 if (c == URL_EOF || redir_isspace(c)) | |
1586 break; | |
1587 if ((q - buf) < sizeof(buf) - 1) | |
1588 *q++ = c; | |
1589 c = url_fgetc(f); | |
1590 } | |
1591 *q = '\0'; | |
1592 //printf("URL='%s'\n", buf); | |
1593 /* try to open the media file */ | |
1594 if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0) | |
1595 break; | |
1596 } | |
1597 if (!ic) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
1598 return AVERROR(EIO); |
2785
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1599 |
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1600 *s = *ic; |
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1601 url_fclose(f); |
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1602 |
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1603 return 0; |
0 | 1604 } |
1605 | |
1167 | 1606 AVInputFormat redir_demuxer = { |
0 | 1607 "redir", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
1608 NULL_IF_CONFIG_SMALL("Redirector format"), |
0 | 1609 0, |
1610 redir_probe, | |
2785
d3b3cfb538d8
Suppress the "redirector hack" from libavformat/utils.c:av_open_input_stream(),
lucabe
parents:
2775
diff
changeset
|
1611 redir_read_header, |
0 | 1612 NULL, |
1613 NULL, | |
1614 }; | |
2053 | 1615 #endif |