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