From Balint Reczey (bug 2233):
authorsake <sake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 3 Feb 2008 10:31:55 +0000 (10:31 +0000)
committersake <sake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 3 Feb 2008 10:31:55 +0000 (10:31 +0000)
The attached patch makes the Statistics -> RTP -> Show All Streams feature of
wireshark accessible via tshark.

I found it helpful in dealing with tons of RTP captures.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@24252 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.common
doc/tshark.pod
gtk/rtp_analysis.c
gtk/rtp_stream.c
tshark.c

index 9156b6b6b4cf2795d3563b45d9f069a632481215..0ba4b0aacffb1a072f4c84a5d082d3be4356cb9d 100644 (file)
@@ -59,6 +59,7 @@ WIRESHARK_COMMON_SRC =        \
        sync_pipe_write.c       \
        timestats.c     \
        util.c  \
+       tap-rtp-common.c        \
        version_info.c
 
 # corresponding headers
@@ -83,6 +84,7 @@ WIRESHARK_COMMON_INCLUDES =   \
        tempfile.h      \
        timestats.h     \
        util.h  \
+       tap-rtp-common.h        \
        version_info.h
 
 # sources for TShark taps
@@ -106,6 +108,7 @@ TSHARK_TAP_SRC =    \
        tap-radiusstat.c        \
        tap-rpcstat.c   \
        tap-rpcprogs.c  \
+       tap-rtp.c       \
        tap-sctpchunkstat.c     \
        tap-sipstat.c \
        tap-smbsids.c   \
index 2450eb4f5239d0a4e1988b22218ae51f8e23448d..378c7d12818009ba9b25bcda5b237632ba3faa6f 100644 (file)
@@ -657,6 +657,12 @@ Data collected is number of calls for each protocol/version, MinRTT,
 MaxRTT and AvgRTT. 
 This option can only be used once on the command line.
 
+B<-z> rtp,streams
+
+Collect statistics for all RTP streams and calculate max. delta, max. and
+mean jitter and packet loss percentages.
+
+
 B<-z> smb,rtt[,I<filter>]
 
 Collect call/reply RTT data for SMB.  Data collected
