From bf0e4f65b40fb1ee155cf26131c965c40b8bff38 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Miguel=20Par=C3=ADs=20D=C3=ADaz?= Date: Tue, 30 Jun 2015 16:56:19 +0200 Subject: [PATCH] rtpstats: add utility for calculating RTP packet rate --- gst/rtpmanager/rtpstats.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ gst/rtpmanager/rtpstats.h | 17 +++++++++++++ 2 files changed, 79 insertions(+) diff --git a/gst/rtpmanager/rtpstats.c b/gst/rtpmanager/rtpstats.c index f9f7c2c..d47578d 100644 --- a/gst/rtpmanager/rtpstats.c +++ b/gst/rtpmanager/rtpstats.c @@ -19,6 +19,68 @@ #include "rtpstats.h" +void +gst_rtp_packet_rate_ctx_reset (RTPPacketRateCtx * ctx, guint32 clock_rate) +{ + ctx->clock_rate = clock_rate; + ctx->probed = FALSE; + ctx->avg_packet_rate = -1; +} + +guint32 +gst_rtp_packet_rate_ctx_update (RTPPacketRateCtx * ctx, guint16 seqnum, + guint32 ts) +{ + guint64 new_ts, diff_ts; + gint diff_seqnum; + guint32 new_packet_rate; + + if (ctx->clock_rate <= 0) { + return ctx->avg_packet_rate; + } + + if (!ctx->probed) { + ctx->last_seqnum = seqnum; + ctx->last_ts = ts; + ctx->probed = TRUE; + return ctx->avg_packet_rate; + } + + new_ts = ctx->last_ts; + gst_rtp_buffer_ext_timestamp (&new_ts, ts); + diff_seqnum = gst_rtp_buffer_compare_seqnum (ctx->last_seqnum, seqnum); + if (diff_seqnum <= 0 || new_ts <= ctx->last_ts) { + return ctx->avg_packet_rate; + } + + diff_ts = new_ts - ctx->last_ts; + diff_ts = gst_util_uint64_scale_int (diff_ts, GST_SECOND, ctx->clock_rate); + new_packet_rate = gst_util_uint64_scale (diff_seqnum, GST_SECOND, diff_ts); + + /* The goal is that higher packet rates "win". + * If there's a sudden burst, the average will go up fast, + * but it will go down again slowly. + * This is useful for bursty cases, where a lot of packets are close + * to each other and should allow a higher reorder/dropout there. + */ + if (ctx->avg_packet_rate > new_packet_rate) { + ctx->avg_packet_rate = (7 * ctx->avg_packet_rate + new_packet_rate + 7) / 8; + } else { + ctx->avg_packet_rate = (ctx->avg_packet_rate + new_packet_rate + 1) / 2; + } + + ctx->last_seqnum = seqnum; + ctx->last_ts = new_ts; + + return ctx->avg_packet_rate; +} + +guint32 +gst_rtp_packet_rate_ctx_get (RTPPacketRateCtx * ctx) +{ + return ctx->avg_packet_rate; +} + /** * rtp_stats_init_defaults: * @stats: an #RTPSessionStats struct diff --git a/gst/rtpmanager/rtpstats.h b/gst/rtpmanager/rtpstats.h index d221aea..9c74039 100644 --- a/gst/rtpmanager/rtpstats.h +++ b/gst/rtpmanager/rtpstats.h @@ -194,6 +194,23 @@ typedef struct { #define RTP_MAX_MISORDER 100 /** + * RTPPacketRateCtx: + * + * Context to calculate the pseudo-average packet rate. + */ +typedef struct { + gboolean probed; + guint32 clock_rate; + guint16 last_seqnum; + guint64 last_ts; + guint32 avg_packet_rate; +} RTPPacketRateCtx; + +void gst_rtp_packet_rate_ctx_reset (RTPPacketRateCtx * ctx, guint32 clock_rate); +guint32 gst_rtp_packet_rate_ctx_update (RTPPacketRateCtx *ctx, guint16 seqnum, guint32 ts); +guint32 gst_rtp_packet_rate_ctx_get (RTPPacketRateCtx *ctx); + +/** * RTPSessionStats: * * Stats kept for a session and used to produce RTCP packet timeouts. -- 2.7.4