Mercurial > libavformat.hg
annotate rtpproto.c @ 6260:5c17c20dd67a libavformat
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
when page buffer is bigger than default buffer size. Max page is 65k.
| author | bcoudurier |
|---|---|
| date | Wed, 14 Jul 2010 23:21:18 +0000 |
| parents | ccb05424c391 |
| children | 37944ce385a0 |
| rev | line source |
|---|---|
| 0 | 1 /* |
| 2 * RTP network protocol | |
|
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4206
diff
changeset
|
3 * Copyright (c) 2002 Fabrice Bellard |
| 0 | 4 * |
|
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
5 * This file is part of FFmpeg. |
|
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
6 * |
|
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
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:
1332
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:
1332
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:
1332
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 */ |
| 3229 | 21 |
| 22 /** | |
|
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5964
diff
changeset
|
23 * @file |
| 3229 | 24 * RTP protocol |
| 25 */ | |
| 26 | |
| 3286 | 27 #include "libavutil/avstring.h" |
| 0 | 28 #include "avformat.h" |
|
5725
334f223fc455
Include rtpdec.h, it contains prototypes for the following functions:
cehoyos
parents:
4640
diff
changeset
|
29 #include "rtpdec.h" |
| 0 | 30 |
| 31 #include <unistd.h> | |
| 32 #include <stdarg.h> | |
|
5837
d605f589f0be
move ff_url_split() and ff_url_join() declarations to internal.h
aurel
parents:
5801
diff
changeset
|
33 #include "internal.h" |
| 1754 | 34 #include "network.h" |
|
2782
419e121ce80a
Add #include "os_support.h" to restore OS/2 support.
diego
parents:
2274
diff
changeset
|
35 #include "os_support.h" |
| 0 | 36 #include <fcntl.h> |
| 4206 | 37 #if HAVE_SYS_SELECT_H |
|
3712
30d4d95e068f
Add needed include, make it compile without -D_BSD_SOURCE.
michael
parents:
3286
diff
changeset
|
38 #include <sys/select.h> |
|
3720
1968303c7566
Surround '#include <sys/select>' by HAVE_SYS_SELECT_H.
diego
parents:
3712
diff
changeset
|
39 #endif |
|
5801
1851c2275530
Using struct timeval requires sys/time.h, fixes compilation on some OSes
mstorsjo
parents:
5776
diff
changeset
|
40 #include <sys/time.h> |
| 0 | 41 |
| 42 #define RTP_TX_BUF_SIZE (64 * 1024) | |
| 43 #define RTP_RX_BUF_SIZE (128 * 1024) | |
| 44 | |
| 45 typedef struct RTPContext { | |
| 46 URLContext *rtp_hd, *rtcp_hd; | |
| 47 int rtp_fd, rtcp_fd; | |
| 48 } RTPContext; | |
| 49 | |
| 50 /** | |
| 51 * If no filename is given to av_open_input_file because you want to | |
| 52 * get the local port first, then you must call this function to set | |
| 53 * the remote server address. | |
| 54 * | |
|
6215
ccb05424c391
Fix misspelled parameter names in Doxygen documentation.
diego
parents:
6182
diff
changeset
|
55 * @param h media file context |
| 0 | 56 * @param uri of the remote server |
| 57 * @return zero if no error. | |
| 58 */ | |
| 3229 | 59 |
| 0 | 60 int rtp_set_remote_url(URLContext *h, const char *uri) |
| 61 { | |
| 62 RTPContext *s = h->priv_data; | |
| 63 char hostname[256]; | |
| 64 int port; | |
| 65 | |
| 66 char buf[1024]; | |
| 67 char path[1024]; | |
| 885 | 68 |
| 6182 | 69 av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, |
| 5776 | 70 path, sizeof(path), uri); |
| 0 | 71 |
|
5756
7c7fe75728dd
Use ff_url_join for assembling URLs, instead of snprintf
mstorsjo
parents:
5752
diff
changeset
|
72 ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path); |
| 0 | 73 udp_set_remote_url(s->rtp_hd, buf); |
| 74 | |
|
5756
7c7fe75728dd
Use ff_url_join for assembling URLs, instead of snprintf
mstorsjo
parents:
5752
diff
changeset
|
75 ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port + 1, "%s", path); |
| 0 | 76 udp_set_remote_url(s->rtcp_hd, buf); |
| 77 return 0; | |
| 78 } | |
| 79 | |
| 80 | |
| 3229 | 81 /** |
| 82 * add option to url of the form: | |
| 83 * "http://host:port/path?option1=val1&option2=val2... | |
| 84 */ | |
| 85 | |
| 64 | 86 static void url_add_option(char *buf, int buf_size, const char *fmt, ...) |
| 0 | 87 { |
| 88 char buf1[1024]; | |
| 89 va_list ap; | |
| 90 | |
| 91 va_start(ap, fmt); | |
| 92 if (strchr(buf, '?')) | |
|
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2079
diff
changeset
|
93 av_strlcat(buf, "&", buf_size); |
| 0 | 94 else |
|
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2079
diff
changeset
|
95 av_strlcat(buf, "?", buf_size); |
| 0 | 96 vsnprintf(buf1, sizeof(buf1), fmt, ap); |
|
2193
5ce5fad0dfac
replace the uses of old string functions that Reimar missed
mru
parents:
2079
diff
changeset
|
97 av_strlcat(buf, buf1, buf_size); |
| 0 | 98 va_end(ap); |
| 99 } | |
| 100 | |
| 64 | 101 static void build_udp_url(char *buf, int buf_size, |
| 887 | 102 const char *hostname, int port, |
| 3228 | 103 int local_port, int ttl, |
| 104 int max_packet_size) | |
| 0 | 105 { |
|
5756
7c7fe75728dd
Use ff_url_join for assembling URLs, instead of snprintf
mstorsjo
parents:
5752
diff
changeset
|
106 ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL); |
| 0 | 107 if (local_port >= 0) |
| 108 url_add_option(buf, buf_size, "localport=%d", local_port); | |
| 109 if (ttl >= 0) | |
| 110 url_add_option(buf, buf_size, "ttl=%d", ttl); | |
| 3228 | 111 if (max_packet_size >=0) |
| 112 url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size); | |
| 0 | 113 } |
| 114 | |
| 3229 | 115 /** |
| 0 | 116 * url syntax: rtp://host:port[?option=val...] |
| 5964 | 117 * option: 'ttl=n' : set the ttl value (for multicast only) |
| 118 * 'rtcpport=n' : set the remote rtcp port to n | |
| 119 * 'localrtpport=n' : set the local rtp port to n | |
| 120 * 'localrtcpport=n' : set the local rtcp port to n | |
| 121 * 'pkt_size=n' : set max packet size | |
| 122 * deprecated option: | |
| 123 * 'localport=n' : set the local port to n | |
| 0 | 124 * |
| 5964 | 125 * if rtcpport isn't set the rtcp port will be the rtp port + 1 |
| 126 * if local rtp port isn't set any available port will be used for the local | |
| 127 * rtp and rtcp ports | |
| 128 * if the local rtcp port is not set it will be the local rtp port + 1 | |
| 0 | 129 */ |
| 3229 | 130 |
| 0 | 131 static int rtp_open(URLContext *h, const char *uri, int flags) |
| 132 { | |
| 133 RTPContext *s; | |
| 5964 | 134 int rtp_port, rtcp_port, |
| 135 is_output, ttl, | |
| 136 local_rtp_port, local_rtcp_port, max_packet_size; | |
| 0 | 137 char hostname[256]; |
| 138 char buf[1024]; | |
| 139 char path[1024]; | |
| 140 const char *p; | |
| 885 | 141 |
| 0 | 142 is_output = (flags & URL_WRONLY); |
| 143 | |
| 144 s = av_mallocz(sizeof(RTPContext)); | |
| 145 if (!s) | |
|
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
146 return AVERROR(ENOMEM); |
| 0 | 147 h->priv_data = s; |
| 885 | 148 |
| 6182 | 149 av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, |
| 5776 | 150 path, sizeof(path), uri); |
| 0 | 151 /* extract parameters */ |
| 152 ttl = -1; | |
| 5964 | 153 rtcp_port = rtp_port+1; |
| 154 local_rtp_port = -1; | |
| 155 local_rtcp_port = -1; | |
| 3228 | 156 max_packet_size = -1; |
| 157 | |
| 0 | 158 p = strchr(uri, '?'); |
| 159 if (p) { | |
| 160 if (find_info_tag(buf, sizeof(buf), "ttl", p)) { | |
| 161 ttl = strtol(buf, NULL, 10); | |
| 162 } | |
| 5964 | 163 if (find_info_tag(buf, sizeof(buf), "rtcpport", p)) { |
| 164 rtcp_port = strtol(buf, NULL, 10); | |
| 165 } | |
| 0 | 166 if (find_info_tag(buf, sizeof(buf), "localport", p)) { |
| 5964 | 167 local_rtp_port = strtol(buf, NULL, 10); |
| 168 } | |
| 169 if (find_info_tag(buf, sizeof(buf), "localrtpport", p)) { | |
| 170 local_rtp_port = strtol(buf, NULL, 10); | |
| 171 } | |
| 172 if (find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { | |
| 173 local_rtcp_port = strtol(buf, NULL, 10); | |
| 0 | 174 } |
| 3228 | 175 if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) { |
| 176 max_packet_size = strtol(buf, NULL, 10); | |
| 177 } | |
| 0 | 178 } |
| 179 | |
| 180 build_udp_url(buf, sizeof(buf), | |
| 5964 | 181 hostname, rtp_port, local_rtp_port, ttl, max_packet_size); |
| 0 | 182 if (url_open(&s->rtp_hd, buf, flags) < 0) |
| 183 goto fail; | |
| 5964 | 184 if (local_rtp_port>=0 && local_rtcp_port<0) |
| 185 local_rtcp_port = udp_get_local_port(s->rtp_hd) + 1; | |
| 885 | 186 |
| 0 | 187 build_udp_url(buf, sizeof(buf), |
| 5964 | 188 hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size); |
| 0 | 189 if (url_open(&s->rtcp_hd, buf, flags) < 0) |
| 190 goto fail; | |
| 885 | 191 |
| 0 | 192 /* just to ease handle access. XXX: need to suppress direct handle |
| 193 access */ | |
|
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
194 s->rtp_fd = url_get_file_handle(s->rtp_hd); |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
195 s->rtcp_fd = url_get_file_handle(s->rtcp_hd); |
| 0 | 196 |
| 885 | 197 h->max_packet_size = url_get_max_packet_size(s->rtp_hd); |
| 0 | 198 h->is_streamed = 1; |
| 199 return 0; | |
| 200 | |
| 201 fail: | |
| 202 if (s->rtp_hd) | |
| 203 url_close(s->rtp_hd); | |
| 204 if (s->rtcp_hd) | |
| 205 url_close(s->rtcp_hd); | |
| 206 av_free(s); | |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2200
diff
changeset
|
207 return AVERROR(EIO); |
| 0 | 208 } |
| 209 | |
| 65 | 210 static int rtp_read(URLContext *h, uint8_t *buf, int size) |
| 0 | 211 { |
| 212 RTPContext *s = h->priv_data; | |
| 213 struct sockaddr_in from; | |
| 1332 | 214 socklen_t from_len; |
| 215 int len, fd_max, n; | |
| 0 | 216 fd_set rfds; |
|
5750
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
217 struct timeval tv; |
| 0 | 218 #if 0 |
| 219 for(;;) { | |
| 220 from_len = sizeof(from); | |
| 221 len = recvfrom (s->rtp_fd, buf, size, 0, | |
| 222 (struct sockaddr *)&from, &from_len); | |
| 223 if (len < 0) { | |
|
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
224 if (ff_neterrno() == FF_NETERROR(EAGAIN) || |
|
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
225 ff_neterrno() == FF_NETERROR(EINTR)) |
| 0 | 226 continue; |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2200
diff
changeset
|
227 return AVERROR(EIO); |
| 0 | 228 } |
| 229 break; | |
| 230 } | |
| 231 #else | |
| 232 for(;;) { | |
|
5750
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
233 if (url_interrupt_cb()) |
|
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
234 return AVERROR(EINTR); |
| 0 | 235 /* build fdset to listen to RTP and RTCP packets */ |
| 236 FD_ZERO(&rfds); | |
| 237 fd_max = s->rtp_fd; | |
| 238 FD_SET(s->rtp_fd, &rfds); | |
| 239 if (s->rtcp_fd > fd_max) | |
| 240 fd_max = s->rtcp_fd; | |
| 241 FD_SET(s->rtcp_fd, &rfds); | |
|
5750
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
242 tv.tv_sec = 0; |
|
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
243 tv.tv_usec = 100 * 1000; |
|
0f9c0db923e5
Check url_interrupt_cb in rtp_read, wait in select for max 100 ms before rechecking url_interrupt_cb
mstorsjo
parents:
5725
diff
changeset
|
244 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
| 0 | 245 if (n > 0) { |
| 246 /* first try RTCP */ | |
| 247 if (FD_ISSET(s->rtcp_fd, &rfds)) { | |
| 248 from_len = sizeof(from); | |
| 249 len = recvfrom (s->rtcp_fd, buf, size, 0, | |
| 250 (struct sockaddr *)&from, &from_len); | |
| 251 if (len < 0) { | |
|
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
252 if (ff_neterrno() == FF_NETERROR(EAGAIN) || |
|
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
253 ff_neterrno() == FF_NETERROR(EINTR)) |
| 0 | 254 continue; |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2200
diff
changeset
|
255 return AVERROR(EIO); |
| 0 | 256 } |
| 257 break; | |
| 258 } | |
| 259 /* then RTP */ | |
| 260 if (FD_ISSET(s->rtp_fd, &rfds)) { | |
| 261 from_len = sizeof(from); | |
| 262 len = recvfrom (s->rtp_fd, buf, size, 0, | |
| 263 (struct sockaddr *)&from, &from_len); | |
| 264 if (len < 0) { | |
|
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
265 if (ff_neterrno() == FF_NETERROR(EAGAIN) || |
|
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
1930
diff
changeset
|
266 ff_neterrno() == FF_NETERROR(EINTR)) |
| 0 | 267 continue; |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2200
diff
changeset
|
268 return AVERROR(EIO); |
| 0 | 269 } |
| 270 break; | |
| 271 } | |
|
5752
cb840f900fef
Return from rtp_read when select returns an error
mstorsjo
parents:
5750
diff
changeset
|
272 } else if (n < 0) { |
|
5896
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
273 if (ff_neterrno() == FF_NETERROR(EINTR)) |
|
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
274 continue; |
|
5752
cb840f900fef
Return from rtp_read when select returns an error
mstorsjo
parents:
5750
diff
changeset
|
275 return AVERROR(EIO); |
| 0 | 276 } |
| 277 } | |
| 278 #endif | |
| 279 return len; | |
| 280 } | |
| 281 | |
| 6068 | 282 static int rtp_write(URLContext *h, const uint8_t *buf, int size) |
| 0 | 283 { |
| 284 RTPContext *s = h->priv_data; | |
| 285 int ret; | |
| 286 URLContext *hd; | |
| 885 | 287 |
| 0 | 288 if (buf[1] >= 200 && buf[1] <= 204) { |
| 289 /* RTCP payload type */ | |
| 290 hd = s->rtcp_hd; | |
| 291 } else { | |
| 292 /* RTP payload type */ | |
| 293 hd = s->rtp_hd; | |
| 294 } | |
| 295 | |
| 296 ret = url_write(hd, buf, size); | |
| 297 #if 0 | |
| 298 { | |
| 299 struct timespec ts; | |
| 300 ts.tv_sec = 0; | |
| 301 ts.tv_nsec = 10 * 1000000; | |
| 302 nanosleep(&ts, NULL); | |
| 303 } | |
| 304 #endif | |
| 305 return ret; | |
| 306 } | |
| 307 | |
| 308 static int rtp_close(URLContext *h) | |
| 309 { | |
| 310 RTPContext *s = h->priv_data; | |
| 311 | |
| 312 url_close(s->rtp_hd); | |
| 313 url_close(s->rtcp_hd); | |
| 314 av_free(s); | |
| 315 return 0; | |
| 316 } | |
| 317 | |
| 318 /** | |
| 5964 | 319 * Return the local rtp port used by the RTP connection |
|
6215
ccb05424c391
Fix misspelled parameter names in Doxygen documentation.
diego
parents:
6182
diff
changeset
|
320 * @param h media file context |
| 5964 | 321 * @return the local port number |
| 322 */ | |
| 323 | |
| 324 int rtp_get_local_rtp_port(URLContext *h) | |
| 325 { | |
| 326 RTPContext *s = h->priv_data; | |
| 327 return udp_get_local_port(s->rtp_hd); | |
| 328 } | |
| 329 | |
| 330 /** | |
| 331 * Return the local rtp port used by the RTP connection | |
|
6215
ccb05424c391
Fix misspelled parameter names in Doxygen documentation.
diego
parents:
6182
diff
changeset
|
332 * @param h media file context |
| 0 | 333 * @return the local port number |
| 334 */ | |
| 3229 | 335 |
| 0 | 336 int rtp_get_local_port(URLContext *h) |
| 337 { | |
| 338 RTPContext *s = h->priv_data; | |
| 339 return udp_get_local_port(s->rtp_hd); | |
| 340 } | |
| 341 | |
| 5964 | 342 /** |
| 343 * Return the local rtcp port used by the RTP connection | |
|
6215
ccb05424c391
Fix misspelled parameter names in Doxygen documentation.
diego
parents:
6182
diff
changeset
|
344 * @param h media file context |
| 5964 | 345 * @return the local port number |
| 346 */ | |
| 347 | |
| 348 int rtp_get_local_rtcp_port(URLContext *h) | |
| 349 { | |
| 350 RTPContext *s = h->priv_data; | |
| 351 return udp_get_local_port(s->rtcp_hd); | |
| 352 } | |
| 353 | |
|
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
354 #if (LIBAVFORMAT_VERSION_MAJOR <= 52) |
| 0 | 355 /** |
| 3229 | 356 * Return the rtp and rtcp file handles for select() usage to wait for |
| 357 * several RTP streams at the same time. | |
| 0 | 358 * @param h media file context |
| 359 */ | |
| 3229 | 360 |
| 0 | 361 void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd) |
| 362 { | |
| 363 RTPContext *s = h->priv_data; | |
| 364 | |
| 365 *prtp_fd = s->rtp_fd; | |
| 366 *prtcp_fd = s->rtcp_fd; | |
| 367 } | |
|
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
368 #endif |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
369 |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
370 static int rtp_get_file_handle(URLContext *h) |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
371 { |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
372 RTPContext *s = h->priv_data; |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
373 return s->rtp_fd; |
|
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
374 } |
| 0 | 375 |
| 376 URLProtocol rtp_protocol = { | |
| 377 "rtp", | |
| 378 rtp_open, | |
| 379 rtp_read, | |
| 380 rtp_write, | |
| 381 NULL, /* seek */ | |
| 382 rtp_close, | |
|
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4331
diff
changeset
|
383 .url_get_file_handle = rtp_get_file_handle, |
| 0 | 384 }; |
