+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;
+}
+