Ticket #513: xr.2.patch

File xr.2.patch, 39.4 KB (added by nanang, 16 years ago)
  • pjsip-apps/src/samples/streamutil.c

     
    168168    info.tx_pt = codec_info->pt; 
    169169    info.ssrc = pj_rand(); 
    170170     
     171#if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 
     172    /* Set default RTCP XR enabled/disabled */ 
     173    info.rtcp_xr_enabled = PJ_TRUE; 
     174#endif 
    171175 
    172176    /* Copy remote address */ 
    173177    pj_memcpy(&info.rem_addr, rem_addr, sizeof(pj_sockaddr_in)); 
     
    695699} 
    696700 
    697701 
     702#define SAMPLES_TO_USEC(usec, samples, clock_rate) \ 
     703    do { \ 
     704        if (samples <= 4294) \ 
     705            usec = samples * 1000000 / clock_rate; \ 
     706        else { \ 
     707            usec = samples * 1000 / clock_rate; \ 
     708            usec *= 1000; \ 
     709        } \ 
     710    } while(0) 
    698711 
     712#define PRINT_VOIP_MTC_VAL(s, v) \ 
     713    if (v == 127) \ 
     714        sprintf(s, "(na)"); \ 
     715    else \ 
     716        sprintf(s, "%d", v) 
     717 
     718 
    699719/* 
    700720 * Print stream statistics 
    701721 */ 
     
    827847           "" 
    828848           ); 
    829849 
     850#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     851    /* RTCP XR Reports */ 
     852    do { 
     853        char loss[16], dup[16]; 
     854        char jitter[80]; 
     855        char toh[80]; 
     856        char plc[16], jba[16], jbr[16]; 
     857        char signal_lvl[16], noise_lvl[16], rerl[16]; 
     858        char r_factor[16], ext_r_factor[16], mos_lq[16], mos_cq[16]; 
     859        pjmedia_rtcp_xr_stat xr_stat; 
     860 
     861        if (pjmedia_stream_get_stat_xr(stream, &xr_stat) != PJ_SUCCESS) 
     862            break; 
     863 
     864        puts("\nExtended reports:"); 
     865 
     866        /* Statistics Summary */ 
     867        puts(" Statistics Summary"); 
     868 
     869        if (xr_stat.rx.stat_sum.l) 
     870            sprintf(loss, "%d", xr_stat.rx.stat_sum.lost); 
     871        else 
     872            sprintf(loss, "(na)"); 
     873 
     874        if (xr_stat.rx.stat_sum.d) 
     875            sprintf(dup, "%d", xr_stat.rx.stat_sum.dup); 
     876        else 
     877            sprintf(dup, "(na)"); 
     878 
     879        if (xr_stat.rx.stat_sum.j) { 
     880            unsigned jmin, jmax, jmean, jdev; 
     881 
     882            SAMPLES_TO_USEC(jmin, xr_stat.rx.stat_sum.jitter.min,  
     883                            port->info.clock_rate); 
     884            SAMPLES_TO_USEC(jmax, xr_stat.rx.stat_sum.jitter.max,  
     885                            port->info.clock_rate); 
     886            SAMPLES_TO_USEC(jmean, xr_stat.rx.stat_sum.jitter.mean,  
     887                            port->info.clock_rate); 
     888            SAMPLES_TO_USEC(jdev, xr_stat.rx.stat_sum.jitter.dev,  
     889                            port->info.clock_rate); 
     890            sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",  
     891                    jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0); 
     892        } else 
     893            sprintf(jitter, "(report not available)"); 
     894 
     895        if (xr_stat.rx.stat_sum.t) { 
     896            sprintf(toh, "%11d %11d %11d %11d",  
     897                    xr_stat.rx.stat_sum.toh.min, 
     898                    xr_stat.rx.stat_sum.toh.mean, 
     899                    xr_stat.rx.stat_sum.toh.max, 
     900                    xr_stat.rx.stat_sum.toh.dev); 
     901        } else 
     902            sprintf(toh, "(report not available)"); 
     903 
     904        if (xr_stat.rx.stat_sum.update.sec == 0) 
     905            strcpy(last_update, "never"); 
     906        else { 
     907            pj_gettimeofday(&now); 
     908            PJ_TIME_VAL_SUB(now, xr_stat.rx.stat_sum.update); 
     909            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     910                    now.sec / 3600, 
     911                    (now.sec % 3600) / 60, 
     912                    now.sec % 60, 
     913                    now.msec); 
     914        } 
     915 
     916        printf(" RX last update: %s\n" 
     917               "    begin seq=%d, end seq=%d%s\n" 
     918               "    pkt loss=%s, dup=%s%s\n" 
     919               "          (msec)    min     avg     max     dev\n" 
     920               "    jitter     : %s\n" 
     921               "    toh        : %s\n", 
     922               last_update, 
     923               xr_stat.rx.stat_sum.begin_seq, xr_stat.rx.stat_sum.end_seq, 
     924               "", 
     925               loss, dup, 
     926               "", 
     927               jitter, 
     928               toh 
     929               ); 
     930 
     931        if (xr_stat.tx.stat_sum.l) 
     932            sprintf(loss, "%d", xr_stat.tx.stat_sum.lost); 
     933        else 
     934            sprintf(loss, "(na)"); 
     935 
     936        if (xr_stat.tx.stat_sum.d) 
     937            sprintf(dup, "%d", xr_stat.tx.stat_sum.dup); 
     938        else 
     939            sprintf(dup, "(na)"); 
     940 
     941        if (xr_stat.tx.stat_sum.j) { 
     942            unsigned jmin, jmax, jmean, jdev; 
     943 
     944            SAMPLES_TO_USEC(jmin, xr_stat.tx.stat_sum.jitter.min,  
     945                            port->info.clock_rate); 
     946            SAMPLES_TO_USEC(jmax, xr_stat.tx.stat_sum.jitter.max,  
     947                            port->info.clock_rate); 
     948            SAMPLES_TO_USEC(jmean, xr_stat.tx.stat_sum.jitter.mean,  
     949                            port->info.clock_rate); 
     950            SAMPLES_TO_USEC(jdev, xr_stat.tx.stat_sum.jitter.dev,  
     951                            port->info.clock_rate); 
     952            sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",  
     953                    jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0); 
     954        } else 
     955            sprintf(jitter, "(report not available)"); 
     956 
     957        if (xr_stat.tx.stat_sum.t) { 
     958            sprintf(toh, "%11d %11d %11d %11d",  
     959                    xr_stat.tx.stat_sum.toh.min, 
     960                    xr_stat.tx.stat_sum.toh.mean, 
     961                    xr_stat.tx.stat_sum.toh.max, 
     962                    xr_stat.tx.stat_sum.toh.dev); 
     963        } else 
     964            sprintf(toh,    "(report not available)"); 
     965 
     966        if (xr_stat.tx.stat_sum.update.sec == 0) 
     967            strcpy(last_update, "never"); 
     968        else { 
     969            pj_gettimeofday(&now); 
     970            PJ_TIME_VAL_SUB(now, xr_stat.tx.stat_sum.update); 
     971            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     972                    now.sec / 3600, 
     973                    (now.sec % 3600) / 60, 
     974                    now.sec % 60, 
     975                    now.msec); 
     976        } 
     977 
     978        printf(" TX last update: %s\n" 
     979               "    begin seq=%d, end seq=%d%s\n" 
     980               "    pkt loss=%s, dup=%s%s\n" 
     981               "          (msec)    min     avg     max     dev\n" 
     982               "    jitter     : %s\n" 
     983               "    toh        : %s\n", 
     984               last_update, 
     985               xr_stat.tx.stat_sum.begin_seq, xr_stat.tx.stat_sum.end_seq, 
     986               "", 
     987               loss, dup, 
     988               "", 
     989               jitter, 
     990               toh 
     991               ); 
     992 
     993        /* VoIP Metrics */ 
     994        puts(" VoIP Metrics"); 
     995 
     996        PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.rx.voip_mtc.signal_lvl); 
     997        PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.rx.voip_mtc.noise_lvl); 
     998        PRINT_VOIP_MTC_VAL(rerl, xr_stat.rx.voip_mtc.rerl); 
     999        PRINT_VOIP_MTC_VAL(r_factor, xr_stat.rx.voip_mtc.r_factor); 
     1000        PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.rx.voip_mtc.ext_r_factor); 
     1001        PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.rx.voip_mtc.mos_lq); 
     1002        PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.rx.voip_mtc.mos_cq); 
     1003 
     1004        switch ((xr_stat.rx.voip_mtc.rx_config>>6) & 3) { 
     1005            case PJMEDIA_RTCP_XR_PLC_DIS: 
     1006                sprintf(plc, "DISABLED"); 
     1007                break; 
     1008            case PJMEDIA_RTCP_XR_PLC_ENH: 
     1009                sprintf(plc, "ENHANCED"); 
     1010                break; 
     1011            case PJMEDIA_RTCP_XR_PLC_STD: 
     1012                sprintf(plc, "STANDARD"); 
     1013                break; 
     1014            case PJMEDIA_RTCP_XR_PLC_UNK: 
     1015            default: 
     1016                sprintf(plc, "UNKNOWN"); 
     1017                break; 
     1018        } 
     1019 
     1020        switch ((xr_stat.rx.voip_mtc.rx_config>>4) & 3) { 
     1021            case PJMEDIA_RTCP_XR_JB_FIXED: 
     1022                sprintf(jba, "FIXED"); 
     1023                break; 
     1024            case PJMEDIA_RTCP_XR_JB_ADAPTIVE: 
     1025                sprintf(jba, "ADAPTIVE"); 
     1026                break; 
     1027            default: 
     1028                sprintf(jba, "UNKNOWN"); 
     1029                break; 
     1030        } 
     1031 
     1032        sprintf(jbr, "%d", xr_stat.rx.voip_mtc.rx_config & 0x0F); 
     1033 
     1034        if (xr_stat.rx.voip_mtc.update.sec == 0) 
     1035            strcpy(last_update, "never"); 
     1036        else { 
     1037            pj_gettimeofday(&now); 
     1038            PJ_TIME_VAL_SUB(now, xr_stat.rx.voip_mtc.update); 
     1039            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1040                    now.sec / 3600, 
     1041                    (now.sec % 3600) / 60, 
     1042                    now.sec % 60, 
     1043                    now.msec); 
     1044        } 
     1045 
     1046        printf(" RX last update: %s\n" 
     1047               "    packets    : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n" 
     1048               "    burst      : density=%d (%.2f%%), duration=%d%s\n" 
     1049               "    gap        : density=%d (%.2f%%), duration=%d%s\n" 
     1050               "    delay      : round trip=%d%s, end system=%d%s\n" 
     1051               "    level      : signal=%s%s, noise=%s%s, RERL=%s%s\n" 
     1052               "    quality    : R factor=%s, ext R factor=%s\n" 
     1053               "                 MOS LQ=%s, MOS CQ=%s\n" 
     1054               "    config     : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n" 
     1055               "    JB delay   : cur=%d%s, max=%d%s, abs max=%d%s\n", 
     1056               last_update, 
     1057               /* pakcets */ 
     1058               xr_stat.rx.voip_mtc.loss_rate, xr_stat.rx.voip_mtc.loss_rate*100.0/256, 
     1059               xr_stat.rx.voip_mtc.discard_rate, xr_stat.rx.voip_mtc.discard_rate*100.0/256, 
     1060               /* burst */ 
     1061               xr_stat.rx.voip_mtc.burst_den, xr_stat.rx.voip_mtc.burst_den*100.0/256, 
     1062               xr_stat.rx.voip_mtc.burst_dur, "ms", 
     1063               /* gap */ 
     1064               xr_stat.rx.voip_mtc.gap_den, xr_stat.rx.voip_mtc.gap_den*100.0/256, 
     1065               xr_stat.rx.voip_mtc.gap_dur, "ms", 
     1066               /* delay */ 
     1067               xr_stat.rx.voip_mtc.rnd_trip_delay, "ms", 
     1068               xr_stat.rx.voip_mtc.end_sys_delay, "ms", 
     1069               /* level */ 
     1070               signal_lvl, "dB", 
     1071               noise_lvl, "dB", 
     1072               rerl, "", 
     1073               /* quality */ 
     1074               r_factor, ext_r_factor, mos_lq, mos_cq, 
     1075               /* config */ 
     1076               plc, jba, jbr, xr_stat.rx.voip_mtc.gmin, 
     1077               /* JB delay */ 
     1078               xr_stat.rx.voip_mtc.jb_nom, "ms", 
     1079               xr_stat.rx.voip_mtc.jb_max, "ms", 
     1080               xr_stat.rx.voip_mtc.jb_abs_max, "ms" 
     1081               ); 
     1082 
     1083        PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.tx.voip_mtc.signal_lvl); 
     1084        PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.tx.voip_mtc.noise_lvl); 
     1085        PRINT_VOIP_MTC_VAL(rerl, xr_stat.tx.voip_mtc.rerl); 
     1086        PRINT_VOIP_MTC_VAL(r_factor, xr_stat.tx.voip_mtc.r_factor); 
     1087        PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.tx.voip_mtc.ext_r_factor); 
     1088        PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.tx.voip_mtc.mos_lq); 
     1089        PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.tx.voip_mtc.mos_cq); 
     1090 
     1091        switch ((xr_stat.tx.voip_mtc.rx_config>>6) & 3) { 
     1092            case PJMEDIA_RTCP_XR_PLC_DIS: 
     1093                sprintf(plc, "DISABLED"); 
     1094                break; 
     1095            case PJMEDIA_RTCP_XR_PLC_ENH: 
     1096                sprintf(plc, "ENHANCED"); 
     1097                break; 
     1098            case PJMEDIA_RTCP_XR_PLC_STD: 
     1099                sprintf(plc, "STANDARD"); 
     1100                break; 
     1101            case PJMEDIA_RTCP_XR_PLC_UNK: 
     1102            default: 
     1103                sprintf(plc, "unknown"); 
     1104                break; 
     1105        } 
     1106 
     1107        switch ((xr_stat.tx.voip_mtc.rx_config>>4) & 3) { 
     1108            case PJMEDIA_RTCP_XR_JB_FIXED: 
     1109                sprintf(jba, "FIXED"); 
     1110                break; 
     1111            case PJMEDIA_RTCP_XR_JB_ADAPTIVE: 
     1112                sprintf(jba, "ADAPTIVE"); 
     1113                break; 
     1114            default: 
     1115                sprintf(jba, "unknown"); 
     1116                break; 
     1117        } 
     1118 
     1119        sprintf(jbr, "%d", xr_stat.tx.voip_mtc.rx_config & 0x0F); 
     1120 
     1121        if (xr_stat.tx.voip_mtc.update.sec == 0) 
     1122            strcpy(last_update, "never"); 
     1123        else { 
     1124            pj_gettimeofday(&now); 
     1125            PJ_TIME_VAL_SUB(now, xr_stat.tx.voip_mtc.update); 
     1126            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1127                    now.sec / 3600, 
     1128                    (now.sec % 3600) / 60, 
     1129                    now.sec % 60, 
     1130                    now.msec); 
     1131        } 
     1132 
     1133        printf(" TX last update: %s\n" 
     1134               "    packets    : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n" 
     1135               "    burst      : density=%d (%.2f%%), duration=%d%s\n" 
     1136               "    gap        : density=%d (%.2f%%), duration=%d%s\n" 
     1137               "    delay      : round trip=%d%s, end system=%d%s\n" 
     1138               "    level      : signal=%s%s, noise=%s%s, RERL=%s%s\n" 
     1139               "    quality    : R factor=%s, ext R factor=%s\n" 
     1140               "                 MOS LQ=%s, MOS CQ=%s\n" 
     1141               "    config     : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n" 
     1142               "    JB delay   : cur=%d%s, max=%d%s, abs max=%d%s\n", 
     1143               last_update, 
     1144               /* pakcets */ 
     1145               xr_stat.tx.voip_mtc.loss_rate, xr_stat.tx.voip_mtc.loss_rate*100.0/256, 
     1146               xr_stat.tx.voip_mtc.discard_rate, xr_stat.tx.voip_mtc.discard_rate*100.0/256, 
     1147               /* burst */ 
     1148               xr_stat.tx.voip_mtc.burst_den, xr_stat.tx.voip_mtc.burst_den*100.0/256, 
     1149               xr_stat.tx.voip_mtc.burst_dur, "ms", 
     1150               /* gap */ 
     1151               xr_stat.tx.voip_mtc.gap_den, xr_stat.tx.voip_mtc.gap_den*100.0/256, 
     1152               xr_stat.tx.voip_mtc.gap_dur, "ms", 
     1153               /* delay */ 
     1154               xr_stat.tx.voip_mtc.rnd_trip_delay, "ms", 
     1155               xr_stat.tx.voip_mtc.end_sys_delay, "ms", 
     1156               /* level */ 
     1157               signal_lvl, "dB", 
     1158               noise_lvl, "dB", 
     1159               rerl, "", 
     1160               /* quality */ 
     1161               r_factor, ext_r_factor, mos_lq, mos_cq, 
     1162               /* config */ 
     1163               plc, jba, jbr, xr_stat.tx.voip_mtc.gmin, 
     1164               /* JB delay */ 
     1165               xr_stat.tx.voip_mtc.jb_nom, "ms", 
     1166               xr_stat.tx.voip_mtc.jb_max, "ms", 
     1167               xr_stat.tx.voip_mtc.jb_abs_max, "ms" 
     1168               ); 
     1169 
     1170 
     1171        /* RTT delay, need this? */ 
     1172        printf("          (msec)    min     avg     max     last\n"); 
     1173        printf(" RTT delay     : %7.3f %7.3f %7.3f %7.3f%s\n",  
     1174               xr_stat.rtt.min / 1000.0, 
     1175               xr_stat.rtt.avg / 1000.0, 
     1176               xr_stat.rtt.max / 1000.0, 
     1177               xr_stat.rtt.last / 1000.0, 
     1178               "" 
     1179               ); 
     1180    } while (0); 
     1181#endif /* PJMEDIA_HAS_RTCP_XR */ 
     1182 
    8301183} 
    8311184 
  • pjmedia/include/pjmedia/rtcp_xr.h

     
    229229typedef struct pjmedia_rtcp_xr_stream_stat 
    230230{ 
    231231    struct { 
    232         pj_uint32_t         begin_seq; 
    233         pj_uint32_t         end_seq; 
     232        pj_time_val         update;     /**< Time of last update.           */ 
     233 
     234        pj_uint32_t         begin_seq;  /**< Begin # seq of this interval.  */ 
     235        pj_uint32_t         end_seq;    /**< End # seq of this interval.    */ 
    234236        unsigned            count;      /**< Number of packets.             */ 
    235237 
    236238        /** 
     
    263265    } stat_sum; 
    264266 
    265267    struct { 
     268        pj_time_val         update;         /**< Time of last update.       */ 
     269 
    266270        pj_uint8_t          loss_rate;      /**< Packet loss rate           */ 
    267271        pj_uint8_t          discard_rate;   /**< Packet discarded rate      */ 
    268272        pj_uint8_t          burst_den;      /**< Burst density              */ 
     
    271275        pj_uint16_t         gap_dur;        /**< Gap duration               */ 
    272276        pj_uint16_t         rnd_trip_delay; /**< Round trip delay           */ 
    273277        pj_uint16_t         end_sys_delay;  /**< End system delay           */ 
    274         pj_uint8_t          signal_lvl;     /**< Signal level               */ 
    275         pj_uint8_t          noise_lvl;      /**< Noise level                */ 
     278        pj_int8_t           signal_lvl;     /**< Signal level               */ 
     279        pj_int8_t           noise_lvl;      /**< Noise level                */ 
    276280        pj_uint8_t          rerl;           /**< Residual Echo Return Loss  */ 
    277281        pj_uint8_t          gmin;           /**< The gap threshold          */ 
    278282        pj_uint8_t          r_factor;       /**< Voice quality metric carried 
  • pjmedia/include/pjmedia/stream.h

     
    9595    pj_sockaddr         rem_rtcp;   /**< Optional remote RTCP address. If 
    9696                                         sin_family is zero, the RTP address 
    9797                                         will be calculated from RTP.       */ 
     98#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     99    pj_bool_t           rtcp_xr_enabled; 
     100                                    /**< Specify whether RTCP XR is enabled.*/ 
     101#endif 
    98102    pjmedia_codec_info  fmt;        /**< Incoming codec format info.        */ 
    99103    pjmedia_codec_param *param;     /**< Optional codec param.              */ 
    100104    unsigned            tx_pt;      /**< Outgoing codec paylaod type.       */ 
     
    206210PJ_DECL(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 
    207211                                              pjmedia_rtcp_stat *stat); 
    208212 
     213#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
    209214/** 
     215 * Get the stream extended report statistics (RTCP XR). 
     216 * 
     217 * @param stream        The media stream. 
     218 * @param stat          Media stream extended report statistics. 
     219 * 
     220 * @return              PJ_SUCCESS on success. 
     221 */ 
     222PJ_DECL(pj_status_t) pjmedia_stream_get_stat_xr( const pjmedia_stream *stream, 
     223                                                 pjmedia_rtcp_xr_stat *stat); 
     224#endif 
     225 
     226/** 
    210227 * Pause the individual channel in the stream. 
    211228 * 
    212229 * @param stream        The media channel. 
  • pjmedia/src/pjmedia/rtcp_xr.c

     
    8686{ 
    8787    pj_bzero(session, sizeof(pjmedia_rtcp_xr_session)); 
    8888 
     89    session->name = parent_session->name; 
    8990    session->rtcp_session = parent_session; 
    9091    pj_memcpy(&session->pkt.common, &session->rtcp_session->rtcp_sr_pkt.common, 
    9192              sizeof(pjmedia_rtcp_common)); 
    9293    session->pkt.common.pt = RTCP_XR; 
    9394 
    9495    /* Init config */ 
    95     session->stat.tx.voip_mtc.gmin = (pj_uint8_t)(gmin? gmin : DEFAULT_GMIN); 
     96    session->stat.rx.voip_mtc.gmin = (pj_uint8_t)(gmin? gmin : DEFAULT_GMIN); 
    9697    session->ptime = session->rtcp_session->pkt_size * 1000 /  
    9798                     session->rtcp_session->clock_rate; 
    9899    session->frames_per_packet = frames_per_packet; 
    99100 
    100101    /* Init Statistics Summary fields which have non-zero default */ 
    101     session->stat.tx.stat_sum.jitter.min = (unsigned) -1; 
    102     session->stat.tx.stat_sum.toh.min = (unsigned) -1; 
     102    session->stat.rx.stat_sum.jitter.min = (unsigned) -1; 
     103    session->stat.rx.stat_sum.toh.min = (unsigned) -1; 
    103104 
    104105    /* Init VoIP Metrics fields which have non-zero default */ 
     106    session->stat.rx.voip_mtc.signal_lvl = 127; 
     107    session->stat.rx.voip_mtc.noise_lvl = 127; 
     108    session->stat.rx.voip_mtc.rerl = 127; 
     109    session->stat.rx.voip_mtc.r_factor = 127; 
     110    session->stat.rx.voip_mtc.ext_r_factor = 127; 
     111    session->stat.rx.voip_mtc.mos_lq = 127; 
     112    session->stat.rx.voip_mtc.mos_cq = 127; 
     113 
    105114    session->stat.tx.voip_mtc.signal_lvl = 127; 
    106115    session->stat.tx.voip_mtc.noise_lvl = 127; 
    107116    session->stat.tx.voip_mtc.rerl = 127; 
     
    189198    /* Statistics Summary Block */ 
    190199    /* Build this block if we have received packets since last build */ 
    191200    if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_STATS)) && 
    192         sess->stat.tx.stat_sum.count > 0) 
     201        sess->stat.rx.stat_sum.count > 0) 
    193202    { 
    194203        pjmedia_rtcp_xr_rb_stats *r; 
    195204        pj_uint8_t specific = 0; 
     
    198207        pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_stats)); 
    199208 
    200209        /* Init block header */ 
    201         specific |= sess->stat.tx.stat_sum.l ? (1 << 7) : 0; 
    202         specific |= sess->stat.tx.stat_sum.d ? (1 << 6) : 0; 
    203         specific |= sess->stat.tx.stat_sum.j ? (1 << 5) : 0; 
    204         specific |= (sess->stat.tx.stat_sum.t & 3) << 3; 
     210        specific |= sess->stat.rx.stat_sum.l ? (1 << 7) : 0; 
     211        specific |= sess->stat.rx.stat_sum.d ? (1 << 6) : 0; 
     212        specific |= sess->stat.rx.stat_sum.j ? (1 << 5) : 0; 
     213        specific |= (sess->stat.rx.stat_sum.t & 3) << 3; 
    205214        r->header.bt = BT_STATS; 
    206215        r->header.specific = specific; 
    207216        r->header.length = pj_htons(9); 
     
    209218        /* Generate block contents */ 
    210219        r->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc); 
    211220        r->begin_seq = pj_htons((pj_uint16_t) 
    212                                 (sess->stat.tx.stat_sum.begin_seq & 0xFFFF)); 
     221                                (sess->stat.rx.stat_sum.begin_seq & 0xFFFF)); 
    213222        r->end_seq = pj_htons((pj_uint16_t) 
    214                               (sess->stat.tx.stat_sum.end_seq & 0xFFFF)); 
    215         if (sess->stat.tx.stat_sum.l) { 
    216             r->lost = pj_htonl(sess->stat.tx.stat_sum.lost); 
     223                              (sess->stat.rx.stat_sum.end_seq & 0xFFFF)); 
     224        if (sess->stat.rx.stat_sum.l) { 
     225            r->lost = pj_htonl(sess->stat.rx.stat_sum.lost); 
    217226        } 
    218         if (sess->stat.tx.stat_sum.d) { 
    219             r->dup = pj_htonl(sess->stat.tx.stat_sum.dup); 
     227        if (sess->stat.rx.stat_sum.d) { 
     228            r->dup = pj_htonl(sess->stat.rx.stat_sum.dup); 
    220229        } 
    221         if (sess->stat.tx.stat_sum.j) { 
    222             r->jitter_min = pj_htonl(sess->stat.tx.stat_sum.jitter.min); 
    223             r->jitter_max = pj_htonl(sess->stat.tx.stat_sum.jitter.max); 
    224             r->jitter_mean = pj_htonl(sess->stat.tx.stat_sum.jitter.mean); 
    225             sess->stat.tx.stat_sum.jitter.dev =  
    226                                 my_isqrt(sess->stat.tx.stat_sum.jitter.dev); 
    227             r->jitter_dev = pj_htonl(sess->stat.tx.stat_sum.jitter.dev); 
     230        if (sess->stat.rx.stat_sum.j) { 
     231            r->jitter_min = pj_htonl(sess->stat.rx.stat_sum.jitter.min); 
     232            r->jitter_max = pj_htonl(sess->stat.rx.stat_sum.jitter.max); 
     233            r->jitter_mean = pj_htonl(sess->stat.rx.stat_sum.jitter.mean); 
     234            sess->stat.rx.stat_sum.jitter.dev =  
     235                                my_isqrt(sess->stat.rx.stat_sum.jitter.dev); 
     236            r->jitter_dev = pj_htonl(sess->stat.rx.stat_sum.jitter.dev); 
    228237        } 
    229         if (sess->stat.tx.stat_sum.t) { 
    230             r->toh_min = sess->stat.tx.stat_sum.toh.min; 
    231             r->toh_max = sess->stat.tx.stat_sum.toh.max; 
    232             r->toh_mean = sess->stat.tx.stat_sum.toh.mean; 
    233             sess->stat.tx.stat_sum.toh.dev =  
    234                                 my_isqrt(sess->stat.tx.stat_sum.toh.dev); 
    235             r->toh_dev = sess->stat.tx.stat_sum.toh.dev; 
     238        if (sess->stat.rx.stat_sum.t) { 
     239            r->toh_min = sess->stat.rx.stat_sum.toh.min; 
     240            r->toh_max = sess->stat.rx.stat_sum.toh.max; 
     241            r->toh_mean = sess->stat.rx.stat_sum.toh.mean; 
     242            sess->stat.rx.stat_sum.toh.dev =  
     243                                my_isqrt(sess->stat.rx.stat_sum.toh.dev); 
     244            r->toh_dev = sess->stat.rx.stat_sum.toh.dev; 
    236245        } 
    237246 
    238247        /* Reset TX statistics summary each time built */ 
    239         pj_bzero(&sess->stat.tx.stat_sum, sizeof(sess->stat.tx.stat_sum)); 
    240         sess->stat.tx.stat_sum.jitter.min = (unsigned) -1; 
    241         sess->stat.tx.stat_sum.toh.min = (unsigned) -1; 
     248        pj_bzero(&sess->stat.rx.stat_sum, sizeof(sess->stat.rx.stat_sum)); 
     249        sess->stat.rx.stat_sum.jitter.min = (unsigned) -1; 
     250        sess->stat.rx.stat_sum.toh.min = (unsigned) -1; 
    242251 
    243252        /* Finally */ 
    244253        size += sizeof(pjmedia_rtcp_xr_rb_stats); 
     254        pj_gettimeofday(&sess->stat.rx.stat_sum.update); 
    245255    } 
    246256 
    247257    /* Voip Metrics Block */ 
     
    288298            } else { 
    289299                p23 = 1 - c22/(c22 + c23); 
    290300            } 
    291             sess->stat.tx.voip_mtc.burst_den = (pj_uint8_t)(256*p23/(p23 + p32)); 
    292             sess->stat.tx.voip_mtc.gap_den = (pj_uint8_t)(256*c14/(c11 + c14)); 
     301            sess->stat.rx.voip_mtc.burst_den = (pj_uint8_t)(256*p23/(p23 + p32)); 
     302            sess->stat.rx.voip_mtc.gap_den = (pj_uint8_t)(256*c14/(c11 + c14)); 
    293303 
    294304            /* Calculate burst and gap durations in ms */ 
    295             sess->stat.tx.voip_mtc.gap_dur = (pj_uint16_t)((c11+c14+c13)*m/c13); 
    296             sess->stat.tx.voip_mtc.burst_dur = (pj_uint16_t)(ctotal*m/c13 -  
    297                                                sess->stat.tx.voip_mtc.gap_dur); 
     305            sess->stat.rx.voip_mtc.gap_dur = (pj_uint16_t)((c11+c14+c13)*m/c13); 
     306            sess->stat.rx.voip_mtc.burst_dur = (pj_uint16_t)(ctotal*m/c13 -  
     307                                               sess->stat.rx.voip_mtc.gap_dur); 
    298308        } else { 
    299309            /* No burst occurred yet until this time? 
    300310             * Just report full gap. 
    301311             */ 
    302             ctotal = sess->rtcp_session->stat.rx.pkt; 
     312            ctotal = sess->rtcp_session->stat.rx.pkt +  
     313                     sess->voip_mtc_stat.loss_count + 
     314                     sess->voip_mtc_stat.discard_count; 
    303315 
    304             sess->stat.tx.voip_mtc.burst_den = 0; 
    305             sess->stat.tx.voip_mtc.gap_den = (pj_uint8_t)(256 *  
     316            sess->stat.rx.voip_mtc.burst_den = 0; 
     317            sess->stat.rx.voip_mtc.gap_den = (pj_uint8_t)(256 *  
    306318                                        (sess->voip_mtc_stat.loss_count +  
    307319                                        sess->voip_mtc_stat.discard_count) /  
    308320                                        ctotal); 
    309321 
    310322            /* Calculate burst and gap durations in ms */ 
    311             sess->stat.tx.voip_mtc.gap_dur = (pj_uint16_t)((m*ctotal) < 0xFFFF? 
     323            sess->stat.rx.voip_mtc.gap_dur = (pj_uint16_t)((m*ctotal) < 0xFFFF? 
    312324                                             (m*ctotal) : 0xFFFF); 
    313             sess->stat.tx.voip_mtc.burst_dur = 0; 
     325            sess->stat.rx.voip_mtc.burst_dur = 0; 
    314326        } 
    315327 
    316328        /* Calculate loss and discard rates */ 
    317         sess->stat.tx.voip_mtc.loss_rate = (pj_uint8_t) 
     329        sess->stat.rx.voip_mtc.loss_rate = (pj_uint8_t) 
    318330                             (256 * sess->voip_mtc_stat.loss_count / ctotal); 
    319         sess->stat.tx.voip_mtc.discard_rate = (pj_uint8_t) 
     331        sess->stat.rx.voip_mtc.discard_rate = (pj_uint8_t) 
    320332                             (256 * sess->voip_mtc_stat.discard_count / ctotal); 
    321333 
    322334        /* Set round trip delay (in ms) to RTT calculated after receiving 
    323335         * DLRR or DLSR. 
    324336         */ 
    325337        if (sess->stat.rtt.last) 
    326             sess->stat.tx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 
     338            sess->stat.rx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 
    327339                                    (sess->stat.rtt.last / 1000); 
    328340        else if (sess->rtcp_session->stat.rtt.last) 
    329             sess->stat.tx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 
     341            sess->stat.rx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 
    330342                                    (sess->rtcp_session->stat.rtt.last / 1000); 
    331343         
    332344        /* End system delay estimation = RTT/2 + current jitter buffer size + 
     
    336348         * Since it is difficult to get the exact value of EXTRA, estimation 
    337349         * is taken to be totally around 50 ms. 
    338350         */ 
    339         sess->stat.tx.voip_mtc.end_sys_delay = (pj_uint16_t) 
    340                                 (sess->stat.tx.voip_mtc.rnd_trip_delay / 2 + 
    341                                  sess->stat.tx.voip_mtc.jb_nom + 50); 
     351        sess->stat.rx.voip_mtc.end_sys_delay = (pj_uint16_t) 
     352                                (sess->stat.rx.voip_mtc.rnd_trip_delay / 2 + 
     353                                 sess->stat.rx.voip_mtc.jb_nom + 50); 
    342354 
    343355        /* Generate block contents */ 
    344356        r->ssrc             = pj_htonl(sess->rtcp_session->peer_ssrc); 
    345         r->loss_rate        = sess->stat.tx.voip_mtc.loss_rate; 
    346         r->discard_rate     = sess->stat.tx.voip_mtc.discard_rate; 
    347         r->burst_den        = sess->stat.tx.voip_mtc.burst_den; 
    348         r->gap_den          = sess->stat.tx.voip_mtc.gap_den; 
    349         r->burst_dur        = pj_htons(sess->stat.tx.voip_mtc.burst_dur); 
    350         r->gap_dur          = pj_htons(sess->stat.tx.voip_mtc.gap_dur); 
    351         r->rnd_trip_delay   = pj_htons(sess->stat.tx.voip_mtc.rnd_trip_delay); 
    352         r->end_sys_delay    = pj_htons(sess->stat.tx.voip_mtc.end_sys_delay); 
    353         r->signal_lvl       = sess->stat.tx.voip_mtc.signal_lvl; 
    354         r->noise_lvl        = sess->stat.tx.voip_mtc.noise_lvl; 
    355         r->rerl             = sess->stat.tx.voip_mtc.rerl; 
    356         r->gmin             = sess->stat.tx.voip_mtc.gmin; 
    357         r->r_factor         = sess->stat.tx.voip_mtc.r_factor; 
    358         r->ext_r_factor     = sess->stat.tx.voip_mtc.ext_r_factor; 
    359         r->mos_lq           = sess->stat.tx.voip_mtc.mos_lq; 
    360         r->mos_cq           = sess->stat.tx.voip_mtc.mos_cq; 
    361         r->rx_config        = sess->stat.tx.voip_mtc.rx_config; 
    362         r->jb_nom           = pj_htons(sess->stat.tx.voip_mtc.jb_nom); 
    363         r->jb_max           = pj_htons(sess->stat.tx.voip_mtc.jb_max); 
    364         r->jb_abs_max       = pj_htons(sess->stat.tx.voip_mtc.jb_abs_max); 
     357        r->loss_rate        = sess->stat.rx.voip_mtc.loss_rate; 
     358        r->discard_rate     = sess->stat.rx.voip_mtc.discard_rate; 
     359        r->burst_den        = sess->stat.rx.voip_mtc.burst_den; 
     360        r->gap_den          = sess->stat.rx.voip_mtc.gap_den; 
     361        r->burst_dur        = pj_htons(sess->stat.rx.voip_mtc.burst_dur); 
     362        r->gap_dur          = pj_htons(sess->stat.rx.voip_mtc.gap_dur); 
     363        r->rnd_trip_delay   = pj_htons(sess->stat.rx.voip_mtc.rnd_trip_delay); 
     364        r->end_sys_delay    = pj_htons(sess->stat.rx.voip_mtc.end_sys_delay); 
     365        /* signal & noise level encoded in two's complement form */ 
     366        r->signal_lvl       = (sess->stat.rx.voip_mtc.signal_lvl >= 0)? 
     367                              sess->stat.rx.voip_mtc.signal_lvl : 
     368                              (sess->stat.rx.voip_mtc.signal_lvl + 256); 
     369        r->noise_lvl        = (sess->stat.rx.voip_mtc.noise_lvl >= 0)? 
     370                              sess->stat.rx.voip_mtc.noise_lvl : 
     371                              (sess->stat.rx.voip_mtc.noise_lvl + 256); 
     372        r->rerl             = sess->stat.rx.voip_mtc.rerl; 
     373        r->gmin             = sess->stat.rx.voip_mtc.gmin; 
     374        r->r_factor         = sess->stat.rx.voip_mtc.r_factor; 
     375        r->ext_r_factor     = sess->stat.rx.voip_mtc.ext_r_factor; 
     376        r->mos_lq           = sess->stat.rx.voip_mtc.mos_lq; 
     377        r->mos_cq           = sess->stat.rx.voip_mtc.mos_cq; 
     378        r->rx_config        = sess->stat.rx.voip_mtc.rx_config; 
     379        r->jb_nom           = pj_htons(sess->stat.rx.voip_mtc.jb_nom); 
     380        r->jb_max           = pj_htons(sess->stat.rx.voip_mtc.jb_max); 
     381        r->jb_abs_max       = pj_htons(sess->stat.rx.voip_mtc.jb_abs_max); 
    365382 
    366383        /* Finally */ 
    367384        size += sizeof(pjmedia_rtcp_xr_rb_voip_mtc); 
     385        pj_gettimeofday(&sess->stat.rx.voip_mtc.update); 
    368386    } 
    369387 
    370388    /* Add RTCP XR header size */ 
     
    532550    if (rb_stats) { 
    533551        pj_uint8_t flags = rb_stats->header.specific; 
    534552 
    535         pj_bzero(&sess->stat.rx.stat_sum, sizeof(sess->stat.rx.stat_sum)); 
     553        pj_bzero(&sess->stat.tx.stat_sum, sizeof(sess->stat.tx.stat_sum)); 
    536554 
    537555        /* Range of packets sequence reported in this blocks */ 
    538         sess->stat.rx.stat_sum.begin_seq = pj_ntohs(rb_stats->begin_seq); 
    539         sess->stat.rx.stat_sum.end_seq   = pj_ntohs(rb_stats->end_seq); 
     556        sess->stat.tx.stat_sum.begin_seq = pj_ntohs(rb_stats->begin_seq); 
     557        sess->stat.tx.stat_sum.end_seq   = pj_ntohs(rb_stats->end_seq); 
    540558 
    541559        /* Get flags of valid fields */ 
    542         sess->stat.rx.stat_sum.l = (flags & (1 << 7)) != 0; 
    543         sess->stat.rx.stat_sum.d = (flags & (1 << 6)) != 0; 
    544         sess->stat.rx.stat_sum.j = (flags & (1 << 5)) != 0; 
    545         sess->stat.rx.stat_sum.t = (flags & (3 << 3)) != 0; 
     560        sess->stat.tx.stat_sum.l = (flags & (1 << 7)) != 0; 
     561        sess->stat.tx.stat_sum.d = (flags & (1 << 6)) != 0; 
     562        sess->stat.tx.stat_sum.j = (flags & (1 << 5)) != 0; 
     563        sess->stat.tx.stat_sum.t = (flags & (3 << 3)) != 0; 
    546564 
    547565        /* Fetch the reports info */ 
    548         if (sess->stat.rx.stat_sum.l) { 
    549             sess->stat.rx.stat_sum.lost = pj_ntohl(rb_stats->lost); 
     566        if (sess->stat.tx.stat_sum.l) { 
     567            sess->stat.tx.stat_sum.lost = pj_ntohl(rb_stats->lost); 
    550568        } 
    551569 
    552         if (sess->stat.rx.stat_sum.d) { 
    553             sess->stat.rx.stat_sum.dup = pj_ntohl(rb_stats->dup); 
     570        if (sess->stat.tx.stat_sum.d) { 
     571            sess->stat.tx.stat_sum.dup = pj_ntohl(rb_stats->dup); 
    554572        } 
    555573 
    556         if (sess->stat.rx.stat_sum.j) { 
    557             sess->stat.rx.stat_sum.jitter.min = pj_ntohl(rb_stats->jitter_min); 
    558             sess->stat.rx.stat_sum.jitter.max = pj_ntohl(rb_stats->jitter_max); 
    559             sess->stat.rx.stat_sum.jitter.mean = pj_ntohl(rb_stats->jitter_mean); 
    560             sess->stat.rx.stat_sum.jitter.dev = pj_ntohl(rb_stats->jitter_dev); 
     574        if (sess->stat.tx.stat_sum.j) { 
     575            sess->stat.tx.stat_sum.jitter.min = pj_ntohl(rb_stats->jitter_min); 
     576            sess->stat.tx.stat_sum.jitter.max = pj_ntohl(rb_stats->jitter_max); 
     577            sess->stat.tx.stat_sum.jitter.mean = pj_ntohl(rb_stats->jitter_mean); 
     578            sess->stat.tx.stat_sum.jitter.dev = pj_ntohl(rb_stats->jitter_dev); 
    561579        } 
    562580 
    563         if (sess->stat.rx.stat_sum.t) { 
    564             sess->stat.rx.stat_sum.toh.min = rb_stats->toh_min; 
    565             sess->stat.rx.stat_sum.toh.max = rb_stats->toh_max; 
    566             sess->stat.rx.stat_sum.toh.mean = rb_stats->toh_mean; 
    567             sess->stat.rx.stat_sum.toh.dev = rb_stats->toh_dev; 
     581        if (sess->stat.tx.stat_sum.t) { 
     582            sess->stat.tx.stat_sum.toh.min = rb_stats->toh_min; 
     583            sess->stat.tx.stat_sum.toh.max = rb_stats->toh_max; 
     584            sess->stat.tx.stat_sum.toh.mean = rb_stats->toh_mean; 
     585            sess->stat.tx.stat_sum.toh.dev = rb_stats->toh_dev; 
    568586        } 
     587 
     588        pj_gettimeofday(&sess->stat.tx.stat_sum.update); 
    569589    } 
    570590 
    571591    /* Receiving VoIP Metrics */ 
    572592    if (rb_voip_mtc) { 
    573         sess->stat.rx.voip_mtc.loss_rate = rb_voip_mtc->loss_rate; 
    574         sess->stat.rx.voip_mtc.discard_rate = rb_voip_mtc->discard_rate; 
    575         sess->stat.rx.voip_mtc.burst_den = rb_voip_mtc->burst_den; 
    576         sess->stat.rx.voip_mtc.gap_den = rb_voip_mtc->gap_den; 
    577         sess->stat.rx.voip_mtc.burst_dur = pj_ntohs(rb_voip_mtc->burst_dur); 
    578         sess->stat.rx.voip_mtc.gap_dur = pj_ntohs(rb_voip_mtc->gap_dur); 
    579         sess->stat.rx.voip_mtc.rnd_trip_delay =  
     593        sess->stat.tx.voip_mtc.loss_rate = rb_voip_mtc->loss_rate; 
     594        sess->stat.tx.voip_mtc.discard_rate = rb_voip_mtc->discard_rate; 
     595        sess->stat.tx.voip_mtc.burst_den = rb_voip_mtc->burst_den; 
     596        sess->stat.tx.voip_mtc.gap_den = rb_voip_mtc->gap_den; 
     597        sess->stat.tx.voip_mtc.burst_dur = pj_ntohs(rb_voip_mtc->burst_dur); 
     598        sess->stat.tx.voip_mtc.gap_dur = pj_ntohs(rb_voip_mtc->gap_dur); 
     599        sess->stat.tx.voip_mtc.rnd_trip_delay =  
    580600                                        pj_ntohs(rb_voip_mtc->rnd_trip_delay); 
    581         sess->stat.rx.voip_mtc.end_sys_delay =  
     601        sess->stat.tx.voip_mtc.end_sys_delay =  
    582602                                        pj_ntohs(rb_voip_mtc->end_sys_delay); 
    583         sess->stat.rx.voip_mtc.signal_lvl = rb_voip_mtc->signal_lvl; 
    584         sess->stat.rx.voip_mtc.noise_lvl = rb_voip_mtc->noise_lvl; 
    585         sess->stat.rx.voip_mtc.rerl = rb_voip_mtc->rerl; 
    586         sess->stat.rx.voip_mtc.gmin = rb_voip_mtc->gmin; 
    587         sess->stat.rx.voip_mtc.r_factor = rb_voip_mtc->r_factor; 
    588         sess->stat.rx.voip_mtc.ext_r_factor = rb_voip_mtc->ext_r_factor; 
    589         sess->stat.rx.voip_mtc.mos_lq = rb_voip_mtc->mos_lq; 
    590         sess->stat.rx.voip_mtc.mos_cq = rb_voip_mtc->mos_cq; 
    591         sess->stat.rx.voip_mtc.rx_config = rb_voip_mtc->rx_config; 
    592         sess->stat.rx.voip_mtc.jb_nom = pj_ntohs(rb_voip_mtc->jb_nom); 
    593         sess->stat.rx.voip_mtc.jb_max = pj_ntohs(rb_voip_mtc->jb_max); 
    594         sess->stat.rx.voip_mtc.jb_abs_max = pj_ntohs(rb_voip_mtc->jb_abs_max); 
     603        /* signal & noise level encoded in two's complement form */ 
     604        sess->stat.tx.voip_mtc.signal_lvl = (rb_voip_mtc->signal_lvl > 127)? 
     605                    (rb_voip_mtc->signal_lvl - 256) : rb_voip_mtc->signal_lvl; 
     606        sess->stat.tx.voip_mtc.noise_lvl = (rb_voip_mtc->noise_lvl > 127)? 
     607                    (rb_voip_mtc->noise_lvl - 256) : rb_voip_mtc->noise_lvl; 
     608        sess->stat.tx.voip_mtc.rerl = rb_voip_mtc->rerl; 
     609        sess->stat.tx.voip_mtc.gmin = rb_voip_mtc->gmin; 
     610        sess->stat.tx.voip_mtc.r_factor = rb_voip_mtc->r_factor; 
     611        sess->stat.tx.voip_mtc.ext_r_factor = rb_voip_mtc->ext_r_factor; 
     612        sess->stat.tx.voip_mtc.mos_lq = rb_voip_mtc->mos_lq; 
     613        sess->stat.tx.voip_mtc.mos_cq = rb_voip_mtc->mos_cq; 
     614        sess->stat.tx.voip_mtc.rx_config = rb_voip_mtc->rx_config; 
     615        sess->stat.tx.voip_mtc.jb_nom = pj_ntohs(rb_voip_mtc->jb_nom); 
     616        sess->stat.tx.voip_mtc.jb_max = pj_ntohs(rb_voip_mtc->jb_max); 
     617        sess->stat.tx.voip_mtc.jb_abs_max = pj_ntohs(rb_voip_mtc->jb_abs_max); 
     618 
     619        pj_gettimeofday(&sess->stat.tx.voip_mtc.update); 
    595620    } 
    596621} 
    597622 
     
    664689    ext_seq = extend_seq(sess, (pj_uint16_t)seq); 
    665690 
    666691    /* Update statistics summary */ 
    667     sess->stat.tx.stat_sum.count++; 
     692    sess->stat.rx.stat_sum.count++; 
    668693 
    669     if (sess->stat.tx.stat_sum.begin_seq == 0 ||  
    670         sess->stat.tx.stat_sum.begin_seq > ext_seq) 
     694    if (sess->stat.rx.stat_sum.begin_seq == 0 ||  
     695        sess->stat.rx.stat_sum.begin_seq > ext_seq) 
    671696    { 
    672         sess->stat.tx.stat_sum.begin_seq = ext_seq; 
     697        sess->stat.rx.stat_sum.begin_seq = ext_seq; 
    673698    } 
    674699 
    675     if (sess->stat.tx.stat_sum.end_seq == 0 ||  
    676         sess->stat.tx.stat_sum.end_seq < ext_seq) 
     700    if (sess->stat.rx.stat_sum.end_seq == 0 ||  
     701        sess->stat.rx.stat_sum.end_seq < ext_seq) 
    677702    { 
    678         sess->stat.tx.stat_sum.end_seq = ext_seq; 
     703        sess->stat.rx.stat_sum.end_seq = ext_seq; 
    679704    } 
    680705 
    681706    if (lost >= 0) { 
    682         sess->stat.tx.stat_sum.l = PJ_TRUE; 
     707        sess->stat.rx.stat_sum.l = PJ_TRUE; 
    683708        if (lost > 0) 
    684             sess->stat.tx.stat_sum.lost++; 
     709            sess->stat.rx.stat_sum.lost++; 
    685710    } 
    686711 
    687712    if (dup >= 0) { 
    688         sess->stat.tx.stat_sum.d = PJ_TRUE; 
     713        sess->stat.rx.stat_sum.d = PJ_TRUE; 
    689714        if (dup > 0) 
    690             sess->stat.tx.stat_sum.dup++; 
     715            sess->stat.rx.stat_sum.dup++; 
    691716    } 
    692717 
    693718    if (jitter >= 0) { 
    694719        pj_int32_t diff; 
    695720 
    696         sess->stat.tx.stat_sum.j = PJ_TRUE; 
    697         if (sess->stat.tx.stat_sum.jitter.min > (pj_uint32_t)jitter) 
    698             sess->stat.tx.stat_sum.jitter.min = jitter; 
    699         if (sess->stat.tx.stat_sum.jitter.max < (pj_uint32_t)jitter) 
    700             sess->stat.tx.stat_sum.jitter.max = jitter; 
    701         sess->stat.tx.stat_sum.jitter.mean =  
    702             (jitter + sess->stat.tx.stat_sum.jitter.mean *  
    703              sess->stat.tx.stat_sum.jitter.count) / 
    704             (sess->stat.tx.stat_sum.jitter.count + 1); 
     721        sess->stat.rx.stat_sum.j = PJ_TRUE; 
     722        if (sess->stat.rx.stat_sum.jitter.min > (pj_uint32_t)jitter) 
     723            sess->stat.rx.stat_sum.jitter.min = jitter; 
     724        if (sess->stat.rx.stat_sum.jitter.max < (pj_uint32_t)jitter) 
     725            sess->stat.rx.stat_sum.jitter.max = jitter; 
     726        sess->stat.rx.stat_sum.jitter.mean =  
     727            (jitter + sess->stat.rx.stat_sum.jitter.mean *  
     728             sess->stat.rx.stat_sum.jitter.count) / 
     729            (sess->stat.rx.stat_sum.jitter.count + 1); 
    705730 
    706         diff = sess->stat.tx.stat_sum.jitter.mean - jitter; 
    707         sess->stat.tx.stat_sum.jitter.dev = 
    708             (diff * diff + sess->stat.tx.stat_sum.jitter.dev *  
    709              sess->stat.tx.stat_sum.jitter.count) / 
    710             (sess->stat.tx.stat_sum.jitter.count + 1); 
     731        diff = sess->stat.rx.stat_sum.jitter.mean - jitter; 
     732        sess->stat.rx.stat_sum.jitter.dev = 
     733            (diff * diff + sess->stat.rx.stat_sum.jitter.dev *  
     734             sess->stat.rx.stat_sum.jitter.count) / 
     735            (sess->stat.rx.stat_sum.jitter.count + 1); 
    711736 
    712         ++sess->stat.tx.stat_sum.jitter.count; 
     737        ++sess->stat.rx.stat_sum.jitter.count; 
    713738    } 
    714739 
    715740    if (toh >= 0) { 
    716741        pj_int32_t diff; 
    717742 
    718         sess->stat.tx.stat_sum.t = toh_ipv4? 1 : 2; 
     743        sess->stat.rx.stat_sum.t = toh_ipv4? 1 : 2; 
    719744 
    720         if (sess->stat.tx.stat_sum.toh.min > (pj_uint32_t)toh) 
    721             sess->stat.tx.stat_sum.toh.min = toh; 
    722         if (sess->stat.tx.stat_sum.toh.max < (pj_uint32_t)toh) 
    723             sess->stat.tx.stat_sum.toh.max = toh; 
    724         sess->stat.tx.stat_sum.toh.mean =  
    725             (toh + sess->stat.tx.stat_sum.toh.mean *  
    726              sess->stat.tx.stat_sum.toh.count) / 
    727             (sess->stat.tx.stat_sum.toh.count + 1); 
     745        if (sess->stat.rx.stat_sum.toh.min > (pj_uint32_t)toh) 
     746            sess->stat.rx.stat_sum.toh.min = toh; 
     747        if (sess->stat.rx.stat_sum.toh.max < (pj_uint32_t)toh) 
     748            sess->stat.rx.stat_sum.toh.max = toh; 
     749        sess->stat.rx.stat_sum.toh.mean =  
     750            (toh + sess->stat.rx.stat_sum.toh.mean *  
     751             sess->stat.rx.stat_sum.toh.count) / 
     752            (sess->stat.rx.stat_sum.toh.count + 1); 
    728753 
    729         diff = sess->stat.tx.stat_sum.toh.mean - toh; 
    730         sess->stat.tx.stat_sum.toh.dev = 
    731             (diff * diff + sess->stat.tx.stat_sum.toh.dev *  
    732              sess->stat.tx.stat_sum.toh.count) / 
    733             (sess->stat.tx.stat_sum.toh.count + 1); 
     754        diff = sess->stat.rx.stat_sum.toh.mean - toh; 
     755        sess->stat.rx.stat_sum.toh.dev = 
     756            (diff * diff + sess->stat.rx.stat_sum.toh.dev *  
     757             sess->stat.rx.stat_sum.toh.count) / 
     758            (sess->stat.rx.stat_sum.toh.count + 1); 
    734759 
    735         ++sess->stat.tx.stat_sum.toh.count; 
     760        ++sess->stat.rx.stat_sum.toh.count; 
    736761    } 
    737762 
    738763    /* Update burst metrics. 
     
    752777            sess->voip_mtc_stat.pkt++; 
    753778        } 
    754779        else { 
    755             if(sess->voip_mtc_stat.pkt >= sess->stat.tx.voip_mtc.gmin) { 
     780            if(sess->voip_mtc_stat.pkt >= sess->stat.rx.voip_mtc.gmin) { 
    756781                /* Gap condition */ 
    757782                if(sess->voip_mtc_stat.lost == 1) { 
    758783                    /* Gap -> Gap */ 
     
    800825 
    801826    switch(info) { 
    802827        case PJMEDIA_RTCP_XR_INFO_SIGNAL_LVL: 
    803             sess->stat.tx.voip_mtc.signal_lvl = (pj_uint8_t) v; 
     828            sess->stat.rx.voip_mtc.signal_lvl = (pj_int8_t) v; 
    804829            break; 
    805830 
    806831        case PJMEDIA_RTCP_XR_INFO_NOISE_LVL: 
    807             sess->stat.tx.voip_mtc.noise_lvl = (pj_uint8_t) v; 
     832            sess->stat.rx.voip_mtc.noise_lvl = (pj_int8_t) v; 
    808833            break; 
    809834 
    810835        case PJMEDIA_RTCP_XR_INFO_RERL: 
    811             sess->stat.tx.voip_mtc.rerl = (pj_uint8_t) v; 
     836            sess->stat.rx.voip_mtc.rerl = (pj_uint8_t) v; 
    812837            break; 
    813838 
    814839        case PJMEDIA_RTCP_XR_INFO_R_FACTOR: 
    815             sess->stat.tx.voip_mtc.ext_r_factor = (pj_uint8_t) v; 
     840            sess->stat.rx.voip_mtc.ext_r_factor = (pj_uint8_t) v; 
    816841            break; 
    817842 
    818843        case PJMEDIA_RTCP_XR_INFO_MOS_LQ: 
    819             sess->stat.tx.voip_mtc.mos_lq = (pj_uint8_t) v; 
     844            sess->stat.rx.voip_mtc.mos_lq = (pj_uint8_t) v; 
    820845            break; 
    821846 
    822847        case PJMEDIA_RTCP_XR_INFO_MOS_CQ: 
    823             sess->stat.tx.voip_mtc.mos_cq = (pj_uint8_t) v; 
     848            sess->stat.rx.voip_mtc.mos_cq = (pj_uint8_t) v; 
    824849            break; 
    825850 
    826851        case PJMEDIA_RTCP_XR_INFO_CONF_PLC: 
    827852            if (v >= 0 && v <= 3) { 
    828                 sess->stat.tx.voip_mtc.rx_config &= 0x3F; 
    829                 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) (v << 6); 
     853                sess->stat.rx.voip_mtc.rx_config &= 0x3F; 
     854                sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) (v << 6); 
    830855            } 
    831856            break; 
    832857 
    833858        case PJMEDIA_RTCP_XR_INFO_CONF_JBA: 
    834859            if (v >= 0 && v <= 3) { 
    835                 sess->stat.tx.voip_mtc.rx_config &= 0xCF; 
    836                 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) (v << 4); 
     860                sess->stat.rx.voip_mtc.rx_config &= 0xCF; 
     861                sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) (v << 4); 
    837862            } 
    838863            break; 
    839864 
    840865        case PJMEDIA_RTCP_XR_INFO_CONF_JBR: 
    841866            if (v >= 0 && v <= 15) { 
    842                 sess->stat.tx.voip_mtc.rx_config &= 0xF0; 
    843                 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) v; 
     867                sess->stat.rx.voip_mtc.rx_config &= 0xF0; 
     868                sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) v; 
    844869            } 
    845870            break; 
    846871 
    847872        case PJMEDIA_RTCP_XR_INFO_JB_NOM: 
    848             sess->stat.tx.voip_mtc.jb_nom = (pj_uint16_t) v; 
     873            sess->stat.rx.voip_mtc.jb_nom = (pj_uint16_t) v; 
    849874            break; 
    850875 
    851876        case PJMEDIA_RTCP_XR_INFO_JB_MAX: 
    852             sess->stat.tx.voip_mtc.jb_max = (pj_uint16_t) v; 
     877            sess->stat.rx.voip_mtc.jb_max = (pj_uint16_t) v; 
    853878            break; 
    854879 
    855880        case PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX: 
    856             sess->stat.tx.voip_mtc.jb_abs_max = (pj_uint16_t) v; 
     881            sess->stat.rx.voip_mtc.jb_abs_max = (pj_uint16_t) v; 
    857882            break; 
    858883 
    859884        default: 
  • pjmedia/src/pjmedia/stream.c

     
    15571557 
    15581558    stream->transport = tp; 
    15591559 
    1560 #if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 
    1561     /* Enable RTCP XR and update some settings */ 
    1562     { 
     1560#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     1561    /* Enable RTCP XR and update stream info/config to RTCP XR */ 
     1562    if (info->rtcp_xr_enabled) { 
    15631563        int i; 
     1564 
    15641565        pjmedia_rtcp_enable_xr(&stream->rtcp, PJ_TRUE); 
    15651566 
    15661567        /* jitter buffer adaptive info */ 
     
    17131714    return PJ_SUCCESS; 
    17141715} 
    17151716 
     1717#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     1718/* 
     1719 * Get stream extended statistics. 
     1720 */ 
     1721PJ_DEF(pj_status_t) pjmedia_stream_get_stat_xr( const pjmedia_stream *stream, 
     1722                                                pjmedia_rtcp_xr_stat *stat) 
     1723{ 
     1724    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL); 
    17161725 
     1726    if (stream->rtcp.xr_enabled) { 
     1727        pj_memcpy(stat, &stream->rtcp.xr_session.stat, sizeof(pjmedia_rtcp_xr_stat)); 
     1728        return PJ_SUCCESS; 
     1729    } 
     1730    return PJ_ENOTFOUND; 
     1731} 
     1732#endif 
     1733 
    17171734/* 
    17181735 * Pause stream. 
    17191736 */ 
  • pjmedia/src/pjmedia/session.c

     
    166166 
    167167    pj_bzero(si, sizeof(*si)); 
    168168 
     169#if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 
     170    /* Set default RTCP XR enabled/disabled */ 
     171    si->rtcp_xr_enabled = PJ_TRUE; 
     172#endif 
     173 
    169174    /* Media type: */ 
    170175 
    171176    if (pj_stricmp(&local_m->desc.media, &ID_AUDIO) == 0) {