nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* tap-rtp-common.c
2 * RTP stream handler functions used by tshark and wireshark
3 *
4 * Copyright 2008, Ericsson AB
5 * By Balint Reczey <balint.reczey@ericsson.com>
6 *
7 * most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analysis.c
8 * Copyright 2003, Alcatel Business Systems
9 * By Lars Ruoff <lars.ruoff@gmx.net>
10 *
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 */
29  
30 #include "config.h"
31  
32 #include <glib.h>
33  
34 #include <math.h>
35 #include "globals.h"
36  
37 #include <string.h>
38 #include <epan/rtp_pt.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/proto_data.h>
41 #include <epan/dissectors/packet-rtp.h>
42 #include "rtp_stream.h"
43 #include "tap-rtp-common.h"
44  
45 /* XXX: are changes needed to properly handle situations where
46 info_all_data_present == FALSE ?
47 E.G., when captured frames are truncated.
48 */
49  
50 /****************************************************************************/
51 /* Type for storing and writing rtpdump information */
52 typedef struct st_rtpdump_info {
53 double rec_time; /**< milliseconds since start of recording */
54 guint16 num_samples; /**< number of bytes in *frame */
55 const guint8 *samples; /**< data bytes */
56 } rtpdump_info_t;
57  
58 /****************************************************************************/
59 /* GCompareFunc style comparison function for _rtp_stream_info */
60 static gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
61 {
62 const struct _rtp_stream_info* a = (const struct _rtp_stream_info*)aa;
63 const struct _rtp_stream_info* b = (const struct _rtp_stream_info*)bb;
64  
65 if (a==b)
66 return 0;
67 if (a==NULL || b==NULL)
68 return 1;
69 if (addresses_equal(&(a->src_addr), &(b->src_addr))
70 && (a->src_port == b->src_port)
71 && addresses_equal(&(a->dest_addr), &(b->dest_addr))
72 && (a->dest_port == b->dest_port)
73 && (a->ssrc == b->ssrc))
74 return 0;
75 else
76 return 1;
77 }
78  
79  
80 /****************************************************************************/
81 /* when there is a [re]reading of packet's */
82 void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
83 {
84 GList* list;
85  
86 if (tapinfo->mode == TAP_ANALYSE) {
87 /* free the data items first */
88 list = g_list_first(tapinfo->strinfo_list);
89 while (list)
90 {
91 g_free(list->data);
92 list = g_list_next(list);
93 }
94 g_list_free(tapinfo->strinfo_list);
95 tapinfo->strinfo_list = NULL;
96 tapinfo->nstreams = 0;
97 tapinfo->npackets = 0;
98 }
99  
100 return;
101 }
102  
103 void rtpstream_reset_cb(void *arg)
104 {
105 rtpstream_tapinfo_t *ti =(rtpstream_tapinfo_t *)arg;
106 if (ti->tap_reset) {
107 /* Give listeners a chance to cleanup references. */
108 ti->tap_reset(ti);
109 }
110 rtpstream_reset(ti);
111 }
112  
113 /*
114 * rtpdump file format
115 *
116 * The file starts with the tool to be used for playing this file,
117 * the multicast/unicast receive address and the port.
118 *
119 * #!rtpplay1.0 224.2.0.1/3456\n
120 *
121 * This is followed by one binary header (RD_hdr_t) and one RD_packet_t
122 * structure for each received packet. All fields are in network byte
123 * order. We don't need the source IP address since we can do mapping
124 * based on SSRC. This saves (a little) space, avoids non-IPv4
125 * problems and privacy/security concerns. The header is followed by
126 * the RTP/RTCP header and (optionally) the actual payload.
127 */
128  
129 #define RTPFILE_VERSION "1.0"
130  
131 /*
132 * Write a header to the current output file.
133 * The header consists of an identifying string, followed
134 * by a binary structure.
135 */
136 void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
137 {
138 guint32 start_sec; /* start of recording (GMT) (seconds) */
139 guint32 start_usec; /* start of recording (GMT) (microseconds)*/
140 guint32 source; /* network source (multicast address) */
141 size_t sourcelen;
142 guint16 port; /* UDP port */
143 guint16 padding; /* 2 padding bytes */
144 char* addr_str = address_to_display(NULL, &(strinfo->dest_addr));
145  
146 fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
147 addr_str,
148 strinfo->dest_port);
149 wmem_free(NULL, addr_str);
150  
151 start_sec = g_htonl(strinfo->start_fd->abs_ts.secs);
152 start_usec = g_htonl(strinfo->start_fd->abs_ts.nsecs / 1000000);
153 /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
154 memset(&source, 0, sizeof source);
155 sourcelen = strinfo->src_addr.len;
156 if (sourcelen > sizeof source)
157 sourcelen = sizeof source;
158 memcpy(&source, strinfo->src_addr.data, sourcelen);
159 port = g_htons(strinfo->src_port);
160 padding = 0;
161  
162 if (fwrite(&start_sec, 4, 1, file) == 0)
163 return;
164 if (fwrite(&start_usec, 4, 1, file) == 0)
165 return;
166 if (fwrite(&source, 4, 1, file) == 0)
167 return;
168 if (fwrite(&port, 2, 1, file) == 0)
169 return;
170 if (fwrite(&padding, 2, 1, file) == 0)
171 return;
172 }
173  
174 /* utility function for writing a sample to file in rtpdump -F dump format (.rtp)*/
175 static void rtp_write_sample(rtpdump_info_t* rtpdump_info, FILE* file)
176 {
177 guint16 length; /* length of packet, including this header (may
178 be smaller than plen if not whole packet recorded) */
179 guint16 plen; /* actual header+payload length for RTP, 0 for RTCP */
180 guint32 offset; /* milliseconds since the start of recording */
181  
182 length = g_htons(rtpdump_info->num_samples + 8);
183 plen = g_htons(rtpdump_info->num_samples);
184 offset = g_htonl(rtpdump_info->rec_time);
185  
186 if (fwrite(&length, 2, 1, file) == 0)
187 return;
188 if (fwrite(&plen, 2, 1, file) == 0)
189 return;
190 if (fwrite(&offset, 4, 1, file) == 0)
191 return;
192 if (fwrite(rtpdump_info->samples, rtpdump_info->num_samples, 1, file) == 0)
193 return;
194 }
195  
196  
197 /****************************************************************************/
198 /* whenever a RTP packet is seen by the tap listener */
199 int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
200 {
201 rtpstream_tapinfo_t *tapinfo = (rtpstream_tapinfo_t *)arg;
202 const struct _rtp_info *rtpinfo = (const struct _rtp_info *)arg2;
203 rtp_stream_info_t new_stream_info;
204 rtp_stream_info_t *stream_info = NULL;
205 GList* list;
206 rtpdump_info_t rtpdump_info;
207  
208 struct _rtp_conversation_info *p_conv_data = NULL;
209  
210 /* gather infos on the stream this packet is part of */
211 memset(&new_stream_info, 0, sizeof(rtp_stream_info_t));
212 copy_address(&(new_stream_info.src_addr), &(pinfo->src));
213 new_stream_info.src_port = pinfo->srcport;
214 copy_address(&(new_stream_info.dest_addr), &(pinfo->dst));
215 new_stream_info.dest_port = pinfo->destport;
216 new_stream_info.ssrc = rtpinfo->info_sync_src;
217 new_stream_info.payload_type = rtpinfo->info_payload_type;
218 new_stream_info.payload_type_name = g_strdup(rtpinfo->info_payload_type_str);
219  
220 if (tapinfo->mode == TAP_ANALYSE) {
221 /* check whether we already have a stream with these parameters in the list */
222 list = g_list_first(tapinfo->strinfo_list);
223 while (list)
224 {
225 if (rtp_stream_info_cmp(&new_stream_info, (rtp_stream_info_t*)(list->data))==0)
226 {
227 stream_info = (rtp_stream_info_t*)(list->data); /*found!*/
228 break;
229 }
230 list = g_list_next(list);
231 }
232  
233 /* not in the list? then create a new entry */
234 if (!stream_info) {
235 new_stream_info.start_fd = pinfo->fd;
236 new_stream_info.start_rel_time = pinfo->rel_ts;
237  
238 /* reset RTP stats */
239 new_stream_info.rtp_stats.first_packet = TRUE;
240 new_stream_info.rtp_stats.reg_pt = PT_UNDEFINED;
241  
242 /* Get the Setup frame number who set this RTP stream */
243 p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name("rtp"), 0);
244 if (p_conv_data)
245 new_stream_info.setup_frame_number = p_conv_data->frame_number;
246 else
247 new_stream_info.setup_frame_number = 0xFFFFFFFF;
248  
249 stream_info = g_new(rtp_stream_info_t,1);
250 *stream_info = new_stream_info; /* memberwise copy of struct */
251 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, stream_info);
252 }
253  
254 /* get RTP stats for the packet */
255 rtp_packet_analyse(&(stream_info->rtp_stats), pinfo, rtpinfo);
256 if (stream_info->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
257 || stream_info->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
258 stream_info->problem = TRUE;
259  
260  
261 /* increment the packets counter for this stream */
262 ++(stream_info->packet_count);
263 stream_info->stop_rel_time = pinfo->rel_ts;
264  
265 /* increment the packets counter of all streams */
266 ++(tapinfo->npackets);
267  
268 return 1; /* refresh output */
269 }
270 else if (tapinfo->mode == TAP_SAVE) {
271 if (rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0) {
272 /* XXX - what if rtpinfo->info_all_data_present is
273 FALSE, so that we don't *have* all the data? */
274 rtpdump_info.rec_time = nstime_to_msec(&pinfo->abs_ts) -
275 nstime_to_msec(&tapinfo->filter_stream_fwd->start_fd->abs_ts);
276 rtpdump_info.num_samples = rtpinfo->info_data_len;
277 rtpdump_info.samples = rtpinfo->info_data;
278 rtp_write_sample(&rtpdump_info, tapinfo->save_file);
279 }
280 }
281 else if (tapinfo->mode == TAP_MARK && tapinfo->tap_mark_packet) {
282 if (rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0
283 || rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_rev)==0)
284 {
285 tapinfo->tap_mark_packet(tapinfo, pinfo->fd);
286 }
287 }
288 return 0;
289 }
290  
291  
292 typedef struct _key_value {
293 guint32 key;
294 guint32 value;
295 } key_value;
296  
297  
298 /* RTP sampling clock rates for fixed payload types as defined in
299 http://www.iana.org/assignments/rtp-parameters */
300 static const key_value clock_map[] = {
301 {PT_PCMU, 8000},
302 {PT_1016, 8000},
303 {PT_G721, 8000},
304 {PT_GSM, 8000},
305 {PT_G723, 8000},
306 {PT_DVI4_8000, 8000},
307 {PT_DVI4_16000, 16000},
308 {PT_LPC, 8000},
309 {PT_PCMA, 8000},
310 {PT_G722, 8000},
311 {PT_L16_STEREO, 44100},
312 {PT_L16_MONO, 44100},
313 {PT_QCELP, 8000},
314 {PT_CN, 8000},
315 {PT_MPA, 90000},
316 {PT_G728, 8000},
317 {PT_G728, 8000},
318 {PT_DVI4_11025, 11025},
319 {PT_DVI4_22050, 22050},
320 {PT_G729, 8000},
321 {PT_CN_OLD, 8000},
322 {PT_CELB, 90000},
323 {PT_JPEG, 90000},
324 {PT_NV, 90000},
325 {PT_H261, 90000},
326 {PT_MPV, 90000},
327 {PT_MP2T, 90000},
328 {PT_H263, 90000},
329 };
330  
331 #define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
332  
333 static guint32
334 get_clock_rate(guint32 key)
335 {
336 size_t i;
337  
338 for (i = 0; i < NUM_CLOCK_VALUES; i++) {
339 if (clock_map[i].key == key)
340 return clock_map[i].value;
341 }
342 return 0;
343 }
344  
345 typedef struct _mimetype_and_clock {
346 const gchar *pt_mime_name_str;
347 guint32 value;
348 } mimetype_and_clock;
349 /* RTP sampling clock rates for
350 "In addition to the RTP payload formats (encodings) listed in the RTP
351 Payload Types table, there are additional payload formats that do not
352 have static RTP payload types assigned but instead use dynamic payload
353 type number assignment. Each payload format is named by a registered
354 MIME subtype"
355 http://www.iana.org/assignments/rtp-parameters.
356  
357 NOTE: Please keep the mimetypes in case insensitive alphabetical order.
358 */
359 static const mimetype_and_clock mimetype_and_clock_map[] = {
360 {"AMR", 8000}, /* [RFC4867][RFC3267] */
361 {"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
362 {"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
363 {"BT656", 90000}, /* [RFC2431],[RFC3555] */
364 {"DV", 90000}, /* [RFC3189] */
365 {"EVRC", 8000}, /* [RFC3558] */
366 {"EVRC0", 8000}, /* [RFC4788] */
367 {"EVRC1", 8000}, /* [RFC4788] */
368 {"EVRCB", 8000}, /* [RFC4788] */
369 {"EVRCB0", 8000}, /* [RFC4788] */
370 {"EVRCB1", 8000}, /* [RFC4788] */
371 {"EVRCWB", 16000}, /* [RFC5188] */
372 {"EVRCWB0", 16000}, /* [RFC5188] */
373 {"EVRCWB1", 16000}, /* [RFC5188] */
374 {"G7221", 16000}, /* [RFC3047] */
375 {"G726-16", 8000}, /* [RFC3551][RFC4856] */
376 {"G726-24", 8000}, /* [RFC3551][RFC4856] */
377 {"G726-32", 8000}, /* [RFC3551][RFC4856] */
378 {"G726-40", 8000}, /* [RFC3551][RFC4856] */
379 {"G729D", 8000}, /* [RFC3551][RFC4856] */
380 {"G729E", 8000}, /* [RFC3551][RFC4856] */
381 {"GSM-EFR", 8000}, /* [RFC3551] */
382 {"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
383 {"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
384 {"H264", 90000}, /* [RFC3984] */
385 {"MP1S", 90000}, /* [RFC2250],[RFC3555] */
386 {"MP2P", 90000}, /* [RFC2250],[RFC3555] */
387 {"MP4V-ES", 90000}, /* [RFC3016] */
388 {"mpa-robust", 90000}, /* [RFC3119] */
389 {"pointer", 90000}, /* [RFC2862] */
390 {"raw", 90000}, /* [RFC4175] */
391 {"red", 1000}, /* [RFC4102] */
392 {"SMV", 8000}, /* [RFC3558] */
393 {"SMV0", 8000}, /* [RFC3558] */
394 {"t140", 1000}, /* [RFC4103] */
395 {"telephone-event", 8000}, /* [RFC4733] */
396 };
397  
398 #define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
399  
400 static guint32
401 get_dyn_pt_clock_rate(const gchar *payload_type_str)
402 {
403 int i;
404  
405 /* Search for matching mimetype in reverse order to avoid false matches
406 * when pt_mime_name_str is the prefix of payload_type_str */
407 for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
408 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)
409 return mimetype_and_clock_map[i].value;
410 }
411  
412 return 0;
413 }
414  
415 /****************************************************************************/
416 void
417 rtp_packet_analyse(tap_rtp_stat_t *statinfo,
418 packet_info *pinfo,
419 const struct _rtp_info *rtpinfo)
420 {
421 double current_time;
422 double current_jitter;
423 double current_diff = 0;
424 double nominaltime;
425 double arrivaltime; /* Time relative to start_time */
426 double expected_time;
427 double absskew;
428 guint32 clock_rate;
429  
430 /* Store the current time */
431 current_time = nstime_to_msec(&pinfo->rel_ts);
432  
433 /* Is this the first packet we got in this direction? */
434 if (statinfo->first_packet) {
435 /* Save the MAC address of the first RTP frame */
436 if( pinfo->dl_src.type == AT_ETHER){
437 copy_address(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src));
438 }
439 statinfo->start_seq_nr = rtpinfo->info_seq_num;
440 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
441 statinfo->seq_num = rtpinfo->info_seq_num;
442 statinfo->start_time = current_time;
443 statinfo->timestamp = rtpinfo->info_timestamp;
444 statinfo->first_timestamp = rtpinfo->info_timestamp;
445 statinfo->time = current_time;
446 statinfo->lastnominaltime = 0;
447 statinfo->pt = rtpinfo->info_payload_type;
448 statinfo->reg_pt = rtpinfo->info_payload_type;
449 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
450 statinfo->bw_history[statinfo->bw_index].time = current_time;
451 statinfo->bw_index++;
452 statinfo->total_bytes += rtpinfo->info_data_len + 28;
453 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
454 /* Not needed ? initialised to zero? */
455 statinfo->delta = 0;
456 statinfo->jitter = 0;
457 statinfo->diff = 0;
458  
459 statinfo->total_nr++;
460 statinfo->flags |= STAT_FLAG_FIRST;
461 if (rtpinfo->info_marker_set) {
462 statinfo->flags |= STAT_FLAG_MARKER;
463 }
464 statinfo->first_packet = FALSE;
465 return;
466 }
467  
468 /* Reset flags */
469 statinfo->flags = 0;
470  
471 /* Chek for duplicates (src mac differs from first_packet_mac_addr) */
472 if( pinfo->dl_src.type == AT_ETHER){
473 if(!addresses_equal(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src))){
474 statinfo->flags |= STAT_FLAG_DUP_PKT;
475 statinfo->delta = current_time-(statinfo->time);
476 return;
477 }
478 }
479  
480 /* When calculating expected rtp packets the seq number can wrap around
481 * so we have to count the number of cycles
482 * Variable cycles counts the wraps around in forwarding connection and
483 * under is flag that indicates where we are
484 *
485 * XXX How to determine number of cycles with all possible lost, late
486 * and duplicated packets without any doubt? It seems to me, that
487 * because of all possible combination of late, duplicated or lost
488 * packets, this can only be more or less good approximation
489 *
490 * There are some combinations (rare but theoretically possible),
491 * where below code won't work correctly - statistic may be wrong then.
492 */
493  
494 /* So if the current sequence number is less than the start one
495 * we assume, that there is another cycle running
496 */
497 if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
498 statinfo->cycles++;
499 statinfo->under = TRUE;
500 }
501 /* what if the start seq nr was 0? Then the above condition will never
502 * be true, so we add another condition. XXX The problem would arise
503 * if one of the packets with seq nr 0 or 65535 would be lost or late
504 */
505 else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
506 (statinfo->under == FALSE)){
507 statinfo->cycles++;
508 statinfo->under = TRUE;
509 }
510 /* the whole round is over, so reset the flag */
511 else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
512 statinfo->under = FALSE;
513 }
514  
515 /* Since it is difficult to count lost, duplicate or late packets separately,
516 * we would like to know at least how many times the sequence number was not ok
517 */
518  
519 /* If the current seq number equals the last one or if we are here for
520 * the first time, then it is ok, we just store the current one as the last one
521 */
522 if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
523 statinfo->seq_num = rtpinfo->info_seq_num;
524 /* If the first one is 65535 we wrap */
525 else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
526 statinfo->seq_num = rtpinfo->info_seq_num;
527 /* Lost packets. If the prev seq is enormously larger than the cur seq
528 * we assume that instead of being massively late we lost the packet(s)
529 * that would have indicated the sequence number wrapping. An imprecise
530 * heuristic at best, but it seems to work well enough.
531 * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5958 */
532 else if (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00) {
533 statinfo->seq_num = rtpinfo->info_seq_num;
534 statinfo->sequence++;
535 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
536 }
537 /* Late or duplicated */
538 else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
539 statinfo->sequence++;
540 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
541 }
542  
543 /* Check payload type */
544 if (rtpinfo->info_payload_type == PT_CN
545 || rtpinfo->info_payload_type == PT_CN_OLD)
546 statinfo->flags |= STAT_FLAG_PT_CN;
547 if (statinfo->pt == PT_CN
548 || statinfo->pt == PT_CN_OLD)
549 statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
550 if (rtpinfo->info_payload_type != statinfo->pt)
551 statinfo->flags |= STAT_FLAG_PT_CHANGE;
552 statinfo->pt = rtpinfo->info_payload_type;
553  
554 /*
555 * Return for unknown payload types
556 * Ignore jitter calculation for clockrate = 0
557 */
558 if (statinfo->pt < 96 ){
559 clock_rate = get_clock_rate(statinfo->pt);
560 }else{ /* Dynamic PT */
561 if ( rtpinfo->info_payload_type_str != NULL ){
562 /* Is it a "telephone-event" ?
563 * Timestamp is not increased for telepone-event packets impacting
564 * calculation of Jitter Skew and clock drift.
565 * see 2.2.1 of RFC 4733
566 */
567 if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0){
568 clock_rate = 0;
569 statinfo->flags |= STAT_FLAG_PT_T_EVENT;
570 }else{
571 if(rtpinfo->info_payload_rate !=0){
572 clock_rate = rtpinfo->info_payload_rate;
573 }else{
574 clock_rate = get_dyn_pt_clock_rate(rtpinfo->info_payload_type_str);
575 }
576 }
577 }else{
578 clock_rate = 0;
579 }
580 }
581  
582 /* Handle wraparound ? */
583 arrivaltime = current_time - statinfo->start_time;
584  
585 if (statinfo->first_timestamp > rtpinfo->info_timestamp){
586 /* Handle wraparound */
587 nominaltime = (double)(rtpinfo->info_timestamp + 0xffffffff - statinfo->first_timestamp + 1);
588 }else{
589 nominaltime = (double)(rtpinfo->info_timestamp - statinfo->first_timestamp);
590 }
591  
592 /* Can only analyze defined sampling rates */
593 if (clock_rate != 0) {
594 statinfo->clock_rate = clock_rate;
595 /* Convert from sampling clock to ms */
596 nominaltime = nominaltime /(clock_rate/1000);
597  
598 /* Calculate the current jitter(in ms) */
599 if (!statinfo->first_packet) {
600 expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
601 current_diff = fabs(current_time - expected_time);
602 current_jitter = (15 * statinfo->jitter + current_diff) / 16;
603  
604 statinfo->delta = current_time-(statinfo->time);
605 statinfo->jitter = current_jitter;
606 statinfo->diff = current_diff;
607 }
608 statinfo->lastnominaltime = nominaltime;
609 /* Calculate skew, i.e. absolute jitter that also catches clock drift
610 * Skew is positive if TS (nominal) is too fast
611 */
612 statinfo->skew = nominaltime - arrivaltime;
613 absskew = fabs(statinfo->skew);
614 if(absskew > fabs(statinfo->max_skew)){
615 statinfo->max_skew = statinfo->skew;
616 }
617 /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
618 #if 0
619 if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
620 /* Skip first packet and possibly alternate payload type packets */
621 double dt;
622 dt = nominaltime - statinfo->lastnominaltime;
623 sumdt += 1.0 * dt;
624 numdt += (dt != 0 ? 1 : 0);
625 mindt = (dt < mindt ? dt : mindt);
626 maxdt = (dt > maxdt ? dt : maxdt);
627 }
628 #endif
629 /* Gather data for calculation of skew least square */
630 statinfo->sumt += 1.0 * current_time;
631 statinfo->sumTS += 1.0 * nominaltime;
632 statinfo->sumt2 += 1.0 * current_time * current_time;
633 statinfo->sumtTS += 1.0 * current_time * nominaltime;
634 }
635  
636 /* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP) + 8bytes(UDP) */
637 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
638 statinfo->bw_history[statinfo->bw_index].time = current_time;
639  
640 /* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
641 while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
642 statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
643 statinfo->bw_start_index++;
644 if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
645 };
646 /* IP hdr + UDP + RTP */
647 statinfo->total_bytes += rtpinfo->info_data_len + 28;
648 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
649 statinfo->bw_index++;
650 if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
651  
652  
653 /* Is it a packet with the mark bit set? */
654 if (rtpinfo->info_marker_set) {
655 statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
656 if (rtpinfo->info_timestamp > statinfo->timestamp){
657 statinfo->flags |= STAT_FLAG_MARKER;
658 }
659 else{
660 statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
661 }
662 }
663 /* Is it a regular packet? */
664 if (!(statinfo->flags & STAT_FLAG_FIRST)
665 && !(statinfo->flags & STAT_FLAG_MARKER)
666 && !(statinfo->flags & STAT_FLAG_PT_CN)
667 && !(statinfo->flags & STAT_FLAG_WRONG_TIMESTAMP)
668 && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
669 /* Include it in maximum delta calculation */
670 if (statinfo->delta > statinfo->max_delta) {
671 statinfo->max_delta = statinfo->delta;
672 statinfo->max_nr = pinfo->num;
673 }
674 if (clock_rate != 0) {
675 /* Maximum and mean jitter calculation */
676 if (statinfo->jitter > statinfo->max_jitter) {
677 statinfo->max_jitter = statinfo->jitter;
678 }
679 statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
680 }
681 }
682 /* Regular payload change? (CN ignored) */
683 if (!(statinfo->flags & STAT_FLAG_FIRST)
684 && !(statinfo->flags & STAT_FLAG_PT_CN)) {
685 if ((statinfo->pt != statinfo->reg_pt)
686 && (statinfo->reg_pt != PT_UNDEFINED)) {
687 statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
688 }
689 }
690  
691 /* Set regular payload*/
692 if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
693 statinfo->reg_pt = statinfo->pt;
694 }
695  
696 statinfo->time = current_time;
697 statinfo->timestamp = rtpinfo->info_timestamp;
698 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
699 statinfo->total_nr++;
700  
701 return;
702 }
703  
704 /*
705 * Editor modelines - http://www.wireshark.org/tools/modelines.html
706 *
707 * Local variables:
708 * c-basic-offset: 8
709 * tab-width: 8
710 * indent-tabs-mode: t
711 * End:
712 *
713 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
714 * :indentSize=8:tabSize=8:noTabs=false:
715 */