]> git.sesse.net Git - vlc/blobdiff - modules/access/rtp/session.c
Set SOCKET_LIBS on Windows too
[vlc] / modules / access / rtp / session.c
index 22f127ea3385a12559cb7f085508cc956831100c..8fc6d5f6439ec3e7dab877b9fa2d551c36dd362f 100644 (file)
@@ -141,6 +141,9 @@ struct rtp_source_t
     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 */
 
@@ -164,6 +167,9 @@ rtp_source_create (demux_t *demux, const rtp_session_t *session,
 
     source->ssrc = ssrc;
     source->jitter = 0;
+    source->ref_rtp = 0;
+    /* TODO: use VLC_TS_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;
@@ -266,7 +272,7 @@ rtp_queue (demux_t *demux, rtp_session_t *session, block_t *block)
         }
 
         /* 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)
@@ -370,78 +376,13 @@ drop:
 }
 
 
-static void
-rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
-{
-    block_t *block = src->blocks;
-
-    assert (block);
-    src->blocks = block->p_next;
-    block->p_next = NULL;
-
-    /* Discontinuity detection */
-    uint16_t delta_seq = rtp_seq (block) - (src->last_seq + 1);
-    if (delta_seq != 0)
-    {
-        if (delta_seq >= 0x8000)
-        {   /* 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);
-
-    /* Match the payload type */
-    void *pt_data;
-    const rtp_pt_t *pt = rtp_find_ptype (session, src, block, &pt_data);
-    if (pt == NULL)
-    {
-        msg_Dbg (demux, "unknown payload (%"PRIu8")",
-                 rtp_ptype (block));
-        goto drop;
-    }
-
-    /* Computes the PTS from the RTP timestamp and payload RTP frequency.
-     * 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;
-
-    /* CSRC count */
-    size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
-
-    /* Extension header (ignored for now) */
-    if (block->p_buffer[0] & 0x10)
-    {
-        skip += 4;
-        if (block->i_buffer < skip)
-            goto drop;
-
-        skip += 4 * GetWBE (block->p_buffer + skip - 2);
-    }
-
-    if (block->i_buffer < skip)
-        goto drop;
-
-    block->p_buffer += skip;
-    block->i_buffer -= skip;
-
-    pt->decode (demux, pt_data, block);
-    return;
-
-drop:
-    block_Release (block);
-}
-
+static void rtp_decode (demux_t *, const rtp_session_t *, rtp_source_t *);
 
 /**
- * Dequeues an RTP packet and pass it to decoder. Not cancellation-safe(?).
+ * Dequeues RTP packets and pass them to decoder. Not cancellation-safe(?).
+ * A packet is decoded if it is the next in sequence order, or if we have
+ * given up waiting on the missing packets (time out) from the last one
+ * already decoded.
  *
  * @param demux VLC demux object
  * @param session RTP session receiving the packet
@@ -468,13 +409,13 @@ bool rtp_dequeue (demux_t *demux, const rtp_session_t *session,
          *
          * 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.
          */
@@ -519,3 +460,93 @@ bool rtp_dequeue (demux_t *demux, const rtp_session_t *session,
     }
     return pending;
 }
+
+/**
+ * Dequeues all RTP packets and pass them to decoder. Not cancellation-safe(?).
+ * This function can be used when the packet source is known not to reorder.
+ */
+void rtp_dequeue_force (demux_t *demux, const rtp_session_t *session)
+{
+    for (unsigned i = 0, max = session->srcc; i < max; i++)
+    {
+        rtp_source_t *src = session->srcv[i];
+        block_t *block;
+
+        while (((block = src->blocks)) != NULL)
+            rtp_decode (demux, session, src);
+    }
+}
+
+/**
+ * Decodes one RTP packet.
+ */
+static void
+rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
+{
+    block_t *block = src->blocks;
+
+    assert (block);
+    src->blocks = block->p_next;
+    block->p_next = NULL;
+
+    /* Discontinuity detection */
+    uint16_t delta_seq = rtp_seq (block) - (src->last_seq + 1);
+    if (delta_seq != 0)
+    {
+        if (delta_seq >= 0x8000)
+        {   /* 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);
+
+    /* Match the payload type */
+    void *pt_data;
+    const rtp_pt_t *pt = rtp_find_ptype (session, src, block, &pt_data);
+    if (pt == NULL)
+    {
+        msg_Dbg (demux, "unknown payload (%"PRIu8")",
+                 rtp_ptype (block));
+        goto drop;
+    }
+
+    /* Computes the PTS from the RTP timestamp and payload RTP frequency.
+     * 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. */
+    const uint32_t timestamp = rtp_timestamp (block);
+    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;
+
+    /* Extension header (ignored for now) */
+    if (block->p_buffer[0] & 0x10)
+    {
+        skip += 4;
+        if (block->i_buffer < skip)
+            goto drop;
+
+        skip += 4 * GetWBE (block->p_buffer + skip - 2);
+    }
+
+    if (block->i_buffer < skip)
+        goto drop;
+
+    block->p_buffer += skip;
+    block->i_buffer -= skip;
+
+    pt->decode (demux, pt_data, block);
+    return;
+
+drop:
+    block_Release (block);
+}