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 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 ****************************************************************************/
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
;
127 ppt
->frequency
= pt
->frequency
;
128 ppt
->number
= pt
->number
;
129 msg_Dbg (demux
, "added payload type %"PRIu8
" (f = %"PRIu32
" Hz)",
130 ppt
->number
, ppt
->frequency
);
132 assert (ppt
->frequency
> 0); /* SIGFPE! */
137 /** State for an RTP source */
141 uint32_t jitter
; /* interarrival delay jitter estimate */
142 vlc_tick_t last_rx
; /* last received packet local timestamp */
143 uint32_t last_ts
; /* last received packet RTP timestamp */
145 uint32_t ref_rtp
; /* sender RTP timestamp reference */
146 vlc_tick_t ref_ntp
; /* sender NTP timestamp reference */
148 uint16_t bad_seq
; /* tentatively next expected sequence for resync */
149 uint16_t max_seq
; /* next expected sequence */
151 uint16_t last_seq
; /* sequence of the next dequeued packet */
152 block_t
*blocks
; /* re-ordered blocks queue */
153 void *opaque
[]; /* Per-source private payload data */
157 * Initializes a new RTP source within an RTP session.
159 static rtp_source_t
*
160 rtp_source_create (demux_t
*demux
, const rtp_session_t
*session
,
161 uint32_t ssrc
, uint16_t init_seq
)
163 rtp_source_t
*source
;
165 source
= malloc (sizeof (*source
) + (sizeof (void *) * session
->ptc
));
172 source
->ref_ntp
= UINT64_C (1) << 62;
173 source
->max_seq
= source
->bad_seq
= init_seq
;
174 source
->last_seq
= init_seq
- 1;
175 source
->blocks
= NULL
;
177 /* Initializes all payload */
178 for (unsigned i
= 0; i
< session
->ptc
; i
++)
179 source
->opaque
[i
] = session
->ptv
[i
].init (demux
);
181 msg_Dbg (demux
, "added RTP source (%08x)", ssrc
);
187 * Destroys an RTP source and its associated streams.
190 rtp_source_destroy (demux_t
*demux
, const rtp_session_t
*session
,
191 rtp_source_t
*source
)
193 msg_Dbg (demux
, "removing RTP source (%08x)", source
->ssrc
);
195 for (unsigned i
= 0; i
< session
->ptc
; i
++)
196 session
->ptv
[i
].destroy (demux
, source
->opaque
[i
]);
197 block_ChainRelease (source
->blocks
);
201 static inline uint16_t rtp_seq (const block_t
*block
)
203 assert (block
->i_buffer
>= 4);
204 return GetWBE (block
->p_buffer
+ 2);
207 static inline uint32_t rtp_timestamp (const block_t
*block
)
209 assert (block
->i_buffer
>= 12);
210 return GetDWBE (block
->p_buffer
+ 4);
213 static const struct rtp_pt_t
*
214 rtp_find_ptype (const rtp_session_t
*session
, rtp_source_t
*source
,
215 const block_t
*block
, void **pt_data
)
217 uint8_t ptype
= rtp_ptype (block
);
219 for (unsigned i
= 0; i
< session
->ptc
; i
++)
221 if (session
->ptv
[i
].number
== ptype
)
224 *pt_data
= source
->opaque
[i
];
225 return &session
->ptv
[i
];
232 * Receives an RTP packet and queues it. Not a cancellation point.
234 * @param demux VLC demux object
235 * @param session RTP session receiving the packet
236 * @param block RTP packet including the RTP header
239 rtp_queue (demux_t
*demux
, rtp_session_t
*session
, block_t
*block
)
241 demux_sys_t
*p_sys
= demux
->p_sys
;
243 /* RTP header sanity checks (see RFC 3550) */
244 if (block
->i_buffer
< 12)
246 if ((block
->p_buffer
[0] >> 6 ) != 2) /* RTP version number */
249 /* Remove padding if present */
250 if (block
->p_buffer
[0] & 0x20)
252 uint8_t padding
= block
->p_buffer
[block
->i_buffer
- 1];
253 if ((padding
== 0) || (block
->i_buffer
< (12u + padding
)))
254 goto drop
; /* illegal value */
256 block
->i_buffer
-= padding
;
259 vlc_tick_t now
= vlc_tick_now ();
260 rtp_source_t
*src
= NULL
;
261 const uint16_t seq
= rtp_seq (block
);
262 const uint32_t ssrc
= GetDWBE (block
->p_buffer
+ 8);
264 /* In most case, we know this source already */
265 for (unsigned i
= 0, max
= session
->srcc
; i
< max
; i
++)
267 rtp_source_t
*tmp
= session
->srcv
[i
];
268 if (tmp
->ssrc
== ssrc
)
274 /* RTP source garbage collection */
275 if ((tmp
->last_rx
+ p_sys
->timeout
) < now
)
277 rtp_source_destroy (demux
, session
, tmp
);
278 if (--session
->srcc
> 0)
279 session
->srcv
[i
] = session
->srcv
[session
->srcc
- 1];
286 if (session
->srcc
>= p_sys
->max_src
)
288 msg_Warn (demux
, "too many RTP sessions");
293 tab
= realloc (session
->srcv
, (session
->srcc
+ 1) * sizeof (*tab
));
298 src
= rtp_source_create (demux
, session
, ssrc
, seq
);
302 tab
[session
->srcc
++] = src
;
303 /* Cannot compute jitter yet */
307 const rtp_pt_t
*pt
= rtp_find_ptype (session
, src
, block
, NULL
);
311 /* Recompute jitter estimate.
312 * That is computed from the RTP timestamps and the system clock.
313 * It is independent of RTP sequence. */
314 uint32_t freq
= pt
->frequency
;
315 int64_t ts
= rtp_timestamp (block
);
316 int64_t d
= samples_from_vlc_tick(now
- src
->last_rx
, freq
);
317 d
-= ts
- src
->last_ts
;
319 src
->jitter
+= ((d
- src
->jitter
) + 8) >> 4;
323 block
->i_pts
= now
; /* store reception time until dequeued */
324 src
->last_ts
= rtp_timestamp (block
);
326 /* Check sequence number */
327 /* NOTE: the sequence number is per-source,
328 * but is independent from the payload type. */
329 int16_t delta_seq
= seq
- src
->max_seq
;
330 if ((delta_seq
> 0) ? (delta_seq
> p_sys
->max_dropout
)
331 : (-delta_seq
> p_sys
->max_misorder
))
333 msg_Dbg (demux
, "sequence discontinuity"
334 " (got: %"PRIu16
", expected: %"PRIu16
")", seq
, src
->max_seq
);
335 if (seq
== src
->bad_seq
)
337 src
->max_seq
= src
->bad_seq
= seq
+ 1;
338 src
->last_seq
= seq
- 0x7fffe; /* hack for rtp_decode() */
339 msg_Warn (demux
, "sequence resynchronized");
340 block_ChainRelease (src
->blocks
);
345 src
->bad_seq
= seq
+ 1;
351 src
->max_seq
= seq
+ 1;
353 /* Queues the block in sequence order,
354 * hence there is a single queue for all payload types. */
355 block_t
**pp
= &src
->blocks
;
356 for (block_t
*prev
= *pp
; prev
!= NULL
; prev
= *pp
)
358 delta_seq
= seq
- rtp_seq (prev
);
363 msg_Dbg (demux
, "duplicate packet (sequence: %"PRIu16
")", seq
);
364 goto drop
; /* duplicate */
371 /*rtp_decode (demux, session, src);*/
375 block_Release (block
);
379 static void rtp_decode (demux_t
*, const rtp_session_t
*, rtp_source_t
*);
382 * Dequeues RTP packets and pass them to decoder. Not cancellation-safe(?).
383 * A packet is decoded if it is the next in sequence order, or if we have
384 * given up waiting on the missing packets (time out) from the last one
387 * @param demux VLC demux object
388 * @param session RTP session receiving the packet
389 * @param deadlinep pointer to deadline to call rtp_dequeue() again
390 * @return true if the buffer is not empty, false otherwise.
391 * In the later case, *deadlinep is undefined.
393 bool rtp_dequeue (demux_t
*demux
, const rtp_session_t
*session
,
394 vlc_tick_t
*restrict deadlinep
)
396 vlc_tick_t now
= vlc_tick_now ();
397 bool pending
= false;
399 *deadlinep
= INT64_MAX
;
401 for (unsigned i
= 0, max
= session
->srcc
; i
< max
; i
++)
403 rtp_source_t
*src
= session
->srcv
[i
];
406 /* Because of IP packet delay variation (IPDV), we need to guesstimate
407 * how long to wait for a missing packet in the RTP sequence
408 * (see RFC3393 for background on IPDV).
410 * This situation occurs if a packet got lost, or if the network has
411 * re-ordered packets. Unfortunately, the MSL is 2 minutes, orders of
412 * magnitude too long for multimedia. We need a trade-off.
413 * If we underestimated IPDV, we may have to discard valid but late
414 * packets. If we overestimate it, we will either cause too much
415 * delay, or worse, underflow our downstream buffers, as we wait for
416 * definitely a lost packets.
418 * The rest of the "de-jitter buffer" work is done by the internal
419 * LibVLC E/S-out clock synchronization. Here, we need to bother about
420 * re-ordering packets, as decoders can't cope with mis-ordered data.
422 while (((block
= src
->blocks
)) != NULL
)
424 if ((int16_t)(rtp_seq (block
) - (src
->last_seq
+ 1)) <= 0)
425 { /* Next (or earlier) block ready, no need to wait */
426 rtp_decode (demux
, session
, src
);
430 /* Wait for 3 times the inter-arrival delay variance (about 99.7%
431 * match for random gaussian jitter).
434 const rtp_pt_t
*pt
= rtp_find_ptype (session
, src
, block
, NULL
);
436 deadline
= vlc_tick_from_samples(3 * src
->jitter
, pt
->frequency
);
438 deadline
= 0; /* no jitter estimate with no frequency :( */
440 /* Make sure we wait at least for 25 msec */
441 if (deadline
< VLC_TICK_FROM_MS(25))
442 deadline
= VLC_TICK_FROM_MS(25);
444 /* Additionnaly, we implicitly wait for the packetization time
445 * multiplied by the number of missing packets. block is the first
446 * non-missing packet (lowest sequence number). We have no better
447 * estimated time of arrival, as we do not know the RTP timestamp
448 * of not yet received packets. */
449 deadline
+= block
->i_pts
;
452 rtp_decode (demux
, session
, src
);
455 if (*deadlinep
> deadline
)
456 *deadlinep
= deadline
;
457 pending
= true; /* packet pending in buffer */
465 * Decodes one RTP packet.
468 rtp_decode (demux_t
*demux
, const rtp_session_t
*session
, rtp_source_t
*src
)
470 block_t
*block
= src
->blocks
;
473 src
->blocks
= block
->p_next
;
474 block
->p_next
= NULL
;
476 /* Discontinuity detection */
477 uint16_t delta_seq
= rtp_seq (block
) - (src
->last_seq
+ 1);
480 if (delta_seq
>= 0x8000)
481 { /* Trash too late packets (and PIM Assert duplicates) */
482 msg_Dbg (demux
, "ignoring late packet (sequence: %"PRIu16
")",
486 msg_Warn (demux
, "%"PRIu16
" packet(s) lost", delta_seq
);
487 block
->i_flags
|= BLOCK_FLAG_DISCONTINUITY
;
489 src
->last_seq
= rtp_seq (block
);
491 /* Match the payload type */
493 const rtp_pt_t
*pt
= rtp_find_ptype (session
, src
, block
, &pt_data
);
496 msg_Dbg (demux
, "unknown payload (%"PRIu8
")",
502 pt
->header(demux
, pt_data
, block
);
504 /* Computes the PTS from the RTP timestamp and payload RTP frequency.
505 * DTS is unknown. Also, while the clock frequency depends on the payload
506 * format, a single source MUST only use payloads of a chosen frequency.
507 * Otherwise it would be impossible to compute consistent timestamps. */
508 const uint32_t timestamp
= rtp_timestamp (block
);
509 block
->i_pts
= src
->ref_ntp
510 + vlc_tick_from_samples(timestamp
- src
->ref_rtp
, pt
->frequency
);
511 /* TODO: proper inter-medias/sessions sync (using RTCP-SR) */
512 src
->ref_ntp
= block
->i_pts
;
513 src
->ref_rtp
= timestamp
;
516 size_t skip
= 12u + (block
->p_buffer
[0] & 0x0F) * 4;
518 /* Extension header (ignored for now) */
519 if (block
->p_buffer
[0] & 0x10)
522 if (block
->i_buffer
< skip
)
525 skip
+= 4 * GetWBE (block
->p_buffer
+ skip
- 2);
528 if (block
->i_buffer
< skip
)
531 block
->p_buffer
+= skip
;
532 block
->i_buffer
-= skip
;
534 pt
->decode (demux
, pt_data
, block
);
538 block_Release (block
);