1 /*****************************************************************************
2 * rtp.c : Real-Time Protocol (RTP) demux module for VLC media player
3 *****************************************************************************
4 * Copyright (C) 2001-2005 the VideoLAN team
5 * Copyright © 2007 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 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_demux.h>
33 #include <vlc_codecs.h>
35 /*****************************************************************************
37 *****************************************************************************/
39 #define RTP_MAX_DROPOUT_TEXT N_("RTP maximum sequence number dropout")
40 #define RTP_MAX_DROPOUT_LONGTEXT N_( \
41 "RTP packets will be discarded if they are too much ahead (i.e. in the " \
42 "future) by this many packets from the last received packet." )
44 #define RTP_MAX_MISORDER_TEXT N_("RTP maximum sequence number misordering")
45 #define RTP_MAX_MISORDER_LONGTEXT N_( \
46 "RTP packets will be discarded if they are too far behind (i.e. in the " \
47 "past) by this many packets from the last received packet." )
49 #define RTP_MIN_SEQUENTIAL_TEXT N_("RTP minimum sequential packets count")
50 #define RTP_MIN_SEQUENTIAL_LONGTEXT N_( \
51 "VLC will wait until it has received this many sequential RTP packets " \
52 "before it considers the RTP stream synchronized." )
55 static int Open (vlc_object_t *);
56 static void Close (vlc_object_t *);
59 set_shortname (_("RTP"));
60 set_description (_("(Experimental) Real-Time Protocol demuxer"));
61 set_category (CAT_INPUT);
62 set_subcategory (SUBCAT_INPUT_DEMUX);
63 set_capability ("access_demux", 10);
64 set_callbacks (Open, Close);
66 add_integer( "rtp-max-dropout", 3000, NULL, RTP_MAX_DROPOUT_TEXT,
67 RTP_MAX_DROPOUT_LONGTEXT, VLC_TRUE );
68 add_integer( "rtp-max-misorder", 100, NULL, RTP_MAX_MISORDER_TEXT,
69 RTP_MAX_MISORDER_LONGTEXT, VLC_TRUE );
70 add_integer( "rtp-min-seq", 2, NULL, RTP_MIN_SEQUENTIAL_TEXT,
71 RTP_MIN_SEQUENTIAL_LONGTEXT, VLC_TRUE );
76 /*****************************************************************************
78 *****************************************************************************/
79 static int Demux (demux_t *);
80 static int Control (demux_t *, int i_query, va_list args);
81 static block_t *ParseRTP (demux_t *obj, block_t *p_block, int8_t *pt,
84 #define RTP_PACKET_SIZE 0xffff
86 typedef int (*rtp_pt_cb) (demux_t *, block_t *, void *);
88 /* State for a RTP source */
89 typedef struct rtp_source_t
91 uint32_t ssrc; /* current synchronization source */
92 int8_t pt; /* current payload type, -1 if none */
94 uint8_t probation; /* how many packets left before resync */
95 uint16_t max_seq; /* next expected sequence */
96 uint16_t bad_seq; /* tentatively next expected sequence for resync */
99 /* State for a RTP session */
100 typedef struct rtp_session_t
102 /*stream_t *feed;*/ /* where data comes from */
103 /* TODO: keep values to sync multiple sessions. */
104 /* We'd need to parse RTCP SR to do that though... */
111 uint16_t max_dropout;
112 uint16_t max_misorder;
113 uint16_t min_sequential;
115 rtp_session_t session;
119 /*****************************************************************************
120 * Open: check stream and initializes structures
121 *****************************************************************************/
122 static int Open (vlc_object_t *obj)
124 demux_t *demux = (demux_t *)obj;
127 assert (demux->s == NULL);
128 msg_Dbg (pbj, "access = %s", obj->psz_access);
130 /* Initializes demux */
131 p_sys = calloc (1, sizeof (*p_sys));
135 p_sys->max_dropout = var_CreateGetInteger (obj, "rtp-max-dropout");
136 p_sys->max_misorder = var_CreateGetInteger (obj, "rtp-max-misorder");
137 p_sys->min_sequential = var_CreateGetInteger (obj, "rtp-min-seq");
139 demux->pf_demux = Demux;
140 demux->pf_control = Control;
141 demux->p_sys = p_sys;
147 /*****************************************************************************
148 * Close: frees unused data
149 *****************************************************************************/
150 static void Close (vlc_object_t *obj)
152 demux_sys_t *p_sys = ((demux_t *)obj)->p_sys;
156 /*****************************************************************************
158 *****************************************************************************/
159 static int Control (demux_t *p_demux, int i_query, va_list args)
161 /*demux_sys_t *p_sys = p_demux->p_sys;*/
165 case DEMUX_GET_POSITION:
169 case DEMUX_GET_LENGTH:
171 int64_t *v = va_arg (args, int64_t *);
181 static int Demux (demux_t *demux)
183 //demux_sys_t *p_sys = demux->p_sys;
184 block_t *block = stream_Block (demux->s, RTP_PACKET_SIZE);
191 block = ParseRTP (demux, block, &pt, &seq);
195 msg_Dbg (demux, "got len = %5u; PT = %3d, seq = %5u", block->i_buffer, pt, seq);
201 static block_t *ParseRTP (demux_t *obj, block_t *p_block, int8_t *pt,
206 /* RTP header sanity checks (see RFC 3550) */
207 if (p_block->i_buffer < 12)
210 if (p_block->i_buffer > RTP_PACKET_SIZE)
212 msg_Err (obj, "RTP packet too big! wrong demux?");
217 if ((p_block->p_buffer[0] >> 6 ) != 2)
220 msg_Dbg (obj, "RTP version is %u instead of 2", p_block->p_buffer[0] >> 6);
225 uint8_t pad = (p_block->p_buffer[0] & 0x20)
226 ? p_block->p_buffer[p_block->i_buffer - 1] : 0;
229 i_skip += (p_block->p_buffer[0] & 0x0F) * 4;
232 if (p_block->p_buffer[0] & 0x10) /* Extension header */
235 if ((size_t)p_block->i_buffer < i_skip)
238 i_skip += 4 * GetWBE (p_block->p_buffer + i_skip - 2);
241 if ((size_t)p_block->i_buffer < (i_skip + pad))
244 *pt = p_block->p_buffer[1] & 0x7F;
245 *seq = GetWBE (p_block->p_buffer + 2);
247 /* This is the place for deciphering and authentication */
249 /* Remove the RTP header */
250 p_block->i_buffer -= i_skip;
251 p_block->p_buffer += i_skip;
253 /* Remove padding (at the end) */
254 p_block->i_buffer -= pad;
259 block_Release (p_block);
260 msg_Dbg (obj, "ignored non-RTP packet");
266 * Initializes a source before any packet has been received
269 void PreinitSource (const demux_sys_t *p_sys, rtp_source_t *src)
272 src->probation = p_sys->min_sequential;
277 * Reinitializes a source (resynchronization)
280 void InitSource (const demux_sys_t *p_sys, rtp_source_t *src, uint32_t ssrc,
286 src->probation = p_sys->min_sequential - 1;
287 src->bad_seq = src->max_seq = seq;
293 * Generic packet handlers
296 /* Ignore a packet */
297 static int pt_ignore (demux_t *obj, block_t *block, rtp_pt_t *self)
300 msg_Dbg (obj, "ignoring unknown payload type");
301 block_Release (block);
306 /* Send a packet to decoder */
308 static void pt_decode (demux_t *obj, block_t *block, rtp_pt_t *self)
310 p_block->i_pts = p_block->i_dts = date_... (...);
311 es_out_Control (obj->out, ES_OUT_SET_PCR, p_block->i_pts);
312 es_out_Send (obj->out, (es_out_id_t *)*p_id, block);
318 /* Send a packet to a chained demuxer */
320 int pt_demux (demux_t *obj, block_t *block, rtp_pt_t *self, const char *demux)
322 stream_t *stream = self->data.demux.stream;
326 stream = stream_DemuxNew (obj, demux, obj->out);
329 self->data.demux.stream = stream;
332 stream_DemuxSend (stream, block);
338 * Static payload types handler
342 * MPA: MPEG Audio (RFC2250, §3.4)
344 static int pt_mpa (demux_t *obj, block_t *block, rtp_pt_t *self)
346 if (block->i_buffer < 4)
349 block->i_buffer -= 4; // 32 bits RTP/MPA header
350 block->p_buffer += 4;
352 return pt_demux (obj, block, self, "mpga");
357 * MPV: MPEG Video (RFC2250, §3.5)
359 static int pt_mpv (demux_t *obj, block_t *block, rtp_pt_t *self)
361 if (block->i_buffer < 4)
364 block->i_buffer -= 4; // 32 bits RTP/MPV header
365 block->p_buffer += 4;
367 if (block->p_buffer[-3] & 0x4)
369 /* MPEG2 Video extension header */
370 /* TODO: shouldn't we skip this too ? */
373 return pt_demux (obj, block, self, "mpgv");
378 * MP2: MPEG TS (RFC2250, §2)
380 static int pt_ts (demux_t *obj, block_t *block, rtp_pt_t *self)
382 return pt_demux (obj, block, self, "ts");
387 * Dynamic payload type handlers
388 * Hmm, none implemented yet.