Changeset 5820


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

Close #2126: Initial implementation of RTCP Feedback.

Location:
pjproject/trunk
Files:
2 added
21 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/build/pjmedia.vcproj

    r5597 r5820  
    56365636                        </File> 
    56375637                        <File 
     5638                                RelativePath="..\src\pjmedia\rtcp_fb.c" 
     5639                                > 
     5640                        </File> 
     5641                        <File 
    56385642                                RelativePath="..\src\pjmedia\rtcp_xr.c" 
    56395643                                > 
     
    76017605                        </File> 
    76027606                        <File 
     7607                                RelativePath="..\include\pjmedia\rtcp_fb.h" 
     7608                                > 
     7609                        </File> 
     7610                        <File 
    76037611                                RelativePath="..\include\pjmedia\rtcp_xr.h" 
    76047612                                > 
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r5786 r5820  
    568568 
    569569/** 
     570 * Specify the maximum number of RTCP Feedback capability definition. 
     571 *  
     572 * Default: 16 
     573 */ 
     574#ifndef PJMEDIA_RTCP_FB_MAX_CAP 
     575#   define PJMEDIA_RTCP_FB_MAX_CAP              16 
     576#endif 
     577 
     578 
     579/** 
    570580 * Specify how long (in miliseconds) the stream should suspend the 
    571581 * silence detector/voice activity detector (VAD) during the initial 
  • pjproject/trunk/pjmedia/include/pjmedia/sdp.h

    r5748 r5820  
    603603 
    604604/** 
     605 * Get media transport protocol info, i.e: base transport and profiles, 
     606 * from the provided SDP media transport name string. 
     607 * 
     608 * @param tp        The SDP media transport name. 
     609 * 
     610 * @return          Media transport info, combination of transport protocol 
     611 *                  and profile bit flag defined in pjmedia_tp_proto. 
     612 */ 
     613PJ_DECL(pj_uint32_t) pjmedia_sdp_transport_get_proto(const pj_str_t *tp); 
     614 
     615 
     616/** 
    605617 * Deactivate SDP media. 
    606618 * 
  • pjproject/trunk/pjmedia/include/pjmedia/stream.h

    r5788 r5820  
    3232#include <pjmedia/port.h> 
    3333#include <pjmedia/rtcp.h> 
     34#include <pjmedia/rtcp_fb.h> 
    3435#include <pjmedia/transport.h> 
    3536#include <pjmedia/vid_codec.h> 
     
    110111                                         this will be ignored.              */ 
    111112#endif 
     113    pjmedia_rtcp_fb_info loc_rtcp_fb; /**< Local RTCP-FB info.              */ 
     114    pjmedia_rtcp_fb_info rem_rtcp_fb; /**< Remote RTCP-FB info.             */ 
    112115    pjmedia_codec_info  fmt;        /**< Incoming codec format info.        */ 
    113116    pjmedia_codec_param *param;     /**< Optional codec param.              */ 
  • pjproject/trunk/pjmedia/include/pjmedia/types.h

    r5166 r5820  
    7373 
    7474/** 
    75  * Media transport protocol. 
     75 * Media transport protocol and profile. 
    7676 */ 
    7777typedef enum pjmedia_tp_proto 
    7878{ 
     79    /* Basic transports */ 
     80 
    7981    /** No transport type */ 
    80     PJMEDIA_TP_PROTO_NONE = 0, 
     82    PJMEDIA_TP_PROTO_NONE           = 0, 
     83 
     84    /** Transport unknown */ 
     85    PJMEDIA_TP_PROTO_UNKNOWN        = (1 << 0), 
     86 
     87    /** UDP transport */ 
     88    PJMEDIA_TP_PROTO_UDP            = (1 << 1), 
     89 
     90    /** RTP transport */ 
     91    PJMEDIA_TP_PROTO_RTP            = (1 << 2), 
     92 
     93    /** DTLS transport */ 
     94    PJMEDIA_TP_PROTO_DTLS           = (1 << 3), 
     95 
     96 
     97    /* Basic profiles */ 
     98     
     99    /** RTCP Feedback profile */ 
     100    PJMEDIA_TP_PROFILE_RTCP_FB      = (1 << 13), 
     101 
     102    /** Secure RTP profile */ 
     103    PJMEDIA_TP_PROFILE_SRTP         = (1 << 14), 
     104 
     105    /** Audio/video profile */ 
     106    PJMEDIA_TP_PROFILE_AVP          = (1 << 15), 
     107 
     108 
     109    /* Predefined transport profiles (commonly used) */ 
    81110 
    82111    /** RTP using A/V profile */ 
    83     PJMEDIA_TP_PROTO_RTP_AVP, 
    84  
    85     /** Secure RTP */ 
    86     PJMEDIA_TP_PROTO_RTP_SAVP, 
    87  
    88     /** Unknown */ 
    89     PJMEDIA_TP_PROTO_UNKNOWN 
     112    PJMEDIA_TP_PROTO_RTP_AVP        = (PJMEDIA_TP_PROTO_RTP | 
     113                                       PJMEDIA_TP_PROFILE_AVP), 
     114 
     115    /** Secure RTP using A/V profile */ 
     116    PJMEDIA_TP_PROTO_RTP_SAVP       = (PJMEDIA_TP_PROTO_RTP_AVP | 
     117                                       PJMEDIA_TP_PROFILE_SRTP), 
     118 
     119    /** Secure RTP using A/V profile and DTLS-SRTP keying */ 
     120    PJMEDIA_TP_PROTO_DTLS_SRTP      = (PJMEDIA_TP_PROTO_DTLS | 
     121                                       PJMEDIA_TP_PROTO_RTP_SAVP), 
     122 
     123    /** RTP using A/V and RTCP feedback profile */ 
     124    PJMEDIA_TP_PROTO_RTP_AVPF       = (PJMEDIA_TP_PROTO_RTP_AVP | 
     125                                       PJMEDIA_TP_PROFILE_RTCP_FB), 
     126 
     127    /** Secure RTP using A/V and RTCP feedback profile */ 
     128    PJMEDIA_TP_PROTO_RTP_SAVPF      = (PJMEDIA_TP_PROTO_RTP_SAVP | 
     129                                       PJMEDIA_TP_PROFILE_RTCP_FB), 
     130 
     131    /** Secure RTP using A/V and RTCP feedback profile and DTLS-SRTP keying */ 
     132    PJMEDIA_TP_PROTO_DTLS_SRTPF     = (PJMEDIA_TP_PROTO_DTLS_SRTP | 
     133                                       PJMEDIA_TP_PROFILE_RTCP_FB), 
    90134 
    91135} pjmedia_tp_proto; 
    92136 
     137/** 
     138 * Macro helper for checking if a transport protocol contains specific 
     139 * transport and profile flags. 
     140 */ 
     141#define PJMEDIA_TP_PROTO_HAS_FLAG(TP_PROTO, FLAGS) \ 
     142                                    (((TP_PROTO) & (FLAGS)) == (FLAGS)) 
     143 
     144/** 
     145 * Macro helper for excluding specific flags in transport protocol. 
     146 */ 
     147#define PJMEDIA_TP_PROTO_TRIM_FLAG(TP_PROTO, FLAGS) ((TP_PROTO) &= ~(FLAGS)) 
    93148 
    94149/** 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp.c

    r5753 r5820  
    16421642                                               const pj_str_t *t2) 
    16431643{ 
    1644     static const pj_str_t ID_RTP_AVP  = { "RTP/AVP", 7 }; 
    1645     static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
     1644    pj_uint32_t t1_proto, t2_proto; 
    16461645 
    16471646    /* Exactly equal? */ 
     
    16491648        return PJ_SUCCESS; 
    16501649 
     1650    /* Check if boths are RTP/AVP based */ 
     1651    t1_proto = pjmedia_sdp_transport_get_proto(t1); 
     1652    t2_proto = pjmedia_sdp_transport_get_proto(t2); 
     1653    if (PJMEDIA_TP_PROTO_HAS_FLAG(t1_proto, PJMEDIA_TP_PROTO_RTP_AVP) &&  
     1654        PJMEDIA_TP_PROTO_HAS_FLAG(t2_proto, PJMEDIA_TP_PROTO_RTP_AVP)) 
     1655    { 
     1656        return PJ_SUCCESS; 
     1657    } 
     1658 
    16511659    /* Compatible? */ 
    1652     if ((!pj_stricmp(t1, &ID_RTP_AVP) || !pj_stricmp(t1, &ID_RTP_SAVP)) && 
    1653         (!pj_stricmp(t2, &ID_RTP_AVP) || !pj_stricmp(t2, &ID_RTP_SAVP))) 
    1654         return PJ_SUCCESS; 
     1660    //{ 
     1661    //  static const pj_str_t ID_RTP_AVP  = { "RTP/AVP", 7 }; 
     1662    //  static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
     1663    //  if ((!pj_stricmp(t1, &ID_RTP_AVP) || !pj_stricmp(t1, &ID_RTP_SAVP)) && 
     1664    //      (!pj_stricmp(t2, &ID_RTP_AVP) || !pj_stricmp(t2, &ID_RTP_SAVP))) 
     1665    //      return PJ_SUCCESS; 
     1666    //} 
    16551667 
    16561668    return PJMEDIA_SDP_ETPORTNOTEQUAL; 
     1669} 
     1670 
     1671 
     1672/* 
     1673 * Get media transport info, e.g: protocol and profile. 
     1674 */ 
     1675PJ_DEF(pj_uint32_t) pjmedia_sdp_transport_get_proto(const pj_str_t *tp) 
     1676{ 
     1677    pj_str_t token, rest = {0}; 
     1678    pj_ssize_t idx; 
     1679 
     1680    PJ_ASSERT_RETURN(tp, PJMEDIA_TP_PROTO_NONE); 
     1681 
     1682    idx = pj_strtok2(tp, "/", &token, 0); 
     1683    if (idx != tp->slen) 
     1684        pj_strset(&rest, tp->ptr + token.slen + 1, tp->slen - token.slen - 1); 
     1685 
     1686    if (pj_stricmp2(&token, "RTP") == 0) { 
     1687        /* Starts with "RTP" */ 
     1688 
     1689        /* RTP/AVP */ 
     1690        if (pj_stricmp2(&rest, "AVP") == 0) 
     1691            return PJMEDIA_TP_PROTO_RTP_AVP; 
     1692 
     1693        /* RTP/SAVP */ 
     1694        if (pj_stricmp2(&rest, "SAVP") == 0) 
     1695            return PJMEDIA_TP_PROTO_RTP_SAVP; 
     1696 
     1697        /* RTP/AVPF */ 
     1698        if (pj_stricmp2(&rest, "AVPF") == 0) 
     1699            return PJMEDIA_TP_PROTO_RTP_AVPF; 
     1700 
     1701        /* RTP/SAVPF */ 
     1702        if (pj_stricmp2(&rest, "SAVPF") == 0) 
     1703            return PJMEDIA_TP_PROTO_RTP_SAVPF; 
     1704 
     1705    } else if (pj_stricmp2(&token, "UDP") == 0) { 
     1706        /* Starts with "UDP" */ 
     1707 
     1708        /* Plain UDP */ 
     1709        if (rest.slen == 0) 
     1710            return PJMEDIA_TP_PROTO_UDP; 
     1711 
     1712        /* DTLS-SRTP */ 
     1713        if (pj_stricmp2(&rest, "TLS/RTP/SAVP") == 0) 
     1714            return PJMEDIA_TP_PROTO_DTLS_SRTP; 
     1715 
     1716        /* DTLS-SRTP with RTCP-FB */ 
     1717        if (pj_stricmp2(&rest, "TLS/RTP/SAVPF") == 0) 
     1718            return PJMEDIA_TP_PROTO_DTLS_SRTPF; 
     1719    } 
     1720 
     1721    /* Unknown transport */ 
     1722    return PJMEDIA_TP_PROTO_UNKNOWN; 
    16571723} 
    16581724 
  • 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 
  • pjproject/trunk/pjmedia/src/pjmedia/stream_info.c

    r5788 r5820  
    2828static const pj_str_t ID_IP4 = { "IP4", 3}; 
    2929static const pj_str_t ID_IP6 = { "IP6", 3}; 
    30 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 
    31 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
    3230//static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 
    3331static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 
     
    417415        return PJMEDIA_SDPNEG_EINVANSTP; 
    418416 
    419     if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) { 
    420  
    421         si->proto = PJMEDIA_TP_PROTO_RTP_AVP; 
    422  
    423     } else if (pj_stristr(&local_m->desc.transport, &ID_RTP_SAVP)) { 
    424  
    425         si->proto = PJMEDIA_TP_PROTO_RTP_SAVP; 
    426  
    427     } else { 
    428  
    429         si->proto = PJMEDIA_TP_PROTO_UNKNOWN; 
     417    /* Get the transport protocol */ 
     418    si->proto = pjmedia_sdp_transport_get_proto(&local_m->desc.transport); 
     419 
     420    /* Just return success if stream is not RTP/AVP compatible */ 
     421    if (!PJMEDIA_TP_PROTO_HAS_FLAG(si->proto, PJMEDIA_TP_PROTO_RTP_AVP)) 
    430422        return PJ_SUCCESS; 
    431     } 
    432  
    433423 
    434424    /* Check address family in remote SDP */ 
     
    602592    /* Get codec info and param */ 
    603593    status = get_audio_codec_info_param(si, pool, mgr, local_m, rem_m); 
     594    if (status != PJ_SUCCESS) 
     595        return status; 
    604596 
    605597    /* Leave SSRC to random. */ 
     
    609601    si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 
    610602 
     603    /* Get local RTCP-FB info */ 
     604    status = pjmedia_rtcp_fb_decode_sdp(pool, endpt, NULL, local, stream_idx, 
     605                                        &si->loc_rtcp_fb); 
     606    if (status != PJ_SUCCESS) 
     607        return status; 
     608 
     609    /* Get remote RTCP-FB info */ 
     610    status = pjmedia_rtcp_fb_decode_sdp(pool, endpt, NULL, remote, stream_idx, 
     611                                        &si->rem_rtcp_fb); 
     612    if (status != PJ_SUCCESS) 
     613        return status; 
     614 
    611615    return status; 
    612616} 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c

    r5788 r5820  
    186186}; 
    187187 
    188 static const pj_str_t STR_RTP_AVP       = { "RTP/AVP", 7 }; 
    189188static const pj_str_t STR_CANDIDATE     = { "candidate", 9}; 
    190189static const pj_str_t STR_REM_CAND      = { "remote-candidates", 17 }; 
     
    14081407     */ 
    14091408    if ((tp_ice->media_option & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) { 
    1410         pjmedia_sdp_media *loc_m, *rem_m; 
    1411  
    1412         rem_m = rem_sdp? rem_sdp->media[media_index] : NULL; 
    1413         loc_m = sdp_local->media[media_index]; 
    1414  
    1415         if (pj_stricmp(&loc_m->desc.transport, &STR_RTP_AVP) || 
    1416            (rem_m && pj_stricmp(&rem_m->desc.transport, &STR_RTP_AVP))) 
     1409        pjmedia_sdp_media *m_rem, *m_loc; 
     1410        pj_uint32_t tp_proto_loc, tp_proto_rem; 
     1411 
     1412        m_rem = rem_sdp? rem_sdp->media[media_index] : NULL; 
     1413        m_loc = sdp_local->media[media_index]; 
     1414 
     1415        tp_proto_loc = pjmedia_sdp_transport_get_proto(&m_loc->desc.transport); 
     1416        tp_proto_rem = m_rem?  
     1417                pjmedia_sdp_transport_get_proto(&m_rem->desc.transport) : 0; 
     1418        PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_loc, PJMEDIA_TP_PROFILE_RTCP_FB); 
     1419        PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_rem, PJMEDIA_TP_PROFILE_RTCP_FB); 
     1420 
     1421        if ((tp_proto_loc != PJMEDIA_TP_PROTO_RTP_AVP) || 
     1422            (m_rem && tp_proto_rem != PJMEDIA_TP_PROTO_RTP_AVP)) 
    14171423        { 
    1418             pjmedia_sdp_media_deactivate(sdp_pool, loc_m); 
     1424            pjmedia_sdp_media_deactivate(sdp_pool, m_loc); 
    14191425            return PJMEDIA_SDP_EINPROTO; 
    14201426        } 
     
    18261832    param.addr_len = addr_len; 
    18271833    param.rtp_cb = rtp_cb; 
     1834    param.rtcp_cb = rtcp_cb; 
    18281835    return transport_attach2(tp, &param); 
    18291836} 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_dtls.c

    r5794 r5820  
    10481048        pjmedia_sdp_media *m_rem = sdp_remote->media[media_index]; 
    10491049        pjmedia_sdp_attr *attr_setup; 
    1050  
    1051         if (pj_stricmp(&m_rem->desc.transport, &ID_TP_DTLS_SRTP)!=0) { 
     1050        pj_uint32_t rem_proto = 0; 
     1051 
     1052        rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 
     1053        if (!PJMEDIA_TP_PROTO_HAS_FLAG(rem_proto, PJMEDIA_TP_PROTO_DTLS_SRTP)) 
     1054        { 
    10521055            /* Remote doesn't signal DTLS-SRTP */ 
    10531056            status = PJMEDIA_SRTP_ESDPINTRANSPORT; 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_sdes.c

    r5755 r5820  
    274274{ 
    275275    struct transport_srtp *srtp = (struct transport_srtp*)tp->user_data; 
     276    pj_uint32_t rem_proto = 0; 
    276277 
    277278    PJ_UNUSED_ARG(options); 
     
    281282    if (!srtp->offerer_side) { 
    282283        pjmedia_sdp_media *m = sdp_remote->media[media_index]; 
    283         if (pj_stricmp(&m->desc.transport, &ID_RTP_AVP)  != 0 && 
    284             pj_stricmp(&m->desc.transport, &ID_RTP_SAVP) != 0) 
     284 
     285        /* Get transport protocol and drop any RTCP-FB flag */ 
     286        rem_proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 
     287        PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 
     288        if (rem_proto != PJMEDIA_TP_PROTO_RTP_AVP && 
     289            rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 
    285290        { 
    286291            return PJMEDIA_SRTP_ESDPINTRANSPORT; 
     
    292297        /* As offerer: do nothing. */ 
    293298    } else { 
    294         pjmedia_sdp_media *m_rem = sdp_remote->media[media_index]; 
    295  
    296299        /* Validate remote media transport based on SRTP usage option. */ 
    297300        switch (srtp->setting.use) { 
    298301            case PJMEDIA_SRTP_DISABLED: 
    299                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
     302                if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 
    300303                    return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    301304                break; 
     
    303306                break; 
    304307            case PJMEDIA_SRTP_MANDATORY: 
    305                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) 
     308                if (rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 
    306309                    return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    307310                break; 
     
    334337    { 
    335338        pjmedia_sdp_media *m = sdp_remote? m_rem : m_loc; 
    336         if (pj_stricmp(&m->desc.transport, &ID_RTP_AVP)  != 0 && 
    337             pj_stricmp(&m->desc.transport, &ID_RTP_SAVP) != 0) 
     339        pj_uint32_t proto = 0; 
     340 
     341        /* Get transport protocol and drop any RTCP-FB flag */ 
     342        proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 
     343        PJMEDIA_TP_PROTO_TRIM_FLAG(proto, PJMEDIA_TP_PROFILE_RTCP_FB); 
     344        if (proto != PJMEDIA_TP_PROTO_RTP_AVP && 
     345            proto != PJMEDIA_TP_PROTO_RTP_SAVP) 
    338346        { 
    339347            return PJMEDIA_SRTP_ESDPINTRANSPORT; 
     
    409417    } else { 
    410418        /* Answerer side */ 
     419        pj_uint32_t rem_proto = 0; 
    411420 
    412421        pj_assert(sdp_remote && m_rem); 
     422 
     423        /* Get transport protocol and drop any RTCP-FB flag */ 
     424        rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 
     425        PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 
    413426 
    414427        /* Generate transport */ 
     
    416429            case PJMEDIA_SRTP_DISABLED: 
    417430                /* Should never reach here */ 
    418                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
     431                if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 
    419432                    return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    420433                return PJ_SUCCESS; 
     
    422435                break; 
    423436            case PJMEDIA_SRTP_MANDATORY: 
    424                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) 
     437                if (rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 
    425438                    return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    426439                break; 
     
    496509                     */ 
    497510                    if ((!has_crypto_attr || matched_idx == -1) && 
    498                         pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0) 
     511                        rem_proto == PJMEDIA_TP_PROTO_RTP_AVP) 
    499512                    { 
    500513                        return PJ_SUCCESS; 
     
    610623 
    611624    /* Verify media transport, it has to be RTP/AVP or RTP/SAVP */ 
    612     if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP)  != 0 && 
    613         pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) 
    614625    { 
    615         return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    616     } 
    617  
    618     if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
    619         srtp->peer_use = PJMEDIA_SRTP_MANDATORY; 
    620     else 
    621         srtp->peer_use = PJMEDIA_SRTP_OPTIONAL; 
     626        pj_uint32_t rem_proto; 
     627 
     628        /* Get transport protocol and drop any RTCP-FB flag */ 
     629        rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 
     630        PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 
     631        if (rem_proto != PJMEDIA_TP_PROTO_RTP_AVP && 
     632            rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 
     633        { 
     634            return PJMEDIA_SRTP_ESDPINTRANSPORT; 
     635        } 
     636 
     637        /* Also check if peer signal SRTP as mandatory */ 
     638        if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 
     639            srtp->peer_use = PJMEDIA_SRTP_MANDATORY; 
     640        else 
     641            srtp->peer_use = PJMEDIA_SRTP_OPTIONAL; 
     642    } 
    622643 
    623644    /* For answerer side, this function will just have to start SRTP as 
     
    647668        fill_local_crypto(srtp->pool, m_loc, loc_crypto, &loc_cryto_cnt); 
    648669    } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 
    649         if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) { 
     670        if (srtp->peer_use != PJMEDIA_SRTP_MANDATORY) { 
    650671            DEACTIVATE_MEDIA(pool, m_loc); 
    651672            return PJMEDIA_SDP_EINPROTO; 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c

    r5788 r5820  
    3737/* Maximum pending write operations */ 
    3838#define MAX_PENDING 4 
    39  
    40 static const pj_str_t ID_RTP_AVP  = { "RTP/AVP", 7 }; 
    4139 
    4240/* Pending write buffer */ 
     
    10311029    if ((udp->media_options & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) { 
    10321030        pjmedia_sdp_media *m_rem, *m_loc; 
     1031        pj_uint32_t tp_proto_loc, tp_proto_rem; 
    10331032 
    10341033        m_rem = rem_sdp? rem_sdp->media[media_index] : NULL; 
    10351034        m_loc = sdp_local->media[media_index]; 
    10361035 
    1037         if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) || 
    1038            (m_rem && pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP))) 
     1036        tp_proto_loc = pjmedia_sdp_transport_get_proto(&m_loc->desc.transport); 
     1037        tp_proto_rem = m_rem?  
     1038                pjmedia_sdp_transport_get_proto(&m_rem->desc.transport) : 0; 
     1039        PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_loc, PJMEDIA_TP_PROFILE_RTCP_FB); 
     1040        PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_rem, PJMEDIA_TP_PROFILE_RTCP_FB); 
     1041 
     1042        if ((tp_proto_loc != PJMEDIA_TP_PROTO_RTP_AVP) || 
     1043            (m_rem && tp_proto_rem != PJMEDIA_TP_PROTO_RTP_AVP)) 
    10391044        { 
    10401045            pjmedia_sdp_media_deactivate(pool, m_loc); 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream_info.c

    r5788 r5820  
    2929static const pj_str_t ID_IP4 = { "IP4", 3}; 
    3030static const pj_str_t ID_IP6 = { "IP6", 3}; 
    31 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 
    32 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
    3331//static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 
    3432static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 
     
    240238        return PJMEDIA_SDPNEG_EINVANSTP; 
    241239 
    242     if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) { 
    243  
    244         si->proto = PJMEDIA_TP_PROTO_RTP_AVP; 
    245  
    246     } else if (pj_stristr(&local_m->desc.transport, &ID_RTP_SAVP)) { 
    247  
    248         si->proto = PJMEDIA_TP_PROTO_RTP_SAVP; 
    249  
    250     } else { 
    251  
    252         si->proto = PJMEDIA_TP_PROTO_UNKNOWN; 
     240    /* Get the transport protocol */ 
     241    si->proto = pjmedia_sdp_transport_get_proto(&local_m->desc.transport); 
     242 
     243    /* Return success if transport protocol is not RTP/AVP compatible */ 
     244    if (!PJMEDIA_TP_PROTO_HAS_FLAG(si->proto, PJMEDIA_TP_PROTO_RTP_AVP)) 
    253245        return PJ_SUCCESS; 
    254     } 
    255246 
    256247 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.i

    r5807 r5820  
    110110typedef enum pjmedia_vid_packing {PJMEDIA_VID_PACKING_UNKNOWN, PJMEDIA_VID_PACKING_PACKETS = 1, PJMEDIA_VID_PACKING_WHOLE = 2} pjmedia_vid_packing; 
    111111 
     112typedef enum pjmedia_rtcp_fb_type {PJMEDIA_RTCP_FB_ACK, PJMEDIA_RTCP_FB_NACK, PJMEDIA_RTCP_FB_TRR_INT, PJMEDIA_RTCP_FB_OTHER} pjmedia_rtcp_fb_type; 
     113 
    112114typedef enum pjsip_cred_data_type {PJSIP_CRED_DATA_PLAIN_PASSWD = 0, PJSIP_CRED_DATA_DIGEST = 1, PJSIP_CRED_DATA_EXT_AKA = 16} pjsip_cred_data_type; 
    113115 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.lst

    r5755 r5820  
    1818pjmedia/format.h                pjmedia_format_id 
    1919pjmedia/vid_codec.h             pjmedia_vid_packing 
     20pjmedia/rtcp_fb.h               pjmedia_rtcp_fb_type 
    2021 
    2122pjsip/sip_auth.h                pjsip_cred_data_type 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5792 r5820  
    39133913    pj_bool_t           enable_rtcp_mux; 
    39143914 
     3915    /** 
     3916     * RTCP Feedback configuration. 
     3917     */ 
     3918    pjmedia_rtcp_fb_setting rtcp_fb_cfg; 
     3919 
    39153920} pjsua_acc_config; 
    39163921 
  • pjproject/trunk/pjsip/include/pjsua2/account.hpp

    r5801 r5820  
    738738typedef std::vector<SrtpCrypto> SrtpCryptoVector; 
    739739 
     740/** 
     741 * SRTP settings. 
     742 */ 
    740743struct SrtpOpt : public PersistentObject 
    741744{ 
     
    772775     */ 
    773776    pjsua_srtp_opt toPj() const; 
     777 
     778public: 
     779    /** 
     780     * Read this object from a container node. 
     781     * 
     782     * @param node              Container to read values from. 
     783     */ 
     784    virtual void readObject(const ContainerNode &node) throw(Error); 
     785 
     786    /** 
     787     * Write this object to a container node. 
     788     * 
     789     * @param node              Container to write values to. 
     790     */ 
     791    virtual void writeObject(ContainerNode &node) const throw(Error); 
     792}; 
     793 
     794/** 
     795 * RTCP Feedback capability. 
     796 */ 
     797struct RtcpFbCap 
     798{ 
     799    /** 
     800     * Specify the codecs to which the capability is applicable. Codec ID is 
     801     * using the same format as in pjmedia_codec_mgr_find_codecs_by_id() and 
     802     * pjmedia_vid_codec_mgr_find_codecs_by_id(), e.g: "L16/8000/1", "PCMU", 
     803     * "H264". This can also be an asterisk ("*") to represent all codecs. 
     804     */ 
     805    string                  codecId; 
     806 
     807    /** 
     808     * Specify the RTCP Feedback type. 
     809     */ 
     810    pjmedia_rtcp_fb_type    type; 
     811 
     812    /** 
     813     * Specify the type name if RTCP Feedback type is PJMEDIA_RTCP_FB_OTHER. 
     814     */ 
     815    string                  typeName; 
     816 
     817    /** 
     818     * Specify the RTCP Feedback parameters. 
     819     */ 
     820    string                  param; 
     821 
     822public: 
     823    /** 
     824     * Constructor. 
     825     */ 
     826    RtcpFbCap() : type(PJMEDIA_RTCP_FB_OTHER) 
     827    {} 
     828 
     829    /** 
     830     * Convert from pjsip 
     831     */ 
     832    void fromPj(const pjmedia_rtcp_fb_cap &prm); 
     833 
     834    /** 
     835     * Convert to pjsip 
     836     */ 
     837    pjmedia_rtcp_fb_cap toPj() const; 
     838}; 
     839 
     840/* Array of RTCP Feedback capabilities. */ 
     841typedef std::vector<RtcpFbCap> RtcpFbCapVector; 
     842 
     843 
     844/** 
     845 * RTCP Feedback settings. 
     846 */ 
     847struct RtcpFbConfig : public PersistentObject 
     848{ 
     849    /** 
     850     * Specify whether transport protocol in SDP media description uses 
     851     * RTP/AVP instead of RTP/AVPF. Note that the standard mandates to signal 
     852     * AVPF profile, but it may cause SDP negotiation failure when negotiating 
     853     * with endpoints that does not support RTCP Feedback (including older 
     854     * version of PJSIP). 
     855     * 
     856     * Default: false. 
     857     */ 
     858    bool                    dontUseAvpf; 
     859 
     860    /** 
     861     * RTCP Feedback capabilities. 
     862     */ 
     863    RtcpFbCapVector         caps; 
     864 
     865public: 
     866    /** 
     867     * Constructor. 
     868     */ 
     869    RtcpFbConfig(); 
     870 
     871    /** 
     872     * Convert from pjsip 
     873     */ 
     874    void fromPj(const pjmedia_rtcp_fb_setting &prm); 
     875 
     876    /** 
     877     * Convert to pjsip 
     878     */ 
     879    pjmedia_rtcp_fb_setting toPj() const; 
    774880 
    775881public: 
     
    854960     */ 
    855961    bool                rtcpMuxEnabled; 
     962 
     963    /** 
     964     * RTCP Feedback settings. 
     965     */ 
     966    RtcpFbConfig        rtcpFbConfig; 
    856967 
    857968public: 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c

    r5805 r5820  
    141141 
    142142    pj_strdup(pool, &dst->ka_data, &src->ka_data); 
     143 
     144    pjmedia_rtcp_fb_setting_dup(pool, &dst->rtcp_fb_cfg, &src->rtcp_fb_cfg); 
    143145} 
    144146 
     
    14331435    acc->cfg.ip_change_cfg.hangup_calls = cfg->ip_change_cfg.hangup_calls;     
    14341436    acc->cfg.ip_change_cfg.reinvite_flags = cfg->ip_change_cfg.reinvite_flags; 
     1437 
     1438    /* RTCP-FB config */ 
     1439    pjmedia_rtcp_fb_setting_dup(acc->pool, &acc->cfg.rtcp_fb_cfg, 
     1440                                &cfg->rtcp_fb_cfg); 
    14351441 
    14361442on_return: 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r5813 r5820  
    292292    pjsua_transport_config_default(&cfg->rtp_cfg); 
    293293    cfg->rtp_cfg.port = DEFAULT_RTP_PORT; 
     294    pjmedia_rtcp_fb_setting_default(&cfg->rtcp_fb_cfg); 
    294295 
    295296    pjsua_media_config_default(&med_cfg); 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r5788 r5820  
    22582258    pj_sockaddr origin; 
    22592259    pjsua_call *call = &pjsua_var.calls[call_id]; 
     2260    pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 
    22602261    pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; 
    22612262    unsigned mi; 
     
    24842485            } 
    24852486        } 
     2487 
     2488        /* Add RTCP-FB info in SDP if we are offerer */ 
     2489        if (rem_sdp == NULL && acc->cfg.rtcp_fb_cfg.cap_count) { 
     2490            status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt, 
     2491                                                &acc->cfg.rtcp_fb_cfg, sdp, 
     2492                                                mi, rem_sdp); 
     2493            if (status != PJ_SUCCESS) { 
     2494                PJ_PERROR(3,(THIS_FILE, status, 
     2495                             "Call %d media %d: Failed to encode RTCP-FB " 
     2496                             "setting to SDP", 
     2497                             call_id, mi)); 
     2498            } 
     2499        } 
    24862500    } 
    24872501 
     
    25292543        sdp->bandw[sdp->bandw_count++] = b; 
    25302544    } 
    2531  
    25322545 
    25332546#if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     
    29612974#endif 
    29622975 
    2963     /* Applying media count limitation. Note that in generating SDP answer, 
    2964      * no media count limitation applied, as we didn't know yet which media 
    2965      * would pass the SDP negotiation. 
     2976    /* We need to re-nego SDP or modify our answer when: 
     2977     * - media count exceeds the configured limit, 
     2978     * - RTCP-FB is enabled (so a=rtcp-fb will only be printed for negotiated 
     2979     *   codecs) 
    29662980     */ 
    2967     if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) 
     2981    if (!pjmedia_sdp_neg_was_answer_remote(call->inv->neg) && 
     2982        ((maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) || 
     2983        (acc->cfg.rtcp_fb_cfg.cap_count))) 
    29682984    { 
    2969         pjmedia_sdp_session *local_sdp2; 
    2970  
    2971         maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt); 
    2972         mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt); 
    2973         local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp); 
    2974  
    2975         for (mi=0; mi < local_sdp2->media_count; ++mi) { 
    2976             pjmedia_sdp_media *m = local_sdp2->media[mi]; 
    2977  
    2978             if (m->desc.port == 0 || 
    2979                 pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) || 
    2980                 pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0]))) 
    2981             { 
    2982                 continue; 
    2983             } 
    2984              
    2985             /* Deactivate this media */ 
    2986             pjmedia_sdp_media_deactivate(tmp_pool, m); 
    2987         } 
    2988  
    2989         local_sdp = local_sdp2; 
     2985        pjmedia_sdp_session *local_sdp_renego = NULL; 
     2986 
     2987        local_sdp_renego = pjmedia_sdp_session_clone(tmp_pool, local_sdp); 
     2988        local_sdp = local_sdp_renego; 
    29902989        need_renego_sdp = PJ_TRUE; 
     2990 
     2991        /* Add RTCP-FB info into local SDP answer */ 
     2992        if (acc->cfg.rtcp_fb_cfg.cap_count) { 
     2993            for (mi=0; mi < local_sdp_renego->media_count; ++mi) { 
     2994                status = pjmedia_rtcp_fb_encode_sdp( 
     2995                                        tmp_pool, pjsua_var.med_endpt, 
     2996                                        &acc->cfg.rtcp_fb_cfg, 
     2997                                        local_sdp_renego, mi, remote_sdp); 
     2998                if (status != PJ_SUCCESS) { 
     2999                    PJ_PERROR(3,(THIS_FILE, status, 
     3000                                 "Call %d media %d: Failed to encode RTCP-FB " 
     3001                                 "setting to SDP", 
     3002                                 call_id, mi)); 
     3003                } 
     3004            } 
     3005        } 
     3006 
     3007        /* Applying media count limitation. Note that in generating SDP 
     3008         * answer, no media count limitation applied as we didn't know yet 
     3009         * which media would pass the SDP negotiation. 
     3010         */ 
     3011        if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) 
     3012        { 
     3013            maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt); 
     3014            mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt); 
     3015 
     3016            for (mi=0; mi < local_sdp_renego->media_count; ++mi) { 
     3017                pjmedia_sdp_media *m = local_sdp_renego->media[mi]; 
     3018 
     3019                if (m->desc.port == 0 || 
     3020                    pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) || 
     3021                    pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0]))) 
     3022                { 
     3023                    continue; 
     3024                } 
     3025             
     3026                /* Deactivate this excess media */ 
     3027                pjmedia_sdp_media_deactivate(tmp_pool, m); 
     3028            } 
     3029        } 
    29913030    } 
    29923031 
     
    33893428              sizeof(call->media_prov[0]) * call->med_prov_cnt); 
    33903429 
    3391     /* Perform SDP re-negotiation if some media have just got disabled 
    3392      * in this function due to media count limit settings. 
    3393      */ 
     3430    /* Perform SDP re-negotiation. */ 
    33943431    if (got_media && need_renego_sdp) { 
    33953432        pjmedia_sdp_neg *neg = call->inv->neg; 
    33963433 
    3397         /* This should only happen when we are the answerer. */ 
    3398         PJ_ASSERT_RETURN(neg && !pjmedia_sdp_neg_was_answer_remote(neg), 
    3399                          PJMEDIA_SDPNEG_EINSTATE); 
    3400          
    34013434        status = pjmedia_sdp_neg_set_remote_offer(tmp_pool, neg, remote_sdp); 
    34023435        if (status != PJ_SUCCESS) 
  • pjproject/trunk/pjsip/src/pjsua2/account.cpp

    r5801 r5820  
    2727 
    2828#define THIS_FILE               "account.cpp" 
     29 
     30/////////////////////////////////////////////////////////////////////////////// 
     31 
     32void RtcpFbCap::fromPj(const pjmedia_rtcp_fb_cap &prm) 
     33{ 
     34    this->codecId   = pj2Str(prm.codec_id); 
     35    this->type      = prm.type; 
     36    this->typeName  = pj2Str(prm.type_name); 
     37    this->param     = pj2Str(prm.param); 
     38} 
     39 
     40pjmedia_rtcp_fb_cap RtcpFbCap::toPj() const 
     41{ 
     42    pjmedia_rtcp_fb_cap cap; 
     43 
     44    pj_bzero(&cap, sizeof(cap)); 
     45    cap.codec_id    = str2Pj(this->codecId); 
     46    cap.type        = this->type; 
     47    cap.type_name   = str2Pj(this->typeName); 
     48    cap.param       = str2Pj(this->param); 
     49 
     50    return cap; 
     51} 
     52 
     53/////////////////////////////////////////////////////////////////////////////// 
     54 
     55RtcpFbConfig::RtcpFbConfig() 
     56{ 
     57    pjmedia_rtcp_fb_setting setting; 
     58    pjmedia_rtcp_fb_setting_default(&setting); 
     59    fromPj(setting); 
     60} 
     61 
     62void RtcpFbConfig::fromPj(const pjmedia_rtcp_fb_setting &prm) 
     63{ 
     64    this->dontUseAvpf = PJ2BOOL(prm.dont_use_avpf); 
     65    this->caps.clear(); 
     66    for (unsigned i = 0; i < prm.cap_count; ++i) { 
     67        RtcpFbCap cap; 
     68        cap.fromPj(prm.caps[i]); 
     69        this->caps.push_back(cap); 
     70    } 
     71} 
     72 
     73pjmedia_rtcp_fb_setting RtcpFbConfig::toPj() const 
     74{ 
     75    pjmedia_rtcp_fb_setting setting; 
     76 
     77    pj_bzero(&setting, sizeof(setting)); 
     78    setting.dont_use_avpf   = this->dontUseAvpf; 
     79    setting.cap_count       = this->caps.size(); 
     80    for (unsigned i = 0; i < setting.cap_count; ++i) { 
     81        setting.caps[i] = this->caps[i].toPj(); 
     82    } 
     83 
     84    return setting; 
     85} 
     86 
     87void RtcpFbConfig::readObject(const ContainerNode &node) throw(Error) 
     88{ 
     89    ContainerNode this_node = node.readContainer("RtcpFbConfig"); 
     90    NODE_READ_BOOL      (this_node, dontUseAvpf); 
     91 
     92    ContainerNode cap_node = this_node.readArray("caps"); 
     93    this->caps.clear(); 
     94    while (cap_node.hasUnread()) { 
     95        RtcpFbCap cap; 
     96        NODE_READ_STRING        (cap_node, cap.codecId); 
     97        NODE_READ_NUM_T         (cap_node, pjmedia_rtcp_fb_type, cap.type); 
     98        NODE_READ_STRING        (cap_node, cap.typeName); 
     99        NODE_READ_STRING        (cap_node, cap.param); 
     100        this->caps.push_back(cap); 
     101    } 
     102} 
     103 
     104void RtcpFbConfig::writeObject(ContainerNode &node) const throw(Error) 
     105{ 
     106    ContainerNode this_node = node.writeNewContainer("RtcpFbConfig"); 
     107    NODE_WRITE_BOOL     (this_node, dontUseAvpf); 
     108 
     109    ContainerNode cap_node = this_node.writeNewArray("caps"); 
     110    for (unsigned i=0; i<this->caps.size(); ++i) { 
     111        NODE_WRITE_STRING       (cap_node, this->caps[i].codecId); 
     112        NODE_WRITE_NUM_T        (cap_node, pjmedia_rtcp_fb_type, 
     113                                 this->caps[i].type); 
     114        NODE_WRITE_STRING       (cap_node, this->caps[i].typeName); 
     115        NODE_WRITE_STRING       (cap_node, this->caps[i].param); 
     116    } 
     117} 
    29118 
    30119/////////////////////////////////////////////////////////////////////////////// 
Note: See TracChangeset for help on using the changeset viewer.