Ignore:
Timestamp:
Feb 27, 2012 2:41:21 PM (8 years ago)
Author:
nanang
Message:

Fix #1440: Send and parse RTCP compound packet, containing report (RR/SR/XR), SDES, and BYE.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/1.x/pjmedia/src/pjmedia/stream.c

    r3900 r3960  
    235235 
    236236 
     237static pj_status_t send_rtcp(pjmedia_stream *stream, 
     238                             pj_bool_t with_sdes, 
     239                             pj_bool_t with_bye, 
     240                             pj_bool_t with_xr); 
     241 
     242 
    237243#if TRACE_JB 
    238244 
     
    415421 
    416422    /* Send RTCP */ 
    417     pjmedia_rtcp_build_rtcp(&stream->rtcp, &pkt, &pkt_len); 
    418     pjmedia_transport_send_rtcp(stream->transport, pkt, pkt_len); 
     423    send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 
    419424 
    420425#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER 
     
    904909 
    905910 
     911static pj_status_t send_rtcp(pjmedia_stream *stream, 
     912                             pj_bool_t with_sdes, 
     913                             pj_bool_t with_bye, 
     914                             pj_bool_t with_xr) 
     915{ 
     916    void *sr_rr_pkt; 
     917    pj_uint8_t *pkt; 
     918    int len, max_len; 
     919    pj_status_t status; 
     920 
     921    /* Build RTCP RR/SR packet */ 
     922    pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 
     923 
     924#if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0) 
     925    with_xr = PJ_FALSE; 
     926#endif 
     927 
     928    if (with_sdes || with_bye || with_xr) { 
     929        pkt = (pj_uint8_t*) stream->enc->out_pkt; 
     930        pj_memcpy(pkt, sr_rr_pkt, len); 
     931        max_len = stream->enc->out_pkt_size; 
     932    } else { 
     933        pkt = sr_rr_pkt; 
     934        max_len = len; 
     935    } 
     936 
     937    /* Build RTCP SDES packet */ 
     938    if (with_sdes) { 
     939        pjmedia_rtcp_sdes sdes; 
     940        unsigned sdes_len; 
     941 
     942        pj_bzero(&sdes, sizeof(sdes)); 
     943        sdes.cname = stream->cname; 
     944        sdes_len = max_len - len; 
     945        status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len, 
     946                                              &sdes_len, &sdes); 
     947        if (status != PJ_SUCCESS) { 
     948            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     949                                     "Error generating RTCP SDES")); 
     950        } else { 
     951            len += sdes_len; 
     952        } 
     953    } 
     954 
     955    /* Build RTCP XR packet */ 
     956#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     957    if (with_xr) { 
     958        int i; 
     959        pjmedia_jb_state jb_state; 
     960        void *xr_pkt; 
     961        int xr_len; 
     962 
     963        /* Update RTCP XR with current JB states */ 
     964        pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     965             
     966        i = jb_state.avg_delay; 
     967        status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
     968                                             PJMEDIA_RTCP_XR_INFO_JB_NOM, i); 
     969        pj_assert(status == PJ_SUCCESS); 
     970 
     971        i = jb_state.max_delay; 
     972        status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
     973                                             PJMEDIA_RTCP_XR_INFO_JB_MAX, i); 
     974        pj_assert(status == PJ_SUCCESS); 
     975 
     976        pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0, 
     977                                   &xr_pkt, &xr_len); 
     978 
     979        if (xr_len + len <= max_len) { 
     980            pj_memcpy(pkt+len, xr_pkt, xr_len); 
     981            len += xr_len; 
     982 
     983            /* Send the RTCP XR to third-party destination if specified */ 
     984            if (stream->rtcp_xr_dest_len) { 
     985                pjmedia_transport_send_rtcp2(stream->transport,  
     986                                             &stream->rtcp_xr_dest, 
     987                                             stream->rtcp_xr_dest_len,  
     988                                             xr_pkt, xr_len); 
     989            } 
     990 
     991        } else { 
     992            PJ_PERROR(4,(stream->port.info.name.ptr, PJ_ETOOBIG, 
     993                         "Error generating RTCP-XR")); 
     994        } 
     995    } 
     996#endif 
     997 
     998    /* Build RTCP BYE packet */ 
     999    if (with_bye) { 
     1000        unsigned bye_len; 
     1001 
     1002        bye_len = max_len - len; 
     1003        status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len, 
     1004                                             &bye_len, NULL); 
     1005        if (status != PJ_SUCCESS) { 
     1006            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     1007                                     "Error generating RTCP BYE")); 
     1008        } else { 
     1009            len += bye_len; 
     1010        } 
     1011    } 
     1012 
     1013    /* Send! */ 
     1014    status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); 
     1015 
     1016    return status; 
     1017} 
     1018 
    9061019/** 
    9071020 * check_tx_rtcp() 
     
    9171030     */ 
    9181031 
    919  
    9201032    if (stream->rtcp_last_tx == 0) { 
    9211033         
     
    9231035 
    9241036    } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { 
    925          
    926         void *rtcp_pkt; 
    927         int len; 
     1037        pj_bool_t with_xr = PJ_FALSE; 
    9281038        pj_status_t status; 
    9291039 
    930         pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); 
    931  
    932         status=pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); 
     1040#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     1041        if (stream->rtcp.xr_enabled) { 
     1042            if (stream->rtcp_xr_last_tx == 0) { 
     1043                stream->rtcp_xr_last_tx = timestamp; 
     1044            } else if (timestamp - stream->rtcp_xr_last_tx >=  
     1045                       stream->rtcp_xr_interval) 
     1046            { 
     1047                with_xr = PJ_TRUE; 
     1048 
     1049                /* Update last tx RTCP XR */ 
     1050                stream->rtcp_xr_last_tx = timestamp; 
     1051            } 
     1052        } 
     1053#endif 
     1054 
     1055        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE, 
     1056                           with_xr); 
    9331057        if (status != PJ_SUCCESS) { 
    9341058            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
    935                         "Error sending RTCP")); 
     1059                        "Error sending RTCP")); 
    9361060        } 
    9371061 
    9381062        stream->rtcp_last_tx = timestamp; 
    9391063    } 
    940  
    941 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
    942     if (stream->rtcp.xr_enabled) { 
    943  
    944         if (stream->rtcp_xr_last_tx == 0) { 
    945          
    946             stream->rtcp_xr_last_tx = timestamp; 
    947  
    948         } else if (timestamp - stream->rtcp_xr_last_tx >=  
    949                    stream->rtcp_xr_interval) 
    950         { 
    951             int i; 
    952             pjmedia_jb_state jb_state; 
    953             void *rtcp_pkt; 
    954             int len; 
    955  
    956             /* Update RTCP XR with current JB states */ 
    957             pjmedia_jbuf_get_state(stream->jb, &jb_state); 
    958              
    959             i = jb_state.avg_delay; 
    960             pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
    961                                         PJMEDIA_RTCP_XR_INFO_JB_NOM, 
    962                                         i); 
    963  
    964             i = jb_state.max_delay; 
    965             pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
    966                                         PJMEDIA_RTCP_XR_INFO_JB_MAX, 
    967                                         i); 
    968  
    969             /* Build RTCP XR packet */ 
    970             pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,  
    971                                        &rtcp_pkt, &len); 
    972  
    973             /* Send the RTCP XR to remote address */ 
    974             pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); 
    975  
    976             /* Send the RTCP XR to third-party destination if specified */ 
    977             if (stream->rtcp_xr_dest_len) { 
    978                 pjmedia_transport_send_rtcp2(stream->transport,  
    979                                              &stream->rtcp_xr_dest, 
    980                                              stream->rtcp_xr_dest_len,  
    981                                              rtcp_pkt, len); 
    982             } 
    983  
    984             /* Update last tx RTCP XR */ 
    985             stream->rtcp_xr_last_tx = timestamp; 
    986         } 
    987     } 
    988 #endif 
    989 } 
    990  
    991 /* Build RTCP SDES packet */ 
    992 static unsigned create_rtcp_sdes(pjmedia_stream *stream, pj_uint8_t *pkt, 
    993                                  unsigned max_len) 
    994 { 
    995     pjmedia_rtcp_common hdr; 
    996     pj_uint8_t *p = pkt; 
    997  
    998     /* SDES header */ 
    999     hdr.version = 2; 
    1000     hdr.p = 0; 
    1001     hdr.count = 1; 
    1002     hdr.pt = 202; 
    1003     hdr.length = 2 + (4+stream->cname.slen+3)/4 - 1; 
    1004     if (max_len < (hdr.length << 2)) { 
    1005         pj_assert(!"Not enough buffer for SDES packet"); 
    1006         return 0; 
    1007     } 
    1008     hdr.length = pj_htons((pj_uint16_t)hdr.length); 
    1009     hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; 
    1010     pj_memcpy(p, &hdr, sizeof(hdr)); 
    1011     p += sizeof(hdr); 
    1012  
    1013     /* CNAME item */ 
    1014     *p++ = 1; 
    1015     *p++ = (pj_uint8_t)stream->cname.slen; 
    1016     pj_memcpy(p, stream->cname.ptr, stream->cname.slen); 
    1017     p += stream->cname.slen; 
    1018  
    1019     /* END */ 
    1020     *p++ = '\0'; 
    1021     *p++ = '\0'; 
    1022  
    1023     /* Pad to 32bit */ 
    1024     while ((p-pkt) % 4) 
    1025         *p++ = '\0'; 
    1026  
    1027     return (p - pkt); 
    1028 } 
    1029  
    1030 /* Build RTCP BYE packet */ 
    1031 static unsigned create_rtcp_bye(pjmedia_stream *stream, pj_uint8_t *pkt, 
    1032                                 unsigned max_len) 
    1033 { 
    1034     pjmedia_rtcp_common hdr; 
    1035  
    1036     /* BYE header */ 
    1037     hdr.version = 2; 
    1038     hdr.p = 0; 
    1039     hdr.count = 1; 
    1040     hdr.pt = 203; 
    1041     hdr.length = 1; 
    1042     if (max_len < (hdr.length << 2)) { 
    1043         pj_assert(!"Not enough buffer for SDES packet"); 
    1044         return 0; 
    1045     } 
    1046     hdr.length = pj_htons((pj_uint16_t)hdr.length); 
    1047     hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; 
    1048     pj_memcpy(pkt, &hdr, sizeof(hdr)); 
    1049  
    1050     return sizeof(hdr); 
    10511064} 
    10521065 
     
    18321845    /* Send RTCP RR and SDES after we receive some RTP packets */ 
    18331846    if (stream->rtcp.received >= 10 && !stream->initial_rr) { 
    1834         void *sr_rr_pkt; 
    1835         pj_uint8_t *pkt; 
    1836         int len; 
    1837  
    1838         /* Build RR or SR */ 
    1839         pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 
    1840  
    1841         if (!stream->rtcp_sdes_bye_disabled) { 
    1842             pkt = (pj_uint8_t*) stream->enc->out_pkt; 
    1843             pj_memcpy(pkt, sr_rr_pkt, len); 
    1844             pkt += len; 
    1845  
    1846             /* Append SDES */ 
    1847             len = create_rtcp_sdes(stream, (pj_uint8_t*)pkt,  
    1848                                    stream->enc->out_pkt_size - len); 
    1849             if (len > 0) { 
    1850                 pkt += len; 
    1851                 len = ((pj_uint8_t*)pkt) - ((pj_uint8_t*)stream->enc->out_pkt); 
    1852                 status = pjmedia_transport_send_rtcp(stream->transport, 
    1853                                                      stream->enc->out_pkt, 
    1854                                                      len); 
    1855                 if (status != PJ_SUCCESS) { 
    1856                     PJ_PERROR(4,(stream->port.info.name.ptr, status, 
    1857                                  "Error sending RTCP SDES")); 
    1858                 } 
    1859             } 
    1860         } else { 
    1861             status = pjmedia_transport_send_rtcp(stream->transport, 
    1862                                                  sr_rr_pkt, len); 
    1863             if (status != PJ_SUCCESS) { 
    1864                 PJ_PERROR(4,(stream->port.info.name.ptr, status, 
    1865                              "Error sending initial RTCP RR")); 
    1866             } 
    1867         } 
    1868  
    1869         stream->initial_rr = PJ_TRUE; 
     1847        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 
     1848                           PJ_FALSE, PJ_FALSE); 
     1849        if (status != PJ_SUCCESS) { 
     1850            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     1851                     "Error sending initial RTCP RR")); 
     1852        } else { 
     1853            stream->initial_rr = PJ_TRUE; 
     1854        } 
    18701855    } 
    18711856} 
     
    24012386    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    24022387 
    2403 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
    2404     /* Send RTCP XR on stream destroy */ 
    2405     if (stream->rtcp.xr_enabled) { 
    2406         int i; 
    2407         pjmedia_jb_state jb_state; 
    2408         void *rtcp_pkt; 
    2409         int len; 
    2410  
    2411         /* Update RTCP XR with current JB states */ 
    2412         pjmedia_jbuf_get_state(stream->jb, &jb_state); 
    2413              
    2414         i = jb_state.avg_delay; 
    2415         pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
    2416                                     PJMEDIA_RTCP_XR_INFO_JB_NOM, 
    2417                                     i); 
    2418  
    2419         i = jb_state.max_delay; 
    2420         pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,  
    2421                                     PJMEDIA_RTCP_XR_INFO_JB_MAX, 
    2422                                     i); 
    2423  
    2424         /* Build RTCP XR packet */ 
    2425         pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,  
    2426                                    &rtcp_pkt, &len); 
    2427  
    2428         /* Send the RTCP XR to remote address */ 
    2429         pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); 
    2430          
    2431         /* Send the RTCP XR to third-party destination if specified */ 
    2432         if (stream->rtcp_xr_dest_len) { 
    2433             pjmedia_transport_send_rtcp2(stream->transport,  
    2434                                          &stream->rtcp_xr_dest, 
    2435                                          stream->rtcp_xr_dest_len,  
    2436                                          rtcp_pkt, len); 
    2437         } 
    2438     } 
    2439 #endif 
    2440  
    2441     /* Send RTCP BYE */ 
     2388    /* Send RTCP BYE (also SDES & XR) */ 
    24422389    if (!stream->rtcp_sdes_bye_disabled) { 
    2443         pjmedia_stream_send_rtcp_bye(stream); 
     2390        send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE); 
    24442391    } 
    24452392 
     
    27952742pjmedia_stream_send_rtcp_sdes( pjmedia_stream *stream ) 
    27962743{ 
    2797     unsigned len; 
    2798  
    27992744    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
    28002745 
    2801     len = create_rtcp_sdes(stream, (pj_uint8_t*)stream->enc->out_pkt, 
    2802                            stream->enc->out_pkt_size); 
    2803     if (len != 0) { 
    2804         return pjmedia_transport_send_rtcp(stream->transport,  
    2805                                            stream->enc->out_pkt, len); 
    2806     } 
    2807  
    2808     return PJ_SUCCESS; 
     2746    return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 
    28092747} 
    28102748 
     
    28182756 
    28192757    if (stream->enc && stream->transport) { 
    2820         unsigned len; 
    2821  
    2822         len = create_rtcp_bye(stream, (pj_uint8_t*)stream->enc->out_pkt, 
    2823                               stream->enc->out_pkt_size); 
    2824         if (len != 0) { 
    2825             return pjmedia_transport_send_rtcp(stream->transport,  
    2826                                                stream->enc->out_pkt, len); 
    2827         } 
     2758        return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE); 
    28282759    } 
    28292760 
Note: See TracChangeset for help on using the changeset viewer.