3 * @brief RTP packet input
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 General Public License
10 * as published by the Free Software Foundation; either version 2.0
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 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 ****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_demux.h>
29 #include <vlc_block.h>
30 #include <vlc_network.h>
42 static bool fd_dead (int fd)
44 struct pollfd ufd = { .fd = fd, };
45 return (poll (&ufd, 1, 0) > 0) && (ufd.revents & POLLHUP);
49 * Gets a datagram from the network.
50 * @param fd datagram file descriptor
51 * @return a block or NULL on fatal error (socket dead)
53 static block_t *rtp_dgram_recv (vlc_object_t *obj, int fd)
55 block_t *block = block_Alloc (0xffff);
58 block_cleanup_push (block);
61 len = net_Read (obj, fd, NULL,
62 block->p_buffer, block->i_buffer, false);
64 if (((len <= 0) && fd_dead (fd)) || !vlc_object_alive (obj))
65 { /* POLLHUP -> permanent (DCCP) socket error */
66 block_Release (block);
74 return block ? block_Realloc (block, 0, len) : NULL;
79 * Gets a framed RTP packet.
80 * @param fd stream file descriptor
81 * @return a block or NULL in case of fatal error
83 static block_t *rtp_stream_recv (vlc_object_t *obj, int fd)
86 uint8_t hdr[2]; /* frame header */
88 /* Receives the RTP frame header */
91 ssize_t val = net_Read (obj, fd, NULL, hdr + len, 2 - len, false);
98 block_t *block = block_Alloc (GetWBE (hdr));
100 /* Receives the RTP packet */
101 for (ssize_t i = 0; i < len;)
105 block_cleanup_push (block);
106 val = net_Read (obj, fd, NULL,
107 block->p_buffer + i, block->i_buffer - i, false);
112 block_Release (block);
122 static block_t *rtp_recv (demux_t *demux)
124 demux_sys_t *p_sys = demux->p_sys;
126 for (block_t *block;; block_Release (block))
128 block = p_sys->framed_rtp
129 ? rtp_stream_recv (VLC_OBJECT (demux), p_sys->fd)
130 : rtp_dgram_recv (VLC_OBJECT (demux), p_sys->fd);
133 msg_Err (demux, "RTP flow stopped");
134 break; /* fatal error */
137 if (block->i_buffer < 2)
141 const uint8_t ptype = rtp_ptype (block);
142 if (ptype >= 72 && ptype <= 76)
143 continue; /* Muxed RTCP, ignore for now */
147 size_t len = block->i_buffer;
150 canc = vlc_savecancel ();
151 err = srtp_recv (p_sys->srtp, block->p_buffer, &len);
152 vlc_restorecancel (canc);
155 msg_Dbg (demux, "SRTP authentication/decryption failed");
158 block->i_buffer = len;
161 return block; /* success! */
167 static void timer_cleanup (void *timer)
169 vlc_timer_destroy ((vlc_timer_t)timer);
172 static void rtp_process (void *data);
174 void *rtp_thread (void *data)
176 demux_t *demux = data;
177 demux_sys_t *p_sys = demux->p_sys;
178 bool autodetect = true;
180 if (vlc_timer_create (&p_sys->timer, rtp_process, data))
182 vlc_cleanup_push (timer_cleanup, (void *)p_sys->timer);
186 block_t *block = rtp_recv (demux);
191 { /* Autodetect payload type, _before_ rtp_queue() */
192 /* No need for lock - the queue is empty. */
193 if (rtp_autodetect (demux, p_sys->session, block))
195 block_Release (block);
201 int canc = vlc_savecancel ();
202 vlc_mutex_lock (&p_sys->lock);
203 rtp_queue (demux, p_sys->session, block);
204 vlc_mutex_unlock (&p_sys->lock);
205 vlc_restorecancel (canc);
215 * Process one RTP packet from the de-jitter queue.
217 static void rtp_process (void *data)
219 demux_t *demux = data;
220 demux_sys_t *p_sys = demux->p_sys;
223 vlc_mutex_lock (&p_sys->lock);
224 if (rtp_dequeue (demux, p_sys->session, &deadline))
225 vlc_timer_schedule (p_sys->timer, true, deadline, 0);
226 vlc_mutex_unlock (&p_sys->lock);