index 6339cd13e97e2960035d0e575edb716067aae822..31ddedae60f317e29054ab889e81ea6b893d648f 100644 (file)
@@ -186,117 +186,6 @@ typedef struct _dialog_data_t {
 
 #define OK_TEXT "[ Ok ]"
 
-typedef struct _key_value {
-  guint32  key;
-  guint32  value;
-} key_value;
-
-
-/* RTP sampling clock rates for fixed payload types as defined in
- http://www.iana.org/assignments/rtp-parameters */
-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 1;
-}
-
-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
-       MIME subtype"
-       http://www.iana.org/assignments/rtp-parameters.
-*/
-static const mimetype_and_clock mimetype_and_clock_map[] = {
-       {"AMR",         8000},                  /* [RFC3267] */
-       {"AMR-WB",      16000},                 /* [RFC3267] */
-       {"EVRC",        8000},                  /* [RFC3558] */
-       {"EVRC0",       8000},                  /* [RFC3558] */
-       {"G7221",       16000},                 /* [RFC3047] */
-       {"G726-16",     8000},                  /* [RFC3551] */
-       {"G726-24",     8000},                  /* [RFC3551] */
-       {"G726-32",     8000},                  /* [RFC3551] */
-       {"G726-40",     8000},                  /* [RFC3551] */
-       {"G729D",       8000},                  /* [RFC3551] */
-       {"G729E",       8000},                  /* [RFC3551] */
-       {"GSM-EFR",     8000},                  /* [RFC3551] */
-       {"mpa-robust",  90000},         /* [RFC3119] */
-       {"SMV",         8000},                  /* [RFC3558] */
-       {"SMV0",        8000},                  /* [RFC3558] */
-       {"red",         1000},                  /* [RFC4102] */
-       {"t140",        1000},                  /* [RFC4103] */
-       {"BMPEG",       90000},                 /* [RFC2343],[RFC3555] */
-       {"BT656",       90000},                 /* [RFC2431],[RFC3555] */
-       {"DV",          90000},                 /* [RFC3189] */
-       {"H263-1998",   90000},         /* [RFC2429],[RFC3555] */
-       {"H263-2000",   90000},         /* [RFC2429],[RFC3555] */
-       {"MP1S",        90000},                 /* [RFC2250],[RFC3555] */
-       {"MP2P",        90000},                 /* [RFC2250],[RFC3555] */
-       {"MP4V-ES",     90000},                 /* [RFC3016] */
-       {"pointer",     90000},                 /* [RFC2862] */
-       {"raw",         90000},                 /* [RFC4175] */
-       {"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(gchar *payload_type_str)
-{
-       size_t i;
-
-       for (i = 0; i < NUM_DYN_CLOCK_VALUES; 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 1;
-}
-
 /* type of error when saving voice in a file didn't succeed */
 typedef enum {
        TAP_RTP_WRONG_CODEC,
@@ -626,179 +515,6 @@ static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *e
 }
 
 
-/****************************************************************************/
-int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
-                              packet_info *pinfo,
-                              const struct _rtp_info *rtpinfo)
-{
-       double current_time;
-       double current_jitter;
-       double current_diff;
-       guint32 clock_rate;
-
-       statinfo->flags = 0;
-       /* 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;
-       /*
-        * XXX - should "get_clock_rate()" return 0 for unknown
-        * payload types, presumably meaning that we should
-        * just ignore this packet?
-        */
-       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;
-       }
-
-       /* 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;
-
-       /* 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;
-       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){
-               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;
-       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? */
-       if (rtpinfo->info_marker_set) {
-               statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
-               if (rtpinfo->info_timestamp > statinfo->timestamp){
-                       statinfo->flags |= STAT_FLAG_MARKER;
-               }
-               else{
-                       statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
-               }
-       }
-       /* 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->fd->num;
-               }
-               /* 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);
-       }
-       /* 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;
-       }
-
-
-       /* 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;
-       statinfo->total_nr++;
-
-       return 0;
-}
-
-
 static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
 static const GdkColor COLOR_ERROR = {0, 0xffff, 0xbfff, 0xbfff};
 static const GdkColor COLOR_WARNING = {0, 0xffff, 0xdfff, 0xbfff};
index 11c1de7c65f116d52169c6d9070085d027fdcb27..fb126a2975febba8ee473b3c8590aea70b2db871 100644 (file)
 
 #include "rtp_stream.h"
 #include "rtp_stream_dlg.h"
-
-
-/****************************************************************************/
-/* the one and only global rtpstream_tapinfo_t structure */
-static rtpstream_tapinfo_t the_tapinfo_struct =
-       {0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, 0, FALSE};
-
-
-/****************************************************************************/
-/* GCompareFunc style comparison function for _rtp_stream_info */
-static gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
-{
-       const struct _rtp_stream_info* a = aa;
-       const struct _rtp_stream_info* b = bb;
-
-       if (a==b)
-               return 0;
-       if (a==NULL || b==NULL)
-               return 1;
-       if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
-               && (a->src_port == b->src_port)
-               && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
-               && (a->dest_port == b->dest_port)
-               && (a->ssrc == b->ssrc))
-               return 0;
-       else
-               return 1;
-}
-
-
-/****************************************************************************/
-/* when there is a [re]reading of packet's */
-void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
-{
-       GList* list;
-
-       if (tapinfo->mode == TAP_ANALYSE) {
-               /* free the data items first */
-               list = g_list_first(tapinfo->strinfo_list);
-               while (list)
-               {
-                       g_free(list->data);
-                       list = g_list_next(list);
-               }
-               g_list_free(tapinfo->strinfo_list);
-               tapinfo->strinfo_list = NULL;
-               tapinfo->nstreams = 0;
-               tapinfo->npackets = 0;
-       }
-
-       ++(tapinfo->launch_count);
-
-       return;
-}
-
-static void rtpstream_reset_cb(void *arg)
-{
-       rtpstream_reset(arg);
-}
+#include "tap-rtp-common.h"
 
 /****************************************************************************/
 /* redraw the output */
@@ -125,213 +67,6 @@ static void rtpstream_draw(void *arg _U_)
 }
 
 
