contrib: soxr: enable by default
[vlc.git] / modules / access / rtp / input.c
blobcf9d9a7cad3175aaf524b6d5d1e9caadaa296e7a
1 /**
2 * @file input.c
3 * @brief RTP packet input
4 */
5 /*****************************************************************************
6 * Copyright © 2008 Rémi Denis-Courmont
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1
11 * of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_demux.h>
29 #include <vlc_block.h>
30 #include <vlc_network.h>
32 #include <limits.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #ifdef HAVE_POLL
36 # include <poll.h>
37 #endif
38 #ifdef HAVE_SYS_UIO_H
39 # include <sys/uio.h>
40 #endif
42 #include "rtp.h"
43 #ifdef HAVE_SRTP
44 # include <srtp.h>
45 #endif
47 #define DEFAULT_MRU (1500u - (20 + 8))
49 /**
50 * Processes a packet received from the RTP socket.
52 static void rtp_process (demux_t *demux, block_t *block)
54 demux_sys_t *sys = demux->p_sys;
56 if (block->i_buffer < 2)
57 goto drop;
58 const uint8_t ptype = rtp_ptype (block);
59 if (ptype >= 72 && ptype <= 76)
60 goto drop; /* Muxed RTCP, ignore for now FIXME */
62 #ifdef HAVE_SRTP
63 if (sys->srtp != NULL)
65 size_t len = block->i_buffer;
66 if (srtp_recv (sys->srtp, block->p_buffer, &len))
68 msg_Dbg (demux, "SRTP authentication/decryption failed");
69 goto drop;
71 block->i_buffer = len;
73 #endif
75 /* TODO: use SDP and get rid of this hack */
76 if (unlikely(sys->autodetect))
77 { /* Autodetect payload type, _before_ rtp_queue() */
78 rtp_autodetect (demux, sys->session, block);
79 sys->autodetect = false;
82 rtp_queue (demux, sys->session, block);
83 return;
84 drop:
85 block_Release (block);
88 static int rtp_timeout (mtime_t deadline)
90 if (deadline == VLC_TS_INVALID)
91 return -1; /* infinite */
93 mtime_t t = mdate ();
94 if (t >= deadline)
95 return 0;
97 t = (deadline - t) / (CLOCK_FREQ / INT64_C(1000));
98 if (unlikely(t > INT_MAX))
99 return INT_MAX;
100 return t;
104 * RTP/RTCP session thread for datagram sockets
106 void *rtp_dgram_thread (void *opaque)
108 demux_t *demux = opaque;
109 demux_sys_t *sys = demux->p_sys;
110 mtime_t deadline = VLC_TS_INVALID;
111 int rtp_fd = sys->fd;
112 struct iovec iov =
114 .iov_len = DEFAULT_MRU,
116 struct msghdr msg =
118 .msg_iov = &iov,
119 .msg_iovlen = 1,
122 struct pollfd ufd[1];
123 ufd[0].fd = rtp_fd;
124 ufd[0].events = POLLIN;
126 for (;;)
128 int n = poll (ufd, 1, rtp_timeout (deadline));
129 if (n == -1)
130 continue;
132 int canc = vlc_savecancel ();
133 if (n == 0)
134 goto dequeue;
136 if (ufd[0].revents)
138 n--;
139 if (unlikely(ufd[0].revents & POLLHUP))
140 break; /* RTP socket dead (DCCP only) */
142 block_t *block = block_Alloc (iov.iov_len);
143 if (unlikely(block == NULL))
145 if (iov.iov_len == DEFAULT_MRU)
146 break; /* we are totallly screwed */
147 iov.iov_len = DEFAULT_MRU;
148 continue; /* retry with shrunk MRU */
151 iov.iov_base = block->p_buffer;
152 #ifdef __linux__
153 msg.msg_flags = MSG_TRUNC;
154 #else
155 msg.msg_flags = 0;
156 #endif
158 ssize_t len = recvmsg (rtp_fd, &msg, 0);
159 if (len != -1)
161 #ifdef MSG_TRUNC
162 if (msg.msg_flags & MSG_TRUNC)
164 msg_Err(demux, "%zd bytes packet truncated (MRU was %zu)",
165 len, iov.iov_len);
166 block->i_flags |= BLOCK_FLAG_CORRUPTED;
167 iov.iov_len = len;
169 else
170 #endif
171 block->i_buffer = len;
173 rtp_process (demux, block);
175 else
177 msg_Warn (demux, "RTP network error: %s",
178 vlc_strerror_c(errno));
179 block_Release (block);
183 dequeue:
184 if (!rtp_dequeue (demux, sys->session, &deadline))
185 deadline = VLC_TS_INVALID;
186 vlc_restorecancel (canc);
188 return NULL;
192 * RTP/RTCP session thread for stream sockets (framed RTP)
194 void *rtp_stream_thread (void *opaque)
196 #ifndef _WIN32
197 demux_t *demux = opaque;
198 demux_sys_t *sys = demux->p_sys;
199 int fd = sys->fd;
201 for (;;)
203 /* There is no reordering on stream sockets, so no timeout. */
204 ssize_t val;
206 uint16_t frame_len;
207 if (recv (fd, &frame_len, 2, MSG_WAITALL) != 2)
208 break;
210 block_t *block = block_Alloc (ntohs (frame_len));
211 if (unlikely(block == NULL))
212 break;
214 block_cleanup_push (block);
215 val = recv (fd, block->p_buffer, block->i_buffer, MSG_WAITALL);
216 vlc_cleanup_pop ();
218 if (val != (ssize_t)block->i_buffer)
220 block_Release (block);
221 break;
224 int canc = vlc_savecancel ();
225 rtp_process (demux, block);
226 rtp_dequeue_force (demux, sys->session);
227 vlc_restorecancel (canc);
229 #else
230 (void) opaque;
231 #endif
232 return NULL;