Mercurial > libavformat.hg
annotate rtsp.c @ 327:741c56c608bb libavformat
using LIBAVFORMAT_IDENT
author | alex |
---|---|
date | Mon, 08 Dec 2003 17:50:38 +0000 |
parents | d58c8859ff8c |
children | 845f9de2c883 |
rev | line source |
---|---|
0 | 1 /* |
2 * RTSP/SDP client | |
3 * Copyright (c) 2002 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avformat.h" | |
20 | |
182 | 21 #include <unistd.h> /* for select() prototype */ |
0 | 22 #include <sys/time.h> |
23 #include <netinet/in.h> | |
24 #include <sys/socket.h> | |
25 #ifndef __BEOS__ | |
26 # include <arpa/inet.h> | |
27 #else | |
28 # include "barpainet.h" | |
29 #endif | |
30 | |
31 //#define DEBUG | |
172 | 32 //#define DEBUG_RTP_TCP |
0 | 33 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
34 enum RTSPClientState { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
35 RTSP_STATE_IDLE, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
36 RTSP_STATE_PLAYING, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
37 RTSP_STATE_PAUSED, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
38 }; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
39 |
0 | 40 typedef struct RTSPState { |
41 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
|
42 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
|
43 struct RTSPStream **rtsp_streams; |
304
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 enum RTSPClientState state; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
46 int64_t seek_timestamp; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
47 |
172 | 48 /* XXX: currently we use unbuffered input */ |
49 // ByteIOContext rtsp_gb; | |
0 | 50 int seq; /* RTSP command sequence number */ |
51 char session_id[512]; | |
52 enum RTSPProtocol protocol; | |
53 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
|
54 RTPDemuxContext *cur_rtp; |
0 | 55 } RTSPState; |
56 | |
57 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
|
58 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
|
59 RTPDemuxContext *rtp_ctx; /* RTP parse context */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
60 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
61 int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */ |
0 | 62 int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */ |
63 char control_url[1024]; /* url for this stream (from SDP) */ | |
64 | |
65 int sdp_port; /* port (from SDP content - not used in RTSP) */ | |
66 struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */ | |
67 int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */ | |
68 int sdp_payload_type; /* payload type - only used in SDP */ | |
69 } RTSPStream; | |
70 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
71 static int rtsp_read_play(AVFormatContext *s); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
72 |
0 | 73 /* XXX: currently, the only way to change the protocols consists in |
74 changing this variable */ | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
75 #if 0 |
0 | 76 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST); |
172 | 77 #else |
78 /* try it if a proxy is used */ | |
79 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP); | |
80 #endif | |
0 | 81 |
82 /* if non zero, then set a range for RTP ports */ | |
83 int rtsp_rtp_port_min = 0; | |
84 int rtsp_rtp_port_max = 0; | |
85 | |
86 FFRTSPCallback *ff_rtsp_callback = NULL; | |
87 | |
88 static int rtsp_probe(AVProbeData *p) | |
89 { | |
90 if (strstart(p->filename, "rtsp:", NULL)) | |
91 return AVPROBE_SCORE_MAX; | |
92 return 0; | |
93 } | |
94 | |
95 static int redir_isspace(int c) | |
96 { | |
97 return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); | |
98 } | |
99 | |
100 static void skip_spaces(const char **pp) | |
101 { | |
102 const char *p; | |
103 p = *pp; | |
104 while (redir_isspace(*p)) | |
105 p++; | |
106 *pp = p; | |
107 } | |
108 | |
109 static void get_word_sep(char *buf, int buf_size, const char *sep, | |
110 const char **pp) | |
111 { | |
112 const char *p; | |
113 char *q; | |
114 | |
115 p = *pp; | |
116 skip_spaces(&p); | |
117 q = buf; | |
118 while (!strchr(sep, *p) && *p != '\0') { | |
119 if ((q - buf) < buf_size - 1) | |
120 *q++ = *p; | |
121 p++; | |
122 } | |
123 if (buf_size > 0) | |
124 *q = '\0'; | |
125 *pp = p; | |
126 } | |
127 | |
128 static void get_word(char *buf, int buf_size, const char **pp) | |
129 { | |
130 const char *p; | |
131 char *q; | |
132 | |
133 p = *pp; | |
134 skip_spaces(&p); | |
135 q = buf; | |
136 while (!redir_isspace(*p) && *p != '\0') { | |
137 if ((q - buf) < buf_size - 1) | |
138 *q++ = *p; | |
139 p++; | |
140 } | |
141 if (buf_size > 0) | |
142 *q = '\0'; | |
143 *pp = p; | |
144 } | |
145 | |
146 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other | |
147 params>] */ | |
148 static int sdp_parse_rtpmap(AVCodecContext *codec, const char *p) | |
149 { | |
150 char buf[256]; | |
151 | |
152 /* codec name */ | |
153 get_word_sep(buf, sizeof(buf), "/", &p); | |
154 if (!strcmp(buf, "MP4V-ES")) { | |
155 codec->codec_id = CODEC_ID_MPEG4; | |
156 return 0; | |
157 } else { | |
158 return -1; | |
159 } | |
160 } | |
161 | |
162 /* return the length and optionnaly the data */ | |
163 static int hex_to_data(uint8_t *data, const char *p) | |
164 { | |
165 int c, len, v; | |
166 | |
167 len = 0; | |
168 v = 1; | |
169 for(;;) { | |
170 skip_spaces(&p); | |
171 if (p == '\0') | |
172 break; | |
173 c = toupper((unsigned char)*p++); | |
174 if (c >= '0' && c <= '9') | |
175 c = c - '0'; | |
176 else if (c >= 'A' && c <= 'F') | |
177 c = c - 'A' + 10; | |
178 else | |
179 break; | |
180 v = (v << 4) | c; | |
181 if (v & 0x100) { | |
182 if (data) | |
183 data[len] = v; | |
184 len++; | |
185 v = 1; | |
186 } | |
187 } | |
188 return len; | |
189 } | |
190 | |
191 static void sdp_parse_fmtp(AVCodecContext *codec, const char *p) | |
192 { | |
193 char attr[256]; | |
194 char value[4096]; | |
195 int len; | |
196 | |
197 /* loop on each attribute */ | |
198 for(;;) { | |
199 skip_spaces(&p); | |
200 if (*p == '\0') | |
201 break; | |
202 get_word_sep(attr, sizeof(attr), "=", &p); | |
203 if (*p == '=') | |
204 p++; | |
205 get_word_sep(value, sizeof(value), ";", &p); | |
206 if (*p == ';') | |
207 p++; | |
208 /* handle MPEG4 video */ | |
209 switch(codec->codec_id) { | |
210 case CODEC_ID_MPEG4: | |
211 if (!strcmp(attr, "config")) { | |
212 /* decode the hexa encoded parameter */ | |
213 len = hex_to_data(NULL, value); | |
214 codec->extradata = av_mallocz(len); | |
215 if (!codec->extradata) | |
216 goto fail; | |
217 codec->extradata_size = len; | |
218 hex_to_data(codec->extradata, value); | |
219 } | |
220 break; | |
221 default: | |
222 /* ignore data for other codecs */ | |
223 break; | |
224 } | |
225 fail: ; | |
226 // printf("'%s' = '%s'\n", attr, value); | |
227 } | |
228 } | |
229 | |
230 typedef struct SDPParseState { | |
231 /* SDP only */ | |
232 struct in_addr default_ip; | |
233 int default_ttl; | |
234 } SDPParseState; | |
235 | |
236 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | |
237 int letter, const char *buf) | |
238 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
239 RTSPState *rt = s->priv_data; |
0 | 240 char buf1[64], st_type[64]; |
241 const char *p; | |
242 int codec_type, payload_type, i; | |
243 AVStream *st; | |
244 RTSPStream *rtsp_st; | |
245 struct in_addr sdp_ip; | |
246 int ttl; | |
247 | |
248 #ifdef DEBUG | |
249 printf("sdp: %c='%s'\n", letter, buf); | |
250 #endif | |
251 | |
252 p = buf; | |
253 switch(letter) { | |
254 case 'c': | |
255 get_word(buf1, sizeof(buf1), &p); | |
256 if (strcmp(buf1, "IN") != 0) | |
257 return; | |
258 get_word(buf1, sizeof(buf1), &p); | |
259 if (strcmp(buf1, "IP4") != 0) | |
260 return; | |
261 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
262 if (inet_aton(buf1, &sdp_ip) == 0) | |
263 return; | |
264 ttl = 16; | |
265 if (*p == '/') { | |
266 p++; | |
267 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
268 ttl = atoi(buf1); | |
269 } | |
270 if (s->nb_streams == 0) { | |
271 s1->default_ip = sdp_ip; | |
272 s1->default_ttl = ttl; | |
273 } else { | |
274 st = s->streams[s->nb_streams - 1]; | |
275 rtsp_st = st->priv_data; | |
276 rtsp_st->sdp_ip = sdp_ip; | |
277 rtsp_st->sdp_ttl = ttl; | |
278 } | |
279 break; | |
280 case 's': | |
281 pstrcpy(s->title, sizeof(s->title), p); | |
282 break; | |
283 case 'i': | |
284 if (s->nb_streams == 0) { | |
285 pstrcpy(s->comment, sizeof(s->comment), p); | |
286 break; | |
287 } | |
288 break; | |
289 case 'm': | |
290 /* new stream */ | |
291 get_word(st_type, sizeof(st_type), &p); | |
292 if (!strcmp(st_type, "audio")) { | |
293 codec_type = CODEC_TYPE_AUDIO; | |
294 } else if (!strcmp(st_type, "video")) { | |
295 codec_type = CODEC_TYPE_VIDEO; | |
296 } else { | |
297 return; | |
298 } | |
299 rtsp_st = av_mallocz(sizeof(RTSPStream)); | |
300 if (!rtsp_st) | |
301 return; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
302 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
|
303 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); |
0 | 304 |
305 rtsp_st->sdp_ip = s1->default_ip; | |
306 rtsp_st->sdp_ttl = s1->default_ttl; | |
307 | |
308 get_word(buf1, sizeof(buf1), &p); /* port */ | |
309 rtsp_st->sdp_port = atoi(buf1); | |
310 | |
311 get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */ | |
312 | |
313 /* XXX: handle list of formats */ | |
314 get_word(buf1, sizeof(buf1), &p); /* format list */ | |
315 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
|
316 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
317 if (rtsp_st->sdp_payload_type == RTP_PT_MPEG2TS) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
318 /* 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
|
319 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
320 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
|
321 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
322 return; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
323 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
|
324 rtsp_st->stream_index = st->index; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
325 st->codec.codec_type = codec_type; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
326 if (rtsp_st->sdp_payload_type < 96) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
327 /* if standard payload type, we can find the codec right now */ |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
328 rtp_get_codec_info(&st->codec, rtsp_st->sdp_payload_type); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
329 } |
0 | 330 } |
331 /* put a default control url */ | |
332 pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename); | |
333 break; | |
334 case 'a': | |
335 if (strstart(p, "control:", &p) && s->nb_streams > 0) { | |
336 char proto[32]; | |
337 /* get the control url */ | |
338 st = s->streams[s->nb_streams - 1]; | |
339 rtsp_st = st->priv_data; | |
340 | |
341 /* XXX: may need to add full url resolution */ | |
342 url_split(proto, sizeof(proto), NULL, 0, NULL, NULL, 0, p); | |
343 if (proto[0] == '\0') { | |
344 /* relative control URL */ | |
345 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/"); | |
346 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); | |
347 } else { | |
348 pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); | |
349 } | |
350 } else if (strstart(p, "rtpmap:", &p)) { | |
351 /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ | |
352 get_word(buf1, sizeof(buf1), &p); | |
353 payload_type = atoi(buf1); | |
354 for(i = 0; i < s->nb_streams;i++) { | |
355 st = s->streams[i]; | |
356 rtsp_st = st->priv_data; | |
357 if (rtsp_st->sdp_payload_type == payload_type) { | |
358 sdp_parse_rtpmap(&st->codec, p); | |
359 } | |
360 } | |
361 } else if (strstart(p, "fmtp:", &p)) { | |
362 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ | |
363 get_word(buf1, sizeof(buf1), &p); | |
364 payload_type = atoi(buf1); | |
365 for(i = 0; i < s->nb_streams;i++) { | |
366 st = s->streams[i]; | |
367 rtsp_st = st->priv_data; | |
368 if (rtsp_st->sdp_payload_type == payload_type) { | |
369 sdp_parse_fmtp(&st->codec, p); | |
370 } | |
371 } | |
372 } | |
373 break; | |
374 } | |
375 } | |
376 | |
64 | 377 static int sdp_parse(AVFormatContext *s, const char *content) |
0 | 378 { |
379 const char *p; | |
380 int letter; | |
381 char buf[1024], *q; | |
382 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state; | |
383 | |
384 memset(s1, 0, sizeof(SDPParseState)); | |
385 p = content; | |
386 for(;;) { | |
387 skip_spaces(&p); | |
388 letter = *p; | |
389 if (letter == '\0') | |
390 break; | |
391 p++; | |
392 if (*p != '=') | |
393 goto next_line; | |
394 p++; | |
395 /* get the content */ | |
396 q = buf; | |
172 | 397 while (*p != '\n' && *p != '\r' && *p != '\0') { |
0 | 398 if ((q - buf) < sizeof(buf) - 1) |
399 *q++ = *p; | |
400 p++; | |
401 } | |
402 *q = '\0'; | |
403 sdp_parse_line(s, s1, letter, buf); | |
404 next_line: | |
405 while (*p != '\n' && *p != '\0') | |
406 p++; | |
407 if (*p == '\n') | |
408 p++; | |
409 } | |
410 return 0; | |
411 } | |
412 | |
413 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) | |
414 { | |
415 const char *p; | |
416 int v; | |
417 | |
418 p = *pp; | |
419 skip_spaces(&p); | |
420 v = strtol(p, (char **)&p, 10); | |
421 if (*p == '-') { | |
422 p++; | |
423 *min_ptr = v; | |
424 v = strtol(p, (char **)&p, 10); | |
425 *max_ptr = v; | |
426 } else { | |
427 *min_ptr = v; | |
428 *max_ptr = v; | |
429 } | |
430 *pp = p; | |
431 } | |
432 | |
433 /* XXX: only one transport specification is parsed */ | |
434 static void rtsp_parse_transport(RTSPHeader *reply, const char *p) | |
435 { | |
436 char transport_protocol[16]; | |
437 char profile[16]; | |
438 char lower_transport[16]; | |
439 char parameter[16]; | |
440 RTSPTransportField *th; | |
441 char buf[256]; | |
442 | |
443 reply->nb_transports = 0; | |
444 | |
445 for(;;) { | |
446 skip_spaces(&p); | |
447 if (*p == '\0') | |
448 break; | |
449 | |
450 th = &reply->transports[reply->nb_transports]; | |
451 | |
452 get_word_sep(transport_protocol, sizeof(transport_protocol), | |
453 "/", &p); | |
454 if (*p == '/') | |
455 p++; | |
456 get_word_sep(profile, sizeof(profile), "/;,", &p); | |
457 lower_transport[0] = '\0'; | |
458 if (*p == '/') { | |
172 | 459 p++; |
0 | 460 get_word_sep(lower_transport, sizeof(lower_transport), |
461 ";,", &p); | |
462 } | |
172 | 463 if (!strcasecmp(lower_transport, "TCP")) |
0 | 464 th->protocol = RTSP_PROTOCOL_RTP_TCP; |
465 else | |
466 th->protocol = RTSP_PROTOCOL_RTP_UDP; | |
467 | |
468 if (*p == ';') | |
469 p++; | |
470 /* get each parameter */ | |
471 while (*p != '\0' && *p != ',') { | |
472 get_word_sep(parameter, sizeof(parameter), "=;,", &p); | |
473 if (!strcmp(parameter, "port")) { | |
474 if (*p == '=') { | |
475 p++; | |
476 rtsp_parse_range(&th->port_min, &th->port_max, &p); | |
477 } | |
478 } else if (!strcmp(parameter, "client_port")) { | |
479 if (*p == '=') { | |
480 p++; | |
481 rtsp_parse_range(&th->client_port_min, | |
482 &th->client_port_max, &p); | |
483 } | |
484 } else if (!strcmp(parameter, "server_port")) { | |
485 if (*p == '=') { | |
486 p++; | |
487 rtsp_parse_range(&th->server_port_min, | |
488 &th->server_port_max, &p); | |
489 } | |
490 } else if (!strcmp(parameter, "interleaved")) { | |
491 if (*p == '=') { | |
492 p++; | |
493 rtsp_parse_range(&th->interleaved_min, | |
494 &th->interleaved_max, &p); | |
495 } | |
496 } else if (!strcmp(parameter, "multicast")) { | |
497 if (th->protocol == RTSP_PROTOCOL_RTP_UDP) | |
498 th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST; | |
499 } else if (!strcmp(parameter, "ttl")) { | |
500 if (*p == '=') { | |
501 p++; | |
502 th->ttl = strtol(p, (char **)&p, 10); | |
503 } | |
504 } else if (!strcmp(parameter, "destination")) { | |
505 struct in_addr ipaddr; | |
506 | |
507 if (*p == '=') { | |
508 p++; | |
509 get_word_sep(buf, sizeof(buf), ";,", &p); | |
510 if (inet_aton(buf, &ipaddr)) | |
511 th->destination = ntohl(ipaddr.s_addr); | |
512 } | |
513 } | |
514 while (*p != ';' && *p != '\0' && *p != ',') | |
515 p++; | |
516 if (*p == ';') | |
517 p++; | |
518 } | |
519 if (*p == ',') | |
520 p++; | |
521 | |
522 reply->nb_transports++; | |
523 } | |
524 } | |
525 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
526 static void rtsp_parse_range_npt(RTSPHeader *reply, const char *p) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
527 { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
528 char buf[256]; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
529 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
530 skip_spaces(&p); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
531 if (!stristart(p, "npt=", &p)) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
532 return; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
533 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
534 reply->range_start = AV_NOPTS_VALUE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
535 reply->range_end = AV_NOPTS_VALUE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
536 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
537 get_word_sep(buf, sizeof(buf), "-", &p); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
538 reply->range_start = parse_date(buf, 1); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
539 if (*p == '-') { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
540 p++; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
541 get_word_sep(buf, sizeof(buf), "-", &p); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
542 reply->range_end = parse_date(buf, 1); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
543 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
544 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
545 |
0 | 546 void rtsp_parse_line(RTSPHeader *reply, const char *buf) |
547 { | |
548 const char *p; | |
549 | |
550 /* NOTE: we do case independent match for broken servers */ | |
551 p = buf; | |
552 if (stristart(p, "Session:", &p)) { | |
553 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); | |
554 } else if (stristart(p, "Content-Length:", &p)) { | |
555 reply->content_length = strtol(p, NULL, 10); | |
556 } else if (stristart(p, "Transport:", &p)) { | |
557 rtsp_parse_transport(reply, p); | |
558 } else if (stristart(p, "CSeq:", &p)) { | |
559 reply->seq = strtol(p, NULL, 10); | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
560 } else if (stristart(p, "Range:", &p)) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
561 rtsp_parse_range_npt(reply, p); |
0 | 562 } |
563 } | |
564 | |
179 | 565 /* skip a RTP/TCP interleaved packet */ |
566 static void rtsp_skip_packet(AVFormatContext *s) | |
567 { | |
568 RTSPState *rt = s->priv_data; | |
569 int ret, len, len1; | |
570 uint8_t buf[1024]; | |
571 | |
572 ret = url_read(rt->rtsp_hd, buf, 3); | |
573 if (ret != 3) | |
574 return; | |
575 len = (buf[1] << 8) | buf[2]; | |
576 #ifdef DEBUG | |
577 printf("skipping RTP packet len=%d\n", len); | |
578 #endif | |
579 /* skip payload */ | |
580 while (len > 0) { | |
581 len1 = len; | |
582 if (len1 > sizeof(buf)) | |
583 len1 = sizeof(buf); | |
584 ret = url_read(rt->rtsp_hd, buf, len1); | |
585 if (ret != len1) | |
586 return; | |
587 len -= len1; | |
588 } | |
589 } | |
0 | 590 |
591 static void rtsp_send_cmd(AVFormatContext *s, | |
592 const char *cmd, RTSPHeader *reply, | |
593 unsigned char **content_ptr) | |
594 { | |
595 RTSPState *rt = s->priv_data; | |
596 char buf[4096], buf1[1024], *q; | |
597 unsigned char ch; | |
598 const char *p; | |
599 int content_length, line_count; | |
600 unsigned char *content = NULL; | |
601 | |
602 memset(reply, 0, sizeof(RTSPHeader)); | |
603 | |
604 rt->seq++; | |
605 pstrcpy(buf, sizeof(buf), cmd); | |
172 | 606 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); |
0 | 607 pstrcat(buf, sizeof(buf), buf1); |
608 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { | |
172 | 609 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); |
0 | 610 pstrcat(buf, sizeof(buf), buf1); |
611 } | |
172 | 612 pstrcat(buf, sizeof(buf), "\r\n"); |
0 | 613 #ifdef DEBUG |
614 printf("Sending:\n%s--\n", buf); | |
615 #endif | |
616 url_write(rt->rtsp_hd, buf, strlen(buf)); | |
617 | |
618 /* parse reply (XXX: use buffers) */ | |
619 line_count = 0; | |
620 rt->last_reply[0] = '\0'; | |
621 for(;;) { | |
622 q = buf; | |
623 for(;;) { | |
179 | 624 if (url_read(rt->rtsp_hd, &ch, 1) != 1) |
0 | 625 break; |
626 if (ch == '\n') | |
627 break; | |
179 | 628 if (ch == '$') { |
629 /* XXX: only parse it if first char on line ? */ | |
630 rtsp_skip_packet(s); | |
631 } else if (ch != '\r') { | |
0 | 632 if ((q - buf) < sizeof(buf) - 1) |
633 *q++ = ch; | |
634 } | |
635 } | |
636 *q = '\0'; | |
637 #ifdef DEBUG | |
638 printf("line='%s'\n", buf); | |
639 #endif | |
640 /* test if last line */ | |
641 if (buf[0] == '\0') | |
642 break; | |
643 p = buf; | |
644 if (line_count == 0) { | |
645 /* get reply code */ | |
646 get_word(buf1, sizeof(buf1), &p); | |
647 get_word(buf1, sizeof(buf1), &p); | |
648 reply->status_code = atoi(buf1); | |
649 } else { | |
650 rtsp_parse_line(reply, p); | |
651 pstrcat(rt->last_reply, sizeof(rt->last_reply), p); | |
652 pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n"); | |
653 } | |
654 line_count++; | |
655 } | |
656 | |
657 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') | |
658 pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id); | |
659 | |
660 content_length = reply->content_length; | |
661 if (content_length > 0) { | |
662 /* leave some room for a trailing '\0' (useful for simple parsing) */ | |
663 content = av_malloc(content_length + 1); | |
664 url_read(rt->rtsp_hd, content, content_length); | |
665 content[content_length] = '\0'; | |
666 } | |
667 if (content_ptr) | |
668 *content_ptr = content; | |
669 } | |
670 | |
671 /* useful for modules: set RTSP callback function */ | |
672 | |
673 void rtsp_set_callback(FFRTSPCallback *rtsp_cb) | |
674 { | |
675 ff_rtsp_callback = rtsp_cb; | |
676 } | |
677 | |
678 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
679 /* 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
|
680 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
|
681 { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
682 int i; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
683 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
|
684 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
685 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
|
686 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
|
687 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
|
688 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
|
689 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
|
690 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
|
691 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
|
692 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
693 av_free(rtsp_st); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
694 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
695 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
|
696 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
697 |
0 | 698 static int rtsp_read_header(AVFormatContext *s, |
699 AVFormatParameters *ap) | |
700 { | |
701 RTSPState *rt = s->priv_data; | |
702 char host[1024], path[1024], tcpname[1024], cmd[2048]; | |
703 URLContext *rtsp_hd; | |
704 int port, i, ret, err; | |
705 RTSPHeader reply1, *reply = &reply1; | |
706 unsigned char *content = NULL; | |
707 RTSPStream *rtsp_st; | |
708 int protocol_mask; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
709 AVStream *st; |
0 | 710 |
711 /* extract hostname and port */ | |
712 url_split(NULL, 0, | |
713 host, sizeof(host), &port, path, sizeof(path), s->filename); | |
714 if (port < 0) | |
715 port = RTSP_DEFAULT_PORT; | |
716 | |
717 /* open the tcp connexion */ | |
718 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); | |
719 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) | |
720 return AVERROR_IO; | |
721 rt->rtsp_hd = rtsp_hd; | |
722 rt->seq = 0; | |
723 | |
724 /* describe the stream */ | |
725 snprintf(cmd, sizeof(cmd), | |
172 | 726 "DESCRIBE %s RTSP/1.0\r\n" |
727 "Accept: application/sdp\r\n", | |
0 | 728 s->filename); |
729 rtsp_send_cmd(s, cmd, reply, &content); | |
730 if (!content) { | |
731 err = AVERROR_INVALIDDATA; | |
732 goto fail; | |
733 } | |
734 if (reply->status_code != RTSP_STATUS_OK) { | |
735 err = AVERROR_INVALIDDATA; | |
736 goto fail; | |
737 } | |
738 | |
739 /* now we got the SDP description, we parse it */ | |
740 ret = sdp_parse(s, (const char *)content); | |
741 av_freep(&content); | |
742 if (ret < 0) { | |
743 err = AVERROR_INVALIDDATA; | |
744 goto fail; | |
745 } | |
746 | |
747 protocol_mask = rtsp_default_protocols; | |
748 | |
749 /* for each stream, make the setup request */ | |
750 /* XXX: we assume the same server is used for the control of each | |
751 RTSP stream */ | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
752 for(i=0;i<rt->nb_rtsp_streams;i++) { |
0 | 753 char transport[2048]; |
754 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
755 rtsp_st = rt->rtsp_streams[i]; |
0 | 756 |
757 /* compute available transports */ | |
758 transport[0] = '\0'; | |
759 | |
760 /* RTP/UDP */ | |
761 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) { | |
762 char buf[256]; | |
763 int j; | |
764 | |
765 /* first try in specified port range */ | |
766 if (rtsp_rtp_port_min != 0) { | |
767 for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) { | |
768 snprintf(buf, sizeof(buf), "rtp://?localport=%d", j); | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
769 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDONLY) == 0) |
0 | 770 goto rtp_opened; |
771 } | |
772 } | |
773 | |
774 /* then try on any port */ | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
775 if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
776 err = AVERROR_INVALIDDATA; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
777 goto fail; |
0 | 778 } |
779 | |
780 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
|
781 port = rtp_get_local_port(rtsp_st->rtp_handle); |
0 | 782 if (transport[0] != '\0') |
783 pstrcat(transport, sizeof(transport), ","); | |
784 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, | |
785 "RTP/AVP/UDP;unicast;client_port=%d-%d", | |
786 port, port + 1); | |
787 } | |
788 | |
789 /* RTP/TCP */ | |
790 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) { | |
791 if (transport[0] != '\0') | |
792 pstrcat(transport, sizeof(transport), ","); | |
793 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, | |
794 "RTP/AVP/TCP"); | |
795 } | |
796 | |
797 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) { | |
798 if (transport[0] != '\0') | |
799 pstrcat(transport, sizeof(transport), ","); | |
800 snprintf(transport + strlen(transport), | |
801 sizeof(transport) - strlen(transport) - 1, | |
802 "RTP/AVP/UDP;multicast"); | |
803 } | |
804 snprintf(cmd, sizeof(cmd), | |
172 | 805 "SETUP %s RTSP/1.0\r\n" |
806 "Transport: %s\r\n", | |
0 | 807 rtsp_st->control_url, transport); |
808 rtsp_send_cmd(s, cmd, reply, NULL); | |
809 if (reply->status_code != RTSP_STATUS_OK || | |
810 reply->nb_transports != 1) { | |
811 err = AVERROR_INVALIDDATA; | |
812 goto fail; | |
813 } | |
814 | |
815 /* XXX: same protocol for all streams is required */ | |
816 if (i > 0) { | |
817 if (reply->transports[0].protocol != rt->protocol) { | |
818 err = AVERROR_INVALIDDATA; | |
819 goto fail; | |
820 } | |
821 } else { | |
822 rt->protocol = reply->transports[0].protocol; | |
823 } | |
824 | |
825 /* close RTP connection if not choosen */ | |
826 if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP && | |
827 (protocol_mask & (1 << 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
|
828 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
|
829 rtsp_st->rtp_handle = NULL; |
0 | 830 } |
831 | |
832 switch(reply->transports[0].protocol) { | |
833 case RTSP_PROTOCOL_RTP_TCP: | |
834 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; | |
835 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; | |
836 break; | |
837 | |
838 case RTSP_PROTOCOL_RTP_UDP: | |
839 { | |
840 char url[1024]; | |
841 | |
842 /* XXX: also use address if specified */ | |
843 snprintf(url, sizeof(url), "rtp://%s:%d", | |
844 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
|
845 if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { |
0 | 846 err = AVERROR_INVALIDDATA; |
847 goto fail; | |
848 } | |
849 } | |
850 break; | |
851 case RTSP_PROTOCOL_RTP_UDP_MULTICAST: | |
852 { | |
853 char url[1024]; | |
854 int ttl; | |
855 | |
856 ttl = reply->transports[0].ttl; | |
857 if (!ttl) | |
858 ttl = 16; | |
859 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", | |
860 host, | |
861 reply->transports[0].server_port_min, | |
862 ttl); | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
863 if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) { |
0 | 864 err = AVERROR_INVALIDDATA; |
865 goto fail; | |
866 } | |
867 } | |
868 break; | |
869 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
870 /* 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
|
871 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
872 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
|
873 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
|
874 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
875 s->ctx_flags |= AVFMTCTX_NOHEADER; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
876 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
877 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
|
878 err = AVERROR_NOMEM; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
879 goto fail; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
880 } |
0 | 881 } |
882 | |
883 /* use callback if available to extend setup */ | |
884 if (ff_rtsp_callback) { | |
885 if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, | |
886 NULL, 0, rt->last_reply) < 0) { | |
887 err = AVERROR_INVALIDDATA; | |
888 goto fail; | |
889 } | |
890 } | |
891 | |
892 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
893 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
894 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
|
895 zero */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
896 if (ap && ap->initial_pause) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
897 /* do not start immediately */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
898 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
899 if (rtsp_read_play(s) < 0) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
900 err = AVERROR_INVALIDDATA; |
0 | 901 goto fail; |
902 } | |
903 } | |
904 return 0; | |
905 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
906 rtsp_close_streams(rt); |
0 | 907 av_freep(&content); |
908 url_close(rt->rtsp_hd); | |
909 return err; | |
910 } | |
911 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
912 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
|
913 uint8_t *buf, int buf_size) |
0 | 914 { |
915 RTSPState *rt = s->priv_data; | |
172 | 916 int id, len, i, ret; |
0 | 917 RTSPStream *rtsp_st; |
918 | |
172 | 919 #ifdef DEBUG_RTP_TCP |
920 printf("tcp_read_packet:\n"); | |
921 #endif | |
0 | 922 redo: |
923 for(;;) { | |
172 | 924 ret = url_read(rt->rtsp_hd, buf, 1); |
925 #ifdef DEBUG_RTP_TCP | |
926 printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]); | |
927 #endif | |
928 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
|
929 return -1; |
172 | 930 if (buf[0] == '$') |
0 | 931 break; |
932 } | |
172 | 933 ret = url_read(rt->rtsp_hd, buf, 3); |
934 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
|
935 return -1; |
172 | 936 id = buf[0]; |
937 len = (buf[1] << 8) | buf[2]; | |
938 #ifdef DEBUG_RTP_TCP | |
939 printf("id=%d len=%d\n", id, len); | |
940 #endif | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
941 if (len > buf_size || len < 12) |
0 | 942 goto redo; |
943 /* get the data */ | |
172 | 944 ret = url_read(rt->rtsp_hd, buf, len); |
945 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
|
946 return -1; |
172 | 947 |
0 | 948 /* 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
|
949 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
|
950 rtsp_st = rt->rtsp_streams[i]; |
172 | 951 if (id >= rtsp_st->interleaved_min && |
952 id <= rtsp_st->interleaved_max) | |
0 | 953 goto found; |
954 } | |
955 goto redo; | |
956 found: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
957 *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
|
958 return len; |
0 | 959 } |
960 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
961 static int udp_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
|
962 uint8_t *buf, int buf_size) |
0 | 963 { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
964 RTSPState *rt = s->priv_data; |
0 | 965 RTSPStream *rtsp_st; |
966 fd_set rfds; | |
967 int fd1, fd2, fd_max, n, i, ret; | |
968 struct timeval tv; | |
969 | |
970 for(;;) { | |
179 | 971 if (url_interrupt_cb()) |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
972 return -1; |
0 | 973 FD_ZERO(&rfds); |
974 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
|
975 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
|
976 rtsp_st = rt->rtsp_streams[i]; |
0 | 977 /* 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
|
978 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 979 if (fd1 > fd_max) |
980 fd_max = fd1; | |
981 FD_SET(fd1, &rfds); | |
982 } | |
983 tv.tv_sec = 0; | |
179 | 984 tv.tv_usec = 100 * 1000; |
0 | 985 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
986 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
|
987 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
|
988 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
|
989 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 990 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
|
991 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
|
992 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
|
993 *prtsp_st = rtsp_st; |
0 | 994 return ret; |
995 } | |
996 } | |
997 } | |
998 } | |
999 } | |
1000 } | |
1001 | |
1002 static int rtsp_read_packet(AVFormatContext *s, | |
1003 AVPacket *pkt) | |
1004 { | |
1005 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
|
1006 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
|
1007 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
|
1008 uint8_t buf[RTP_MAX_PACKET_LENGTH]; |
0 | 1009 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1010 /* 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
|
1011 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
|
1012 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
|
1013 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
|
1014 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
|
1015 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1016 } 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
|
1017 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1018 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1019 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
|
1020 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1021 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1022 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1023 /* 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
|
1024 redo: |
0 | 1025 switch(rt->protocol) { |
1026 default: | |
1027 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
|
1028 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
0 | 1029 break; |
1030 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
|
1031 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
|
1032 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
0 | 1033 break; |
1034 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1035 if (len < 0) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1036 return AVERROR_IO; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1037 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
|
1038 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
|
1039 goto redo; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1040 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
|
1041 /* 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
|
1042 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
|
1043 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1044 return 0; |
0 | 1045 } |
1046 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1047 static int rtsp_read_play(AVFormatContext *s) |
179 | 1048 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1049 RTSPState *rt = s->priv_data; |
179 | 1050 RTSPHeader reply1, *reply = &reply1; |
1051 char cmd[1024]; | |
1052 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1053 printf("hello state=%d\n", rt->state); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1054 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1055 if (rt->state == RTSP_STATE_PAUSED) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1056 snprintf(cmd, sizeof(cmd), |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1057 "PLAY %s RTSP/1.0\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1058 s->filename); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1059 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1060 snprintf(cmd, sizeof(cmd), |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1061 "PLAY %s RTSP/1.0\r\n" |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1062 "Range: npt=%0.3f-\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1063 s->filename, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1064 (double)rt->seek_timestamp / AV_TIME_BASE); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1065 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1066 rtsp_send_cmd(s, cmd, reply, NULL); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1067 if (reply->status_code != RTSP_STATUS_OK) { |
179 | 1068 return -1; |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1069 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1070 rt->state = RTSP_STATE_PLAYING; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1071 return 0; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1072 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1073 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1074 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1075 /* pause the stream */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1076 static int rtsp_read_pause(AVFormatContext *s) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1077 { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1078 RTSPState *rt = s->priv_data; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1079 RTSPHeader reply1, *reply = &reply1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1080 char cmd[1024]; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1081 |
179 | 1082 rt = s->priv_data; |
1083 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1084 if (rt->state != RTSP_STATE_PLAYING) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1085 return 0; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1086 |
179 | 1087 snprintf(cmd, sizeof(cmd), |
1088 "PAUSE %s RTSP/1.0\r\n", | |
1089 s->filename); | |
1090 rtsp_send_cmd(s, cmd, reply, NULL); | |
1091 if (reply->status_code != RTSP_STATUS_OK) { | |
1092 return -1; | |
1093 } else { | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1094 rt->state = RTSP_STATE_PAUSED; |
179 | 1095 return 0; |
1096 } | |
1097 } | |
1098 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1099 static int rtsp_read_seek(AVFormatContext *s, int stream_index, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1100 int64_t timestamp) |
179 | 1101 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1102 RTSPState *rt = s->priv_data; |
179 | 1103 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1104 rt->seek_timestamp = timestamp; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1105 switch(rt->state) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1106 default: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1107 case RTSP_STATE_IDLE: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1108 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1109 case RTSP_STATE_PLAYING: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1110 if (rtsp_read_play(s) != 0) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1111 return -1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1112 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1113 case RTSP_STATE_PAUSED: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1114 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1115 break; |
179 | 1116 } |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1117 return 0; |
179 | 1118 } |
1119 | |
0 | 1120 static int rtsp_read_close(AVFormatContext *s) |
1121 { | |
1122 RTSPState *rt = s->priv_data; | |
1123 RTSPHeader reply1, *reply = &reply1; | |
1124 char cmd[1024]; | |
1125 | |
172 | 1126 #if 0 |
0 | 1127 /* NOTE: it is valid to flush the buffer here */ |
1128 if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { | |
1129 url_fclose(&rt->rtsp_gb); | |
1130 } | |
172 | 1131 #endif |
0 | 1132 snprintf(cmd, sizeof(cmd), |
172 | 1133 "TEARDOWN %s RTSP/1.0\r\n", |
0 | 1134 s->filename); |
1135 rtsp_send_cmd(s, cmd, reply, NULL); | |
1136 | |
1137 if (ff_rtsp_callback) { | |
1138 ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, | |
1139 NULL, 0, NULL); | |
1140 } | |
1141 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1142 rtsp_close_streams(rt); |
0 | 1143 url_close(rt->rtsp_hd); |
1144 return 0; | |
1145 } | |
1146 | |
179 | 1147 AVInputFormat rtsp_demux = { |
0 | 1148 "rtsp", |
1149 "RTSP input format", | |
1150 sizeof(RTSPState), | |
1151 rtsp_probe, | |
1152 rtsp_read_header, | |
1153 rtsp_read_packet, | |
1154 rtsp_read_close, | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1155 rtsp_read_seek, |
0 | 1156 .flags = AVFMT_NOFILE, |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1157 .read_play = rtsp_read_play, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1158 .read_pause = rtsp_read_pause, |
0 | 1159 }; |
1160 | |
1161 static int sdp_probe(AVProbeData *p1) | |
1162 { | |
1163 const char *p; | |
1164 | |
1165 /* we look for a line beginning "c=IN IP4" */ | |
1166 p = p1->buf; | |
1167 while (*p != '\0') { | |
1168 if (strstart(p, "c=IN IP4", NULL)) | |
1169 return AVPROBE_SCORE_MAX / 2; | |
1170 p = strchr(p, '\n'); | |
1171 if (!p) | |
1172 break; | |
1173 p++; | |
1174 if (*p == '\r') | |
1175 p++; | |
1176 } | |
1177 return 0; | |
1178 } | |
1179 | |
1180 #define SDP_MAX_SIZE 8192 | |
1181 | |
1182 static int sdp_read_header(AVFormatContext *s, | |
1183 AVFormatParameters *ap) | |
1184 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1185 RTSPState *rt = s->priv_data; |
0 | 1186 RTSPStream *rtsp_st; |
1187 int size, i, err; | |
1188 char *content; | |
1189 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
|
1190 AVStream *st; |
0 | 1191 |
1192 /* read the whole sdp file */ | |
1193 /* XXX: better loading */ | |
1194 content = av_malloc(SDP_MAX_SIZE); | |
1195 size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1); | |
1196 if (size <= 0) { | |
1197 av_free(content); | |
1198 return AVERROR_INVALIDDATA; | |
1199 } | |
1200 content[size] ='\0'; | |
1201 | |
1202 sdp_parse(s, content); | |
1203 av_free(content); | |
1204 | |
1205 /* 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
|
1206 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
|
1207 rtsp_st = rt->rtsp_streams[i]; |
0 | 1208 |
1209 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", | |
1210 inet_ntoa(rtsp_st->sdp_ip), | |
1211 rtsp_st->sdp_port, | |
1212 rtsp_st->sdp_ttl); | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1213 if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) { |
0 | 1214 err = AVERROR_INVALIDDATA; |
1215 goto fail; | |
1216 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1217 /* 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
|
1218 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1219 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
|
1220 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
|
1221 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1222 s->ctx_flags |= AVFMTCTX_NOHEADER; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1223 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type); |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1224 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
|
1225 err = AVERROR_NOMEM; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1226 goto fail; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1227 } |
0 | 1228 } |
1229 return 0; | |
1230 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1231 rtsp_close_streams(rt); |
0 | 1232 return err; |
1233 } | |
1234 | |
1235 static int sdp_read_packet(AVFormatContext *s, | |
1236 AVPacket *pkt) | |
1237 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1238 return rtsp_read_packet(s, pkt); |
0 | 1239 } |
1240 | |
1241 static int sdp_read_close(AVFormatContext *s) | |
1242 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1243 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
|
1244 rtsp_close_streams(rt); |
0 | 1245 return 0; |
1246 } | |
1247 | |
1248 | |
1249 static AVInputFormat sdp_demux = { | |
1250 "sdp", | |
1251 "SDP", | |
1252 sizeof(RTSPState), | |
1253 sdp_probe, | |
1254 sdp_read_header, | |
1255 sdp_read_packet, | |
1256 sdp_read_close, | |
1257 }; | |
1258 | |
1259 | |
1260 /* dummy redirector format (used directly in av_open_input_file now) */ | |
1261 static int redir_probe(AVProbeData *pd) | |
1262 { | |
1263 const char *p; | |
1264 p = pd->buf; | |
1265 while (redir_isspace(*p)) | |
1266 p++; | |
1267 if (strstart(p, "http://", NULL) || | |
1268 strstart(p, "rtsp://", NULL)) | |
1269 return AVPROBE_SCORE_MAX; | |
1270 return 0; | |
1271 } | |
1272 | |
1273 /* called from utils.c */ | |
1274 int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f) | |
1275 { | |
1276 char buf[4096], *q; | |
1277 int c; | |
1278 AVFormatContext *ic = NULL; | |
1279 | |
1280 /* parse each URL and try to open it */ | |
1281 c = url_fgetc(f); | |
1282 while (c != URL_EOF) { | |
1283 /* skip spaces */ | |
1284 for(;;) { | |
1285 if (!redir_isspace(c)) | |
1286 break; | |
1287 c = url_fgetc(f); | |
1288 } | |
1289 if (c == URL_EOF) | |
1290 break; | |
1291 /* record url */ | |
1292 q = buf; | |
1293 for(;;) { | |
1294 if (c == URL_EOF || redir_isspace(c)) | |
1295 break; | |
1296 if ((q - buf) < sizeof(buf) - 1) | |
1297 *q++ = c; | |
1298 c = url_fgetc(f); | |
1299 } | |
1300 *q = '\0'; | |
1301 //printf("URL='%s'\n", buf); | |
1302 /* try to open the media file */ | |
1303 if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0) | |
1304 break; | |
1305 } | |
1306 *ic_ptr = ic; | |
1307 if (!ic) | |
1308 return AVERROR_IO; | |
1309 else | |
1310 return 0; | |
1311 } | |
1312 | |
1313 AVInputFormat redir_demux = { | |
1314 "redir", | |
1315 "Redirector format", | |
1316 0, | |
1317 redir_probe, | |
1318 NULL, | |
1319 NULL, | |
1320 NULL, | |
1321 }; | |
1322 | |
1323 int rtsp_init(void) | |
1324 { | |
1325 av_register_input_format(&rtsp_demux); | |
1326 av_register_input_format(&redir_demux); | |
1327 av_register_input_format(&sdp_demux); | |
1328 return 0; | |
1329 } |