blob: eed5fc0667805dc2dc3ccef459a4663f4a84301c [file] [log] [blame]
Benny Prijono16a6b0e2006-05-12 10:20:03 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21/*
22 * DO NOT COMPILE THIS FILE ON ITS OWN!
23 *
24 * This file is included by siprtp.c to implement the reporting capability
25 * to a separate file, so that user can implement different reporting
26 * functionality (such as writing to XML file).
27 */
28
29static const char *good_number(char *buf, pj_int32_t val)
30{
31 if (val < 1000) {
32 pj_ansi_sprintf(buf, "%d", val);
33 } else if (val < 1000000) {
34 pj_ansi_sprintf(buf, "%d.%dK",
35 val / 1000,
36 (val % 1000) / 100);
37 } else {
38 pj_ansi_sprintf(buf, "%d.%02dM",
39 val / 1000000,
40 (val % 1000000) / 10000);
41 }
42
43 return buf;
44}
45
46
47static void print_call(int call_index)
48{
49 struct call *call = &app.call[call_index];
50 int len;
51 pjsip_inv_session *inv = call->inv;
52 pjsip_dialog *dlg = inv->dlg;
53 struct media_stream *audio = &call->media[0];
54 char userinfo[128];
55 char duration[80], last_update[80];
56 char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16];
57 pj_time_val now;
58
59 pj_gettimeofday(&now);
60
Benny Prijonofcb36722006-05-18 18:34:21 +000061 if (app.report_filename)
62 puts(app.report_filename);
63
Benny Prijono16a6b0e2006-05-12 10:20:03 +000064 /* Print duration */
Benny Prijono65382db2006-05-14 18:50:09 +000065 if (inv->state >= PJSIP_INV_STATE_CONFIRMED && call->connect_time.sec) {
Benny Prijono16a6b0e2006-05-12 10:20:03 +000066
67 PJ_TIME_VAL_SUB(now, call->connect_time);
68
69 sprintf(duration, " [duration: %02ld:%02ld:%02ld.%03ld]",
70 now.sec / 3600,
71 (now.sec % 3600) / 60,
72 (now.sec % 60),
73 now.msec);
74
75 } else {
76 duration[0] = '\0';
77 }
78
79
80
81 /* Call number and state */
82 printf("Call #%d: %s%s\n", call_index, pjsip_inv_state_name(inv->state),
83 duration);
84
85
86
87 /* Call identification */
88 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo));
89 if (len < 1)
90 pj_ansi_strcpy(userinfo, "<--uri too long-->");
91 else
92 userinfo[len] = '\0';
93
94 printf(" %s\n", userinfo);
95
96
97 if (call->inv == NULL || call->inv->state < PJSIP_INV_STATE_CONFIRMED ||
98 call->connect_time.sec == 0)
99 {
100 return;
101 }
102
103
104 /* Signaling quality */
105 {
106 char pdd[64], connectdelay[64];
107 pj_time_val t;
108
109 if (call->response_time.sec) {
110 t = call->response_time;
111 PJ_TIME_VAL_SUB(t, call->start_time);
112 sprintf(pdd, "got 1st response in %ld ms", PJ_TIME_VAL_MSEC(t));
113 } else {
114 pdd[0] = '\0';
115 }
116
117 if (call->connect_time.sec) {
118 t = call->connect_time;
119 PJ_TIME_VAL_SUB(t, call->start_time);
120 sprintf(connectdelay, ", connected after: %ld ms",
121 PJ_TIME_VAL_MSEC(t));
122 } else {
123 connectdelay[0] = '\0';
124 }
125
126 printf(" Signaling quality: %s%s\n", pdd, connectdelay);
127 }
128
129
130 printf(" Stream #0: audio %.*s@%dHz, %dms/frame, %sB/s (%sB/s +IP hdr)\n",
131 (int)audio->si.fmt.encoding_name.slen,
132 audio->si.fmt.encoding_name.ptr,
133 audio->clock_rate,
134 audio->samples_per_frame * 1000 / audio->clock_rate,
135 good_number(bps, audio->bytes_per_frame * audio->clock_rate / audio->samples_per_frame),
136 good_number(ipbps, (audio->bytes_per_frame+32) * audio->clock_rate / audio->samples_per_frame));
137
138 if (audio->rtcp.stat.rx.update_cnt == 0)
139 strcpy(last_update, "never");
140 else {
141 pj_gettimeofday(&now);
142 PJ_TIME_VAL_SUB(now, audio->rtcp.stat.rx.update);
143 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
144 now.sec / 3600,
145 (now.sec % 3600) / 60,
146 now.sec % 60,
147 now.msec);
148 }
149
150 printf(" RX stat last update: %s\n"
151 " total %s packets %sB received (%sB +IP hdr)%s\n"
152 " pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
153 " (msec) min avg max last\n"
154 " loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
155 " jitter : %7.3f %7.3f %7.3f %7.3f%s\n",
156 last_update,
157 good_number(packets, audio->rtcp.stat.rx.pkt),
158 good_number(bytes, audio->rtcp.stat.rx.bytes),
159 good_number(ipbytes, audio->rtcp.stat.rx.bytes + audio->rtcp.stat.rx.pkt * 32),
160 "",
161 audio->rtcp.stat.rx.loss,
Benny Prijonof9016512006-06-29 09:41:34 +0000162 audio->rtcp.stat.rx.loss * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000163 audio->rtcp.stat.rx.dup,
Benny Prijonob12106f2006-06-29 14:45:17 +0000164 audio->rtcp.stat.rx.dup * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000165 audio->rtcp.stat.rx.reorder,
Benny Prijonob12106f2006-06-29 14:45:17 +0000166 audio->rtcp.stat.rx.reorder * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000167 "",
168 audio->rtcp.stat.rx.loss_period.min / 1000.0,
169 audio->rtcp.stat.rx.loss_period.avg / 1000.0,
170 audio->rtcp.stat.rx.loss_period.max / 1000.0,
171 audio->rtcp.stat.rx.loss_period.last / 1000.0,
172 "",
173 audio->rtcp.stat.rx.jitter.min / 1000.0,
174 audio->rtcp.stat.rx.jitter.avg / 1000.0,
175 audio->rtcp.stat.rx.jitter.max / 1000.0,
176 audio->rtcp.stat.rx.jitter.last / 1000.0,
177 ""
178 );
179
180
181 if (audio->rtcp.stat.tx.update_cnt == 0)
182 strcpy(last_update, "never");
183 else {
184 pj_gettimeofday(&now);
185 PJ_TIME_VAL_SUB(now, audio->rtcp.stat.tx.update);
186 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
187 now.sec / 3600,
188 (now.sec % 3600) / 60,
189 now.sec % 60,
190 now.msec);
191 }
192
193 printf(" TX stat last update: %s\n"
194 " total %s packets %sB sent (%sB +IP hdr)%s\n"
195 " pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
196 " (msec) min avg max last\n"
197 " loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
198 " jitter : %7.3f %7.3f %7.3f %7.3f%s\n",
199 last_update,
200 good_number(packets, audio->rtcp.stat.tx.pkt),
201 good_number(bytes, audio->rtcp.stat.tx.bytes),
202 good_number(ipbytes, audio->rtcp.stat.tx.bytes + audio->rtcp.stat.tx.pkt * 32),
203 "",
204 audio->rtcp.stat.tx.loss,
Benny Prijonof9016512006-06-29 09:41:34 +0000205 audio->rtcp.stat.tx.loss * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000206 audio->rtcp.stat.tx.dup,
Benny Prijonob12106f2006-06-29 14:45:17 +0000207 audio->rtcp.stat.tx.dup * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000208 audio->rtcp.stat.tx.reorder,
Benny Prijonob12106f2006-06-29 14:45:17 +0000209 audio->rtcp.stat.tx.reorder * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
Benny Prijono16a6b0e2006-05-12 10:20:03 +0000210 "",
211 audio->rtcp.stat.tx.loss_period.min / 1000.0,
212 audio->rtcp.stat.tx.loss_period.avg / 1000.0,
213 audio->rtcp.stat.tx.loss_period.max / 1000.0,
214 audio->rtcp.stat.tx.loss_period.last / 1000.0,
215 "",
216 audio->rtcp.stat.tx.jitter.min / 1000.0,
217 audio->rtcp.stat.tx.jitter.avg / 1000.0,
218 audio->rtcp.stat.tx.jitter.max / 1000.0,
219 audio->rtcp.stat.tx.jitter.last / 1000.0,
220 ""
221 );
222
223
224 printf(" RTT delay : %7.3f %7.3f %7.3f %7.3f%s\n",
225 audio->rtcp.stat.rtt.min / 1000.0,
226 audio->rtcp.stat.rtt.avg / 1000.0,
227 audio->rtcp.stat.rtt.max / 1000.0,
228 audio->rtcp.stat.rtt.last / 1000.0,
229 ""
230 );
231
232}
233