*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2.0
+ * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
+ * You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <assert.h>
#include <errno.h>
-#include <vlc/vlc.h>
+#include <vlc_common.h>
#include <vlc_demux.h>
#include "rtp.h"
mtime_t last_rx; /* last received packet local timestamp */
uint32_t last_ts; /* last received packet RTP timestamp */
+ uint32_t ref_rtp; /* sender RTP timestamp reference */
+ mtime_t ref_ntp; /* sender NTP timestamp reference */
+
uint16_t bad_seq; /* tentatively next expected sequence for resync */
uint16_t max_seq; /* next expected sequence */
source->ssrc = ssrc;
source->jitter = 0;
+ source->ref_rtp = 0;
+ /* TODO: use 0, but VLC does not like negative PTS at the moment */
+ source->ref_ntp = UINT64_C (1) << 62;
source->max_seq = source->bad_seq = init_seq;
source->last_seq = init_seq - 1;
source->blocks = NULL;
}
/* RTP source garbage collection */
- if ((tmp->last_rx + (p_sys->timeout * CLOCK_FREQ)) < now)
+ if ((tmp->last_rx + p_sys->timeout) < now)
{
rtp_source_destroy (demux, session, tmp);
if (--session->srcc > 0)
}
}
src->last_rx = now;
+ block->i_pts = now; /* store reception time until dequeued */
src->last_ts = rtp_timestamp (block);
/* Check sequence number */
/* NOTE: the sequence number is per-source,
* but is independent from the payload type. */
- int delta_seq = seq - src->max_seq;
+ int16_t delta_seq = seq - src->max_seq;
if ((delta_seq > 0) ? (delta_seq > p_sys->max_dropout)
: (-delta_seq > p_sys->max_misorder))
{
block_t **pp = &src->blocks;
for (block_t *prev = *pp; prev != NULL; prev = *pp)
{
- int delta_seq = seq - rtp_seq (prev);
+ int16_t delta_seq = seq - rtp_seq (prev);
if (delta_seq < 0)
break;
if (delta_seq == 0)
if (delta_seq != 0)
{
if (delta_seq >= 0x8000)
- { /* Unrecoverable if later packets have already been dequeued */
- msg_Warn (demux, "ignoring late packet (sequence: %"PRIu16")",
+ { /* Trash too late packets (and PIM Assert duplicates) */
+ msg_Dbg (demux, "ignoring late packet (sequence: %"PRIu16")",
rtp_seq (block));
goto drop;
}
+ msg_Warn (demux, "%"PRIu16" packet(s) lost", delta_seq);
block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
}
src->last_seq = rtp_seq (block);
* DTS is unknown. Also, while the clock frequency depends on the payload
* format, a single source MUST only use payloads of a chosen frequency.
* Otherwise it would be impossible to compute consistent timestamps. */
- /* FIXME: handle timestamp wrap properly */
- /* TODO: inter-medias/sessions sync (using RTCP-SR) */
const uint32_t timestamp = rtp_timestamp (block);
- block->i_pts = CLOCK_FREQ * timestamp / pt->frequency;
+ block->i_pts = src->ref_ntp
+ + CLOCK_FREQ * (int32_t)(timestamp - src->ref_rtp) / pt->frequency;
+ /* TODO: proper inter-medias/sessions sync (using RTCP-SR) */
+ src->ref_ntp = block->i_pts;
+ src->ref_rtp = timestamp;
/* CSRC count */
size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
mtime_t now = mdate ();
bool pending = false;
+ *deadlinep = INT64_MAX;
+
for (unsigned i = 0, max = session->srcc; i < max; i++)
{
rtp_source_t *src = session->srcv[i];
*
* This situation occurs if a packet got lost, or if the network has
* re-ordered packets. Unfortunately, the MSL is 2 minutes, orders of
- * magnitude too long for multimedia. We need a tradeoff.
+ * magnitude too long for multimedia. We need a trade-off.
* If we underestimated IPDV, we may have to discard valid but late
* packets. If we overestimate it, we will either cause too much
* delay, or worse, underflow our downstream buffers, as we wait for
* definitely a lost packets.
*
- * The rest of the "de-jitter buffer" work is done by the interval
+ * The rest of the "de-jitter buffer" work is done by the internal
* LibVLC E/S-out clock synchronization. Here, we need to bother about
* re-ordering packets, as decoders can't cope with mis-ordered data.
*/
}
/* Wait for 3 times the inter-arrival delay variance (about 99.7%
- * match for random gaussian jitter). Additionnaly, we implicitly
- * wait for misordering times the packetization time.
+ * match for random gaussian jitter).
*/
- mtime_t deadline = src->last_rx;
+ mtime_t deadline;
const rtp_pt_t *pt = rtp_find_ptype (session, src, block, NULL);
if (pt)
- deadline += CLOCK_FREQ * 3 * src->jitter / pt->frequency;
-
+ deadline = CLOCK_FREQ * 3 * src->jitter / pt->frequency;
+ else
+ deadline = 0; /* no jitter estimate with no frequency :( */
+
+ /* Make sure we wait at least for 25 msec */
+ if (deadline < (CLOCK_FREQ / 40))
+ deadline = CLOCK_FREQ / 40;
+
+ /* Additionnaly, we implicitly wait for the packetization time
+ * multiplied by the number of missing packets. block is the first
+ * non-missing packet (lowest sequence number). We have no better
+ * estimated time of arrival, as we do not know the RTP timestamp
+ * of not yet received packets. */
+ deadline += block->i_pts;
if (now >= deadline)
{
rtp_decode (demux, session, src);