Mercurial > libavformat.hg
annotate rtsp.c @ 1960:c0289552590f libavformat
Change the vhook code to send real timestamps to the filters instead of the
current time of day, which is useless, and which the filters could just as
easily query for themselves.
patch by Bobby Bingham, uhmmmm gmail com
author | diego |
---|---|
date | Thu, 29 Mar 2007 05:24:35 +0000 |
parents | 3e1bdfd67724 |
children | 5b54f43626d0 |
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 */ |
21 #include "avformat.h" | |
22 | |
1808
572ce77d7333
Fix compilation on Mac OS X, patch by Marc Hoffman, mmh pleasantst com.
diego
parents:
1754
diff
changeset
|
23 #include <sys/time.h> |
182 | 24 #include <unistd.h> /* for select() prototype */ |
1754 | 25 #include "network.h" |
0 | 26 |
1419 | 27 #include "rtp_internal.h" |
28 | |
0 | 29 //#define DEBUG |
172 | 30 //#define DEBUG_RTP_TCP |
0 | 31 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
32 enum RTSPClientState { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
33 RTSP_STATE_IDLE, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
34 RTSP_STATE_PLAYING, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
35 RTSP_STATE_PAUSED, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
36 }; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
37 |
0 | 38 typedef struct RTSPState { |
39 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
|
40 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
|
41 struct RTSPStream **rtsp_streams; |
885 | 42 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
43 enum RTSPClientState state; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
44 int64_t seek_timestamp; |
885 | 45 |
172 | 46 /* XXX: currently we use unbuffered input */ |
47 // ByteIOContext rtsp_gb; | |
0 | 48 int seq; /* RTSP command sequence number */ |
49 char session_id[512]; | |
50 enum RTSPProtocol protocol; | |
51 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
|
52 RTPDemuxContext *cur_rtp; |
0 | 53 } RTSPState; |
54 | |
55 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
|
56 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
|
57 RTPDemuxContext *rtp_ctx; /* RTP parse context */ |
885 | 58 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
59 int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */ |
0 | 60 int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */ |
61 char control_url[1024]; /* url for this stream (from SDP) */ | |
62 | |
63 int sdp_port; /* port (from SDP content - not used in RTSP) */ | |
64 struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */ | |
65 int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */ | |
66 int sdp_payload_type; /* payload type - only used in SDP */ | |
774 | 67 rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */ |
1419 | 68 |
69 RTPDynamicProtocolHandler *dynamic_handler; ///< Only valid if it's a dynamic protocol. (This is the handler structure) | |
70 void *dynamic_protocol_context; ///< Only valid if it's a dynamic protocol. (This is any private data associated with the dynamic protocol) | |
0 | 71 } RTSPStream; |
72 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
73 static int rtsp_read_play(AVFormatContext *s); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
74 |
0 | 75 /* XXX: currently, the only way to change the protocols consists in |
76 changing this variable */ | |
77 | |
774 | 78 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP); |
0 | 79 |
80 FFRTSPCallback *ff_rtsp_callback = NULL; | |
81 | |
82 static int rtsp_probe(AVProbeData *p) | |
83 { | |
84 if (strstart(p->filename, "rtsp:", NULL)) | |
85 return AVPROBE_SCORE_MAX; | |
86 return 0; | |
87 } | |
88 | |
89 static int redir_isspace(int c) | |
90 { | |
91 return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); | |
92 } | |
93 | |
94 static void skip_spaces(const char **pp) | |
95 { | |
96 const char *p; | |
97 p = *pp; | |
98 while (redir_isspace(*p)) | |
99 p++; | |
100 *pp = p; | |
101 } | |
102 | |
885 | 103 static void get_word_sep(char *buf, int buf_size, const char *sep, |
0 | 104 const char **pp) |
105 { | |
106 const char *p; | |
107 char *q; | |
108 | |
109 p = *pp; | |
774 | 110 if (*p == '/') |
111 p++; | |
0 | 112 skip_spaces(&p); |
113 q = buf; | |
114 while (!strchr(sep, *p) && *p != '\0') { | |
115 if ((q - buf) < buf_size - 1) | |
116 *q++ = *p; | |
117 p++; | |
118 } | |
119 if (buf_size > 0) | |
120 *q = '\0'; | |
121 *pp = p; | |
122 } | |
123 | |
124 static void get_word(char *buf, int buf_size, const char **pp) | |
125 { | |
126 const char *p; | |
127 char *q; | |
128 | |
129 p = *pp; | |
130 skip_spaces(&p); | |
131 q = buf; | |
132 while (!redir_isspace(*p) && *p != '\0') { | |
133 if ((q - buf) < buf_size - 1) | |
134 *q++ = *p; | |
135 p++; | |
136 } | |
137 if (buf_size > 0) | |
138 *q = '\0'; | |
139 *pp = p; | |
140 } | |
141 | |
142 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other | |
143 params>] */ | |
1419 | 144 static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p) |
0 | 145 { |
146 char buf[256]; | |
774 | 147 int i; |
148 AVCodec *c; | |
1124
d3aff2c607f9
Add const to (mostly) char* and make some functions static, which aren't used
diego
parents:
1003
diff
changeset
|
149 const char *c_name; |
0 | 150 |
774 | 151 /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and |
152 see if we can handle this kind of payload */ | |
0 | 153 get_word_sep(buf, sizeof(buf), "/", &p); |
774 | 154 if (payload_type >= RTP_PT_PRIVATE) { |
1419 | 155 RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler; |
156 while(handler) { | |
157 if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) { | |
158 codec->codec_id = handler->codec_id; | |
159 rtsp_st->dynamic_handler= handler; | |
160 if(handler->open) { | |
161 rtsp_st->dynamic_protocol_context= handler->open(); | |
162 } | |
774 | 163 break; |
164 } | |
1419 | 165 handler= handler->next; |
166 } | |
774 | 167 } else { |
168 /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */ | |
169 /* search into AVRtpPayloadTypes[] */ | |
170 for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i) | |
171 if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){ | |
172 codec->codec_id = AVRtpPayloadTypes[i].codec_id; | |
173 break; | |
174 } | |
175 } | |
176 | |
177 c = avcodec_find_decoder(codec->codec_id); | |
178 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
|
179 c_name = c->name; |
774 | 180 else |
181 c_name = (char *)NULL; | |
182 | |
183 if (c_name) { | |
184 get_word_sep(buf, sizeof(buf), "/", &p); | |
185 i = atoi(buf); | |
186 switch (codec->codec_type) { | |
187 case CODEC_TYPE_AUDIO: | |
188 av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name); | |
189 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE; | |
190 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS; | |
191 if (i > 0) { | |
192 codec->sample_rate = i; | |
193 get_word_sep(buf, sizeof(buf), "/", &p); | |
194 i = atoi(buf); | |
195 if (i > 0) | |
196 codec->channels = i; | |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
197 // 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
|
198 // frequency. No problem, but the sample rate is being set here by the sdp line. Upcoming patch forthcoming. (rdm) |
774 | 199 } |
200 av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate); | |
201 av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels); | |
202 break; | |
203 case CODEC_TYPE_VIDEO: | |
204 av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name); | |
205 break; | |
206 default: | |
207 break; | |
208 } | |
0 | 209 return 0; |
210 } | |
774 | 211 |
212 return -1; | |
0 | 213 } |
214 | |
215 /* return the length and optionnaly the data */ | |
216 static int hex_to_data(uint8_t *data, const char *p) | |
217 { | |
218 int c, len, v; | |
219 | |
220 len = 0; | |
221 v = 1; | |
222 for(;;) { | |
223 skip_spaces(&p); | |
224 if (p == '\0') | |
225 break; | |
226 c = toupper((unsigned char)*p++); | |
227 if (c >= '0' && c <= '9') | |
228 c = c - '0'; | |
229 else if (c >= 'A' && c <= 'F') | |
230 c = c - 'A' + 10; | |
231 else | |
232 break; | |
233 v = (v << 4) | c; | |
234 if (v & 0x100) { | |
235 if (data) | |
236 data[len] = v; | |
237 len++; | |
238 v = 1; | |
239 } | |
240 } | |
241 return len; | |
242 } | |
243 | |
774 | 244 static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value) |
245 { | |
246 switch (codec->codec_id) { | |
247 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
|
248 case CODEC_ID_AAC: |
774 | 249 if (!strcmp(attr, "config")) { |
250 /* decode the hexa encoded parameter */ | |
251 int len = hex_to_data(NULL, value); | |
252 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); | |
253 if (!codec->extradata) | |
254 return; | |
255 codec->extradata_size = len; | |
256 hex_to_data(codec->extradata, value); | |
257 } | |
258 break; | |
259 default: | |
260 break; | |
261 } | |
262 return; | |
263 } | |
264 | |
265 typedef struct attrname_map | |
266 { | |
1124
d3aff2c607f9
Add const to (mostly) char* and make some functions static, which aren't used
diego
parents:
1003
diff
changeset
|
267 const char *str; |
774 | 268 uint16_t type; |
269 uint32_t offset; | |
270 } attrname_map_t; | |
271 | |
272 /* All known fmtp parmeters and the corresping RTPAttrTypeEnum */ | |
273 #define ATTR_NAME_TYPE_INT 0 | |
274 #define ATTR_NAME_TYPE_STR 1 | |
275 static attrname_map_t attr_names[]= | |
276 { | |
277 {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)}, | |
278 {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)}, | |
279 {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)}, | |
280 {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)}, | |
281 {"StreamType", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)}, | |
282 {"mode", ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)}, | |
283 {NULL, -1, -1}, | |
284 }; | |
285 | |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
286 /** 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
|
287 * 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
|
288 */ |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
289 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
|
290 { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
291 skip_spaces(p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
292 if(**p) |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
293 { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
294 get_word_sep(attr, attr_size, "=", p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
295 if (**p == '=') |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
296 (*p)++; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
297 get_word_sep(value, value_size, ";", p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
298 if (**p == ';') |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
299 (*p)++; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
300 return 1; |
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 return 0; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
303 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
304 |
774 | 305 /* parse a SDP line and save stream attributes */ |
306 static void sdp_parse_fmtp(AVStream *st, const char *p) | |
0 | 307 { |
308 char attr[256]; | |
309 char value[4096]; | |
774 | 310 int i; |
311 | |
312 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
|
313 AVCodecContext *codec = st->codec; |
774 | 314 rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data; |
0 | 315 |
316 /* loop on each attribute */ | |
1514
958decd51c1f
remove duplicate code, patch by Ryan Martell rdm4 A martellventures P com
gpoirier
parents:
1472
diff
changeset
|
317 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
|
318 { |
887 | 319 /* grab the codec extra_data from the config parameter of the fmtp line */ |
774 | 320 sdp_parse_fmtp_config(codec, attr, value); |
321 /* Looking for a known attribute */ | |
322 for (i = 0; attr_names[i].str; ++i) { | |
323 if (!strcasecmp(attr, attr_names[i].str)) { | |
324 if (attr_names[i].type == ATTR_NAME_TYPE_INT) | |
325 *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value); | |
326 else if (attr_names[i].type == ATTR_NAME_TYPE_STR) | |
327 *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value); | |
887 | 328 } |
0 | 329 } |
330 } | |
331 } | |
332 | |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
333 /** 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
|
334 * and end time. |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
335 * 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
|
336 */ |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
337 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
|
338 { |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
339 char buf[256]; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
340 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
341 skip_spaces(&p); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
342 if (!stristart(p, "npt=", &p)) |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
343 return; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
344 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
345 *start = AV_NOPTS_VALUE; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
346 *end = AV_NOPTS_VALUE; |
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 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
|
349 *start = parse_date(buf, 1); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
350 if (*p == '-') { |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
351 p++; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
352 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
|
353 *end = parse_date(buf, 1); |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
354 } |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
355 // 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
|
356 // 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
|
357 } |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
358 |
0 | 359 typedef struct SDPParseState { |
360 /* SDP only */ | |
361 struct in_addr default_ip; | |
362 int default_ttl; | |
363 } SDPParseState; | |
364 | |
365 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | |
366 int letter, const char *buf) | |
367 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
368 RTSPState *rt = s->priv_data; |
0 | 369 char buf1[64], st_type[64]; |
370 const char *p; | |
371 int codec_type, payload_type, i; | |
372 AVStream *st; | |
373 RTSPStream *rtsp_st; | |
374 struct in_addr sdp_ip; | |
375 int ttl; | |
376 | |
377 #ifdef DEBUG | |
378 printf("sdp: %c='%s'\n", letter, buf); | |
379 #endif | |
380 | |
381 p = buf; | |
382 switch(letter) { | |
383 case 'c': | |
384 get_word(buf1, sizeof(buf1), &p); | |
385 if (strcmp(buf1, "IN") != 0) | |
386 return; | |
387 get_word(buf1, sizeof(buf1), &p); | |
388 if (strcmp(buf1, "IP4") != 0) | |
389 return; | |
390 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
391 if (inet_aton(buf1, &sdp_ip) == 0) | |
392 return; | |
393 ttl = 16; | |
394 if (*p == '/') { | |
395 p++; | |
396 get_word_sep(buf1, sizeof(buf1), "/", &p); | |
397 ttl = atoi(buf1); | |
398 } | |
399 if (s->nb_streams == 0) { | |
400 s1->default_ip = sdp_ip; | |
401 s1->default_ttl = ttl; | |
402 } else { | |
403 st = s->streams[s->nb_streams - 1]; | |
404 rtsp_st = st->priv_data; | |
405 rtsp_st->sdp_ip = sdp_ip; | |
406 rtsp_st->sdp_ttl = ttl; | |
407 } | |
408 break; | |
409 case 's': | |
410 pstrcpy(s->title, sizeof(s->title), p); | |
411 break; | |
412 case 'i': | |
413 if (s->nb_streams == 0) { | |
414 pstrcpy(s->comment, sizeof(s->comment), p); | |
415 break; | |
416 } | |
417 break; | |
418 case 'm': | |
419 /* new stream */ | |
420 get_word(st_type, sizeof(st_type), &p); | |
421 if (!strcmp(st_type, "audio")) { | |
422 codec_type = CODEC_TYPE_AUDIO; | |
423 } else if (!strcmp(st_type, "video")) { | |
424 codec_type = CODEC_TYPE_VIDEO; | |
425 } else { | |
426 return; | |
427 } | |
428 rtsp_st = av_mallocz(sizeof(RTSPStream)); | |
429 if (!rtsp_st) | |
430 return; | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
431 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
|
432 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); |
0 | 433 |
434 rtsp_st->sdp_ip = s1->default_ip; | |
435 rtsp_st->sdp_ttl = s1->default_ttl; | |
436 | |
437 get_word(buf1, sizeof(buf1), &p); /* port */ | |
438 rtsp_st->sdp_port = atoi(buf1); | |
439 | |
440 get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */ | |
885 | 441 |
0 | 442 /* XXX: handle list of formats */ |
443 get_word(buf1, sizeof(buf1), &p); /* format list */ | |
444 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
|
445 |
774 | 446 if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
447 /* 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
|
448 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
449 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
|
450 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
451 return; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
452 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
|
453 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
|
454 st->codec->codec_type = codec_type; |
774 | 455 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
|
456 /* 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
|
457 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
|
458 } |
0 | 459 } |
460 /* put a default control url */ | |
461 pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename); | |
462 break; | |
463 case 'a': | |
464 if (strstart(p, "control:", &p) && s->nb_streams > 0) { | |
465 char proto[32]; | |
466 /* get the control url */ | |
467 st = s->streams[s->nb_streams - 1]; | |
468 rtsp_st = st->priv_data; | |
885 | 469 |
0 | 470 /* 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
|
471 url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p); |
0 | 472 if (proto[0] == '\0') { |
473 /* relative control URL */ | |
474 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/"); | |
475 pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); | |
476 } else { | |
477 pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); | |
478 } | |
479 } else if (strstart(p, "rtpmap:", &p)) { | |
480 /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ | |
885 | 481 get_word(buf1, sizeof(buf1), &p); |
0 | 482 payload_type = atoi(buf1); |
483 for(i = 0; i < s->nb_streams;i++) { | |
484 st = s->streams[i]; | |
485 rtsp_st = st->priv_data; | |
486 if (rtsp_st->sdp_payload_type == payload_type) { | |
1419 | 487 sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p); |
0 | 488 } |
489 } | |
490 } else if (strstart(p, "fmtp:", &p)) { | |
491 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' 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 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { |
499 if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) { | |
500 sdp_parse_fmtp(st, p); | |
501 } | |
502 } else { | |
1424
1c39ce5c6a5d
indentation fix, patch by Ryan Martell % rdm4 A martellventures P com %
gpoirier
parents:
1419
diff
changeset
|
503 sdp_parse_fmtp(st, p); |
1419 | 504 } |
0 | 505 } |
506 } | |
1431
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
507 } else if(strstart(p, "framesize:", &p)) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
508 // 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
|
509 get_word(buf1, sizeof(buf1), &p); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
510 payload_type = atoi(buf1); |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
511 for(i = 0; i < s->nb_streams;i++) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
512 st = s->streams[i]; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
513 rtsp_st = st->priv_data; |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
514 if (rtsp_st->sdp_payload_type == payload_type) { |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
515 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
|
516 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
|
517 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
518 } |
2d8a17631520
fix more dynamic protocol stuff, needed by the forthcoming h264
gpoirier
parents:
1425
diff
changeset
|
519 } |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
520 } else if(strstart(p, "range:", &p)) { |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
521 int64_t start, end; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
522 |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
523 // 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
|
524 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
|
525 s->start_time= start; |
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
526 s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek) |
0 | 527 } |
528 break; | |
529 } | |
530 } | |
531 | |
64 | 532 static int sdp_parse(AVFormatContext *s, const char *content) |
0 | 533 { |
534 const char *p; | |
535 int letter; | |
536 char buf[1024], *q; | |
537 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state; | |
885 | 538 |
0 | 539 memset(s1, 0, sizeof(SDPParseState)); |
540 p = content; | |
541 for(;;) { | |
542 skip_spaces(&p); | |
543 letter = *p; | |
544 if (letter == '\0') | |
545 break; | |
546 p++; | |
547 if (*p != '=') | |
548 goto next_line; | |
549 p++; | |
550 /* get the content */ | |
551 q = buf; | |
172 | 552 while (*p != '\n' && *p != '\r' && *p != '\0') { |
0 | 553 if ((q - buf) < sizeof(buf) - 1) |
554 *q++ = *p; | |
555 p++; | |
556 } | |
557 *q = '\0'; | |
558 sdp_parse_line(s, s1, letter, buf); | |
559 next_line: | |
560 while (*p != '\n' && *p != '\0') | |
561 p++; | |
562 if (*p == '\n') | |
563 p++; | |
564 } | |
565 return 0; | |
566 } | |
567 | |
568 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) | |
569 { | |
570 const char *p; | |
571 int v; | |
572 | |
573 p = *pp; | |
574 skip_spaces(&p); | |
575 v = strtol(p, (char **)&p, 10); | |
576 if (*p == '-') { | |
577 p++; | |
578 *min_ptr = v; | |
579 v = strtol(p, (char **)&p, 10); | |
580 *max_ptr = v; | |
581 } else { | |
582 *min_ptr = v; | |
583 *max_ptr = v; | |
584 } | |
585 *pp = p; | |
586 } | |
587 | |
588 /* XXX: only one transport specification is parsed */ | |
589 static void rtsp_parse_transport(RTSPHeader *reply, const char *p) | |
590 { | |
591 char transport_protocol[16]; | |
592 char profile[16]; | |
593 char lower_transport[16]; | |
594 char parameter[16]; | |
595 RTSPTransportField *th; | |
596 char buf[256]; | |
885 | 597 |
0 | 598 reply->nb_transports = 0; |
885 | 599 |
0 | 600 for(;;) { |
601 skip_spaces(&p); | |
602 if (*p == '\0') | |
603 break; | |
604 | |
605 th = &reply->transports[reply->nb_transports]; | |
606 | |
885 | 607 get_word_sep(transport_protocol, sizeof(transport_protocol), |
0 | 608 "/", &p); |
609 if (*p == '/') | |
610 p++; | |
611 get_word_sep(profile, sizeof(profile), "/;,", &p); | |
612 lower_transport[0] = '\0'; | |
613 if (*p == '/') { | |
172 | 614 p++; |
885 | 615 get_word_sep(lower_transport, sizeof(lower_transport), |
0 | 616 ";,", &p); |
617 } | |
172 | 618 if (!strcasecmp(lower_transport, "TCP")) |
0 | 619 th->protocol = RTSP_PROTOCOL_RTP_TCP; |
620 else | |
621 th->protocol = RTSP_PROTOCOL_RTP_UDP; | |
885 | 622 |
0 | 623 if (*p == ';') |
624 p++; | |
625 /* get each parameter */ | |
626 while (*p != '\0' && *p != ',') { | |
627 get_word_sep(parameter, sizeof(parameter), "=;,", &p); | |
628 if (!strcmp(parameter, "port")) { | |
629 if (*p == '=') { | |
630 p++; | |
631 rtsp_parse_range(&th->port_min, &th->port_max, &p); | |
632 } | |
633 } else if (!strcmp(parameter, "client_port")) { | |
634 if (*p == '=') { | |
635 p++; | |
885 | 636 rtsp_parse_range(&th->client_port_min, |
0 | 637 &th->client_port_max, &p); |
638 } | |
639 } else if (!strcmp(parameter, "server_port")) { | |
640 if (*p == '=') { | |
641 p++; | |
885 | 642 rtsp_parse_range(&th->server_port_min, |
0 | 643 &th->server_port_max, &p); |
644 } | |
645 } else if (!strcmp(parameter, "interleaved")) { | |
646 if (*p == '=') { | |
647 p++; | |
885 | 648 rtsp_parse_range(&th->interleaved_min, |
0 | 649 &th->interleaved_max, &p); |
650 } | |
651 } else if (!strcmp(parameter, "multicast")) { | |
652 if (th->protocol == RTSP_PROTOCOL_RTP_UDP) | |
653 th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST; | |
654 } else if (!strcmp(parameter, "ttl")) { | |
655 if (*p == '=') { | |
656 p++; | |
657 th->ttl = strtol(p, (char **)&p, 10); | |
658 } | |
659 } else if (!strcmp(parameter, "destination")) { | |
660 struct in_addr ipaddr; | |
661 | |
662 if (*p == '=') { | |
663 p++; | |
664 get_word_sep(buf, sizeof(buf), ";,", &p); | |
885 | 665 if (inet_aton(buf, &ipaddr)) |
0 | 666 th->destination = ntohl(ipaddr.s_addr); |
667 } | |
668 } | |
669 while (*p != ';' && *p != '\0' && *p != ',') | |
670 p++; | |
671 if (*p == ';') | |
672 p++; | |
673 } | |
674 if (*p == ',') | |
675 p++; | |
676 | |
677 reply->nb_transports++; | |
678 } | |
679 } | |
680 | |
681 void rtsp_parse_line(RTSPHeader *reply, const char *buf) | |
682 { | |
683 const char *p; | |
684 | |
685 /* NOTE: we do case independent match for broken servers */ | |
686 p = buf; | |
687 if (stristart(p, "Session:", &p)) { | |
688 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); | |
689 } else if (stristart(p, "Content-Length:", &p)) { | |
690 reply->content_length = strtol(p, NULL, 10); | |
691 } else if (stristart(p, "Transport:", &p)) { | |
692 rtsp_parse_transport(reply, p); | |
693 } else if (stristart(p, "CSeq:", &p)) { | |
694 reply->seq = strtol(p, NULL, 10); | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
695 } else if (stristart(p, "Range:", &p)) { |
1453
c0235bab9e92
Add support for getting duration of a RTP stream (for seeking in stream)
gpoirier
parents:
1431
diff
changeset
|
696 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end); |
0 | 697 } |
698 } | |
699 | |
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
|
700 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
|
701 { |
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
|
702 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
|
703 |
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
|
704 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
|
705 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
|
706 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
|
707 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
|
708 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
|
709 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
|
710 } |
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
|
711 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
|
712 } |
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
|
713 |
179 | 714 /* skip a RTP/TCP interleaved packet */ |
715 static void rtsp_skip_packet(AVFormatContext *s) | |
716 { | |
717 RTSPState *rt = s->priv_data; | |
718 int ret, len, len1; | |
719 uint8_t buf[1024]; | |
720 | |
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
|
721 ret = url_readbuf(rt->rtsp_hd, buf, 3); |
179 | 722 if (ret != 3) |
723 return; | |
724 len = (buf[1] << 8) | buf[2]; | |
725 #ifdef DEBUG | |
726 printf("skipping RTP packet len=%d\n", len); | |
727 #endif | |
728 /* skip payload */ | |
729 while (len > 0) { | |
730 len1 = len; | |
731 if (len1 > sizeof(buf)) | |
732 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
|
733 ret = url_readbuf(rt->rtsp_hd, buf, len1); |
179 | 734 if (ret != len1) |
735 return; | |
736 len -= len1; | |
737 } | |
738 } | |
0 | 739 |
885 | 740 static void rtsp_send_cmd(AVFormatContext *s, |
741 const char *cmd, RTSPHeader *reply, | |
0 | 742 unsigned char **content_ptr) |
743 { | |
744 RTSPState *rt = s->priv_data; | |
745 char buf[4096], buf1[1024], *q; | |
746 unsigned char ch; | |
747 const char *p; | |
748 int content_length, line_count; | |
749 unsigned char *content = NULL; | |
750 | |
751 memset(reply, 0, sizeof(RTSPHeader)); | |
752 | |
753 rt->seq++; | |
754 pstrcpy(buf, sizeof(buf), cmd); | |
172 | 755 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); |
0 | 756 pstrcat(buf, sizeof(buf), buf1); |
757 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { | |
172 | 758 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); |
0 | 759 pstrcat(buf, sizeof(buf), buf1); |
760 } | |
172 | 761 pstrcat(buf, sizeof(buf), "\r\n"); |
0 | 762 #ifdef DEBUG |
763 printf("Sending:\n%s--\n", buf); | |
764 #endif | |
765 url_write(rt->rtsp_hd, buf, strlen(buf)); | |
766 | |
767 /* parse reply (XXX: use buffers) */ | |
768 line_count = 0; | |
769 rt->last_reply[0] = '\0'; | |
770 for(;;) { | |
771 q = buf; | |
772 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
|
773 if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1) |
0 | 774 break; |
775 if (ch == '\n') | |
776 break; | |
179 | 777 if (ch == '$') { |
778 /* XXX: only parse it if first char on line ? */ | |
779 rtsp_skip_packet(s); | |
780 } else if (ch != '\r') { | |
0 | 781 if ((q - buf) < sizeof(buf) - 1) |
782 *q++ = ch; | |
783 } | |
784 } | |
785 *q = '\0'; | |
786 #ifdef DEBUG | |
787 printf("line='%s'\n", buf); | |
788 #endif | |
789 /* test if last line */ | |
790 if (buf[0] == '\0') | |
791 break; | |
792 p = buf; | |
793 if (line_count == 0) { | |
794 /* get reply code */ | |
795 get_word(buf1, sizeof(buf1), &p); | |
796 get_word(buf1, sizeof(buf1), &p); | |
797 reply->status_code = atoi(buf1); | |
798 } else { | |
799 rtsp_parse_line(reply, p); | |
800 pstrcat(rt->last_reply, sizeof(rt->last_reply), p); | |
801 pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n"); | |
802 } | |
803 line_count++; | |
804 } | |
885 | 805 |
0 | 806 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') |
807 pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id); | |
885 | 808 |
0 | 809 content_length = reply->content_length; |
810 if (content_length > 0) { | |
811 /* leave some room for a trailing '\0' (useful for simple parsing) */ | |
812 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
|
813 (void)url_readbuf(rt->rtsp_hd, content, content_length); |
0 | 814 content[content_length] = '\0'; |
815 } | |
816 if (content_ptr) | |
817 *content_ptr = content; | |
818 } | |
819 | |
820 | |
821 void rtsp_set_callback(FFRTSPCallback *rtsp_cb) | |
822 { | |
823 ff_rtsp_callback = rtsp_cb; | |
824 } | |
825 | |
826 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
827 /* 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
|
828 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
|
829 { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
830 int i; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
831 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
|
832 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
833 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
|
834 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
|
835 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
|
836 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
|
837 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
|
838 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
|
839 url_close(rtsp_st->rtp_handle); |
1419 | 840 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) |
841 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
|
842 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
843 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
|
844 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
845 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
|
846 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
847 |
0 | 848 static int rtsp_read_header(AVFormatContext *s, |
849 AVFormatParameters *ap) | |
850 { | |
851 RTSPState *rt = s->priv_data; | |
852 char host[1024], path[1024], tcpname[1024], cmd[2048]; | |
853 URLContext *rtsp_hd; | |
774 | 854 int port, i, j, ret, err; |
0 | 855 RTSPHeader reply1, *reply = &reply1; |
856 unsigned char *content = NULL; | |
857 RTSPStream *rtsp_st; | |
858 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
|
859 AVStream *st; |
0 | 860 |
861 /* extract hostname and port */ | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
391
diff
changeset
|
862 url_split(NULL, 0, NULL, 0, |
0 | 863 host, sizeof(host), &port, path, sizeof(path), s->filename); |
864 if (port < 0) | |
865 port = RTSP_DEFAULT_PORT; | |
866 | |
867 /* open the tcp connexion */ | |
868 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); | |
869 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) | |
870 return AVERROR_IO; | |
871 rt->rtsp_hd = rtsp_hd; | |
872 rt->seq = 0; | |
885 | 873 |
0 | 874 /* describe the stream */ |
885 | 875 snprintf(cmd, sizeof(cmd), |
172 | 876 "DESCRIBE %s RTSP/1.0\r\n" |
877 "Accept: application/sdp\r\n", | |
0 | 878 s->filename); |
879 rtsp_send_cmd(s, cmd, reply, &content); | |
880 if (!content) { | |
881 err = AVERROR_INVALIDDATA; | |
882 goto fail; | |
883 } | |
884 if (reply->status_code != RTSP_STATUS_OK) { | |
885 err = AVERROR_INVALIDDATA; | |
886 goto fail; | |
887 } | |
885 | 888 |
0 | 889 /* now we got the SDP description, we parse it */ |
890 ret = sdp_parse(s, (const char *)content); | |
891 av_freep(&content); | |
892 if (ret < 0) { | |
893 err = AVERROR_INVALIDDATA; | |
894 goto fail; | |
895 } | |
885 | 896 |
0 | 897 protocol_mask = rtsp_default_protocols; |
898 | |
899 /* for each stream, make the setup request */ | |
900 /* XXX: we assume the same server is used for the control of each | |
901 RTSP stream */ | |
774 | 902 |
903 for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) { | |
0 | 904 char transport[2048]; |
905 | |
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_st = rt->rtsp_streams[i]; |
0 | 907 |
908 /* compute available transports */ | |
909 transport[0] = '\0'; | |
910 | |
911 /* RTP/UDP */ | |
912 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) { | |
913 char buf[256]; | |
914 | |
915 /* first try in specified port range */ | |
774 | 916 if (RTSP_RTP_PORT_MIN != 0) { |
917 while(j <= RTSP_RTP_PORT_MAX) { | |
0 | 918 snprintf(buf, sizeof(buf), "rtp://?localport=%d", j); |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
919 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) { |
774 | 920 j += 2; /* we will use two port by rtp stream (rtp and rtcp) */ |
0 | 921 goto rtp_opened; |
774 | 922 } |
0 | 923 } |
924 } | |
925 | |
774 | 926 /* then try on any port |
927 ** if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { | |
928 ** err = AVERROR_INVALIDDATA; | |
929 ** goto fail; | |
930 ** } | |
931 */ | |
0 | 932 |
933 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
|
934 port = rtp_get_local_port(rtsp_st->rtp_handle); |
0 | 935 if (transport[0] != '\0') |
936 pstrcat(transport, sizeof(transport), ","); | |
937 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, | |
938 "RTP/AVP/UDP;unicast;client_port=%d-%d", | |
939 port, port + 1); | |
940 } | |
941 | |
942 /* RTP/TCP */ | |
774 | 943 else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) { |
0 | 944 if (transport[0] != '\0') |
945 pstrcat(transport, sizeof(transport), ","); | |
946 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, | |
947 "RTP/AVP/TCP"); | |
948 } | |
949 | |
774 | 950 else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) { |
0 | 951 if (transport[0] != '\0') |
952 pstrcat(transport, sizeof(transport), ","); | |
885 | 953 snprintf(transport + strlen(transport), |
0 | 954 sizeof(transport) - strlen(transport) - 1, |
955 "RTP/AVP/UDP;multicast"); | |
956 } | |
885 | 957 snprintf(cmd, sizeof(cmd), |
172 | 958 "SETUP %s RTSP/1.0\r\n" |
959 "Transport: %s\r\n", | |
0 | 960 rtsp_st->control_url, transport); |
961 rtsp_send_cmd(s, cmd, reply, NULL); | |
962 if (reply->status_code != RTSP_STATUS_OK || | |
963 reply->nb_transports != 1) { | |
964 err = AVERROR_INVALIDDATA; | |
965 goto fail; | |
966 } | |
967 | |
968 /* XXX: same protocol for all streams is required */ | |
969 if (i > 0) { | |
970 if (reply->transports[0].protocol != rt->protocol) { | |
971 err = AVERROR_INVALIDDATA; | |
972 goto fail; | |
973 } | |
974 } else { | |
975 rt->protocol = reply->transports[0].protocol; | |
976 } | |
977 | |
978 /* close RTP connection if not choosen */ | |
979 if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP && | |
980 (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
|
981 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
|
982 rtsp_st->rtp_handle = NULL; |
0 | 983 } |
984 | |
985 switch(reply->transports[0].protocol) { | |
986 case RTSP_PROTOCOL_RTP_TCP: | |
987 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; | |
988 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; | |
989 break; | |
885 | 990 |
0 | 991 case RTSP_PROTOCOL_RTP_UDP: |
992 { | |
993 char url[1024]; | |
885 | 994 |
0 | 995 /* XXX: also use address if specified */ |
885 | 996 snprintf(url, sizeof(url), "rtp://%s:%d", |
0 | 997 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
|
998 if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { |
0 | 999 err = AVERROR_INVALIDDATA; |
1000 goto fail; | |
1001 } | |
1002 } | |
1003 break; | |
1004 case RTSP_PROTOCOL_RTP_UDP_MULTICAST: | |
1005 { | |
1006 char url[1024]; | |
1007 int ttl; | |
1008 | |
1009 ttl = reply->transports[0].ttl; | |
1010 if (!ttl) | |
1011 ttl = 16; | |
885 | 1012 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", |
1013 host, | |
0 | 1014 reply->transports[0].server_port_min, |
1015 ttl); | |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1016 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
0 | 1017 err = AVERROR_INVALIDDATA; |
1018 goto fail; | |
1019 } | |
1020 } | |
1021 break; | |
1022 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1023 /* 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
|
1024 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1025 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
|
1026 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
|
1027 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1028 s->ctx_flags |= AVFMTCTX_NOHEADER; |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1029 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); |
774 | 1030 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1031 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
|
1032 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
|
1033 goto fail; |
1419 | 1034 } else { |
1035 if(rtsp_st->dynamic_handler) { | |
1036 rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context; | |
1037 rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet; | |
1038 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1039 } |
0 | 1040 } |
1041 | |
1042 /* use callback if available to extend setup */ | |
1043 if (ff_rtsp_callback) { | |
885 | 1044 if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, |
0 | 1045 NULL, 0, rt->last_reply) < 0) { |
1046 err = AVERROR_INVALIDDATA; | |
1047 goto fail; | |
1048 } | |
1049 } | |
885 | 1050 |
0 | 1051 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1052 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1053 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
|
1054 zero */ |
1003 | 1055 if (ap->initial_pause) { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1056 /* do not start immediately */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1057 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1058 if (rtsp_read_play(s) < 0) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1059 err = AVERROR_INVALIDDATA; |
0 | 1060 goto fail; |
1061 } | |
1062 } | |
1063 return 0; | |
1064 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1065 rtsp_close_streams(rt); |
0 | 1066 av_freep(&content); |
1067 url_close(rt->rtsp_hd); | |
1068 return err; | |
1069 } | |
1070 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1071 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
|
1072 uint8_t *buf, int buf_size) |
0 | 1073 { |
1074 RTSPState *rt = s->priv_data; | |
172 | 1075 int id, len, i, ret; |
0 | 1076 RTSPStream *rtsp_st; |
1077 | |
172 | 1078 #ifdef DEBUG_RTP_TCP |
1079 printf("tcp_read_packet:\n"); | |
1080 #endif | |
0 | 1081 redo: |
1082 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
|
1083 ret = url_readbuf(rt->rtsp_hd, buf, 1); |
172 | 1084 #ifdef DEBUG_RTP_TCP |
1085 printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]); | |
1086 #endif | |
1087 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
|
1088 return -1; |
172 | 1089 if (buf[0] == '$') |
0 | 1090 break; |
1091 } | |
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
|
1092 ret = url_readbuf(rt->rtsp_hd, buf, 3); |
172 | 1093 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
|
1094 return -1; |
172 | 1095 id = buf[0]; |
1096 len = (buf[1] << 8) | buf[2]; | |
1097 #ifdef DEBUG_RTP_TCP | |
1098 printf("id=%d len=%d\n", id, len); | |
1099 #endif | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1100 if (len > buf_size || len < 12) |
0 | 1101 goto redo; |
1102 /* 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
|
1103 ret = url_readbuf(rt->rtsp_hd, buf, len); |
172 | 1104 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
|
1105 return -1; |
885 | 1106 |
0 | 1107 /* 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
|
1108 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
|
1109 rtsp_st = rt->rtsp_streams[i]; |
885 | 1110 if (id >= rtsp_st->interleaved_min && |
1111 id <= rtsp_st->interleaved_max) | |
0 | 1112 goto found; |
1113 } | |
1114 goto redo; | |
1115 found: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1116 *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
|
1117 return len; |
0 | 1118 } |
1119 | |
885 | 1120 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
|
1121 uint8_t *buf, int buf_size) |
0 | 1122 { |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1123 RTSPState *rt = s->priv_data; |
0 | 1124 RTSPStream *rtsp_st; |
1125 fd_set rfds; | |
1126 int fd1, fd2, fd_max, n, i, ret; | |
1127 struct timeval tv; | |
1128 | |
1129 for(;;) { | |
179 | 1130 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
|
1131 return -1; |
0 | 1132 FD_ZERO(&rfds); |
1133 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
|
1134 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
|
1135 rtsp_st = rt->rtsp_streams[i]; |
0 | 1136 /* 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
|
1137 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 1138 if (fd1 > fd_max) |
1139 fd_max = fd1; | |
1140 FD_SET(fd1, &rfds); | |
1141 } | |
1142 tv.tv_sec = 0; | |
179 | 1143 tv.tv_usec = 100 * 1000; |
0 | 1144 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
1145 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
|
1146 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
|
1147 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
|
1148 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); |
0 | 1149 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
|
1150 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
|
1151 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
|
1152 *prtsp_st = rtsp_st; |
0 | 1153 return ret; |
1154 } | |
1155 } | |
1156 } | |
1157 } | |
1158 } | |
1159 } | |
1160 | |
1161 static int rtsp_read_packet(AVFormatContext *s, | |
1162 AVPacket *pkt) | |
1163 { | |
1164 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
|
1165 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
|
1166 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
|
1167 uint8_t buf[RTP_MAX_PACKET_LENGTH]; |
0 | 1168 |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1169 /* 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
|
1170 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
|
1171 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
|
1172 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
|
1173 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
|
1174 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1175 } 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
|
1176 return 0; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1177 } else { |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1178 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
|
1179 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1180 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1181 |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1182 /* 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
|
1183 redo: |
0 | 1184 switch(rt->protocol) { |
1185 default: | |
1186 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
|
1187 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
0 | 1188 break; |
1189 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
|
1190 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
|
1191 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf)); |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1192 if (rtsp_st->rtp_ctx) |
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1193 rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len); |
0 | 1194 break; |
1195 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1196 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
|
1197 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
|
1198 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
|
1199 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
|
1200 goto redo; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1201 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
|
1202 /* 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
|
1203 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
|
1204 } |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1205 return 0; |
0 | 1206 } |
1207 | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1208 static int rtsp_read_play(AVFormatContext *s) |
179 | 1209 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1210 RTSPState *rt = s->priv_data; |
179 | 1211 RTSPHeader reply1, *reply = &reply1; |
1212 char cmd[1024]; | |
1213 | |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
304
diff
changeset
|
1214 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
|
1215 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1216 if (rt->state == RTSP_STATE_PAUSED) { |
885 | 1217 snprintf(cmd, sizeof(cmd), |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1218 "PLAY %s RTSP/1.0\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1219 s->filename); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1220 } else { |
885 | 1221 snprintf(cmd, sizeof(cmd), |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1222 "PLAY %s RTSP/1.0\r\n" |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1223 "Range: npt=%0.3f-\r\n", |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1224 s->filename, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1225 (double)rt->seek_timestamp / AV_TIME_BASE); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1226 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1227 rtsp_send_cmd(s, cmd, reply, NULL); |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1228 if (reply->status_code != RTSP_STATUS_OK) { |
179 | 1229 return -1; |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1230 } else { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1231 rt->state = RTSP_STATE_PLAYING; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1232 return 0; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1233 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1234 } |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1235 |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1236 /* pause the stream */ |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1237 static int rtsp_read_pause(AVFormatContext *s) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1238 { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1239 RTSPState *rt = s->priv_data; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1240 RTSPHeader reply1, *reply = &reply1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1241 char cmd[1024]; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1242 |
179 | 1243 rt = s->priv_data; |
885 | 1244 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1245 if (rt->state != RTSP_STATE_PLAYING) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1246 return 0; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1247 |
885 | 1248 snprintf(cmd, sizeof(cmd), |
179 | 1249 "PAUSE %s RTSP/1.0\r\n", |
1250 s->filename); | |
1251 rtsp_send_cmd(s, cmd, reply, NULL); | |
1252 if (reply->status_code != RTSP_STATUS_OK) { | |
1253 return -1; | |
1254 } else { | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1255 rt->state = RTSP_STATE_PAUSED; |
179 | 1256 return 0; |
1257 } | |
1258 } | |
1259 | |
885 | 1260 static int rtsp_read_seek(AVFormatContext *s, int stream_index, |
558 | 1261 int64_t timestamp, int flags) |
179 | 1262 { |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1263 RTSPState *rt = s->priv_data; |
885 | 1264 |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1265 rt->seek_timestamp = timestamp; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1266 switch(rt->state) { |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1267 default: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1268 case RTSP_STATE_IDLE: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1269 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1270 case RTSP_STATE_PLAYING: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1271 if (rtsp_read_play(s) != 0) |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1272 return -1; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1273 break; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1274 case RTSP_STATE_PAUSED: |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1275 rt->state = RTSP_STATE_IDLE; |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1276 break; |
179 | 1277 } |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1278 return 0; |
179 | 1279 } |
1280 | |
0 | 1281 static int rtsp_read_close(AVFormatContext *s) |
1282 { | |
1283 RTSPState *rt = s->priv_data; | |
1284 RTSPHeader reply1, *reply = &reply1; | |
1285 char cmd[1024]; | |
1286 | |
172 | 1287 #if 0 |
0 | 1288 /* NOTE: it is valid to flush the buffer here */ |
1289 if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { | |
1290 url_fclose(&rt->rtsp_gb); | |
1291 } | |
172 | 1292 #endif |
885 | 1293 snprintf(cmd, sizeof(cmd), |
172 | 1294 "TEARDOWN %s RTSP/1.0\r\n", |
0 | 1295 s->filename); |
1296 rtsp_send_cmd(s, cmd, reply, NULL); | |
1297 | |
1298 if (ff_rtsp_callback) { | |
885 | 1299 ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, |
0 | 1300 NULL, 0, NULL); |
1301 } | |
1302 | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1303 rtsp_close_streams(rt); |
0 | 1304 url_close(rt->rtsp_hd); |
1305 return 0; | |
1306 } | |
1307 | |
1167 | 1308 AVInputFormat rtsp_demuxer = { |
0 | 1309 "rtsp", |
1310 "RTSP input format", | |
1311 sizeof(RTSPState), | |
1312 rtsp_probe, | |
1313 rtsp_read_header, | |
1314 rtsp_read_packet, | |
1315 rtsp_read_close, | |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1316 rtsp_read_seek, |
0 | 1317 .flags = AVFMT_NOFILE, |
304
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1318 .read_play = rtsp_read_play, |
d58c8859ff8c
initial seek support - more generic play/pause support
bellard
parents:
294
diff
changeset
|
1319 .read_pause = rtsp_read_pause, |
0 | 1320 }; |
1321 | |
1322 static int sdp_probe(AVProbeData *p1) | |
1323 { | |
706
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1324 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; |
0 | 1325 |
1326 /* 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
|
1327 while (p < p_end && *p != '\0') { |
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1328 if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL)) |
0 | 1329 return AVPROBE_SCORE_MAX / 2; |
706
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1330 |
fc254f396f15
buffer overflow in sdp_probe() fix by (Gildas Bazin )gbazin altern org)
michael
parents:
587
diff
changeset
|
1331 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
|
1332 if (++p >= p_end) |
0 | 1333 break; |
1334 if (*p == '\r') | |
1335 p++; | |
1336 } | |
1337 return 0; | |
1338 } | |
1339 | |
1340 #define SDP_MAX_SIZE 8192 | |
1341 | |
1342 static int sdp_read_header(AVFormatContext *s, | |
1343 AVFormatParameters *ap) | |
1344 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1345 RTSPState *rt = s->priv_data; |
0 | 1346 RTSPStream *rtsp_st; |
1347 int size, i, err; | |
1348 char *content; | |
1349 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
|
1350 AVStream *st; |
0 | 1351 |
1352 /* read the whole sdp file */ | |
1353 /* XXX: better loading */ | |
1354 content = av_malloc(SDP_MAX_SIZE); | |
1355 size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1); | |
1356 if (size <= 0) { | |
1357 av_free(content); | |
1358 return AVERROR_INVALIDDATA; | |
1359 } | |
1360 content[size] ='\0'; | |
1361 | |
1362 sdp_parse(s, content); | |
1363 av_free(content); | |
1364 | |
1365 /* 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
|
1366 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
|
1367 rtsp_st = rt->rtsp_streams[i]; |
885 | 1368 |
1369 snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", | |
1370 inet_ntoa(rtsp_st->sdp_ip), | |
0 | 1371 rtsp_st->sdp_port, |
1372 rtsp_st->sdp_ttl); | |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1373 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
0 | 1374 err = AVERROR_INVALIDDATA; |
1375 goto fail; | |
1376 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1377 /* 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
|
1378 st = NULL; |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1379 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
|
1380 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
|
1381 if (!st) |
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1382 s->ctx_flags |= AVFMTCTX_NOHEADER; |
1425
00d9393a126f
make ffmpeg able to send back a RTCP receiver report.
gpoirier
parents:
1424
diff
changeset
|
1383 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
|
1384 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
|
1385 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
|
1386 goto fail; |
1419 | 1387 } else { |
1388 if(rtsp_st->dynamic_handler) { | |
1389 rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context; | |
1390 rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet; | |
1391 } | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1392 } |
0 | 1393 } |
1394 return 0; | |
1395 fail: | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1396 rtsp_close_streams(rt); |
0 | 1397 return err; |
1398 } | |
1399 | |
1400 static int sdp_read_packet(AVFormatContext *s, | |
1401 AVPacket *pkt) | |
1402 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1403 return rtsp_read_packet(s, pkt); |
0 | 1404 } |
1405 | |
1406 static int sdp_read_close(AVFormatContext *s) | |
1407 { | |
294
6091b76cfc2a
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
bellard
parents:
229
diff
changeset
|
1408 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
|
1409 rtsp_close_streams(rt); |
0 | 1410 return 0; |
1411 } | |
1412 | |
1169 | 1413 #ifdef CONFIG_SDP_DEMUXER |
1414 AVInputFormat sdp_demuxer = { | |
0 | 1415 "sdp", |
1416 "SDP", | |
1417 sizeof(RTSPState), | |
1418 sdp_probe, | |
1419 sdp_read_header, | |
1420 sdp_read_packet, | |
1421 sdp_read_close, | |
1422 }; | |
1169 | 1423 #endif |
0 | 1424 |
1425 /* dummy redirector format (used directly in av_open_input_file now) */ | |
1426 static int redir_probe(AVProbeData *pd) | |
1427 { | |
1428 const char *p; | |
1429 p = pd->buf; | |
1430 while (redir_isspace(*p)) | |
1431 p++; | |
1432 if (strstart(p, "http://", NULL) || | |
1433 strstart(p, "rtsp://", NULL)) | |
1434 return AVPROBE_SCORE_MAX; | |
1435 return 0; | |
1436 } | |
1437 | |
1438 /* called from utils.c */ | |
1439 int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f) | |
1440 { | |
1441 char buf[4096], *q; | |
1442 int c; | |
1443 AVFormatContext *ic = NULL; | |
1444 | |
1445 /* parse each URL and try to open it */ | |
1446 c = url_fgetc(f); | |
1447 while (c != URL_EOF) { | |
1448 /* skip spaces */ | |
1449 for(;;) { | |
1450 if (!redir_isspace(c)) | |
1451 break; | |
1452 c = url_fgetc(f); | |
1453 } | |
1454 if (c == URL_EOF) | |
1455 break; | |
1456 /* record url */ | |
1457 q = buf; | |
1458 for(;;) { | |
1459 if (c == URL_EOF || redir_isspace(c)) | |
1460 break; | |
1461 if ((q - buf) < sizeof(buf) - 1) | |
1462 *q++ = c; | |
1463 c = url_fgetc(f); | |
1464 } | |
1465 *q = '\0'; | |
1466 //printf("URL='%s'\n", buf); | |
1467 /* try to open the media file */ | |
1468 if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0) | |
1469 break; | |
1470 } | |
1471 *ic_ptr = ic; | |
1472 if (!ic) | |
1473 return AVERROR_IO; | |
1474 else | |
1475 return 0; | |
1476 } | |
1477 | |
1167 | 1478 AVInputFormat redir_demuxer = { |
0 | 1479 "redir", |
1480 "Redirector format", | |
1481 0, | |
1482 redir_probe, | |
1483 NULL, | |
1484 NULL, | |
1485 NULL, | |
1486 }; |