3 * @brief RTP session handling
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
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 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 ****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_demux.h>
36 typedef struct rtp_source_t rtp_source_t;
38 /** State for a RTP session: */
48 rtp_source_create (demux_t *, const rtp_session_t *, uint32_t, uint16_t);
50 rtp_source_destroy (demux_t *, const rtp_session_t *, rtp_source_t *);
52 static void rtp_decode (demux_t *, const rtp_session_t *, rtp_source_t *);
55 * Creates a new RTP session.
58 rtp_session_create (demux_t *demux)
60 rtp_session_t *session = malloc (sizeof (*session));
75 * Destroys an RTP session.
77 void rtp_session_destroy (demux_t *demux, rtp_session_t *session)
79 for (unsigned i = 0; i < session->srcc; i++)
80 rtp_source_destroy (demux, session, session->srcv[i]);
88 static void *no_init (demux_t *demux)
94 static void no_destroy (demux_t *demux, void *opaque)
96 (void)demux; (void)opaque;
99 static void no_decode (demux_t *demux, void *opaque, block_t *block)
101 (void)demux; (void)opaque;
102 block_Release (block);
106 * Adds a payload type to an RTP session.
108 int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt)
112 msg_Err (demux, "cannot change RTP payload formats during session");
116 rtp_pt_t *ppt = realloc (ses->ptv, (ses->ptc + 1) * sizeof (rtp_pt_t));
123 ppt->init = pt->init ? pt->init : no_init;
124 ppt->destroy = pt->destroy ? pt->destroy : no_destroy;
125 ppt->decode = pt->decode ? pt->decode : no_decode;
126 ppt->frequency = pt->frequency;
127 ppt->number = pt->number;
128 msg_Dbg (demux, "added payload type %"PRIu8" (f = %"PRIu32" Hz)",
129 ppt->number, ppt->frequency);
131 assert (ppt->frequency > 0); /* SIGFPE! */
136 /** State for an RTP source */
140 uint32_t jitter; /* interarrival delay jitter estimate */
141 mtime_t last_rx; /* last received packet local timestamp */
142 uint32_t last_ts; /* last received packet RTP timestamp */
144 uint16_t bad_seq; /* tentatively next expected sequence for resync */
145 uint16_t max_seq; /* next expected sequence */
147 uint16_t last_seq; /* sequence of the next dequeued packet */
148 block_t *blocks; /* re-ordered blocks queue */
149 mtime_t ref_ts; /* reference timestamp for reordering */
150 void *opaque[0]; /* Per-source private payload data */
154 * Initializes a new RTP source within an RTP session.
156 static rtp_source_t *
157 rtp_source_create (demux_t *demux, const rtp_session_t *session,
158 uint32_t ssrc, uint16_t init_seq)
160 rtp_source_t *source;
162 source = malloc (sizeof (*source) + (sizeof (void *) * session->ptc));
169 source->max_seq = source->bad_seq = init_seq;
170 source->last_seq = init_seq - 1;
171 source->blocks = NULL;
173 /* Initializes all payload */
174 for (unsigned i = 0; i < session->ptc; i++)
175 source->opaque[i] = session->ptv[i].init (demux);
177 msg_Dbg (demux, "added RTP source (%08x)", ssrc);
183 * Destroys an RTP source and its associated streams.
186 rtp_source_destroy (demux_t *demux, const rtp_session_t *session,
187 rtp_source_t *source)
189 msg_Dbg (demux, "removing RTP source (%08x)", source->ssrc);
191 for (unsigned i = 0; i < session->ptc; i++)
192 session->ptv[i].destroy (demux, source->opaque[i]);
193 block_ChainRelease (source->blocks);
197 static inline uint16_t rtp_seq (const block_t *block)
199 assert (block->i_buffer >= 4);
200 return GetWBE (block->p_buffer + 2);
203 static inline uint32_t rtp_timestamp (const block_t *block)
205 assert (block->i_buffer >= 12);
206 return GetDWBE (block->p_buffer + 4);
209 static const struct rtp_pt_t *
210 rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
211 const block_t *block, void **pt_data)
213 uint8_t ptype = rtp_ptype (block);
215 for (unsigned i = 0; i < session->ptc; i++)
217 if (session->ptv[i].number == ptype)
220 *pt_data = source->opaque[i];
221 return &session->ptv[i];
228 * Receives an RTP packet and queues it. Not a cancellation point.
230 * @param demux VLC demux object
231 * @param session RTP session receiving the packet
232 * @param block RTP packet including the RTP header
235 rtp_queue (demux_t *demux, rtp_session_t *session, block_t *block)
237 demux_sys_t *p_sys = demux->p_sys;
239 /* RTP header sanity checks (see RFC 3550) */
240 if (block->i_buffer < 12)
242 if ((block->p_buffer[0] >> 6 ) != 2) /* RTP version number */
245 /* Remove padding if present */
246 if (block->p_buffer[0] & 0x20)
248 uint8_t padding = block->p_buffer[block->i_buffer - 1];
249 if ((padding == 0) || (block->i_buffer < (12u + padding)))
250 goto drop; /* illegal value */
252 block->i_buffer -= padding;
255 mtime_t now = mdate ();
256 rtp_source_t *src = NULL;
257 const uint16_t seq = rtp_seq (block);
258 const uint32_t ssrc = GetDWBE (block->p_buffer + 8);
260 /* In most case, we know this source already */
261 for (unsigned i = 0, max = session->srcc; i < max; i++)
263 rtp_source_t *tmp = session->srcv[i];
264 if (tmp->ssrc == ssrc)
270 /* RTP source garbage collection */
271 if ((tmp->last_rx + (p_sys->timeout * CLOCK_FREQ)) < now)
273 rtp_source_destroy (demux, session, tmp);
274 if (--session->srcc > 0)
275 session->srcv[i] = session->srcv[session->srcc - 1];
282 if (session->srcc >= p_sys->max_src)
284 msg_Warn (demux, "too many RTP sessions");
289 tab = realloc (session->srcv, (session->srcc + 1) * sizeof (*tab));
294 src = rtp_source_create (demux, session, ssrc, seq);
298 tab[session->srcc++] = src;
299 /* Cannot compute jitter yet */
303 const rtp_pt_t *pt = rtp_find_ptype (session, src, block, NULL);
307 /* Recompute jitter estimate.
308 * That is computed from the RTP timestamps and the system clock.
309 * It is independent of RTP sequence. */
310 uint32_t freq = pt->frequency;
311 int64_t ts = rtp_timestamp (block);
312 int64_t d = ((now - src->last_rx) * freq) / CLOCK_FREQ;
313 d -= ts - src->last_ts;
315 src->jitter += ((d - src->jitter) + 8) >> 4;
319 src->last_ts = rtp_timestamp (block);
321 /* Check sequence number */
322 /* NOTE: the sequence number is per-source,
323 * but is independent from the payload type. */
324 int16_t delta_seq = seq - src->max_seq;
325 if ((delta_seq > 0) ? (delta_seq > p_sys->max_dropout)
326 : (-delta_seq > p_sys->max_misorder))
328 msg_Dbg (demux, "sequence discontinuity"
329 " (got: %"PRIu16", expected: %"PRIu16")", seq, src->max_seq);
330 if (seq == src->bad_seq)
332 src->max_seq = src->bad_seq = seq + 1;
333 src->last_seq = seq - 0x7fffe; /* hack for rtp_decode() */
334 msg_Warn (demux, "sequence resynchronized");
335 block_ChainRelease (src->blocks);
340 src->bad_seq = seq + 1;
346 src->max_seq = seq + 1;
348 /* Queues the block in sequence order,
349 * hence there is a single queue for all payload types. */
350 block_t **pp = &src->blocks;
351 for (block_t *prev = *pp; prev != NULL; prev = *pp)
353 int16_t delta_seq = seq - rtp_seq (prev);
358 msg_Dbg (demux, "duplicate packet (sequence: %"PRIu16")", seq);
359 goto drop; /* duplicate */
366 /*rtp_decode (demux, session, src);*/
370 block_Release (block);
375 rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
377 block_t *block = src->blocks;
380 src->blocks = block->p_next;
381 block->p_next = NULL;
383 /* Discontinuity detection */
384 uint16_t delta_seq = rtp_seq (block) - (src->last_seq + 1);
387 if (delta_seq >= 0x8000)
388 { /* Trash too late packets (and PIM Assert duplicates) */
389 msg_Dbg (demux, "ignoring late packet (sequence: %"PRIu16")",
393 msg_Warn (demux, "%"PRIu16" packet(s) lost", delta_seq);
394 block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
396 src->last_seq = rtp_seq (block);
398 /* Match the payload type */
400 const rtp_pt_t *pt = rtp_find_ptype (session, src, block, &pt_data);
403 msg_Dbg (demux, "unknown payload (%"PRIu8")",
408 /* Computes the PTS from the RTP timestamp and payload RTP frequency.
409 * DTS is unknown. Also, while the clock frequency depends on the payload
410 * format, a single source MUST only use payloads of a chosen frequency.
411 * Otherwise it would be impossible to compute consistent timestamps. */
412 /* FIXME: handle timestamp wrap properly */
413 /* TODO: inter-medias/sessions sync (using RTCP-SR) */
414 const uint32_t timestamp = rtp_timestamp (block);
416 block->i_pts = CLOCK_FREQ * timestamp / pt->frequency;
419 size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
421 /* Extension header (ignored for now) */
422 if (block->p_buffer[0] & 0x10)
425 if (block->i_buffer < skip)
428 skip += 4 * GetWBE (block->p_buffer + skip - 2);
431 if (block->i_buffer < skip)
434 block->p_buffer += skip;
435 block->i_buffer -= skip;
437 pt->decode (demux, pt_data, block);
441 block_Release (block);
446 * Dequeues an RTP packet and pass it to decoder. Not cancellation-safe(?).
448 * @param demux VLC demux object
449 * @param session RTP session receiving the packet
450 * @param deadlinep pointer to deadline to call rtp_dequeue() again
451 * @return true if the buffer is not empty, false otherwise.
452 * In the later case, *deadlinep is undefined.
454 bool rtp_dequeue (demux_t *demux, const rtp_session_t *session,
455 mtime_t *restrict deadlinep)
457 mtime_t now = mdate ();
458 bool pending = false;
460 *deadlinep = INT64_MAX;
462 for (unsigned i = 0, max = session->srcc; i < max; i++)
464 rtp_source_t *src = session->srcv[i];
467 /* Because of IP packet delay variation (IPDV), we need to guesstimate
468 * how long to wait for a missing packet in the RTP sequence
469 * (see RFC3393 for background on IPDV).
471 * This situation occurs if a packet got lost, or if the network has
472 * re-ordered packets. Unfortunately, the MSL is 2 minutes, orders of
473 * magnitude too long for multimedia. We need a tradeoff.
474 * If we underestimated IPDV, we may have to discard valid but late
475 * packets. If we overestimate it, we will either cause too much
476 * delay, or worse, underflow our downstream buffers, as we wait for
477 * definitely a lost packets.
479 * The rest of the "de-jitter buffer" work is done by the interval
480 * LibVLC E/S-out clock synchronization. Here, we need to bother about
481 * re-ordering packets, as decoders can't cope with mis-ordered data.
483 while (((block = src->blocks)) != NULL)
485 if ((int16_t)(rtp_seq (block) - (src->last_seq + 1)) <= 0)
486 { /* Next (or earlier) block ready, no need to wait */
487 rtp_decode (demux, session, src);
491 /* Wait for 3 times the inter-arrival delay variance (about 99.7%
492 * match for random gaussian jitter). Additionnaly, we implicitly
493 * wait for misordering times the packetization time.
495 mtime_t deadline = src->ref_ts;
496 const rtp_pt_t *pt = rtp_find_ptype (session, src, block, NULL);
498 deadline = src->ref_ts = now;
500 deadline += CLOCK_FREQ * 3 * src->jitter / pt->frequency;
502 /* Make sure we wait at least for 25 msec */
503 deadline = __MAX(deadline, src->ref_ts + CLOCK_FREQ / 40);
507 rtp_decode (demux, session, src);
510 if (*deadlinep > deadline)
511 *deadlinep = deadline;
512 pending = true; /* packet pending in buffer */