-/*
-* rtpdump file format
-*
-* The file starts with the tool to be used for playing this file,
-* the multicast/unicast receive address and the port.
-*
-* #!rtpplay1.0 224.2.0.1/3456\n
-*
-* This is followed by one binary header (RD_hdr_t) and one RD_packet_t
-* structure for each received packet.  All fields are in network byte
-* order.  We don't need the source IP address since we can do mapping
-* based on SSRC.  This saves (a little) space, avoids non-IPv4
-* problems and privacy/security concerns. The header is followed by
-* the RTP/RTCP header and (optionally) the actual payload.
-*/
-
-#define RTPFILE_VERSION "1.0"
-
-/*
-* Write a header to the current output file.
-* The header consists of an identifying string, followed
-* by a binary structure.
-*/
-static void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
-{
-       guint32 start_sec;     /* start of recording (GMT) (seconds) */
-       guint32 start_usec;    /* start of recording (GMT) (microseconds)*/
-       guint32 source;        /* network source (multicast address) */
-       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);
-
-       start_sec = g_htonl(strinfo->start_sec);
-       start_usec = g_htonl(strinfo->start_usec);
-       /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
-       memset(&source, 0, sizeof source);
-       sourcelen = strinfo->src_addr.len;
-       if (sourcelen > sizeof source)
-               sourcelen = sizeof source;
-       memcpy(&source, strinfo->src_addr.data, sourcelen);
-       port = g_htons(strinfo->src_port);
-       padding = 0;
-
-       if (fwrite(&start_sec, 4, 1, file) == 0)
-               return;
-       if (fwrite(&start_usec, 4, 1, file) == 0)
-               return;
-       if (fwrite(&source, 4, 1, file) == 0)
-               return;
-       if (fwrite(&port, 2, 1, file) == 0)
-               return;
-       if (fwrite(&padding, 2, 1, file) == 0)
-               return;
-}
-
-/* utility function for writing a sample to file in rtpdump -F dump format (.rtp)*/
-static void rtp_write_sample(rtp_sample_t* sample, FILE* file)
-{
-       guint16 length;    /* length of packet, including this header (may
-                            be smaller than plen if not whole packet recorded) */
-       guint16 plen;      /* actual header+payload length for RTP, 0 for RTCP */
-       guint32 offset;    /* milliseconds since the start of recording */
-
-       length = g_htons(sample->header.frame_length + 8);
-       plen = g_htons(sample->header.frame_length);
-       offset = g_htonl(sample->header.rec_time);
-
-       if (fwrite(&length, 2, 1, file) == 0)
-               return;
-       if (fwrite(&plen, 2, 1, file) == 0)
-               return;
-       if (fwrite(&offset, 4, 1, file) == 0)
-               return;
-       if (fwrite(sample->frame, sample->header.frame_length, 1, file) == 0)
-               return;
-}
-
-
-/****************************************************************************/
-/* whenever a RTP packet is seen by the tap listener */
-static int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
-{
-       rtpstream_tapinfo_t *tapinfo = arg;
-       const struct _rtp_info *rtpinfo = arg2;
-       rtp_stream_info_t tmp_strinfo;
-       rtp_stream_info_t *strinfo = NULL;
-       GList* list;
-       rtp_sample_t sample;
-
-       struct _rtp_conversation_info *p_conv_data = NULL;
-
-       /* gather infos on the stream this packet is part of */
-       COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
-       tmp_strinfo.src_port = pinfo->srcport;
-       COPY_ADDRESS(&(tmp_strinfo.dest_addr), &(pinfo->dst));
-       tmp_strinfo.dest_port = pinfo->destport;
-       tmp_strinfo.ssrc = rtpinfo->info_sync_src;
-       tmp_strinfo.pt = rtpinfo->info_payload_type;
-       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 */
-               list = g_list_first(tapinfo->strinfo_list);
-               while (list)
-               {
-                       if (rtp_stream_info_cmp(&tmp_strinfo, (rtp_stream_info_t*)(list->data))==0)
-                       {
-                               strinfo = (rtp_stream_info_t*)(list->data);  /*found!*/
-                               break;
-                       }
-                       list = g_list_next(list);
-               }
-
-               /* not in the list? then create a new entry */
-               if (!strinfo) {
-                       tmp_strinfo.npackets = 0;
-                       tmp_strinfo.first_frame_num = pinfo->fd->num;
-                       tmp_strinfo.start_sec = (guint32) pinfo->fd->abs_ts.secs;
-                       tmp_strinfo.start_usec = pinfo->fd->abs_ts.nsecs/1000;
-                       tmp_strinfo.start_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
-                       tmp_strinfo.start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
-                       tmp_strinfo.tag_vlan_error = 0;
-                       tmp_strinfo.tag_diffserv_error = 0;
-                       tmp_strinfo.vlan_id = 0;
-                       tmp_strinfo.problem = FALSE;
-
-                       /* reset RTP stats */
-                       tmp_strinfo.rtp_stats.first_packet = TRUE;
-                       tmp_strinfo.rtp_stats.max_delta = 0;
-                       tmp_strinfo.rtp_stats.max_jitter = 0;
-                       tmp_strinfo.rtp_stats.mean_jitter = 0;
-                       tmp_strinfo.rtp_stats.delta = 0;
-                       tmp_strinfo.rtp_stats.diff = 0;
-                       tmp_strinfo.rtp_stats.jitter = 0;
-                       tmp_strinfo.rtp_stats.bandwidth = 0;
-                       tmp_strinfo.rtp_stats.total_bytes = 0;
-                       tmp_strinfo.rtp_stats.bw_start_index = 0;
-                       tmp_strinfo.rtp_stats.bw_index = 0;
-                       tmp_strinfo.rtp_stats.timestamp = 0;
-                       tmp_strinfo.rtp_stats.max_nr = 0;
-                       tmp_strinfo.rtp_stats.total_nr = 0;
-                       tmp_strinfo.rtp_stats.sequence = 0;
-                       tmp_strinfo.rtp_stats.start_seq_nr = 0;
-                       tmp_strinfo.rtp_stats.stop_seq_nr = 0;
-                       tmp_strinfo.rtp_stats.cycles = 0;
-                       tmp_strinfo.rtp_stats.under = FALSE;
-                       tmp_strinfo.rtp_stats.start_time = 0;
-                       tmp_strinfo.rtp_stats.time = 0;
-                       tmp_strinfo.rtp_stats.reg_pt = PT_UNDEFINED;
-
-            /* Get the Setup frame number who set this RTP stream */
-            p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
-            if (p_conv_data)
-                               tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
-            else
-                tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
-
-                       strinfo = g_malloc(sizeof(rtp_stream_info_t));
-                       *strinfo = tmp_strinfo;  /* memberwise copy of struct */
-                       tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
-               }
-
-               /* get RTP stats for the packet */
-               rtp_packet_analyse(&(strinfo->rtp_stats), pinfo, rtpinfo);
-               if (strinfo->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
-                       || strinfo->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
-                       strinfo->problem = TRUE;
-
-
-               /* increment the packets counter for this stream */
-               ++(strinfo->npackets);
-               strinfo->stop_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
-               strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
-
-               /* 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 = 
-                               (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;
-                       sample.frame = rtpinfo->info_data;
-                       rtp_write_sample(&sample, tapinfo->save_file);
-               }
-       }
-       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);
-               }
-       }
-
-       return 0;
-}
-
 /****************************************************************************/
 /* scan for RTP streams */
 void rtpstream_scan(void)
index 1e1e077bca8ab294272503a12d1bee08e339c8dc..2d7deeb7d5c67c480480f634538950175bee08e6 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -185,6 +185,34 @@ static void read_failure_message(const char *filename, int err);
 
 capture_file cfile;
 
+/*
+ * Mark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_mark_frame(capture_file *cf, frame_data *frame)
+{
+  if (! frame->flags.marked) {
+    frame->flags.marked = TRUE;
+    if (cf->count > cf->marked_count)
+      cf->marked_count++;
+  }
+}
+
+/*
+ * Unmark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_unmark_frame(capture_file *cf, frame_data *frame)
+{
+  if (frame->flags.marked) {
+    frame->flags.marked = FALSE;
+    if (cf->marked_count > 0)
+      cf->marked_count--;
+  }
+}
+
 
 static void list_capture_types(void) {
     int i;