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