White space changes.
[obnox/wireshark/wip.git] / tap-rtp-common.c
index de49e03d20f77cc9b7efba6a638ad4a3cfff8775..206fd61db04733005520ddf6501f481ff743411b 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2008, Ericsson AB
  * By Balint Reczey <balint.reczey@ericsson.com>
  *
- * most functions are copied from gtk/rtp_stream.c and gtk/rtp_analisys.c
+ * most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analisys.c
  * Copyright 2003, Alcatel Business Systems
  * By Lars Ruoff <lars.ruoff@gmx.net>
  *
 # include "config.h"
 #endif
 
+#include <stdio.h>
 #include <math.h>
 #include "globals.h"
 
 #include <epan/tap.h>
-#include "register.h"
 #include <string.h>
 #include <epan/rtp_pt.h>
 #include <epan/addr_resolv.h>
 #include <epan/dissectors/packet-rtp.h>
-#include "gtk/rtp_stream.h"
+#include "ui/gtk/rtp_stream.h"
 #include "tap-rtp-common.h"
 
-
+/* XXX: are changes needed to properly handle situations where
+        info_all_data_present == FALSE ?
+        E.G., when captured frames are truncated.
+ */
 
 /****************************************************************************/
 /* GCompareFunc style comparison function for _rtp_stream_info */
@@ -130,7 +133,7 @@ void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
        size_t sourcelen;
        guint16 port;          /* UDP port */
        guint16 padding;       /* 2 padding bytes */
-       
+
        fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
                get_addr_name(&(strinfo->dest_addr)),
                strinfo->dest_port);
@@ -204,7 +207,7 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
        tmp_strinfo.info_payload_type_str = rtpinfo->info_payload_type_str;
 
        if (tapinfo->mode == TAP_ANALYSE) {
-               /* check wether we already have a stream with these parameters in the list */
+               /* check whether we already have a stream with these parameters in the list */
                list = g_list_first(tapinfo->strinfo_list);
                while (list)
                {
@@ -279,14 +282,14 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
 
                /* increment the packets counter of all streams */
                ++(tapinfo->npackets);
-               
+
                return 1;  /* refresh output */
        }
        else if (tapinfo->mode == TAP_SAVE) {
                if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0) {
                        /* XXX - what if rtpinfo->info_all_data_present is
                           FALSE, so that we don't *have* all the data? */
-                       sample.header.rec_time = 
+                       sample.header.rec_time =
                                (pinfo->fd->abs_ts.nsecs/1000 + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
                                + (guint32) (pinfo->fd->abs_ts.secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
                        sample.header.frame_length = rtpinfo->info_data_len;
@@ -294,15 +297,15 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        rtp_write_sample(&sample, tapinfo->save_file);
                }
        }
+#ifdef __GTK_H__
        else if (tapinfo->mode == TAP_MARK) {
-
                if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0
                        || rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_rev)==0)
                {
                        cf_mark_frame(&cfile, pinfo->fd);
                }
        }
-
+#endif
        return 0;
 }
 
@@ -357,7 +360,7 @@ get_clock_rate(guint32 key)
                if (clock_map[i].key == key)
                        return clock_map[i].value;
        }
