gst/rtpmanager/gstrtpjitterbuffer.c: Report NO_PREROLL when going to PAUSED.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 25 Apr 2007 13:19:36 +0000 (13:19 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 11 Aug 2009 01:30:25 +0000 (02:30 +0100)
Original commit message from CVS:
* gst/rtpmanager/gstrtpjitterbuffer.c:
(gst_rtp_jitter_buffer_change_state):
Report NO_PREROLL when going to PAUSED.
* gst/rtpmanager/gstrtpsession.c: (rtcp_thread):
Don't send RTCP right before we are shutting down.
* gst/rtpmanager/rtpsession.c: (rtp_session_process_rtp),
(rtp_session_process_sr), (session_report_blocks),
(rtp_session_perform_reporting):
Improve report blocks.
* gst/rtpmanager/rtpsource.c: (calculate_jitter), (init_seq),
(rtp_source_process_rtp), (rtp_source_process_sr),
(rtp_source_process_rb), (rtp_source_get_last_sr),
(rtp_source_get_last_rb):
* gst/rtpmanager/rtpsource.h:
* gst/rtpmanager/rtpstats.h:
Cleanups, add methods to access stats.

gst/rtpmanager/gstrtpjitterbuffer.c
gst/rtpmanager/gstrtpsession.c
gst/rtpmanager/rtpsession.c
gst/rtpmanager/rtpsource.c
gst/rtpmanager/rtpsource.h
gst/rtpmanager/rtpstats.h

index 1973e9b4322a211e630efafb1cc5e18155d3460f..cad8324a9e9887a845d2dc2a1b9a12d77f3aa8b4 100644 (file)
@@ -553,6 +553,8 @@ gst_rtp_jitter_buffer_change_state (GstElement * element,
       async_jitter_queue_set_blocking_unlocked (jitterbuffer->priv->queue,
           TRUE);
       async_jitter_queue_unlock (priv->queue);
+      if (ret != GST_STATE_CHANGE_FAILURE)
+        ret = GST_STATE_CHANGE_NO_PREROLL;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       break;
index b11dbbba2eff1caea44a8b9a719e3a0065eb5a67..39c63e3299f696858e7c3e94a4c1ddd3e59504f3 100644 (file)
@@ -304,21 +304,27 @@ rtcp_thread (GstRTPSession * rtpsession)
   while (!rtpsession->priv->stop_thread) {
     gdouble timeout;
     GstClockTime target;
+    GstClockReturn res;
 
     timeout = rtp_session_get_reporting_interval (rtpsession->priv->session);
     GST_DEBUG_OBJECT (rtpsession, "next RTCP timeout: %lf", timeout);
 
     target = gst_clock_get_time (clock);
     target += GST_SECOND * timeout;
+
+
     id = rtpsession->priv->id = gst_clock_new_single_shot_id (clock, target);
     GST_RTP_SESSION_UNLOCK (rtpsession);
 
-    gst_clock_id_wait (id, NULL);
-
-    GST_DEBUG_OBJECT (rtpsession, "got RTCP timeout");
+    res = gst_clock_id_wait (id, NULL);
+    if (res != GST_CLOCK_UNSCHEDULED) {
+      GST_DEBUG_OBJECT (rtpsession, "got RTCP timeout");
 
-    /* make the session manager produce RTCP, we ignore the result. */
-    rtp_session_perform_reporting (rtpsession->priv->session);
+      /* make the session manager produce RTCP, we ignore the result. */
+      rtp_session_perform_reporting (rtpsession->priv->session);
+    } else {
+      GST_DEBUG_OBJECT (rtpsession, "got unscheduled");
+    }
 
     GST_RTP_SESSION_LOCK (rtpsession);
     gst_clock_id_unref (id);
index e4925a2af09d917624b1d124510b427727b9c8bc..27d6dabb773e34c2b9f4c70897a93be68166345c 100644 (file)
@@ -893,6 +893,7 @@ rtp_session_process_rtp (RTPSession * sess, GstBuffer * buffer)
   prevsender = RTP_SOURCE_IS_SENDER (source);
   prevactive = RTP_SOURCE_IS_ACTIVE (source);
 
+  /* we need to ref so that we can process the CSRCs later */
   gst_buffer_ref (buffer);
 
   /* let source process the packet */
@@ -982,7 +983,8 @@ rtp_session_process_sr (RTPSession * sess, GstRTCPPacket * packet,
   prevsender = RTP_SOURCE_IS_SENDER (source);
 
   /* first update the source */
-  rtp_source_process_sr (source, ntptime, rtptime, packet_count, octet_count);
+  rtp_source_process_sr (source, ntptime, rtptime, packet_count, octet_count,
+      arrival->time);
 
   if (prevsender != RTP_SOURCE_IS_SENDER (source)) {
     sess->stats.sender_sources++;
@@ -1004,7 +1006,7 @@ rtp_session_process_sr (RTPSession * sess, GstRTCPPacket * packet,
 
     if (ssrc == sess->source->ssrc) {
       /* only deal with report blocks for our session, we update the stats of
-       * the sender of the TCP message. We could also compare our stats against
+       * the sender of the RTCP message. We could also compare our stats against
        * the other sender to see if we are better or worse. */
       rtp_source_process_rb (source, fractionlost, packetslost,
           exthighestseq, jitter, lsr, dlsr);
@@ -1292,6 +1294,7 @@ typedef struct
 {
   RTPSession *sess;
   GstBuffer *rtcp;
+  GstClockTime time;
   GstRTCPPacket packet;
 } ReportData;
 
@@ -1322,29 +1325,25 @@ session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
     }
   }
   if (gst_rtcp_packet_get_rb_count (packet) < GST_RTCP_MAX_RB_COUNT) {
-    /* only report about other sources */
-    if (source != sess->source) {
+    /* only report about other sender sources */
+    if (source != sess->source && RTP_SOURCE_IS_SENDER (source)) {
       RTPSourceStats *stats;
-      guint32 extended_max, expected;
-      guint32 expected_interval, received_interval;
-      guint32 lost, lost_interval, fraction;
+      guint64 extended_max, expected;
+      guint64 expected_interval, received_interval, ntptime;
+      gint64 lost, lost_interval;
+      guint32 fraction, LSR, DLSR;
+      GstClockTime time;
 
       stats = &source->stats;
 
-      extended_max = (stats->cycles << 16) + stats->max_seq;
+      extended_max = stats->cycles + stats->max_seq;
       expected = extended_max - stats->base_seq + 1;
 
-      if (expected > stats->packets_received) {
-        lost = expected - stats->packets_received;
-        if (lost > 0x7fffff)
-          lost = 0x7fffff;
-      } else {
-        lost = stats->packets_received - expected;
-        if (lost > 0x800000)
-          lost = 0x800000;
-        else
-          lost = -lost;
-      }
+      GST_DEBUG ("ext_max %d, expected %d, received %d, base_seq %d",
+          extended_max, expected, stats->packets_received, stats->base_seq);
+
+      lost = expected - stats->packets_received;
+      lost = CLAMP (lost, -0x800000, 0x7fffff);
 
       expected_interval = expected - stats->prev_expected;
       stats->prev_expected = expected;
@@ -1363,9 +1362,21 @@ session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
       GST_DEBUG ("fraction %d, lost %d, extseq %u, jitter %d", fraction, lost,
           extended_max, stats->jitter >> 4);
 
+      if (rtp_source_get_last_sr (source, &ntptime, NULL, NULL, NULL, &time)) {
+        /* LSR is middle bits of the last ntptime */
+        LSR = (ntptime >> 16) & 0xffffffff;
+        /* DLSR, delay since last SR is expressed in 1/65536 second units */
+        DLSR = gst_util_uint64_scale_int (data->time - time, 65536, GST_SECOND);
+      } else {
+        /* No valid SR received, LSR/DLSR are set to 0 then */
+        LSR = 0;
+        DLSR = 0;
+      }
+      GST_DEBUG ("LSR %08x, DLSR %08x", LSR, DLSR);
+
       /* packet is not yet filled, add report block for this source. */
       gst_rtcp_packet_add_rb (packet, source->ssrc, fraction, lost,
-          extended_max, stats->jitter >> 4, 0, 0);
+          extended_max, stats->jitter >> 4, LSR, DLSR);
     }
   }
 }
@@ -1413,6 +1424,9 @@ rtp_session_perform_reporting (RTPSession * sess)
   data.sess = sess;
   data.rtcp = NULL;
 
+  /* get time so it can be used later */
+  data.time = sess->callbacks.get_time (sess, sess->user_data);
+
   RTP_SESSION_LOCK (sess);
   /* loop over all known sources and do something */
   g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
index 43acb0847a241e48304c2238695e80dc5eee2c64..e1e6aaca550be6695a91d429f1f95606ede4c813 100644 (file)
@@ -248,15 +248,19 @@ calculate_jitter (RTPSource * src, GstBuffer * buffer,
 
   /* transit time is difference with RTP timestamp */
   transit = rtparrival - rtptime;
-  /* get diff with previous transit time */
-  if (src->stats.transit != -1)
-    diff = transit - src->stats.transit;
-  else
+
+  /* get ABS diff with previous transit time */
+  if (src->stats.transit != -1) {
+    if (transit > src->stats.transit)
+      diff = transit - src->stats.transit;
+    else
+      diff = src->stats.transit - transit;
+  } else
     diff = 0;
+
   src->stats.transit = transit;
-  if (diff < 0)
-    diff = -diff;
-  /* update jitter */
+
+  /* update jitter, the value we store is scaled up so we can keep precision. */
   src->stats.jitter += diff - ((src->stats.jitter + 8) >> 4);
 
   src->stats.prev_rtptime = src->stats.last_rtptime;
@@ -292,6 +296,8 @@ init_seq (RTPSource * src, guint16 seq)
   src->stats.bytes_received = 0;
   src->stats.prev_received = 0;
   src->stats.prev_expected = 0;
+
+  GST_DEBUG ("base_seq %d", seq);
 }
 
 /**
@@ -319,7 +325,7 @@ rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer,
   seqnr = gst_rtp_buffer_get_seq (buffer);
 
   if (stats->cycles == -1) {
-    GST_DEBUG ("first buffer");
+    GST_DEBUG ("received first buffer");
     /* first time we heard of this source */
     init_seq (src, seqnr);
     src->stats.max_seq = seqnr - 1;
@@ -366,7 +372,7 @@ rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer,
     /* in order, with permissible gap */
     if (seqnr < stats->max_seq) {
       /* sequence number wrapped - count another 64K cycle. */
-      stats->cycles++;
+      stats->cycles += RTP_SEQ_MOD;
     }
     stats->max_seq = seqnr;
   } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
@@ -392,8 +398,8 @@ rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer,
   src->is_sender = TRUE;
   src->validated = TRUE;
 
-  GST_DEBUG ("PC: %" G_GUINT64_FORMAT ", OC: %" G_GUINT64_FORMAT,
-      src->stats.packets_received, src->stats.octets_received);
+  GST_DEBUG ("seq %d, PC: %" G_GUINT64_FORMAT ", OC: %" G_GUINT64_FORMAT,
+      seqnr, src->stats.packets_received, src->stats.octets_received);
 
   /* calculate jitter */
   calculate_jitter (src, buffer, arrival);
@@ -470,20 +476,21 @@ rtp_source_send_rtp (RTPSource * src, GstBuffer * buffer)
  * @rtptime: the RTP time
  * @packet_count: the packet count
  * @octet_count: the octect count
+ * @time: time of packet arrival
  *
  * Update the sender report in @src.
  */
 void
 rtp_source_process_sr (RTPSource * src, guint64 ntptime, guint32 rtptime,
-    guint32 packet_count, guint32 octet_count)
+    guint32 packet_count, guint32 octet_count, GstClockTime time)
 {
   RTPSenderReport *curr;
   gint curridx;
 
   g_return_if_fail (RTP_IS_SOURCE (src));
 
-  GST_DEBUG ("got SR packet: SSRC %08x, NTP %" G_GUINT64_FORMAT
-      ", RTP %u, PC %u, OC %u", src->ssrc, ntptime, rtptime, packet_count,
+  GST_DEBUG ("got SR packet: SSRC %08x, NTP %08x:%08x, RTP %u, PC %u, OC %u",
+      src->ssrc, ntptime >> 32, ntptime & 0xffffffff, rtptime, packet_count,
       octet_count);
 
   curridx = src->stats.curr_sr ^ 1;
@@ -498,6 +505,7 @@ rtp_source_process_sr (RTPSource * src, guint64 ntptime, guint32 rtptime,
   curr->rtptime = rtptime;
   curr->packet_count = packet_count;
   curr->octet_count = octet_count;
+  curr->time = time;
 
   /* make current */
   src->stats.curr_sr = curridx;
@@ -525,7 +533,7 @@ rtp_source_process_rb (RTPSource * src, guint8 fractionlost, gint32 packetslost,
   g_return_if_fail (RTP_IS_SOURCE (src));
 
   GST_DEBUG ("got RB packet %d: SSRC %08x, FL %u"
-      ", PL %u, HS %u, JITTER %u, LSR %u, DLSR %u", src->ssrc, fractionlost,
+      ", PL %u, HS %u, JITTER %u, LSR %08x, DLSR %08x", src->ssrc, fractionlost,
       packetslost, exthighestseq, jitter, lsr, dlsr);
 
   curridx = src->stats.curr_rr ^ 1;
@@ -543,3 +551,85 @@ rtp_source_process_rb (RTPSource * src, guint8 fractionlost, gint32 packetslost,
   /* make current */
   src->stats.curr_rr = curridx;
 }
+
+/**
+ * rtp_source_get_last_sr:
+ * @src: an #RTPSource
+ * @ntptime: the NTP time
+ * @rtptime: the RTP time
+ * @packet_count: the packet count
+ * @octet_count: the octect count
+ * @time: time of packet arrival
+ *
+ * Get the values of the last sender report as set with rtp_source_process_sr().
+ *
+ * Returns: %TRUE if there was a valid SR report.
+ */
+gboolean
+rtp_source_get_last_sr (RTPSource * src, guint64 * ntptime, guint32 * rtptime,
+    guint32 * packet_count, guint32 * octet_count, GstClockTime * time)
+{
+  RTPSenderReport *curr;
+
+  g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
+
+  curr = &src->stats.sr[src->stats.curr_sr];
+  if (!curr->is_valid)
+    return FALSE;
+
+  if (ntptime)
+    *ntptime = curr->ntptime;
+  if (rtptime)
+    *rtptime = curr->rtptime;
+  if (packet_count)
+    *packet_count = curr->packet_count;
+  if (octet_count)
+    *octet_count = curr->octet_count;
+  if (time)
+    *time = curr->time;
+
+  return TRUE;
+}
+
+/**
+ * rtp_source_get_last_rb:
+ * @src: an #RTPSource
+ * @fractionlost: fraction lost since last SR/RR
+ * @packetslost: the cumululative number of packets lost
+ * @exthighestseq: the extended last sequence number received
+ * @jitter: the interarrival jitter
+ * @lsr: the last SR packet from this source
+ * @dlsr: the delay since last SR packet
+ *
+ * Get the values of the last RB report set with rtp_source_process_rb().
+ *
+ * Returns: %TRUE if there was a valid SB report.
+ */
+gboolean
+rtp_source_get_last_rb (RTPSource * src, guint8 * fractionlost,
+    gint32 * packetslost, guint32 * exthighestseq, guint32 * jitter,
+    guint32 * lsr, guint32 * dlsr)
+{
+  RTPReceiverReport *curr;
+
+  g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
+
+  curr = &src->stats.rr[src->stats.curr_rr];
+  if (!curr->is_valid)
+    return FALSE;
+
+  if (fractionlost)
+    *fractionlost = curr->fractionlost;
+  if (packetslost)
+    *packetslost = curr->packetslost;
+  if (exthighestseq)
+    *exthighestseq = curr->exthighestseq;
+  if (jitter)
+    *jitter = curr->jitter;
+  if (lsr)
+    *lsr = curr->lsr;
+  if (dlsr)
+    *dlsr = curr->dlsr;
+
+  return TRUE;
+}
index 2f997fb5e972587f97ce21a08201f4b85644a703..f5ca2a1ced206f34592d5af2ca1b1cbf7df1bfff 100644 (file)
@@ -167,9 +167,15 @@ GstFlowReturn   rtp_source_send_rtp       (RTPSource *src, GstBuffer *buffer);
 /* RTCP messages */
 void            rtp_source_process_bye    (RTPSource *src, const gchar *reason);
 void            rtp_source_process_sr     (RTPSource *src, guint64 ntptime, guint32 rtptime,
-                                           guint32 packet_count, guint32 octet_count);
+                                           guint32 packet_count, guint32 octet_count, GstClockTime time);
 void            rtp_source_process_rb     (RTPSource *src, guint8 fractionlost, gint32 packetslost,
                                            guint32 exthighestseq, guint32 jitter,
                                            guint32 lsr, guint32 dlsr);
 
+gboolean        rtp_source_get_last_sr    (RTPSource *src, guint64 *ntptime, guint32 *rtptime,
+                                           guint32 *packet_count, guint32 *octet_count, GstClockTime *time);
+gboolean        rtp_source_get_last_rb    (RTPSource *src, guint8 *fractionlost, gint32 *packetslost,
+                                           guint32 *exthighestseq, guint32 *jitter,
+                                           guint32 *lsr, guint32 *dlsr);
+
 #endif /* __RTP_SOURCE_H__ */
index 64321427820b0aaa82fb843fe8c6bce34d4b7025..e8ea98163182fab4c753c3bc5cd7aa4f958f1365 100644 (file)
@@ -34,6 +34,7 @@ typedef struct {
   guint32 rtptime;
   guint32 packet_count;
   guint32 octet_count;
+  GstClockTime time;
 } RTPSenderReport;
 
 /**
@@ -100,7 +101,7 @@ typedef struct {
   guint32      prev_received;
 
   guint16      max_seq;
-  guint32      cycles;
+  guint64      cycles;
   guint32      base_seq;
   guint32      bad_seq;
   guint32      transit;