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 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 ****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_demux.h>
29 #include <vlc_block.h>
30 #include <vlc_network.h>
47 #define DEFAULT_MRU (1500u - (20 + 8))
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)
58 const uint8_t ptype
= rtp_ptype (block
);
59 if (ptype
>= 72 && ptype
<= 76)
60 goto drop
; /* Muxed RTCP, ignore for now FIXME */
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");
71 block
->i_buffer
= len
;
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
);
85 block_Release (block
);
88 static int rtp_timeout (mtime_t deadline
)
90 if (deadline
== VLC_TS_INVALID
)
91 return -1; /* infinite */
97 t
= (deadline
- t
) / (CLOCK_FREQ
/ INT64_C(1000));
98 if (unlikely(t
> INT_MAX
))
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
;
114 .iov_len
= DEFAULT_MRU
,
122 struct pollfd ufd
[1];
124 ufd
[0].events
= POLLIN
;
128 int n
= poll (ufd
, 1, rtp_timeout (deadline
));
132 int canc
= vlc_savecancel ();
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
;
153 msg
.msg_flags
= MSG_TRUNC
;
158 ssize_t len
= recvmsg (rtp_fd
, &msg
, 0);
162 if (msg
.msg_flags
& MSG_TRUNC
)
164 msg_Err(demux
, "%zd bytes packet truncated (MRU was %zu)",
166 block
->i_flags
|= BLOCK_FLAG_CORRUPTED
;
171 block
->i_buffer
= len
;
173 rtp_process (demux
, block
);
177 msg_Warn (demux
, "RTP network error: %s",
178 vlc_strerror_c(errno
));
179 block_Release (block
);
184 if (!rtp_dequeue (demux
, sys
->session
, &deadline
))
185 deadline
= VLC_TS_INVALID
;
186 vlc_restorecancel (canc
);
192 * RTP/RTCP session thread for stream sockets (framed RTP)
194 void *rtp_stream_thread (void *opaque
)
197 demux_t
*demux
= opaque
;
198 demux_sys_t
*sys
= demux
->p_sys
;
203 /* There is no reordering on stream sockets, so no timeout. */
207 if (recv (fd
, &frame_len
, 2, MSG_WAITALL
) != 2)
210 block_t
*block
= block_Alloc (ntohs (frame_len
));
211 if (unlikely(block
== NULL
))
214 block_cleanup_push (block
);
215 val
= recv (fd
, block
->p_buffer
, block
->i_buffer
, MSG_WAITALL
);
218 if (val
!= (ssize_t
)block
->i_buffer
)
220 block_Release (block
);
224 int canc
= vlc_savecancel ();
225 rtp_process (demux
, block
);
226 rtp_dequeue_force (demux
, sys
->session
);
227 vlc_restorecancel (canc
);