Ignore:
Timestamp:
Jul 12, 2018 8:22:31 AM (11 months ago)
Author:
nanang
Message:

Close #2126: Initial implementation of RTCP Feedback.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r5813 r5820  
    9797    int             ebit_cnt;               /**< # of E bit transmissions   */ 
    9898}; 
     99 
    99100 
    100101/** 
     
    246247    pj_uint32_t              rtp_rx_last_ts;        /**< Last received RTP timestamp*/ 
    247248    pj_status_t              rtp_rx_last_err;       /**< Last RTP recv() error */ 
     249 
     250    /* RTCP Feedback */ 
     251    pj_bool_t                send_rtcp_fb_nack;/**< Should we send NACK?    */ 
     252    pjmedia_rtcp_fb_nack     rtcp_fb_nack;     /**< NACK state.             */ 
     253 
     254 
    248255}; 
    249256 
     
    278285                             pj_bool_t with_sdes, 
    279286                             pj_bool_t with_bye, 
    280                              pj_bool_t with_xr); 
     287                             pj_bool_t with_xr, 
     288                             pj_bool_t with_fb); 
    281289 
    282290 
     
    461469 
    462470    /* Send RTCP */ 
    463     send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 
     471    send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 
    464472     
    465473    /* Update stats in case the stream is paused */ 
     
    9921000 
    9931001 
     1002static pj_status_t build_rtcp_fb(pjmedia_stream *stream, void *buf, 
     1003                                 pj_size_t *length) 
     1004{ 
     1005    pj_status_t status; 
     1006 
     1007    /* Generic NACK */ 
     1008    if (stream->send_rtcp_fb_nack && stream->rtcp_fb_nack.pid >= 0) 
     1009    { 
     1010        status = pjmedia_rtcp_fb_build_nack(&stream->rtcp, buf, length, 1, 
     1011                                            &stream->rtcp_fb_nack); 
     1012        if (status != PJ_SUCCESS) 
     1013            return status; 
     1014 
     1015        /* Reset Packet ID */ 
     1016        stream->rtcp_fb_nack.pid = -1; 
     1017    } 
     1018 
     1019    return PJ_SUCCESS; 
     1020} 
     1021 
     1022 
    9941023static pj_status_t send_rtcp(pjmedia_stream *stream, 
    9951024                             pj_bool_t with_sdes, 
    9961025                             pj_bool_t with_bye, 
    997                              pj_bool_t with_xr) 
     1026                             pj_bool_t with_xr, 
     1027                             pj_bool_t with_fb) 
    9981028{ 
    9991029    void *sr_rr_pkt; 
     
    10091039#endif 
    10101040 
    1011     if (with_sdes || with_bye || with_xr) { 
     1041    if (with_sdes || with_bye || with_xr || with_fb) { 
    10121042        pkt = (pj_uint8_t*) stream->out_rtcp_pkt; 
    10131043        pj_memcpy(pkt, sr_rr_pkt, len); 
     
    10171047        max_len = len; 
    10181048    } 
     1049 
     1050    /* RTCP FB must be sent in compound (i.e: with RR/SR and SDES) */ 
     1051    if (with_fb) 
     1052        with_sdes = PJ_TRUE; 
    10191053 
    10201054    /* Build RTCP SDES packet */ 
     
    10361070    } 
    10371071 
     1072    if (with_fb) { 
     1073        pj_size_t fb_len = max_len - len; 
     1074        status = build_rtcp_fb(stream, pkt+len, &fb_len); 
     1075        if (status != PJ_SUCCESS) { 
     1076            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     1077                                     "Error generating RTCP FB")); 
     1078        } else { 
     1079            len += (int)fb_len; 
     1080        } 
     1081    } 
     1082 
    10381083    /* Build RTCP XR packet */ 
    10391084#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
     
    11371182 
    11381183        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE, 
    1139                            with_xr); 
     1184                           with_xr, PJ_FALSE); 
    11401185        if (status != PJ_SUCCESS) { 
    11411186            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     
    16801725    const void *payload; 
    16811726    unsigned payloadlen; 
    1682     pjmedia_rtp_status seq_st; 
     1727    pjmedia_rtp_status seq_st = {0}; 
    16831728    pj_status_t status; 
    16841729    pj_bool_t pkt_discarded = PJ_FALSE; 
     
    20062051                         pj_ntohl(hdr->ts), payloadlen, pkt_discarded); 
    20072052 
     2053    /* RTCP-FB generic NACK */ 
     2054    if (stream->rtcp.received >= 10 && seq_st.diff > 1 && 
     2055        stream->send_rtcp_fb_nack && pj_ntohs(hdr->seq) >= seq_st.diff) 
     2056    { 
     2057        int i; 
     2058        pj_bzero(&stream->rtcp_fb_nack, sizeof(stream->rtcp_fb_nack)); 
     2059        stream->rtcp_fb_nack.pid = pj_ntohs(hdr->seq) - seq_st.diff + 1; 
     2060        for (i = 0; i < (seq_st.diff - 1); ++i) { 
     2061            stream->rtcp_fb_nack.blp <<= 1; 
     2062            stream->rtcp_fb_nack.blp |= 1; 
     2063        } 
     2064 
     2065        /* Send it immediately */ 
     2066        status = send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_TRUE); 
     2067        if (status != PJ_SUCCESS) { 
     2068            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     2069                      "Error sending RTCP FB generic NACK")); 
     2070        } else { 
     2071            stream->initial_rr = PJ_TRUE; 
     2072        } 
     2073    } 
     2074 
    20082075    /* Send RTCP RR and SDES after we receive some RTP packets */ 
    20092076    if (stream->rtcp.received >= 10 && !stream->initial_rr) { 
    20102077        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 
    2011                            PJ_FALSE, PJ_FALSE); 
     2078                           PJ_FALSE, PJ_FALSE, PJ_FALSE); 
    20122079        if (status != PJ_SUCCESS) { 
    20132080            PJ_PERROR(4,(stream->port.info.name.ptr, status, 
     
    21612228    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 
    21622229    stream->own_pool = own_pool; 
     2230 
     2231    /* Duplicate stream info */ 
    21632232    pj_memcpy(&stream->si, info, sizeof(*info)); 
    21642233    pj_strdup(pool, &stream->si.fmt.encoding_name, &info->fmt.encoding_name); 
    21652234    if (info->param) 
    21662235        stream->si.param = pjmedia_codec_param_clone(pool, info->param); 
     2236    pjmedia_rtcp_fb_info_dup(pool, &stream->si.loc_rtcp_fb, 
     2237                             &info->loc_rtcp_fb); 
     2238    pjmedia_rtcp_fb_info_dup(pool, &stream->si.rem_rtcp_fb, 
     2239                             &info->rem_rtcp_fb); 
    21672240 
    21682241    /* Init stream/port name */ 
     
    22002273    stream->last_dtmf = -1; 
    22012274    stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME; 
     2275    stream->rtcp_fb_nack.pid = -1; 
    22022276 
    22032277#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
     
    25912665#endif 
    25922666 
     2667    /* Check if RTCP-FB generic NACK is enabled for this codec */ 
     2668    if (stream->si.rem_rtcp_fb.cap_count) { 
     2669        pjmedia_rtcp_fb_info *rfi = &stream->si.rem_rtcp_fb; 
     2670        char cid[32]; 
     2671        unsigned i; 
     2672 
     2673        pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid)); 
     2674 
     2675        for (i = 0; i < rfi->cap_count; ++i) { 
     2676            if (rfi->caps[i].type == PJMEDIA_RTCP_FB_NACK && 
     2677                (!pj_strcmp2( &rfi->caps[i].codec_id, "*") || 
     2678                 !pj_stricmp2(&rfi->caps[i].codec_id, cid))) 
     2679            { 
     2680                stream->send_rtcp_fb_nack = PJ_TRUE; 
     2681                break; 
     2682            } 
     2683        } 
     2684    } 
     2685 
    25932686    /* Update the stream info's codec param */ 
    25942687    stream->si.param = &stream->codec_param; 
     
    26592752    /* Send RTCP BYE (also SDES & XR) */ 
    26602753    if (!stream->rtcp_sdes_bye_disabled) { 
    2661         send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE); 
     2754        send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE, PJ_FALSE); 
    26622755    } 
    26632756 
     
    30743167    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
    30753168 
    3076     return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 
     3169    return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 
    30773170} 
    30783171 
     
    30863179 
    30873180    if (stream->enc && stream->transport) { 
    3088         return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE); 
     3181        return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE, PJ_FALSE); 
    30893182    } 
    30903183 
Note: See TracChangeset for help on using the changeset viewer.