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