Ignore:
Timestamp:
Apr 6, 2006 7:29:03 PM (18 years ago)
Author:
bennylp
Message:

Integrate (stream) quality monitoring into RTCP framework, and update all RTCP clients accordingly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/samples/siprtp.c

    r389 r390  
    5252 
    5353 
    54 /* Unidirectional media stat: */ 
    55 struct stream_stat 
    56 { 
    57     pj_uint32_t     pkt, payload; 
    58     pj_uint32_t     discard, reorder; 
    59     unsigned        loss_min, loss_avg, loss_max; 
    60     char           *loss_type; 
    61     unsigned        jitter_min_us, jitter_avg_us, jitter_max_us; 
    62     unsigned        rtcp_cnt; 
    63 }; 
    64  
    65  
    6654/* A bidirectional media stream */ 
    6755struct media_stream 
     
    8876    /* RTCP stats: */ 
    8977    pjmedia_rtcp_session rtcp;              /* incoming RTCP session.   */ 
    90     pjmedia_rtcp_pkt     rem_rtcp;          /* received RTCP stat.      */ 
    91  
    92     /* More stats: */ 
    93     struct stream_stat   rx_stat;           /* incoming stream stat     */ 
    94     struct stream_stat   tx_stat;           /* outgoing stream stat.    */ 
    9578 
    9679    /* Thread: */ 
     
    10741057            } 
    10751058 
    1076             ++strm->rx_stat.pkt; 
    1077             strm->rx_stat.payload += (size - 12); 
    10781059 
    10791060            /* Decode RTP packet. */ 
     
    10841065            if (status != PJ_SUCCESS) { 
    10851066                app_perror(THIS_FILE, "RTP decode error", status); 
    1086                 strm->rx_stat.discard++; 
    10871067                continue; 
    10881068            } 
    10891069 
    1090             /* Update RTP session */ 
    1091             status = pjmedia_rtp_session_update(&strm->in_sess, hdr); 
    1092             if (status != PJ_SUCCESS &&  
    1093                 status != PJMEDIA_RTP_ESESSPROBATION &&  
    1094                 status != PJMEDIA_RTP_ESESSRESTART)  
    1095             { 
    1096                 app_perror(THIS_FILE, "RTP update error", status); 
    1097                 PJ_LOG(3,(THIS_FILE,"RTP packet detail: pt=%d, seq=%d", 
    1098                           hdr->pt, pj_ntohs(hdr->seq))); 
    1099                 strm->rx_stat.discard++; 
    1100                 continue; 
    1101             } 
    1102  
    11031070            /* Update the RTCP session. */ 
    11041071            pjmedia_rtcp_rx_rtp(&strm->rtcp, pj_ntohs(hdr->seq), 
    1105                                 pj_ntohl(hdr->ts)); 
    1106  
     1072                                pj_ntohl(hdr->ts), payload_len); 
     1073 
     1074            /* Update RTP session */ 
     1075            pjmedia_rtp_session_update(&strm->in_sess, hdr, NULL); 
    11071076        }  
    11081077         
     
    11191088            if (status != PJ_SUCCESS) 
    11201089                app_perror(THIS_FILE, "Error receiving RTCP packet", status); 
    1121             else { 
    1122                 if (size != sizeof(strm->rem_rtcp)) { 
    1123                     PJ_LOG(3,(THIS_FILE, "Error: RTCP packet size mismatch " 
    1124                                          "(recv %d bytes, expecting %d)", 
    1125                                          size, sizeof(strm->rem_rtcp))); 
    1126                     status = -1; 
    1127                 } else { 
    1128                     pj_memcpy(&strm->rem_rtcp, packet, size); 
    1129                     status = PJ_SUCCESS; 
    1130  
    1131                     /* Report receipt of RTCP to RTCP session */ 
    1132                     pjmedia_rtcp_rx_rtcp(&strm->rtcp, packet, size); 
    1133                 } 
    1134             } 
    1135  
    1136             if (status == PJ_SUCCESS) { 
    1137                 /* Process RTCP stats */ 
    1138                 unsigned jitter; 
    1139                  
    1140                 jitter = (unsigned)(pj_ntohl(strm->rem_rtcp.rr.jitter) *  
    1141                                     1000000.0 / strm->clock_rate); 
    1142                 if (jitter < strm->tx_stat.jitter_min_us) 
    1143                     strm->tx_stat.jitter_min_us = jitter; 
    1144                 if (jitter > strm->tx_stat.jitter_max_us) 
    1145                     strm->tx_stat.jitter_max_us = jitter; 
    1146                 strm->tx_stat.jitter_avg_us =  
    1147                         (strm->tx_stat.jitter_avg_us * strm->tx_stat.rtcp_cnt + 
    1148                          jitter) / (strm->tx_stat.rtcp_cnt + 1); 
    1149  
    1150                 strm->tx_stat.rtcp_cnt++; 
    1151             } 
     1090            else 
     1091                pjmedia_rtcp_rx_rtcp(&strm->rtcp, packet, size); 
    11521092        } 
    11531093 
     
    11941134            /* Schedule next send */ 
    11951135            next_rtp.u64 += (msec_interval * freq.u64 / 1000); 
    1196  
    1197             /* Update stats */ 
    1198             strm->tx_stat.pkt++; 
    1199             strm->tx_stat.payload += strm->bytes_per_frame; 
    12001136        } 
    12011137 
     
    12291165            } 
    12301166             
    1231  
    1232             /* Process RTCP stats */ 
    1233             { 
    1234                 unsigned jitter; 
    1235                  
    1236                 jitter = (unsigned) (pj_ntohl(rtcp_pkt->rr.jitter) *  
    1237                                      1000000.0 / strm->clock_rate); 
    1238                 if (jitter < strm->rx_stat.jitter_min_us) 
    1239                     strm->rx_stat.jitter_min_us = jitter; 
    1240                 if (jitter > strm->rx_stat.jitter_max_us) 
    1241                     strm->rx_stat.jitter_max_us = jitter; 
    1242                 strm->rx_stat.jitter_avg_us =  
    1243                         (strm->rx_stat.jitter_avg_us * strm->rx_stat.rtcp_cnt + 
    1244                          jitter) / (strm->rx_stat.rtcp_cnt + 1); 
    1245  
    1246                 strm->rx_stat.rtcp_cnt++; 
    1247             } 
    1248  
     1167            /* Schedule next send */ 
    12491168            next_rtcp.u64 += (freq.u64 * RTCP_INTERVAL); 
    12501169        } 
     
    13191238                             pj_rand()); 
    13201239    pjmedia_rtp_session_init(&audio->in_sess, audio->si.fmt.pt, 0); 
    1321     pjmedia_rtcp_init(&audio->rtcp, audio->clock_rate, 0); 
    1322  
    1323  
    1324     /* Clear media statistics */ 
    1325     pj_memset(&audio->rx_stat, 0, sizeof(audio->rx_stat)); 
    1326     pj_memset(&audio->tx_stat, 0, sizeof(audio->tx_stat)); 
     1240    pjmedia_rtcp_init(&audio->rtcp, audio->clock_rate,  
     1241                      audio->samples_per_frame, 0); 
     1242 
    13271243 
    13281244 
     
    14111327    struct media_stream *audio = &call->media[0]; 
    14121328    char userinfo[128]; 
    1413     char duration[80]; 
     1329    char duration[80], last_update[80]; 
    14141330    char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16]; 
    1415     pj_uint32_t total_loss; 
    1416  
     1331    pj_time_val now; 
     1332 
     1333    pj_gettimeofday(&now); 
    14171334 
    14181335    /* Print duration */ 
    14191336    if (inv->state >= PJSIP_INV_STATE_CONFIRMED) { 
    1420         pj_time_val now; 
    1421  
    1422         pj_gettimeofday(&now); 
     1337 
    14231338        PJ_TIME_VAL_SUB(now, call->connect_time); 
    14241339 
     
    14891404        good_number(ipbps, (audio->bytes_per_frame+32) * audio->clock_rate / audio->samples_per_frame)); 
    14901405 
    1491     total_loss = (audio->rtcp.rtcp_pkt.rr.total_lost_2 << 16) + 
    1492                  (audio->rtcp.rtcp_pkt.rr.total_lost_1 << 8) + 
    1493                  audio->rtcp.rtcp_pkt.rr.total_lost_0; 
    1494  
    1495     printf("              RX total %s packets %sB received (%sB +IP hdr)%s\n" 
    1496            "                 pkt discards=%d (%3.1f%%), loss=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n" 
    1497            "                 loss period min=%dms, avg=%dms, max=%dms%s\n" 
    1498            "                 jitter min=%5.3fms, avg=%5.3fms, max=%5.3fms, curr=%5.3f ms%s\n", 
    1499            good_number(packets, audio->rx_stat.pkt), 
    1500            good_number(bytes, audio->rx_stat.payload), 
    1501            good_number(ipbytes, audio->rx_stat.payload + audio->rx_stat.pkt * 32), 
     1406    if (audio->rtcp.stat.rx.update_cnt == 0) 
     1407        strcpy(last_update, "never"); 
     1408    else { 
     1409        pj_gettimeofday(&now); 
     1410        PJ_TIME_VAL_SUB(now, audio->rtcp.stat.rx.update); 
     1411        sprintf(last_update, "%02dh:%02dm:%02d.%03ds ago", 
     1412                now.sec / 3600, 
     1413                (now.sec % 3600) / 60, 
     1414                now.sec % 60, 
     1415                now.msec); 
     1416    } 
     1417 
     1418    printf("              RX stat last update: %s\n" 
     1419           "                 total %s packets %sB received (%sB +IP hdr)%s\n" 
     1420           "                 pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n" 
     1421           "                 loss period min=%5.3fms, avg=%5.3fms, max=%5.3fms, last=%5.3f%s\n" 
     1422           "                 jitter min=%5.3fms, avg=%5.3fms, max=%5.3fms, last=%5.3fms%s\n", 
     1423           last_update, 
     1424           good_number(packets, audio->rtcp.stat.rx.pkt), 
     1425           good_number(bytes, audio->rtcp.stat.rx.bytes), 
     1426           good_number(ipbytes, audio->rtcp.stat.rx.bytes + audio->rtcp.stat.rx.pkt * 32), 
    15021427           "", 
    1503            audio->rx_stat.discard,  
    1504            audio->rx_stat.discard * 100.0 / audio->rx_stat.pkt, 
    1505            total_loss, 
    1506            total_loss * 100.0 / audio->rx_stat.pkt, 
    1507            0, 0.0, 
     1428           audio->rtcp.stat.rx.loss, 
     1429           audio->rtcp.stat.rx.loss * 100.0 / audio->rtcp.stat.rx.pkt, 
     1430           audio->rtcp.stat.rx.dup,  
     1431           audio->rtcp.stat.rx.dup * 100.0 / audio->rtcp.stat.rx.pkt, 
     1432           audio->rtcp.stat.rx.reorder,  
     1433           audio->rtcp.stat.rx.reorder * 100.0 / audio->rtcp.stat.rx.pkt, 
    15081434           "", 
    1509            -1, -1, -1,  
     1435           audio->rtcp.stat.rx.loss_period.min / 1000.0,  
     1436           audio->rtcp.stat.rx.loss_period.avg / 1000.0,  
     1437           audio->rtcp.stat.rx.loss_period.max / 1000.0, 
     1438           audio->rtcp.stat.rx.loss_period.last / 1000.0, 
    15101439           "", 
    1511            (audio->rx_stat.rtcp_cnt? audio->rx_stat.jitter_min_us/1000.0 : -1.), 
    1512            (audio->rx_stat.rtcp_cnt? audio->rx_stat.jitter_avg_us/1000.0 : -1.), 
    1513            (audio->rx_stat.rtcp_cnt? audio->rx_stat.jitter_max_us/1000.0 : -1.), 
    1514            (audio->rx_stat.rtcp_cnt? pj_ntohl(audio->rtcp.rtcp_pkt.rr.jitter)*1000.0/audio->clock_rate : -1.), 
     1440           audio->rtcp.stat.rx.jitter.min / 1000.0, 
     1441           audio->rtcp.stat.rx.jitter.avg / 1000.0, 
     1442           audio->rtcp.stat.rx.jitter.max / 1000.0, 
     1443           audio->rtcp.stat.rx.jitter.last / 1000.0, 
    15151444           "" 
    15161445           ); 
    15171446 
    15181447 
    1519     total_loss = (audio->rem_rtcp.rr.total_lost_2 << 16) + 
    1520                  (audio->rem_rtcp.rr.total_lost_1 << 8) + 
    1521                   audio->rem_rtcp.rr.total_lost_0; 
    1522  
    1523     printf("              TX total %s packets %sB sent (%sB +IP hdr)%s\n" 
    1524            "                 pkt discards=%d (%3.1f%%), loss=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n" 
    1525            "                 loss period min=%dms, avg=%dms, max=%dms%s\n" 
    1526            "                 jitter min=%5.3fms, avg=%5.3fms, max=%5.3fms, curr=%5.3f ms%s\n", 
    1527            good_number(packets, audio->tx_stat.pkt), 
    1528            good_number(bytes, audio->tx_stat.payload), 
    1529            good_number(ipbytes, audio->tx_stat.payload + audio->tx_stat.pkt * 32), 
     1448    if (audio->rtcp.stat.tx.update_cnt == 0) 
     1449        strcpy(last_update, "never"); 
     1450    else { 
     1451        pj_gettimeofday(&now); 
     1452        PJ_TIME_VAL_SUB(now, audio->rtcp.stat.tx.update); 
     1453        sprintf(last_update, "%02dh:%02dm:%02d.%03ds ago", 
     1454                now.sec / 3600, 
     1455                (now.sec % 3600) / 60, 
     1456                now.sec % 60, 
     1457                now.msec); 
     1458    } 
     1459 
     1460    printf("              TX stat last update: %s\n" 
     1461           "                 total %s packets %sB received (%sB +IP hdr)%s\n" 
     1462           "                 pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n" 
     1463           "                 loss period min=%5.3fms, avg=%5.3fms, max=%5.3fms, last=%5.3f%s\n" 
     1464           "                 jitter min=%5.3fms, avg=%5.3fms, max=%5.3fms, last=%5.3fms%s\n", 
     1465           last_update, 
     1466           good_number(packets, audio->rtcp.stat.tx.pkt), 
     1467           good_number(bytes, audio->rtcp.stat.tx.bytes), 
     1468           good_number(ipbytes, audio->rtcp.stat.tx.bytes + audio->rtcp.stat.tx.pkt * 32), 
    15301469           "", 
    1531            audio->tx_stat.discard,  
    1532            audio->tx_stat.discard * 100.0 / audio->tx_stat.pkt, 
    1533            total_loss, 
    1534            total_loss * 100.0 / audio->tx_stat.pkt, 
    1535            0, 0.0, 
     1470           audio->rtcp.stat.tx.loss, 
     1471           audio->rtcp.stat.tx.loss * 100.0 / audio->rtcp.stat.tx.pkt, 
     1472           audio->rtcp.stat.tx.dup,  
     1473           audio->rtcp.stat.tx.dup * 100.0 / audio->rtcp.stat.tx.pkt, 
     1474           audio->rtcp.stat.tx.reorder,  
     1475           audio->rtcp.stat.tx.reorder * 100.0 / audio->rtcp.stat.tx.pkt, 
    15361476           "", 
    1537            -1, -1, -1,  
     1477           audio->rtcp.stat.tx.loss_period.min / 1000.0,  
     1478           audio->rtcp.stat.tx.loss_period.avg / 1000.0,  
     1479           audio->rtcp.stat.tx.loss_period.max / 1000.0, 
     1480           audio->rtcp.stat.tx.loss_period.last / 1000.0, 
    15381481           "", 
    1539            (audio->tx_stat.rtcp_cnt? audio->tx_stat.jitter_min_us/1000.0 : -1.), 
    1540            (audio->tx_stat.rtcp_cnt? audio->tx_stat.jitter_avg_us/1000.0 : -1.), 
    1541            (audio->tx_stat.rtcp_cnt? audio->tx_stat.jitter_max_us/1000.0 : -1.), 
    1542            (audio->tx_stat.rtcp_cnt? pj_ntohl(audio->rem_rtcp.rr.jitter)*1000.0/audio->clock_rate : -1.), 
     1482           audio->rtcp.stat.tx.jitter.min / 1000.0, 
     1483           audio->rtcp.stat.tx.jitter.avg / 1000.0, 
     1484           audio->rtcp.stat.tx.jitter.max / 1000.0, 
     1485           audio->rtcp.stat.tx.jitter.last / 1000.0, 
    15431486           "" 
    15441487           ); 
    15451488 
    1546     printf("              End to end delay: %5.3f ms\n",  
    1547            audio->rtcp.rtt_us / 1000.0); 
     1489 
     1490    printf("             RTT min=%5.3fms, avg=%5.3fms, max=%5.3fms, last=%5.3fms%s\n",  
     1491           audio->rtcp.stat.rtt.min / 1000.0, 
     1492           audio->rtcp.stat.rtt.avg / 1000.0, 
     1493           audio->rtcp.stat.rtt.max / 1000.0, 
     1494           audio->rtcp.stat.rtt.last / 1000.0, 
     1495           "" 
     1496           ); 
    15481497 
    15491498} 
Note: See TracChangeset for help on using the changeset viewer.