-       return 1;
+       return 0;
 }
 
 typedef struct _mimetype_and_clock {
@@ -399,7 +402,7 @@ static const mimetype_and_clock mimetype_and_clock_map[] = {
        {"GSM-EFR",     8000},                  /* [RFC3551] */
        {"H263-1998",   90000},         /* [RFC2429],[RFC3555] */
        {"H263-2000",   90000},         /* [RFC2429],[RFC3555] */
-       {"H264", 90000},            /* [RFC3984] */
+       {"H264",        90000},         /* [RFC3984] */
        {"MP1S",        90000},                 /* [RFC2250],[RFC3555] */
        {"MP2P",        90000},                 /* [RFC2250],[RFC3555] */
        {"MP4V-ES",     90000},                 /* [RFC3016] */
@@ -419,7 +422,7 @@ static guint32
 get_dyn_pt_clock_rate(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--) {
@@ -427,7 +430,7 @@ get_dyn_pt_clock_rate(gchar *payload_type_str)
                        return mimetype_and_clock_map[i].value;
        }
 
-       return 1;
+       return 0;
 }
 
 /****************************************************************************/
@@ -437,11 +440,110 @@ int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
 {
        double current_time;
        double current_jitter;
-       double current_diff;
+       double current_diff = 0;
+       double nominaltime;
+       double arrivaltime;             /* Time relative to start_time */
+       double expected_time;
+       double absskew;
        guint32 clock_rate;
 
+       /* Store the current time */
+       current_time = nstime_to_msec(&pinfo->fd->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->first_timestamp = rtpinfo->info_timestamp;
+               statinfo->time = current_time;
+               statinfo->lastnominaltime = 0;
+               statinfo->pt = rtpinfo->info_payload_type;
+               statinfo->reg_pt = rtpinfo->info_payload_type;
+               statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
+               statinfo->bw_history[statinfo->bw_index].time = current_time;
+               statinfo->bw_index++;
+               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->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 = FALSE;
+               return 0;
+       }
+
+       /* Reset flags */
        statinfo->flags = 0;
-       /* check payload type */
+
+       /* When calculating expected rtp packets the seq number can wrap around
+        * so we have to count the number of cycles
+        * Variable 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.
+        */
+
+       /* 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) && (statinfo->under == FALSE)){
+               statinfo->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) &&
+               (statinfo->under == FALSE)){
+               statinfo->cycles++;
+               statinfo->under = TRUE;
+       }
+       /* the whole round is over, so reset the flag */
+       else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (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 ( (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. XXX same problem as above: if seq 65535 or 0 is lost... */
+       else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
+               statinfo->seq_num = rtpinfo->info_seq_num;
+       /* Lost packets */
+       else if (statinfo->seq_num+1 < rtpinfo->info_seq_num) {
+               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;
@@ -451,54 +553,107 @@ int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
        if (rtpinfo->info_payload_type != statinfo->pt)
                statinfo->flags |= STAT_FLAG_PT_CHANGE;
        statinfo->pt = rtpinfo->info_payload_type;
+
        /*
-        * XXX - should "get_clock_rate()" return 0 for unknown
-        * payload types, presumably meaning that we should
-        * just ignore this packet?
+        * Return 0 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 )
-                       clock_rate = get_dyn_pt_clock_rate(rtpinfo-> info_payload_type_str);
-               else
-                       clock_rate = 1;
+       }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;
+               }
        }
 
-       /* store the current time and calculate the current jitter */
-       current_time = nstime_to_sec(&pinfo->fd->rel_ts);
-       current_diff = fabs (current_time - (statinfo->time) - ((double)(rtpinfo->info_timestamp)-(double)(statinfo->timestamp))/clock_rate);
-       current_jitter = statinfo->jitter + ( current_diff - statinfo->jitter)/16;
-       statinfo->delta = current_time-(statinfo->time);
-       statinfo->jitter = current_jitter;
-       statinfo->diff = current_diff;
+               /* Handle wraparound ? */
+       arrivaltime = current_time - statinfo->start_time;
+
+       if (statinfo->first_timestamp > rtpinfo->info_timestamp){
+               /* Handle wraparound */
+               nominaltime = (double)(rtpinfo->info_timestamp + 0xffffffff - statinfo->first_timestamp + 1);
+       }else{
+               nominaltime = (double)(rtpinfo->info_timestamp - statinfo->first_timestamp);
+       }
+
+       /* Can only analyze defined sampling rates */
+    if (clock_rate != 0) {
+               statinfo->clock_rate = clock_rate;
+               /* Convert from sampling clock to ms */
+               nominaltime = nominaltime /(clock_rate/1000);
+
+               /* Calculate the current jitter(in ms) */
+               if (!statinfo->first_packet) {
+                       expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
+                       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;
+               }
+               statinfo->lastnominaltime = nominaltime;
+               /* 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 * current_time;
+               statinfo->sumTS  += 1.0 * nominaltime;
+               statinfo->sumt2  += 1.0 * current_time * current_time;
+               statinfo->sumtTS += 1.0 * current_time * nominaltime;
+       }
 
-       /* calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP)+8bytes(UDP) = 28bytes */
-       statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
+       /* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> IP header+8bytes(UDP) */
+       statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + pinfo->iphdrlen + 8;
        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+1)<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;
        };
-       statinfo->total_bytes += rtpinfo->info_data_len + 28;
+       /* IP hdr + UDP + RTP */
+       statinfo->total_bytes += rtpinfo->info_data_len + pinfo->iphdrlen + 8;
        statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
        statinfo->bw_index++;
        if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
 
 
-       /*  is this the first packet we got in this direction? */
-       if (statinfo->first_packet) {
-               statinfo->start_seq_nr = rtpinfo->info_seq_num;
-               statinfo->start_time = current_time;
-               statinfo->delta = 0;
-               statinfo->jitter = 0;
-               statinfo->diff = 0;
-               statinfo->flags |= STAT_FLAG_FIRST;
-               statinfo->first_packet = FALSE;
-       }
-       /* is it a packet with the mark bit set? */
+       /* Is it a packet with the mark bit set? */
        if (rtpinfo->info_marker_set) {
                statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
                if (rtpinfo->info_timestamp > statinfo->timestamp){
@@ -508,24 +663,26 @@ int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
                        statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
                }
        }
-       /* is it a regular packet? */
+       /* 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 */
+               /* Include it in maximum delta calculation */
                if (statinfo->delta > statinfo->max_delta) {
                        statinfo->max_delta = statinfo->delta;
                        statinfo->max_nr = pinfo->fd->num;
                }
-               /* maximum and mean jitter calculation */
-               if (statinfo->jitter > statinfo->max_jitter) {
-                       statinfo->max_jitter = statinfo->jitter;
+               if (clock_rate != 0) {
+                       /* Maximum and mean jitter calculation */
+                       if (statinfo->jitter > statinfo->max_jitter) {
+                               statinfo->max_jitter = statinfo->jitter;
+                       }
+                       statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
                }
-               statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
        }
-       /* regular payload change? (CN ignored) */
+       /* Regular payload change? (CN ignored) */
        if (!(statinfo->flags & STAT_FLAG_FIRST)
                && !(statinfo->flags & STAT_FLAG_PT_CN)) {
                if ((statinfo->pt != statinfo->reg_pt)
@@ -534,66 +691,11 @@ int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
                }
        }
 
-       /* set regular payload*/
+       /* Set regular payload*/
        if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
                statinfo->reg_pt = statinfo->pt;
        }
 
-
-       /* When calculating expected rtp packets the seq number can wrap around
-       * so we have to count the number of cycles
-       * Variable 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.
-       */
-
-       /* 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) && (statinfo->under == FALSE)){
-               statinfo->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) &&
-               (statinfo->under == FALSE)){
-               statinfo->cycles++;
-               statinfo->under = TRUE;
-       }
-       /* the whole round is over, so reset the flag */
-       else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (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 ( (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. XXX same problem as above: if seq 65535 or 0 is lost... */
-       else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
-               statinfo->seq_num = rtpinfo->info_seq_num;
-       /* lost packets */
-       else if (statinfo->seq_num+1 < rtpinfo->info_seq_num) {
-               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;
-       }
        statinfo->time = current_time;
        statinfo->timestamp = rtpinfo->info_timestamp;
        statinfo->stop_seq_nr = rtpinfo->info_seq_num;