- Timestamp:
- Jul 7, 2011 7:46:33 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_call.c
r3573 r3609 1117 1117 1118 1118 1119 #if DISABLED_FOR_TICKET_11851120 /*1121 * Retrieve the media session associated with this call.1122 */1123 PJ_DEF(pjmedia_session*) pjsua_call_get_media_session(pjsua_call_id call_id)1124 {1125 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,1126 NULL);1127 return pjsua_var.calls[call_id].session;1128 }1129 1130 1131 /*1132 * Retrieve the media transport instance that is used for this call.1133 */1134 PJ_DEF(pjmedia_transport*) pjsua_call_get_media_transport(pjsua_call_id cid)1135 {1136 PJ_ASSERT_RETURN(cid>=0 && cid<(int)pjsua_var.ua_cfg.max_calls,1137 NULL);1138 return pjsua_var.calls[cid].tp;1139 }1140 #endif /* Removed in 2.0 */1141 1142 1119 /* Acquire lock to the specified call_id */ 1143 1120 pj_status_t acquire_call(const char *title, … … 1337 1314 1338 1315 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 1339 info->media[info->media_cnt].stream.aud io.conf_slot =1316 info->media[info->media_cnt].stream.aud.conf_slot = 1340 1317 call_med->strm.a.conf_slot; 1341 1318 } else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 1342 info->media[info->media_cnt].stream.video.capturer =1343 call_med->strm.v.capturer;1344 info->media[info->media_cnt].stream.vid eo.renderer=1345 call_med->strm.v.renderer;1319 PJ_TODO(vid_fill_in_call_info); 1320 info->media[info->media_cnt].stream.vid.win_in = PJSUA_INVALID_ID; 1321 info->media[info->media_cnt].stream.vid.cap_dev = 1322 PJMEDIA_VID_INVALID_DEV; 1346 1323 } else { 1347 1324 continue; … … 2183 2160 } 2184 2161 2185 2186 const char *good_number(char *buf, pj_int32_t val)2187 {2188 if (val < 1000) {2189 pj_ansi_sprintf(buf, "%d", val);2190 } else if (val < 1000000) {2191 pj_ansi_sprintf(buf, "%d.%dK",2192 val / 1000,2193 (val % 1000) / 100);2194 } else {2195 pj_ansi_sprintf(buf, "%d.%02dM",2196 val / 1000000,2197 (val % 1000000) / 10000);2198 }2199 2200 return buf;2201 }2202 2203 static unsigned dump_media_stat(const char *indent,2204 char *buf, unsigned maxlen,2205 const pjmedia_rtcp_stat *stat,2206 const char *rx_info, const char *tx_info)2207 {2208 char last_update[64];2209 char packets[32], bytes[32], ipbytes[32], avg_bps[32], avg_ipbps[32];2210 pj_time_val media_duration, now;2211 char *p = buf, *end = buf+maxlen;2212 int len;2213 2214 if (stat->rx.update_cnt == 0)2215 strcpy(last_update, "never");2216 else {2217 pj_gettimeofday(&now);2218 PJ_TIME_VAL_SUB(now, stat->rx.update);2219 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2220 now.sec / 3600,2221 (now.sec % 3600) / 60,2222 now.sec % 60,2223 now.msec);2224 }2225 2226 pj_gettimeofday(&media_duration);2227 PJ_TIME_VAL_SUB(media_duration, stat->start);2228 if (PJ_TIME_VAL_MSEC(media_duration) == 0)2229 media_duration.msec = 1;2230 2231 len = pj_ansi_snprintf(p, end-p,2232 "%s RX %s last update:%s\n"2233 "%s total %spkt %sB (%sB +IP hdr) @avg=%sbps/%sbps\n"2234 "%s pkt loss=%d (%3.1f%%), discrd=%d (%3.1f%%), dup=%d (%2.1f%%), reord=%d (%3.1f%%)\n"2235 "%s (msec) min avg max last dev\n"2236 "%s loss period: %7.3f %7.3f %7.3f %7.3f %7.3f\n"2237 "%s jitter : %7.3f %7.3f %7.3f %7.3f %7.3f\n"2238 #if defined(PJMEDIA_RTCP_STAT_HAS_RAW_JITTER) && PJMEDIA_RTCP_STAT_HAS_RAW_JITTER!=02239 "%s raw jitter : %7.3f %7.3f %7.3f %7.3f %7.3f\n"2240 #endif2241 #if defined(PJMEDIA_RTCP_STAT_HAS_IPDV) && PJMEDIA_RTCP_STAT_HAS_IPDV!=02242 "%s IPDV : %7.3f %7.3f %7.3f %7.3f %7.3f\n"2243 #endif2244 "%s",2245 indent,2246 rx_info? rx_info : "",2247 last_update,2248 2249 indent,2250 good_number(packets, stat->rx.pkt),2251 good_number(bytes, stat->rx.bytes),2252 good_number(ipbytes, stat->rx.bytes + stat->rx.pkt * 40),2253 good_number(avg_bps, (pj_int32_t)((pj_int64_t)stat->rx.bytes * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))),2254 good_number(avg_ipbps, (pj_int32_t)(((pj_int64_t)stat->rx.bytes + stat->rx.pkt * 40) * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))),2255 indent,2256 stat->rx.loss,2257 (stat->rx.loss? stat->rx.loss * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0),2258 stat->rx.discard,2259 (stat->rx.discard? stat->rx.discard * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0),2260 stat->rx.dup,2261 (stat->rx.dup? stat->rx.dup * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0),2262 stat->rx.reorder,2263 (stat->rx.reorder? stat->rx.reorder * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0),2264 indent, indent,2265 stat->rx.loss_period.min / 1000.0,2266 stat->rx.loss_period.mean / 1000.0,2267 stat->rx.loss_period.max / 1000.0,2268 stat->rx.loss_period.last / 1000.0,2269 pj_math_stat_get_stddev(&stat->rx.loss_period) / 1000.0,2270 indent,2271 stat->rx.jitter.min / 1000.0,2272 stat->rx.jitter.mean / 1000.0,2273 stat->rx.jitter.max / 1000.0,2274 stat->rx.jitter.last / 1000.0,2275 pj_math_stat_get_stddev(&stat->rx.jitter) / 1000.0,2276 #if defined(PJMEDIA_RTCP_STAT_HAS_RAW_JITTER) && PJMEDIA_RTCP_STAT_HAS_RAW_JITTER!=02277 indent,2278 stat->rx_raw_jitter.min / 1000.0,2279 stat->rx_raw_jitter.mean / 1000.0,2280 stat->rx_raw_jitter.max / 1000.0,2281 stat->rx_raw_jitter.last / 1000.0,2282 pj_math_stat_get_stddev(&stat->rx_raw_jitter) / 1000.0,2283 #endif2284 #if defined(PJMEDIA_RTCP_STAT_HAS_IPDV) && PJMEDIA_RTCP_STAT_HAS_IPDV!=02285 indent,2286 stat->rx_ipdv.min / 1000.0,2287 stat->rx_ipdv.mean / 1000.0,2288 stat->rx_ipdv.max / 1000.0,2289 stat->rx_ipdv.last / 1000.0,2290 pj_math_stat_get_stddev(&stat->rx_ipdv) / 1000.0,2291 #endif2292 ""2293 );2294 2295 if (len < 1 || len > end-p) {2296 *p = '\0';2297 return (p-buf);2298 }2299 p += len;2300 2301 if (stat->tx.update_cnt == 0)2302 strcpy(last_update, "never");2303 else {2304 pj_gettimeofday(&now);2305 PJ_TIME_VAL_SUB(now, stat->tx.update);2306 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2307 now.sec / 3600,2308 (now.sec % 3600) / 60,2309 now.sec % 60,2310 now.msec);2311 }2312 2313 len = pj_ansi_snprintf(p, end-p,2314 "%s TX %s last update:%s\n"2315 "%s total %spkt %sB (%sB +IP hdr) @avg %sbps/%sbps\n"2316 "%s pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n"2317 "%s (msec) min avg max last dev \n"2318 "%s loss period: %7.3f %7.3f %7.3f %7.3f %7.3f\n"2319 "%s jitter : %7.3f %7.3f %7.3f %7.3f %7.3f\n",2320 indent,2321 tx_info,2322 last_update,2323 2324 indent,2325 good_number(packets, stat->tx.pkt),2326 good_number(bytes, stat->tx.bytes),2327 good_number(ipbytes, stat->tx.bytes + stat->tx.pkt * 40),2328 good_number(avg_bps, (pj_int32_t)((pj_int64_t)stat->tx.bytes * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))),2329 good_number(avg_ipbps, (pj_int32_t)(((pj_int64_t)stat->tx.bytes + stat->tx.pkt * 40) * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))),2330 2331 indent,2332 stat->tx.loss,2333 (stat->tx.loss? stat->tx.loss * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0),2334 stat->tx.dup,2335 (stat->tx.dup? stat->tx.dup * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0),2336 stat->tx.reorder,2337 (stat->tx.reorder? stat->tx.reorder * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0),2338 2339 indent, indent,2340 stat->tx.loss_period.min / 1000.0,2341 stat->tx.loss_period.mean / 1000.0,2342 stat->tx.loss_period.max / 1000.0,2343 stat->tx.loss_period.last / 1000.0,2344 pj_math_stat_get_stddev(&stat->tx.loss_period) / 1000.0,2345 indent,2346 stat->tx.jitter.min / 1000.0,2347 stat->tx.jitter.mean / 1000.0,2348 stat->tx.jitter.max / 1000.0,2349 stat->tx.jitter.last / 1000.0,2350 pj_math_stat_get_stddev(&stat->tx.jitter) / 1000.02351 );2352 2353 if (len < 1 || len > end-p) {2354 *p = '\0';2355 return (p-buf);2356 }2357 p += len;2358 2359 len = pj_ansi_snprintf(p, end-p,2360 "%s RTT msec : %7.3f %7.3f %7.3f %7.3f %7.3f\n",2361 indent,2362 stat->rtt.min / 1000.0,2363 stat->rtt.mean / 1000.0,2364 stat->rtt.max / 1000.0,2365 stat->rtt.last / 1000.0,2366 pj_math_stat_get_stddev(&stat->rtt) / 1000.02367 );2368 if (len < 1 || len > end-p) {2369 *p = '\0';2370 return (p-buf);2371 }2372 p += len;2373 2374 return (p-buf);2375 }2376 2377 2378 /* Dump media session */2379 static void dump_media_session(const char *indent,2380 char *buf, unsigned maxlen,2381 pjsua_call *call)2382 {2383 unsigned i;2384 char *p = buf, *end = buf+maxlen;2385 int len;2386 2387 for (i=0; i<call->med_cnt; ++i) {2388 pjsua_call_media *call_med = &call->media[i];2389 pjmedia_rtcp_stat stat;2390 pj_bool_t has_stat;2391 pjmedia_transport_info tp_info;2392 char rem_addr_buf[80];2393 char codec_info[32] = {'0'};2394 char rx_info[80] = {'\0'};2395 char tx_info[80] = {'\0'};2396 const char *rem_addr;2397 const char *dir_str;2398 const char *media_type_str;2399 2400 switch (call_med->type) {2401 case PJMEDIA_TYPE_AUDIO:2402 media_type_str = "audio";2403 break;2404 case PJMEDIA_TYPE_VIDEO:2405 media_type_str = "video";2406 break;2407 case PJMEDIA_TYPE_APPLICATION:2408 media_type_str = "application";2409 break;2410 default:2411 media_type_str = "unknown";2412 break;2413 }2414 2415 /* Check if the stream is deactivated */2416 if (call_med->tp == NULL ||2417 (!call_med->strm.a.stream && !call_med->strm.v.stream))2418 {2419 len = pj_ansi_snprintf(p, end-p,2420 "%s #%d %s deactivated\n",2421 indent, i, media_type_str);2422 if (len < 1 || len > end-p) {2423 *p = '\0';2424 return;2425 }2426 2427 p += len;2428 continue;2429 }2430 2431 pjmedia_transport_info_init(&tp_info);2432 pjmedia_transport_get_info(call_med->tp, &tp_info);2433 2434 // rem_addr will contain actual address of RTP originator, instead of2435 // remote RTP address specified by stream which is fetched from the SDP.2436 // Please note that we are assuming only one stream per call.2437 //rem_addr = pj_sockaddr_print(&info.stream_info[i].rem_addr,2438 // rem_addr_buf, sizeof(rem_addr_buf), 3);2439 if (pj_sockaddr_has_addr(&tp_info.src_rtp_name)) {2440 rem_addr = pj_sockaddr_print(&tp_info.src_rtp_name, rem_addr_buf,2441 sizeof(rem_addr_buf), 3);2442 } else {2443 pj_ansi_snprintf(rem_addr_buf, sizeof(rem_addr_buf), "-");2444 rem_addr = rem_addr_buf;2445 }2446 2447 if (call_med->dir == PJMEDIA_DIR_NONE) {2448 /* To handle when the stream that is currently being paused2449 * (http://trac.pjsip.org/repos/ticket/1079)2450 */2451 dir_str = "inactive";2452 } else if (call_med->dir == PJMEDIA_DIR_ENCODING)2453 dir_str = "sendonly";2454 else if (call_med->dir == PJMEDIA_DIR_DECODING)2455 dir_str = "recvonly";2456 else if (call_med->dir == PJMEDIA_DIR_ENCODING_DECODING)2457 dir_str = "sendrecv";2458 else2459 dir_str = "inactive";2460 2461 if (call_med->type == PJMEDIA_TYPE_AUDIO) {2462 pjmedia_stream *stream = call_med->strm.a.stream;2463 pjmedia_stream_info info;2464 2465 pjmedia_stream_get_stat(stream, &stat);2466 has_stat = PJ_TRUE;2467 2468 pjmedia_stream_get_info(stream, &info);2469 pj_ansi_snprintf(codec_info, sizeof(codec_info), " %.*s @%dkHz",2470 (int)info.fmt.encoding_name.slen,2471 info.fmt.encoding_name.ptr,2472 info.fmt.clock_rate / 1000);2473 pj_ansi_snprintf(rx_info, sizeof(rx_info), "pt=%d,",2474 info.fmt.pt);2475 pj_ansi_snprintf(tx_info, sizeof(tx_info), "pt=%d, ptime=%d,",2476 info.tx_pt,2477 info.param->setting.frm_per_pkt*2478 info.param->info.frm_ptime);2479 } else if (call_med->type == PJMEDIA_TYPE_VIDEO) {2480 pjmedia_vid_stream *stream = call_med->strm.v.stream;2481 pjmedia_vid_stream_info info;2482 2483 pjmedia_vid_stream_get_stat(stream, &stat);2484 has_stat = PJ_TRUE;2485 2486 pjmedia_vid_stream_get_info(stream, &info);2487 pj_ansi_snprintf(codec_info, sizeof(codec_info), " %.*s",2488 (int)info.codec_info.encoding_name.slen,2489 info.codec_info.encoding_name.ptr);2490 if (call_med->dir & PJMEDIA_DIR_DECODING) {2491 pjmedia_video_format_detail *vfd;2492 vfd = pjmedia_format_get_video_format_detail(2493 &info.codec_param->dec_fmt, PJ_TRUE);2494 pj_ansi_snprintf(rx_info, sizeof(rx_info),2495 "pt=%d, size=%dx%d, fps=%.2f,",2496 info.rx_pt,2497 vfd->size.w, vfd->size.h,2498 vfd->fps.num*1.0/vfd->fps.denum);2499 }2500 if (call_med->dir & PJMEDIA_DIR_ENCODING) {2501 pjmedia_video_format_detail *vfd;2502 vfd = pjmedia_format_get_video_format_detail(2503 &info.codec_param->enc_fmt, PJ_TRUE);2504 pj_ansi_snprintf(tx_info, sizeof(tx_info),2505 "pt=%d, size=%dx%d, fps=%.2f,",2506 info.tx_pt,2507 vfd->size.w, vfd->size.h,2508 vfd->fps.num*1.0/vfd->fps.denum);2509 }2510 } else {2511 has_stat = PJ_FALSE;2512 }2513 2514 len = pj_ansi_snprintf(p, end-p,2515 "%s #%d %s%s, %s, peer=%s\n",2516 indent,2517 call_med->idx,2518 media_type_str,2519 codec_info,2520 dir_str,2521 rem_addr);2522 if (len < 1 || len > end-p) {2523 *p = '\0';2524 return;2525 }2526 p += len;2527 2528 /* Get and ICE SRTP status */2529 if (call_med->tp) {2530 pjmedia_transport_info tp_info;2531 2532 pjmedia_transport_info_init(&tp_info);2533 pjmedia_transport_get_info(call_med->tp, &tp_info);2534 if (tp_info.specific_info_cnt > 0) {2535 unsigned j;2536 for (j = 0; j < tp_info.specific_info_cnt; ++j) {2537 if (tp_info.spc_info[j].type == PJMEDIA_TRANSPORT_TYPE_SRTP)2538 {2539 pjmedia_srtp_info *srtp_info =2540 (pjmedia_srtp_info*) tp_info.spc_info[j].buffer;2541 2542 len = pj_ansi_snprintf(p, end-p,2543 " %s SRTP status: %s Crypto-suite: %s",2544 indent,2545 (srtp_info->active?"Active":"Not active"),2546 srtp_info->tx_policy.name.ptr);2547 if (len > 0 && len < end-p) {2548 p += len;2549 *p++ = '\n';2550 *p = '\0';2551 }2552 } else if (tp_info.spc_info[j].type==PJMEDIA_TRANSPORT_TYPE_ICE) {2553 const pjmedia_ice_transport_info *ii;2554 2555 ii = (const pjmedia_ice_transport_info*)2556 tp_info.spc_info[j].buffer;2557 2558 len = pj_ansi_snprintf(p, end-p,2559 " %s ICE role: %s, state: %s, comp_cnt: %u",2560 indent,2561 pj_ice_sess_role_name(ii->role),2562 pj_ice_strans_state_name(ii->sess_state),2563 ii->comp_cnt);2564 if (len > 0 && len < end-p) {2565 p += len;2566 *p++ = '\n';2567 *p = '\0';2568 }2569 }2570 }2571 }2572 }2573 2574 2575 if (has_stat) {2576 len = dump_media_stat(indent, p, end-p, &stat,2577 rx_info, tx_info);2578 p += len;2579 }2580 2581 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)2582 # define SAMPLES_TO_USEC(usec, samples, clock_rate) \2583 do { \2584 if (samples <= 4294) \2585 usec = samples * 1000000 / clock_rate; \2586 else { \2587 usec = samples * 1000 / clock_rate; \2588 usec *= 1000; \2589 } \2590 } while(0)2591 2592 # define PRINT_VOIP_MTC_VAL(s, v) \2593 if (v == 127) \2594 sprintf(s, "(na)"); \2595 else \2596 sprintf(s, "%d", v)2597 2598 # define VALIDATE_PRINT_BUF() \2599 if (len < 1 || len > end-p) { *p = '\0'; return; } \2600 p += len; *p++ = '\n'; *p = '\0'2601 2602 2603 if (call_med->type == PJMEDIA_TYPE_AUDIO) {2604 pjmedia_stream_info info;2605 char last_update[64];2606 char loss[16], dup[16];2607 char jitter[80];2608 char toh[80];2609 char plc[16], jba[16], jbr[16];2610 char signal_lvl[16], noise_lvl[16], rerl[16];2611 char r_factor[16], ext_r_factor[16], mos_lq[16], mos_cq[16];2612 pjmedia_rtcp_xr_stat xr_stat;2613 unsigned clock_rate;2614 pj_time_val now;2615 2616 if (pjmedia_stream_get_stat_xr(call_med->strm.a.stream,2617 &xr_stat) != PJ_SUCCESS)2618 {2619 continue;2620 }2621 2622 if (pjmedia_stream_get_info(call_med->strm.a.stream, &info)2623 != PJ_SUCCESS)2624 {2625 continue;2626 }2627 2628 clock_rate = info.fmt.clock_rate;2629 pj_gettimeofday(&now);2630 2631 len = pj_ansi_snprintf(p, end-p, "\n%s Extended reports:", indent);2632 VALIDATE_PRINT_BUF();2633 2634 /* Statistics Summary */2635 len = pj_ansi_snprintf(p, end-p, "%s Statistics Summary", indent);2636 VALIDATE_PRINT_BUF();2637 2638 if (xr_stat.rx.stat_sum.l)2639 sprintf(loss, "%d", xr_stat.rx.stat_sum.lost);2640 else2641 sprintf(loss, "(na)");2642 2643 if (xr_stat.rx.stat_sum.d)2644 sprintf(dup, "%d", xr_stat.rx.stat_sum.dup);2645 else2646 sprintf(dup, "(na)");2647 2648 if (xr_stat.rx.stat_sum.j) {2649 unsigned jmin, jmax, jmean, jdev;2650 2651 SAMPLES_TO_USEC(jmin, xr_stat.rx.stat_sum.jitter.min,2652 clock_rate);2653 SAMPLES_TO_USEC(jmax, xr_stat.rx.stat_sum.jitter.max,2654 clock_rate);2655 SAMPLES_TO_USEC(jmean, xr_stat.rx.stat_sum.jitter.mean,2656 clock_rate);2657 SAMPLES_TO_USEC(jdev,2658 pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.jitter),2659 clock_rate);2660 sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",2661 jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0);2662 } else2663 sprintf(jitter, "(report not available)");2664 2665 if (xr_stat.rx.stat_sum.t) {2666 sprintf(toh, "%11d %11d %11d %11d",2667 xr_stat.rx.stat_sum.toh.min,2668 xr_stat.rx.stat_sum.toh.mean,2669 xr_stat.rx.stat_sum.toh.max,2670 pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh));2671 } else2672 sprintf(toh, "(report not available)");2673 2674 if (xr_stat.rx.stat_sum.update.sec == 0)2675 strcpy(last_update, "never");2676 else {2677 pj_gettimeofday(&now);2678 PJ_TIME_VAL_SUB(now, xr_stat.rx.stat_sum.update);2679 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2680 now.sec / 3600,2681 (now.sec % 3600) / 60,2682 now.sec % 60,2683 now.msec);2684 }2685 2686 len = pj_ansi_snprintf(p, end-p,2687 "%s RX last update: %s\n"2688 "%s begin seq=%d, end seq=%d\n"2689 "%s pkt loss=%s, dup=%s\n"2690 "%s (msec) min avg max dev\n"2691 "%s jitter : %s\n"2692 "%s toh : %s",2693 indent, last_update,2694 indent,2695 xr_stat.rx.stat_sum.begin_seq, xr_stat.rx.stat_sum.end_seq,2696 indent, loss, dup,2697 indent,2698 indent, jitter,2699 indent, toh2700 );2701 VALIDATE_PRINT_BUF();2702 2703 if (xr_stat.tx.stat_sum.l)2704 sprintf(loss, "%d", xr_stat.tx.stat_sum.lost);2705 else2706 sprintf(loss, "(na)");2707 2708 if (xr_stat.tx.stat_sum.d)2709 sprintf(dup, "%d", xr_stat.tx.stat_sum.dup);2710 else2711 sprintf(dup, "(na)");2712 2713 if (xr_stat.tx.stat_sum.j) {2714 unsigned jmin, jmax, jmean, jdev;2715 2716 SAMPLES_TO_USEC(jmin, xr_stat.tx.stat_sum.jitter.min,2717 clock_rate);2718 SAMPLES_TO_USEC(jmax, xr_stat.tx.stat_sum.jitter.max,2719 clock_rate);2720 SAMPLES_TO_USEC(jmean, xr_stat.tx.stat_sum.jitter.mean,2721 clock_rate);2722 SAMPLES_TO_USEC(jdev,2723 pj_math_stat_get_stddev(&xr_stat.tx.stat_sum.jitter),2724 clock_rate);2725 sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",2726 jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0);2727 } else2728 sprintf(jitter, "(report not available)");2729 2730 if (xr_stat.tx.stat_sum.t) {2731 sprintf(toh, "%11d %11d %11d %11d",2732 xr_stat.tx.stat_sum.toh.min,2733 xr_stat.tx.stat_sum.toh.mean,2734 xr_stat.tx.stat_sum.toh.max,2735 pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh));2736 } else2737 sprintf(toh, "(report not available)");2738 2739 if (xr_stat.tx.stat_sum.update.sec == 0)2740 strcpy(last_update, "never");2741 else {2742 pj_gettimeofday(&now);2743 PJ_TIME_VAL_SUB(now, xr_stat.tx.stat_sum.update);2744 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2745 now.sec / 3600,2746 (now.sec % 3600) / 60,2747 now.sec % 60,2748 now.msec);2749 }2750 2751 len = pj_ansi_snprintf(p, end-p,2752 "%s TX last update: %s\n"2753 "%s begin seq=%d, end seq=%d\n"2754 "%s pkt loss=%s, dup=%s\n"2755 "%s (msec) min avg max dev\n"2756 "%s jitter : %s\n"2757 "%s toh : %s",2758 indent, last_update,2759 indent,2760 xr_stat.tx.stat_sum.begin_seq, xr_stat.tx.stat_sum.end_seq,2761 indent, loss, dup,2762 indent,2763 indent, jitter,2764 indent, toh2765 );2766 VALIDATE_PRINT_BUF();2767 2768 2769 /* VoIP Metrics */2770 len = pj_ansi_snprintf(p, end-p, "%s VoIP Metrics", indent);2771 VALIDATE_PRINT_BUF();2772 2773 PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.rx.voip_mtc.signal_lvl);2774 PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.rx.voip_mtc.noise_lvl);2775 PRINT_VOIP_MTC_VAL(rerl, xr_stat.rx.voip_mtc.rerl);2776 PRINT_VOIP_MTC_VAL(r_factor, xr_stat.rx.voip_mtc.r_factor);2777 PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.rx.voip_mtc.ext_r_factor);2778 PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.rx.voip_mtc.mos_lq);2779 PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.rx.voip_mtc.mos_cq);2780 2781 switch ((xr_stat.rx.voip_mtc.rx_config>>6) & 3) {2782 case PJMEDIA_RTCP_XR_PLC_DIS:2783 sprintf(plc, "DISABLED");2784 break;2785 case PJMEDIA_RTCP_XR_PLC_ENH:2786 sprintf(plc, "ENHANCED");2787 break;2788 case PJMEDIA_RTCP_XR_PLC_STD:2789 sprintf(plc, "STANDARD");2790 break;2791 case PJMEDIA_RTCP_XR_PLC_UNK:2792 default:2793 sprintf(plc, "UNKNOWN");2794 break;2795 }2796 2797 switch ((xr_stat.rx.voip_mtc.rx_config>>4) & 3) {2798 case PJMEDIA_RTCP_XR_JB_FIXED:2799 sprintf(jba, "FIXED");2800 break;2801 case PJMEDIA_RTCP_XR_JB_ADAPTIVE:2802 sprintf(jba, "ADAPTIVE");2803 break;2804 default:2805 sprintf(jba, "UNKNOWN");2806 break;2807 }2808 2809 sprintf(jbr, "%d", xr_stat.rx.voip_mtc.rx_config & 0x0F);2810 2811 if (xr_stat.rx.voip_mtc.update.sec == 0)2812 strcpy(last_update, "never");2813 else {2814 pj_gettimeofday(&now);2815 PJ_TIME_VAL_SUB(now, xr_stat.rx.voip_mtc.update);2816 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2817 now.sec / 3600,2818 (now.sec % 3600) / 60,2819 now.sec % 60,2820 now.msec);2821 }2822 2823 len = pj_ansi_snprintf(p, end-p,2824 "%s RX last update: %s\n"2825 "%s packets : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n"2826 "%s burst : density=%d (%.2f%%), duration=%d%s\n"2827 "%s gap : density=%d (%.2f%%), duration=%d%s\n"2828 "%s delay : round trip=%d%s, end system=%d%s\n"2829 "%s level : signal=%s%s, noise=%s%s, RERL=%s%s\n"2830 "%s quality : R factor=%s, ext R factor=%s\n"2831 "%s MOS LQ=%s, MOS CQ=%s\n"2832 "%s config : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n"2833 "%s JB delay : cur=%d%s, max=%d%s, abs max=%d%s",2834 indent,2835 last_update,2836 /* packets */2837 indent,2838 xr_stat.rx.voip_mtc.loss_rate, xr_stat.rx.voip_mtc.loss_rate*100.0/256,2839 xr_stat.rx.voip_mtc.discard_rate, xr_stat.rx.voip_mtc.discard_rate*100.0/256,2840 /* burst */2841 indent,2842 xr_stat.rx.voip_mtc.burst_den, xr_stat.rx.voip_mtc.burst_den*100.0/256,2843 xr_stat.rx.voip_mtc.burst_dur, "ms",2844 /* gap */2845 indent,2846 xr_stat.rx.voip_mtc.gap_den, xr_stat.rx.voip_mtc.gap_den*100.0/256,2847 xr_stat.rx.voip_mtc.gap_dur, "ms",2848 /* delay */2849 indent,2850 xr_stat.rx.voip_mtc.rnd_trip_delay, "ms",2851 xr_stat.rx.voip_mtc.end_sys_delay, "ms",2852 /* level */2853 indent,2854 signal_lvl, "dB",2855 noise_lvl, "dB",2856 rerl, "",2857 /* quality */2858 indent,2859 r_factor, ext_r_factor,2860 indent,2861 mos_lq, mos_cq,2862 /* config */2863 indent,2864 plc, jba, jbr, xr_stat.rx.voip_mtc.gmin,2865 /* JB delay */2866 indent,2867 xr_stat.rx.voip_mtc.jb_nom, "ms",2868 xr_stat.rx.voip_mtc.jb_max, "ms",2869 xr_stat.rx.voip_mtc.jb_abs_max, "ms"2870 );2871 VALIDATE_PRINT_BUF();2872 2873 PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.tx.voip_mtc.signal_lvl);2874 PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.tx.voip_mtc.noise_lvl);2875 PRINT_VOIP_MTC_VAL(rerl, xr_stat.tx.voip_mtc.rerl);2876 PRINT_VOIP_MTC_VAL(r_factor, xr_stat.tx.voip_mtc.r_factor);2877 PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.tx.voip_mtc.ext_r_factor);2878 PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.tx.voip_mtc.mos_lq);2879 PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.tx.voip_mtc.mos_cq);2880 2881 switch ((xr_stat.tx.voip_mtc.rx_config>>6) & 3) {2882 case PJMEDIA_RTCP_XR_PLC_DIS:2883 sprintf(plc, "DISABLED");2884 break;2885 case PJMEDIA_RTCP_XR_PLC_ENH:2886 sprintf(plc, "ENHANCED");2887 break;2888 case PJMEDIA_RTCP_XR_PLC_STD:2889 sprintf(plc, "STANDARD");2890 break;2891 case PJMEDIA_RTCP_XR_PLC_UNK:2892 default:2893 sprintf(plc, "unknown");2894 break;2895 }2896 2897 switch ((xr_stat.tx.voip_mtc.rx_config>>4) & 3) {2898 case PJMEDIA_RTCP_XR_JB_FIXED:2899 sprintf(jba, "FIXED");2900 break;2901 case PJMEDIA_RTCP_XR_JB_ADAPTIVE:2902 sprintf(jba, "ADAPTIVE");2903 break;2904 default:2905 sprintf(jba, "unknown");2906 break;2907 }2908 2909 sprintf(jbr, "%d", xr_stat.tx.voip_mtc.rx_config & 0x0F);2910 2911 if (xr_stat.tx.voip_mtc.update.sec == 0)2912 strcpy(last_update, "never");2913 else {2914 pj_gettimeofday(&now);2915 PJ_TIME_VAL_SUB(now, xr_stat.tx.voip_mtc.update);2916 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",2917 now.sec / 3600,2918 (now.sec % 3600) / 60,2919 now.sec % 60,2920 now.msec);2921 }2922 2923 len = pj_ansi_snprintf(p, end-p,2924 "%s TX last update: %s\n"2925 "%s packets : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n"2926 "%s burst : density=%d (%.2f%%), duration=%d%s\n"2927 "%s gap : density=%d (%.2f%%), duration=%d%s\n"2928 "%s delay : round trip=%d%s, end system=%d%s\n"2929 "%s level : signal=%s%s, noise=%s%s, RERL=%s%s\n"2930 "%s quality : R factor=%s, ext R factor=%s\n"2931 "%s MOS LQ=%s, MOS CQ=%s\n"2932 "%s config : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n"2933 "%s JB delay : cur=%d%s, max=%d%s, abs max=%d%s",2934 indent,2935 last_update,2936 /* pakcets */2937 indent,2938 xr_stat.tx.voip_mtc.loss_rate, xr_stat.tx.voip_mtc.loss_rate*100.0/256,2939 xr_stat.tx.voip_mtc.discard_rate, xr_stat.tx.voip_mtc.discard_rate*100.0/256,2940 /* burst */2941 indent,2942 xr_stat.tx.voip_mtc.burst_den, xr_stat.tx.voip_mtc.burst_den*100.0/256,2943 xr_stat.tx.voip_mtc.burst_dur, "ms",2944 /* gap */2945 indent,2946 xr_stat.tx.voip_mtc.gap_den, xr_stat.tx.voip_mtc.gap_den*100.0/256,2947 xr_stat.tx.voip_mtc.gap_dur, "ms",2948 /* delay */2949 indent,2950 xr_stat.tx.voip_mtc.rnd_trip_delay, "ms",2951 xr_stat.tx.voip_mtc.end_sys_delay, "ms",2952 /* level */2953 indent,2954 signal_lvl, "dB",2955 noise_lvl, "dB",2956 rerl, "",2957 /* quality */2958 indent,2959 r_factor, ext_r_factor,2960 indent,2961 mos_lq, mos_cq,2962 /* config */2963 indent,2964 plc, jba, jbr, xr_stat.tx.voip_mtc.gmin,2965 /* JB delay */2966 indent,2967 xr_stat.tx.voip_mtc.jb_nom, "ms",2968 xr_stat.tx.voip_mtc.jb_max, "ms",2969 xr_stat.tx.voip_mtc.jb_abs_max, "ms"2970 );2971 VALIDATE_PRINT_BUF();2972 2973 2974 /* RTT delay (by receiver side) */2975 len = pj_ansi_snprintf(p, end-p,2976 "%s RTT (from recv) min avg max last dev",2977 indent);2978 VALIDATE_PRINT_BUF();2979 len = pj_ansi_snprintf(p, end-p,2980 "%s RTT msec : %7.3f %7.3f %7.3f %7.3f %7.3f",2981 indent,2982 xr_stat.rtt.min / 1000.0,2983 xr_stat.rtt.mean / 1000.0,2984 xr_stat.rtt.max / 1000.0,2985 xr_stat.rtt.last / 1000.0,2986 pj_math_stat_get_stddev(&xr_stat.rtt) / 1000.02987 );2988 VALIDATE_PRINT_BUF();2989 } /* if audio */;2990 #endif2991 2992 }2993 }2994 2995 2996 /* Print call info */2997 void print_call(const char *title,2998 int call_id,2999 char *buf, pj_size_t size)3000 {3001 int len;3002 pjsip_inv_session *inv = pjsua_var.calls[call_id].inv;3003 pjsip_dialog *dlg = inv->dlg;3004 char userinfo[128];3005 3006 /* Dump invite sesion info. */3007 3008 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo));3009 if (len < 0)3010 pj_ansi_strcpy(userinfo, "<--uri too long-->");3011 else3012 userinfo[len] = '\0';3013 3014 len = pj_ansi_snprintf(buf, size, "%s[%s] %s",3015 title,3016 pjsip_inv_state_name(inv->state),3017 userinfo);3018 if (len < 1 || len >= (int)size) {3019 pj_ansi_strcpy(buf, "<--uri too long-->");3020 len = 18;3021 } else3022 buf[len] = '\0';3023 }3024 3025 3026 /*3027 * Dump call and media statistics to string.3028 */3029 PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,3030 pj_bool_t with_media,3031 char *buffer,3032 unsigned maxlen,3033 const char *indent)3034 {3035 pjsua_call *call;3036 pjsip_dialog *dlg;3037 pj_time_val duration, res_delay, con_delay;3038 char tmp[128];3039 char *p, *end;3040 pj_status_t status;3041 int len;3042 3043 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,3044 PJ_EINVAL);3045 3046 status = acquire_call("pjsua_call_dump()", call_id, &call, &dlg);3047 if (status != PJ_SUCCESS)3048 return status;3049 3050 *buffer = '\0';3051 p = buffer;3052 end = buffer + maxlen;3053 len = 0;3054 3055 print_call(indent, call_id, tmp, sizeof(tmp));3056 3057 len = pj_ansi_strlen(tmp);3058 pj_ansi_strcpy(buffer, tmp);3059 3060 p += len;3061 *p++ = '\r';3062 *p++ = '\n';3063 3064 /* Calculate call duration */3065 if (call->conn_time.sec != 0) {3066 pj_gettimeofday(&duration);3067 PJ_TIME_VAL_SUB(duration, call->conn_time);3068 con_delay = call->conn_time;3069 PJ_TIME_VAL_SUB(con_delay, call->start_time);3070 } else {3071 duration.sec = duration.msec = 0;3072 con_delay.sec = con_delay.msec = 0;3073 }3074 3075 /* Calculate first response delay */3076 if (call->res_time.sec != 0) {3077 res_delay = call->res_time;3078 PJ_TIME_VAL_SUB(res_delay, call->start_time);3079 } else {3080 res_delay.sec = res_delay.msec = 0;3081 }3082 3083 /* Print duration */3084 len = pj_ansi_snprintf(p, end-p,3085 "%s Call time: %02dh:%02dm:%02ds, "3086 "1st res in %d ms, conn in %dms",3087 indent,3088 (int)(duration.sec / 3600),3089 (int)((duration.sec % 3600)/60),3090 (int)(duration.sec % 60),3091 (int)PJ_TIME_VAL_MSEC(res_delay),3092 (int)PJ_TIME_VAL_MSEC(con_delay));3093 3094 if (len > 0 && len < end-p) {3095 p += len;3096 *p++ = '\n';3097 *p = '\0';3098 }3099 3100 /* Dump session statistics */3101 if (with_media && pjsua_call_has_media(call_id))3102 dump_media_session(indent, p, end-p, call);3103 3104 pjsip_dlg_dec_lock(dlg);3105 3106 return PJ_SUCCESS;3107 }3108 2162 3109 2163 /* Proto */
Note: See TracChangeset
for help on using the changeset viewer.