summaryrefslogtreecommitdiffstats
path: root/ui/tap-rtp-analysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui/tap-rtp-analysis.c')
-rw-r--r--ui/tap-rtp-analysis.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/ui/tap-rtp-analysis.c b/ui/tap-rtp-analysis.c
new file mode 100644
index 00000000..bd2438fa
--- /dev/null
+++ b/ui/tap-rtp-analysis.c
@@ -0,0 +1,545 @@
+/* tap-rtp-analysis.c
+ * RTP stream handler functions used by tshark and wireshark
+ *
+ * Copyright 2008, Ericsson AB
+ * By Balint Reczey <balint.reczey@ericsson.com>
+ *
+ * most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analysis.c
+ * Copyright 2003, Alcatel Business Systems
+ * By Lars Ruoff <lars.ruoff@gmx.net>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <math.h>
+#include "globals.h"
+
+#include <string.h>
+#include <epan/rtp_pt.h>
+#include <epan/addr_resolv.h>
+#include <epan/proto_data.h>
+#include <epan/dissectors/packet-rtp.h>
+#include "rtp_stream.h"
+#include "tap-rtp-common.h"
+#include "tap-rtp-analysis.h"
+
+typedef struct _key_value {
+ guint32 key;
+ guint32 value;
+} key_value;
+
+
+/* RTP sampling clock rates for fixed payload types as defined in
+ https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
+static const key_value clock_map[] = {
+ {PT_PCMU, 8000},
+ {PT_1016, 8000},
+ {PT_G721, 8000},
+ {PT_GSM, 8000},
+ {PT_G723, 8000},
+ {PT_DVI4_8000, 8000},
+ {PT_DVI4_16000, 16000},
+ {PT_LPC, 8000},
+ {PT_PCMA, 8000},
+ {PT_G722, 8000},
+ {PT_L16_STEREO, 44100},
+ {PT_L16_MONO, 44100},
+ {PT_QCELP, 8000},
+ {PT_CN, 8000},
+ {PT_MPA, 90000},
+ {PT_G728, 8000},
+ {PT_G728, 8000},
+ {PT_DVI4_11025, 11025},
+ {PT_DVI4_22050, 22050},
+ {PT_G729, 8000},
+ {PT_CN_OLD, 8000},
+ {PT_CELB, 90000},
+ {PT_JPEG, 90000},
+ {PT_NV, 90000},
+ {PT_H261, 90000},
+ {PT_MPV, 90000},
+ {PT_MP2T, 90000},
+ {PT_H263, 90000},
+};
+
+#define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
+
+static guint32
+get_clock_rate(guint32 key)
+{
+ size_t i;
+
+ for (i = 0; i < NUM_CLOCK_VALUES; i++) {
+ if (clock_map[i].key == key)
+ return clock_map[i].value;
+ }
+ return 0;
+}
+
+typedef struct _mimetype_and_clock {
+ const gchar *pt_mime_name_str;
+ guint32 value;
+} mimetype_and_clock;
+/* RTP sampling clock rates for
+ "In addition to the RTP payload formats (encodings) listed in the RTP
+ Payload Types table, there are additional payload formats that do not
+ have static RTP payload types assigned but instead use dynamic payload
+ type number assignment. Each payload format is named by a registered
+ media subtype"
+ https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml.
+
+ NOTE: Please keep the mimetypes in case insensitive alphabetical order.
+*/
+static const mimetype_and_clock mimetype_and_clock_map[] = {
+ {"AMR", 8000}, /* [RFC4867][RFC3267] */
+ {"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
+ {"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
+ {"BT656", 90000}, /* [RFC2431],[RFC3555] */
+ {"DV", 90000}, /* [RFC3189] */
+ {"EVRC", 8000}, /* [RFC3558] */
+ {"EVRC0", 8000}, /* [RFC4788] */
+ {"EVRC1", 8000}, /* [RFC4788] */
+ {"EVRCB", 8000}, /* [RFC4788] */
+ {"EVRCB0", 8000}, /* [RFC4788] */
+ {"EVRCB1", 8000}, /* [RFC4788] */
+ {"EVRCWB", 16000}, /* [RFC5188] */
+ {"EVRCWB0", 16000}, /* [RFC5188] */
+ {"EVRCWB1", 16000}, /* [RFC5188] */
+ {"EVS", 16000}, /* [3GPP TS 26.445] */
+ {"G7221", 16000}, /* [RFC3047] */
+ {"G726-16", 8000}, /* [RFC3551][RFC4856] */
+ {"G726-24", 8000}, /* [RFC3551][RFC4856] */
+ {"G726-32", 8000}, /* [RFC3551][RFC4856] */
+ {"G726-40", 8000}, /* [RFC3551][RFC4856] */
+ {"G729D", 8000}, /* [RFC3551][RFC4856] */
+ {"G729E", 8000}, /* [RFC3551][RFC4856] */
+ {"GSM-EFR", 8000}, /* [RFC3551] */
+ {"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
+ {"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
+ {"H264", 90000}, /* [RFC3984] */
+ {"MP1S", 90000}, /* [RFC2250],[RFC3555] */
+ {"MP2P", 90000}, /* [RFC2250],[RFC3555] */
+ {"MP4V-ES", 90000}, /* [RFC3016] */
+ {"mpa-robust", 90000}, /* [RFC3119] */
+ {"pointer", 90000}, /* [RFC2862] */
+ {"raw", 90000}, /* [RFC4175] */
+ {"red", 1000}, /* [RFC4102] */
+ {"SMV", 8000}, /* [RFC3558] */
+ {"SMV0", 8000}, /* [RFC3558] */
+ {"t140", 1000}, /* [RFC4103] */
+ {"telephone-event", 8000}, /* [RFC4733] */
+};
+
+#define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
+
+static guint32
+get_dyn_pt_clock_rate(const gchar *payload_type_str)
+{
+ int i;
+
+ /* Search for matching mimetype in reverse order to avoid false matches
+ * when pt_mime_name_str is the prefix of payload_type_str */
+ for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
+ if (g_ascii_strncasecmp(mimetype_and_clock_map[i].pt_mime_name_str,payload_type_str,(strlen(mimetype_and_clock_map[i].pt_mime_name_str))) == 0)
+ return mimetype_and_clock_map[i].value;
+ }
+
+ return 0;
+}
+
+#define TIMESTAMP_DIFFERENCE(v1,v2) ((gint64)v2-(gint64)v1)
+
+/****************************************************************************/
+void
+rtppacket_analyse(tap_rtp_stat_t *statinfo,
+ const packet_info *pinfo,
+ const struct _rtp_info *rtpinfo)
+{
+ double current_time;
+ double current_jitter = 0;
+ double current_diff = 0;
+ double nominaltime;
+ double nominaltime_diff;
+ double arrivaltime;
+ double expected_time;
+ double absskew;
+ guint32 clock_rate;
+ gboolean in_time_sequence;
+
+ /* Store the current time */
+ current_time = nstime_to_msec(&pinfo->rel_ts);
+
+ /* Is this the first packet we got in this direction? */
+ if (statinfo->first_packet) {
+ statinfo->start_seq_nr = rtpinfo->info_seq_num;
+ statinfo->stop_seq_nr = rtpinfo->info_seq_num;
+ statinfo->seq_num = rtpinfo->info_seq_num;
+ statinfo->start_time = current_time;
+ statinfo->timestamp = rtpinfo->info_timestamp;
+ statinfo->seq_timestamp = rtpinfo->info_timestamp;
+ statinfo->first_timestamp = rtpinfo->info_timestamp;
+ statinfo->time = current_time;
+ statinfo->lastnominaltime = 0;
+ statinfo->lastarrivaltime = 0;
+ statinfo->pt = rtpinfo->info_payload_type;
+ statinfo->reg_pt = rtpinfo->info_payload_type;
+ if (pinfo->net_src.type == AT_IPv6) {
+ statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
+ } else {
+ statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
+ }
+ statinfo->bw_history[statinfo->bw_index].time = current_time;
+ statinfo->bw_index++;
+ if (pinfo->net_src.type == AT_IPv6) {
+ statinfo->total_bytes += rtpinfo->info_data_len + 48;
+ } else {
+ statinfo->total_bytes += rtpinfo->info_data_len + 28;
+ }
+ statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
+ /* Not needed ? initialised to zero? */
+ statinfo->delta = 0;
+ statinfo->max_delta = 0;
+ statinfo->min_delta = -1;
+ statinfo->mean_delta = 0;
+ statinfo->jitter = 0;
+ statinfo->min_jitter = -1;
+ statinfo->max_jitter = 0;
+ statinfo->diff = 0;
+
+ statinfo->total_nr++;
+ statinfo->flags |= STAT_FLAG_FIRST;
+ if (rtpinfo->info_marker_set) {
+ statinfo->flags |= STAT_FLAG_MARKER;
+ }
+ statinfo->first_packet_num = pinfo->num;
+ statinfo->first_packet = FALSE;
+ return;
+ }
+
+ /* Reset flags */
+ statinfo->flags = 0;
+
+ /* When calculating expected rtp packets the seq number can wrap around
+ * so we have to count the number of cycles
+ * Variable seq_cycles counts the wraps around in forwarding connection and
+ * under is flag that indicates where we are
+ *
+ * XXX How to determine number of cycles with all possible lost, late
+ * and duplicated packets without any doubt? It seems to me, that
+ * because of all possible combination of late, duplicated or lost
+ * packets, this can only be more or less good approximation
+ *
+ * There are some combinations (rare but theoretically possible),
+ * where below code won't work correctly - statistic may be wrong then.
+ */
+
+ /* Check if time sequence of packets is in order. We check whether
+ * timestamp difference is below 1/2 of timestamp range (hours or days).
+ * Packets can be in pure sequence or sequence can be wrapped around
+ * 0xFFFFFFFF.
+ */
+ if ((statinfo->first_timestamp <= rtpinfo->info_timestamp) &&
+ TIMESTAMP_DIFFERENCE(statinfo->first_timestamp, rtpinfo->info_timestamp) < 0x80000000) {
+ // Normal timestamp sequence
+ in_time_sequence = TRUE;
+ } else if ((statinfo->first_timestamp > rtpinfo->info_timestamp) &&
+ (TIMESTAMP_DIFFERENCE(statinfo->first_timestamp, 0xFFFFFFFF) + TIMESTAMP_DIFFERENCE(0x00000000, rtpinfo->info_timestamp)) < 0x80000000) {
+ // Normal timestamp sequence with wraparound
+ in_time_sequence = TRUE;
+ } else {
+ // New packet is not in sequence (is in past)
+ in_time_sequence = FALSE;
+ statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
+ }
+
+ /* So if the current sequence number is less than the start one
+ * we assume, that there is another cycle running
+ */
+ if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) &&
+ in_time_sequence &&
+ (statinfo->under == FALSE)) {
+ statinfo->seq_cycles++;
+ statinfo->under = TRUE;
+ }
+ /* what if the start seq nr was 0? Then the above condition will never
+ * be true, so we add another condition. XXX The problem would arise
+ * if one of the packets with seq nr 0 or 65535 would be lost or late
+ */
+ else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
+ in_time_sequence &&
+ (statinfo->under == FALSE)) {
+ statinfo->seq_cycles++;
+ statinfo->under = TRUE;
+ }
+ /* the whole round is over, so reset the flag */
+ else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) &&
+ in_time_sequence &&
+ (statinfo->under != FALSE)) {
+ statinfo->under = FALSE;
+ }
+
+ /* Since it is difficult to count lost, duplicate or late packets separately,
+ * we would like to know at least how many times the sequence number was not ok
+ */
+
+ /* If the current seq number equals the last one or if we are here for
+ * the first time, then it is ok, we just store the current one as the last one
+ */
+ if ( in_time_sequence &&
+ ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
+ ) {
+ statinfo->seq_num = rtpinfo->info_seq_num;
+ }
+ /* If the first one is 65535 we wrap */
+ else if ( in_time_sequence &&
+ ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
+ ) {
+ statinfo->seq_num = rtpinfo->info_seq_num;
+ }
+ /* Lost packets. If the prev seq is enormously larger than the cur seq
+ * we assume that instead of being massively late we lost the packet(s)
+ * that would have indicated the sequence number wrapping. An imprecise
+ * heuristic at best, but it seems to work well enough.
+ * https://gitlab.com/wireshark/wireshark/-/issues/5958 */
+ else if ( in_time_sequence &&
+ (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00)
+ ) {
+ statinfo->seq_num = rtpinfo->info_seq_num;
+ statinfo->sequence++;
+ statinfo->flags |= STAT_FLAG_WRONG_SEQ;
+ }
+ /* Late or duplicated */
+ else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
+ statinfo->sequence++;
+ statinfo->flags |= STAT_FLAG_WRONG_SEQ;
+ }
+
+ /* Check payload type */
+ if (rtpinfo->info_payload_type == PT_CN
+ || rtpinfo->info_payload_type == PT_CN_OLD)
+ statinfo->flags |= STAT_FLAG_PT_CN;
+ if (statinfo->pt == PT_CN
+ || statinfo->pt == PT_CN_OLD)
+ statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
+ if (rtpinfo->info_payload_type != statinfo->pt)
+ statinfo->flags |= STAT_FLAG_PT_CHANGE;
+ statinfo->pt = rtpinfo->info_payload_type;
+
+ /*
+ * Return for unknown payload types
+ * Ignore jitter calculation for clockrate = 0
+ */
+ if (statinfo->pt < 96 ){
+ clock_rate = get_clock_rate(statinfo->pt);
+ } else { /* Dynamic PT */
+ if ( rtpinfo->info_payload_type_str != NULL ) {
+ /* Is it a "telephone-event" ?
+ * Timestamp is not increased for telepone-event packets impacting
+ * calculation of Jitter Skew and clock drift.
+ * see 2.2.1 of RFC 4733
+ */
+ if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0) {
+ clock_rate = 0;
+ statinfo->flags |= STAT_FLAG_PT_T_EVENT;
+ } else {
+ if(rtpinfo->info_payload_rate !=0) {
+ clock_rate = rtpinfo->info_payload_rate;
+ } else {
+ clock_rate = get_dyn_pt_clock_rate(rtpinfo->info_payload_type_str);
+ }
+ }
+ } else {
+ clock_rate = 0;
+ }
+ }
+
+ /* diff/jitter/skew calculations are done just for in sequence packets */
+ /* Note, "in_time_sequence" just means relative to the first packet in
+ * stream (within 0x80000000), excluding packets that are before the first
+ * packet in timestamp (or implausibly far away.)
+ * XXX: Do we really need to exclude those? The underlying problem in
+ * #16330 was not allowing the time difference to be negative.
+ */
+ if ( in_time_sequence || TRUE ) {
+ /* XXX: We try to handle clock rate changes, but if the clock rate
+ * changed during a dropped packet (or if we go backwards because
+ * a packet is reorderd), it won't be quite right.
+ */
+ nominaltime_diff = (double)(TIMESTAMP_DIFFERENCE(statinfo->seq_timestamp, rtpinfo->info_timestamp));
+
+ /* Can only analyze defined sampling rates */
+ if (clock_rate != 0) {
+ statinfo->clock_rate = clock_rate;
+ /* Convert from sampling clock to ms */
+ nominaltime_diff = nominaltime_diff /(clock_rate/1000);
+
+ /* Calculate the current jitter(in ms) */
+ if (!statinfo->first_packet) {
+ expected_time = statinfo->time + nominaltime_diff;
+ current_diff = fabs(current_time - expected_time);
+ current_jitter = (15 * statinfo->jitter + current_diff) / 16;
+
+ statinfo->delta = current_time-(statinfo->time);
+ statinfo->jitter = current_jitter;
+ statinfo->diff = current_diff;
+ }
+ nominaltime = statinfo->lastnominaltime + nominaltime_diff;
+ arrivaltime = statinfo->lastarrivaltime + statinfo->delta;
+ /* Calculate skew, i.e. absolute jitter that also catches clock drift
+ * Skew is positive if TS (nominal) is too fast
+ */
+ statinfo->skew = nominaltime - arrivaltime;
+ absskew = fabs(statinfo->skew);
+ if (absskew > fabs(statinfo->max_skew)) {
+ statinfo->max_skew = statinfo->skew;
+ }
+ /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
+ #if 0
+ if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
+ /* Skip first packet and possibly alternate payload type packets */
+ double dt;
+ dt = nominaltime - statinfo->lastnominaltime;
+ sumdt += 1.0 * dt;
+ numdt += (dt != 0 ? 1 : 0);
+ mindt = (dt < mindt ? dt : mindt);
+ maxdt = (dt > maxdt ? dt : maxdt);
+ }
+ #endif
+ /* Gather data for calculation of skew least square */
+ statinfo->sumt += 1.0 * arrivaltime;
+ statinfo->sumTS += 1.0 * nominaltime;
+ statinfo->sumt2 += 1.0 * arrivaltime * arrivaltime;
+ statinfo->sumtTS += 1.0 * arrivaltime * nominaltime;
+ statinfo->lastnominaltime = nominaltime;
+ statinfo->lastarrivaltime = arrivaltime;
+ } else {
+ if (!statinfo->first_packet) {
+ statinfo->delta = current_time-(statinfo->time);
+ }
+ }
+ }
+
+ /* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP) + 8bytes(UDP) */
+ if (pinfo->net_src.type == AT_IPv6) {
+ statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
+ } else {
+ statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
+ }
+ statinfo->bw_history[statinfo->bw_index].time = current_time;
+
+ /* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
+ while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
+ statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
+ statinfo->bw_start_index++;
+ if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
+ };
+ /* IP hdr + UDP + RTP */
+ if (pinfo->net_src.type == AT_IPv6){
+ statinfo->total_bytes += rtpinfo->info_data_len + 48;
+ }else{
+ statinfo->total_bytes += rtpinfo->info_data_len + 28;
+ }
+ statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
+ statinfo->bw_index++;
+ if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
+
+
+ /* Is it a packet with the mark bit set? */
+ if (rtpinfo->info_marker_set) {
+ statinfo->flags |= STAT_FLAG_MARKER;
+ }
+
+ /* Is it a regular packet? */
+ if (!(statinfo->flags & STAT_FLAG_FIRST)
+ && !(statinfo->flags & STAT_FLAG_MARKER)
+ && !(statinfo->flags & STAT_FLAG_PT_CN)
+ && !(statinfo->flags & STAT_FLAG_WRONG_TIMESTAMP)
+ && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
+ /* Include it in maximum delta calculation */
+ if (statinfo->delta > statinfo->max_delta) {
+ statinfo->max_delta = statinfo->delta;
+ statinfo->max_nr = pinfo->num;
+ }
+ /* Include it in minimum delta calculation */
+ if (statinfo->min_delta == -1 ) {
+ statinfo->min_delta = statinfo->delta;
+ } else if (statinfo->delta < statinfo->min_delta) {
+ statinfo->min_delta = statinfo->delta;
+ }
+ /* Mean delta calculation; average over the deltas between packets.
+ * For N packets there are N-1 deltas between them. The first packet
+ * has total_nr == 1, but here while we're processing the Nth
+ * packet, total_nr isn't incremented yet.
+ * E.g., when we arrive here and total_nr == 1, we're actually on
+ * packet #2, and thus, the first delta. So interestingly, when we
+ * divide by total_nr here, we're not dividing by the number of
+ * packets, but by the number of deltas.
+ * Important: total_nr here is never 0; when the first packet is
+ * handled, that logic increments total_nr from 0 to 1; here, it is
+ * always >=1 .
+ */
+ statinfo->mean_delta = (statinfo->mean_delta*(statinfo->total_nr-1) + statinfo->delta) / statinfo->total_nr;
+
+ if (clock_rate != 0) {
+ /* Maximum and mean jitter calculation */
+ if (statinfo->jitter > statinfo->max_jitter) {
+ statinfo->max_jitter = statinfo->jitter;
+ }
+ /* Mean jitter calculation; average over the diffs between packets.
+ * For N packets there are N-1 diffs between them. The first packet
+ * has total_nr == 1, but here while we're processing the Nth
+ * packet, total_nr isn't incremented yet.
+ * E.g., when we arrive here and total_nr == 1, we're actually on
+ * packet #2, and thus, the first diff. So interestingly, when we
+ * divide by total_nr here, we're not dividing by the number of
+ * packets, but by the number of diffs.
+ * Important: total_nr here is never 0; when the first packet is
+ * handled, that logic increments total_nr from 0 to 1; here, it is
+ * always >=1 .
+ */
+ statinfo->mean_jitter = (statinfo->mean_jitter*(statinfo->total_nr-1) + current_jitter) / statinfo->total_nr;
+
+ /* Minimum jitter calculation */
+ if (statinfo->min_jitter == -1 ) {
+ statinfo->min_jitter = statinfo->jitter;
+ } else if (statinfo->jitter < statinfo->min_jitter) {
+ statinfo->min_jitter = statinfo->jitter;
+ }
+ }
+ }
+ /* Regular payload change? (CN ignored) */
+ if (!(statinfo->flags & STAT_FLAG_FIRST)
+ && !(statinfo->flags & STAT_FLAG_PT_CN)) {
+ if ((statinfo->pt != statinfo->reg_pt)
+ && (statinfo->reg_pt != PT_UNDEFINED)) {
+ statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
+ }
+ }
+
+ /* Set regular payload*/
+ if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
+ statinfo->reg_pt = statinfo->pt;
+ }
+
+ if (in_time_sequence) {
+ /* We remember last time just for in_time sequence packets
+ * therefore diff calculations are correct for it
+ */
+ statinfo->time = current_time;
+ statinfo->seq_timestamp = rtpinfo->info_timestamp;
+ }
+ statinfo->timestamp = rtpinfo->info_timestamp;
+ statinfo->stop_seq_nr = rtpinfo->info_seq_num;
+ statinfo->total_nr++;
+ statinfo->last_payload_len = rtpinfo->info_payload_len;
+
+ return;
+}