2 * RTP stream handler functions used by tshark and wireshark
6 * Copyright 2008, Ericsson AB
7 * By Balint Reczey <balint.reczey@ericsson.com>
9 * most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analisys.c
10 * Copyright 2003, Alcatel Business Systems
11 * By Lars Ruoff <lars.ruoff@gmx.net>
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #include <epan/rtp_pt.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/dissectors/packet-rtp.h>
45 #include "ui/gtk/rtp_stream.h"
46 #include "tap-rtp-common.h"
48 /* XXX: are changes needed to properly handle situations where
49 info_all_data_present == FALSE ?
50 E.G., when captured frames are truncated.
53 /****************************************************************************/
54 /* GCompareFunc style comparison function for _rtp_stream_info */
55 gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
57 const struct _rtp_stream_info* a = aa;
58 const struct _rtp_stream_info* b = bb;
62 if (a==NULL || b==NULL)
64 if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
65 && (a->src_port == b->src_port)
66 && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
67 && (a->dest_port == b->dest_port)
68 && (a->ssrc == b->ssrc))
75 /****************************************************************************/
76 /* when there is a [re]reading of packet's */
77 void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
81 if (tapinfo->mode == TAP_ANALYSE) {
82 /* free the data items first */
83 list = g_list_first(tapinfo->strinfo_list);
87 list = g_list_next(list);
89 g_list_free(tapinfo->strinfo_list);
90 tapinfo->strinfo_list = NULL;
91 tapinfo->nstreams = 0;
92 tapinfo->npackets = 0;
95 ++(tapinfo->launch_count);
100 void rtpstream_reset_cb(void *arg)
102 rtpstream_reset(arg);
106 * rtpdump file format
108 * The file starts with the tool to be used for playing this file,
109 * the multicast/unicast receive address and the port.
111 * #!rtpplay1.0 224.2.0.1/3456\n
113 * This is followed by one binary header (RD_hdr_t) and one RD_packet_t
114 * structure for each received packet. All fields are in network byte
115 * order. We don't need the source IP address since we can do mapping
116 * based on SSRC. This saves (a little) space, avoids non-IPv4
117 * problems and privacy/security concerns. The header is followed by
118 * the RTP/RTCP header and (optionally) the actual payload.
121 #define RTPFILE_VERSION "1.0"
124 * Write a header to the current output file.
125 * The header consists of an identifying string, followed
126 * by a binary structure.
128 void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
130 guint32 start_sec; /* start of recording (GMT) (seconds) */
131 guint32 start_usec; /* start of recording (GMT) (microseconds)*/
132 guint32 source; /* network source (multicast address) */
134 guint16 port; /* UDP port */
135 guint16 padding; /* 2 padding bytes */
137 fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
138 get_addr_name(&(strinfo->dest_addr)),
141 start_sec = g_htonl(strinfo->start_sec);
142 start_usec = g_htonl(strinfo->start_usec);
143 /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
144 memset(&source, 0, sizeof source);
145 sourcelen = strinfo->src_addr.len;
146 if (sourcelen > sizeof source)
147 sourcelen = sizeof source;
148 memcpy(&source, strinfo->src_addr.data, sourcelen);
149 port = g_htons(strinfo->src_port);
152 if (fwrite(&start_sec, 4, 1, file) == 0)
154 if (fwrite(&start_usec, 4, 1, file) == 0)
156 if (fwrite(&source, 4, 1, file) == 0)
158 if (fwrite(&port, 2, 1, file) == 0)
160 if (fwrite(&padding, 2, 1, file) == 0)
164 /* utility function for writing a sample to file in rtpdump -F dump format (.rtp)*/
165 void rtp_write_sample(rtp_sample_t* sample, FILE* file)
167 guint16 length; /* length of packet, including this header (may
168 be smaller than plen if not whole packet recorded) */
169 guint16 plen; /* actual header+payload length for RTP, 0 for RTCP */
170 guint32 offset; /* milliseconds since the start of recording */
172 length = g_htons(sample->header.frame_length + 8);
173 plen = g_htons(sample->header.frame_length);
174 offset = g_htonl(sample->header.rec_time);
176 if (fwrite(&length, 2, 1, file) == 0)
178 if (fwrite(&plen, 2, 1, file) == 0)
180 if (fwrite(&offset, 4, 1, file) == 0)
182 if (fwrite(sample->frame, sample->header.frame_length, 1, file) == 0)
187 /****************************************************************************/
188 /* whenever a RTP packet is seen by the tap listener */
189 int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
191 rtpstream_tapinfo_t *tapinfo = arg;
192 const struct _rtp_info *rtpinfo = arg2;
193 rtp_stream_info_t tmp_strinfo;
194 rtp_stream_info_t *strinfo = NULL;
198 struct _rtp_conversation_info *p_conv_data = NULL;
200 /* gather infos on the stream this packet is part of */
201 COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
202 tmp_strinfo.src_port = pinfo->srcport;
203 COPY_ADDRESS(&(tmp_strinfo.dest_addr), &(pinfo->dst));
204 tmp_strinfo.dest_port = pinfo->destport;
205 tmp_strinfo.ssrc = rtpinfo->info_sync_src;
206 tmp_strinfo.pt = rtpinfo->info_payload_type;
207 tmp_strinfo.info_payload_type_str = rtpinfo->info_payload_type_str;
209 if (tapinfo->mode == TAP_ANALYSE) {
210 /* check whether we already have a stream with these parameters in the list */
211 list = g_list_first(tapinfo->strinfo_list);
214 if (rtp_stream_info_cmp(&tmp_strinfo, (rtp_stream_info_t*)(list->data))==0)
216 strinfo = (rtp_stream_info_t*)(list->data); /*found!*/
219 list = g_list_next(list);
222 /* not in the list? then create a new entry */
224 tmp_strinfo.npackets = 0;
225 tmp_strinfo.first_frame_num = pinfo->fd->num;
226 tmp_strinfo.start_sec = (guint32) pinfo->fd->abs_ts.secs;
227 tmp_strinfo.start_usec = pinfo->fd->abs_ts.nsecs/1000;
228 tmp_strinfo.start_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
229 tmp_strinfo.start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
230 tmp_strinfo.tag_vlan_error = 0;
231 tmp_strinfo.tag_diffserv_error = 0;
232 tmp_strinfo.vlan_id = 0;
233 tmp_strinfo.problem = FALSE;
235 /* reset RTP stats */
236 tmp_strinfo.rtp_stats.first_packet = TRUE;
237 tmp_strinfo.rtp_stats.max_delta = 0;
238 tmp_strinfo.rtp_stats.max_jitter = 0;
239 tmp_strinfo.rtp_stats.mean_jitter = 0;
240 tmp_strinfo.rtp_stats.delta = 0;
241 tmp_strinfo.rtp_stats.diff = 0;
242 tmp_strinfo.rtp_stats.jitter = 0;
243 tmp_strinfo.rtp_stats.bandwidth = 0;
244 tmp_strinfo.rtp_stats.total_bytes = 0;
245 tmp_strinfo.rtp_stats.bw_start_index = 0;
246 tmp_strinfo.rtp_stats.bw_index = 0;
247 tmp_strinfo.rtp_stats.timestamp = 0;
248 tmp_strinfo.rtp_stats.max_nr = 0;
249 tmp_strinfo.rtp_stats.total_nr = 0;
250 tmp_strinfo.rtp_stats.sequence = 0;
251 tmp_strinfo.rtp_stats.start_seq_nr = 0;
252 tmp_strinfo.rtp_stats.stop_seq_nr = 0;
253 tmp_strinfo.rtp_stats.cycles = 0;
254 tmp_strinfo.rtp_stats.under = FALSE;
255 tmp_strinfo.rtp_stats.start_time = 0;
256 tmp_strinfo.rtp_stats.time = 0;
257 tmp_strinfo.rtp_stats.reg_pt = PT_UNDEFINED;
259 /* Get the Setup frame number who set this RTP stream */
260 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
262 tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
264 tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
266 strinfo = g_malloc(sizeof(rtp_stream_info_t));
267 *strinfo = tmp_strinfo; /* memberwise copy of struct */
268 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
271 /* get RTP stats for the packet */
272 rtp_packet_analyse(&(strinfo->rtp_stats), pinfo, rtpinfo);
273 if (strinfo->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
274 || strinfo->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
275 strinfo->problem = TRUE;
278 /* increment the packets counter for this stream */
279 ++(strinfo->npackets);
280 strinfo->stop_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
281 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
283 /* increment the packets counter of all streams */
284 ++(tapinfo->npackets);
286 return 1; /* refresh output */
288 else if (tapinfo->mode == TAP_SAVE) {
289 if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0) {
290 /* XXX - what if rtpinfo->info_all_data_present is
291 FALSE, so that we don't *have* all the data? */
292 sample.header.rec_time =
293 (pinfo->fd->abs_ts.nsecs/1000 + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
294 + (guint32) (pinfo->fd->abs_ts.secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
295 sample.header.frame_length = rtpinfo->info_data_len;
296 sample.frame = rtpinfo->info_data;
297 rtp_write_sample(&sample, tapinfo->save_file);
301 else if (tapinfo->mode == TAP_MARK) {
302 if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0
303 || rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_rev)==0)
305 cf_mark_frame(&cfile, pinfo->fd);
313 typedef struct _key_value {
319 /* RTP sampling clock rates for fixed payload types as defined in
320 http://www.iana.org/assignments/rtp-parameters */
321 static const key_value clock_map[] = {
327 {PT_DVI4_8000, 8000},
328 {PT_DVI4_16000, 16000},
332 {PT_L16_STEREO, 44100},
333 {PT_L16_MONO, 44100},
339 {PT_DVI4_11025, 11025},
340 {PT_DVI4_22050, 22050},
352 #define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
355 get_clock_rate(guint32 key)
359 for (i = 0; i < NUM_CLOCK_VALUES; i++) {
360 if (clock_map[i].key == key)
361 return clock_map[i].value;
366 typedef struct _mimetype_and_clock {
367 const gchar *pt_mime_name_str;
369 } mimetype_and_clock;
370 /* RTP sampling clock rates for
371 "In addition to the RTP payload formats (encodings) listed in the RTP
372 Payload Types table, there are additional payload formats that do not
373 have static RTP payload types assigned but instead use dynamic payload
374 type number assignment. Each payload format is named by a registered
376 http://www.iana.org/assignments/rtp-parameters.
378 NOTE: Please keep the mimetypes in case insensitive alphabetical order.
380 static const mimetype_and_clock mimetype_and_clock_map[] = {
381 {"AMR", 8000}, /* [RFC4867][RFC3267] */
382 {"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
383 {"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
384 {"BT656", 90000}, /* [RFC2431],[RFC3555] */
385 {"DV", 90000}, /* [RFC3189] */
386 {"EVRC", 8000}, /* [RFC3558] */
387 {"EVRC0", 8000}, /* [RFC4788] */
388 {"EVRC1", 8000}, /* [RFC4788] */
389 {"EVRCB", 8000}, /* [RFC4788] */
390 {"EVRCB0", 8000}, /* [RFC4788] */
391 {"EVRCB1", 8000}, /* [RFC4788] */
392 {"EVRCWB", 16000}, /* [RFC5188] */
393 {"EVRCWB0", 16000}, /* [RFC5188] */
394 {"EVRCWB1", 16000}, /* [RFC5188] */
395 {"G7221", 16000}, /* [RFC3047] */
396 {"G726-16", 8000}, /* [RFC3551][RFC4856] */
397 {"G726-24", 8000}, /* [RFC3551][RFC4856] */
398 {"G726-32", 8000}, /* [RFC3551][RFC4856] */
399 {"G726-40", 8000}, /* [RFC3551][RFC4856] */
400 {"G729D", 8000}, /* [RFC3551][RFC4856] */
401 {"G729E", 8000}, /* [RFC3551][RFC4856] */
402 {"GSM-EFR", 8000}, /* [RFC3551] */
403 {"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
404 {"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
405 {"H264", 90000}, /* [RFC3984] */
406 {"MP1S", 90000}, /* [RFC2250],[RFC3555] */
407 {"MP2P", 90000}, /* [RFC2250],[RFC3555] */
408 {"MP4V-ES", 90000}, /* [RFC3016] */
409 {"mpa-robust", 90000}, /* [RFC3119] */
410 {"pointer", 90000}, /* [RFC2862] */
411 {"raw", 90000}, /* [RFC4175] */
412 {"red", 1000}, /* [RFC4102] */
413 {"SMV", 8000}, /* [RFC3558] */
414 {"SMV0", 8000}, /* [RFC3558] */
415 {"t140", 1000}, /* [RFC4103] */
416 {"telephone-event", 8000}, /* [RFC4733] */
419 #define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
422 get_dyn_pt_clock_rate(gchar *payload_type_str)
426 /* Search for matching mimetype in reverse order to avoid false matches
427 * when pt_mime_name_str is the prefix of payload_type_str */
428 for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
429 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)
430 return mimetype_and_clock_map[i].value;
436 /****************************************************************************/
437 int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
439 const struct _rtp_info *rtpinfo)
442 double current_jitter;
443 double current_diff = 0;
445 double arrivaltime; /* Time relative to start_time */
446 double expected_time;
450 /* Store the current time */
451 current_time = nstime_to_msec(&pinfo->fd->rel_ts);
453 /* Is this the first packet we got in this direction? */
454 if (statinfo->first_packet) {
455 statinfo->start_seq_nr = rtpinfo->info_seq_num;
456 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
457 statinfo->seq_num = rtpinfo->info_seq_num;
458 statinfo->start_time = current_time;
459 statinfo->timestamp = rtpinfo->info_timestamp;
460 statinfo->first_timestamp = rtpinfo->info_timestamp;
461 statinfo->time = current_time;
462 statinfo->lastnominaltime = 0;
463 statinfo->pt = rtpinfo->info_payload_type;
464 statinfo->reg_pt = rtpinfo->info_payload_type;
465 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
466 statinfo->bw_history[statinfo->bw_index].time = current_time;
467 statinfo->bw_index++;
468 statinfo->total_bytes += rtpinfo->info_data_len + 28;
469 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
470 /* Not needed ? initialised to zero? */
472 statinfo->jitter = 0;
475 statinfo->total_nr++;
476 statinfo->flags |= STAT_FLAG_FIRST;
477 if (rtpinfo->info_marker_set) {
478 statinfo->flags |= STAT_FLAG_MARKER;
480 statinfo->first_packet = FALSE;
487 /* When calculating expected rtp packets the seq number can wrap around
488 * so we have to count the number of cycles
489 * Variable cycles counts the wraps around in forwarding connection and
490 * under is flag that indicates where we are
492 * XXX How to determine number of cycles with all possible lost, late
493 * and duplicated packets without any doubt? It seems to me, that
494 * because of all possible combination of late, duplicated or lost
495 * packets, this can only be more or less good approximation
497 * There are some combinations (rare but theoretically possible),
498 * where below code won't work correctly - statistic may be wrong then.
501 /* So if the current sequence number is less than the start one
502 * we assume, that there is another cycle running
504 if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
506 statinfo->under = TRUE;
508 /* what if the start seq nr was 0? Then the above condition will never
509 * be true, so we add another condition. XXX The problem would arise
510 * if one of the packets with seq nr 0 or 65535 would be lost or late
512 else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
513 (statinfo->under == FALSE)){
515 statinfo->under = TRUE;
517 /* the whole round is over, so reset the flag */
518 else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
519 statinfo->under = FALSE;
522 /* Since it is difficult to count lost, duplicate or late packets separately,
523 * we would like to know at least how many times the sequence number was not ok
526 /* If the current seq number equals the last one or if we are here for
527 * the first time, then it is ok, we just store the current one as the last one
529 if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
530 statinfo->seq_num = rtpinfo->info_seq_num;
531 /* If the first one is 65535. XXX same problem as above: if seq 65535 or 0 is lost... */
532 else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
533 statinfo->seq_num = rtpinfo->info_seq_num;
535 else if (statinfo->seq_num+1 < rtpinfo->info_seq_num) {
536 statinfo->seq_num = rtpinfo->info_seq_num;
537 statinfo->sequence++;
538 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
540 /* Late or duplicated */
541 else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
542 statinfo->sequence++;
543 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
546 /* Check payload type */
547 if (rtpinfo->info_payload_type == PT_CN
548 || rtpinfo->info_payload_type == PT_CN_OLD)
549 statinfo->flags |= STAT_FLAG_PT_CN;
550 if (statinfo->pt == PT_CN
551 || statinfo->pt == PT_CN_OLD)
552 statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
553 if (rtpinfo->info_payload_type != statinfo->pt)
554 statinfo->flags |= STAT_FLAG_PT_CHANGE;
555 statinfo->pt = rtpinfo->info_payload_type;
558 * Return 0 for unknown payload types
559 * Ignore jitter calculation for clockrate = 0
561 if (statinfo->pt < 96 ){
562 clock_rate = get_clock_rate(statinfo->pt);
563 }else{ /* Dynamic PT */
564 if ( rtpinfo->info_payload_type_str != NULL ){
565 /* Is it a "telephone-event" ?
566 * Timestamp is not increased for telepone-event packets impacting
567 * calculation of Jitter Skew and clock drift.
568 * see 2.2.1 of RFC 4733
570 if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0){
572 statinfo->flags |= STAT_FLAG_PT_T_EVENT;
574 if(rtpinfo->info_payload_rate !=0){
575 clock_rate = rtpinfo->info_payload_rate;
577 clock_rate = get_dyn_pt_clock_rate(rtpinfo-> info_payload_type_str);
585 /* Handle wraparound ? */
586 arrivaltime = current_time - statinfo->start_time;
588 if (statinfo->first_timestamp > rtpinfo->info_timestamp){
589 /* Handle wraparound */
590 nominaltime = (double)(rtpinfo->info_timestamp + 0xffffffff - statinfo->first_timestamp + 1);
592 nominaltime = (double)(rtpinfo->info_timestamp - statinfo->first_timestamp);
595 /* Can only analyze defined sampling rates */
596 if (clock_rate != 0) {
597 statinfo->clock_rate = clock_rate;
598 /* Convert from sampling clock to ms */
599 nominaltime = nominaltime /(clock_rate/1000);
601 /* Calculate the current jitter(in ms) */
602 if (!statinfo->first_packet) {
603 expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
604 current_diff = fabs(current_time - expected_time);
605 current_jitter = (15 * statinfo->jitter + current_diff) / 16;
607 statinfo->delta = current_time-(statinfo->time);
608 statinfo->jitter = current_jitter;
609 statinfo->diff = current_diff;
611 statinfo->lastnominaltime = nominaltime;
612 /* Calculate skew, i.e. absolute jitter that also catches clock drift
613 * Skew is positive if TS (nominal) is too fast
615 statinfo->skew = nominaltime - arrivaltime;
616 absskew = fabs(statinfo->skew);
617 if(absskew > fabs(statinfo->max_skew)){
618 statinfo->max_skew = statinfo->skew;
620 /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
622 if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
623 /* Skip first packet and possibly alternate payload type packets */
625 dt = nominaltime - statinfo->lastnominaltime;
627 numdt += (dt != 0 ? 1 : 0);
628 mindt = (dt < mindt ? dt : mindt);
629 maxdt = (dt > maxdt ? dt : maxdt);
632 /* Gather data for calculation of skew least square */
633 statinfo->sumt += 1.0 * current_time;
634 statinfo->sumTS += 1.0 * nominaltime;
635 statinfo->sumt2 += 1.0 * current_time * current_time;
636 statinfo->sumtTS += 1.0 * current_time * nominaltime;
639 /* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> IP header+8bytes(UDP) */
640 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + pinfo->iphdrlen + 8;
641 statinfo->bw_history[statinfo->bw_index].time = current_time;
643 /* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
644 while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
645 statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
646 statinfo->bw_start_index++;
647 if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
649 /* IP hdr + UDP + RTP */
650 statinfo->total_bytes += rtpinfo->info_data_len + pinfo->iphdrlen + 8;
651 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
652 statinfo->bw_index++;
653 if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
656 /* Is it a packet with the mark bit set? */
657 if (rtpinfo->info_marker_set) {
658 statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
659 if (rtpinfo->info_timestamp > statinfo->timestamp){
660 statinfo->flags |= STAT_FLAG_MARKER;
663 statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
666 /* Is it a regular packet? */
667 if (!(statinfo->flags & STAT_FLAG_FIRST)
668 && !(statinfo->flags & STAT_FLAG_MARKER)
669 && !(statinfo->flags & STAT_FLAG_PT_CN)
670 && !(statinfo->flags & STAT_FLAG_WRONG_TIMESTAMP)
671 && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
672 /* Include it in maximum delta calculation */
673 if (statinfo->delta > statinfo->max_delta) {
674 statinfo->max_delta = statinfo->delta;
675 statinfo->max_nr = pinfo->fd->num;
677 if (clock_rate != 0) {
678 /* Maximum and mean jitter calculation */
679 if (statinfo->jitter > statinfo->max_jitter) {
680 statinfo->max_jitter = statinfo->jitter;
682 statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
685 /* Regular payload change? (CN ignored) */
686 if (!(statinfo->flags & STAT_FLAG_FIRST)
687 && !(statinfo->flags & STAT_FLAG_PT_CN)) {
688 if ((statinfo->pt != statinfo->reg_pt)
689 && (statinfo->reg_pt != PT_UNDEFINED)) {
690 statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
694 /* Set regular payload*/
695 if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
696 statinfo->reg_pt = statinfo->pt;
699 statinfo->time = current_time;
700 statinfo->timestamp = rtpinfo->info_timestamp;
701 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
702 statinfo->total_nr++;