Ignore:
Timestamp:
Mar 8, 2018 2:01:26 AM (3 years ago)
Author:
ming
Message:

Fixed #865: More clever RTP transport remote address switch

The summary of changes:

  • To solve no 2:

Add callback rtp_cb2(pjmedia_tp_cb_param *param) which allows application to get more info from the media transport, such as the packet's source address.

  • To solve no 3:

Add compile time option PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR (by default enabled). Currently, there are already runtime options PJMEDIA_UDP_NO_SRC_ADDR_CHECKING and PJMEDIA_ICE_NO_SRC_ADDR_CHECKING, but there are a few drawbacks:

  • the options are not exported to the higher level, such as stream, or pjsua.
  • the options are separate for each transport, UDP and ICE, there's no single option to do this.
  • To solve no 1:

Using the new rtp_cb2() callback, move the functionality to check the packet's source address to the stream/video stream.
By checking the RTP pt and SSRC, there are a few advantages:

  • When receiving packets from multiple sources, stream can choose the packet with the correct SSRC as advertised from the SDP, and discard the others (see also ticket #1366).
  • If remote address switch is enabled, a faster switch can be achieved as soon as packet with correct ssrc is received, instead of waiting for several consecutive packets (according to setting PJMEDIA_RTP_NAT_PROBATION_CNT).
File:
1 edited

Legend:

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

    r5748 r5752  
    231231#endif 
    232232 
     233    pj_sockaddr              rem_rtp_addr;     /**< Remote RTP address      */ 
     234    unsigned                 rem_rtp_flag;     /**< Indicator flag about 
     235                                                    packet from this addr.  
     236                                                    0=no pkt, 1=good ssrc,  
     237                                                    2=bad ssrc pkts         */ 
     238    unsigned                 rtp_src_cnt;      /**< How many pkt from 
     239                                                    this addr.              */ 
     240 
    233241#if TRACE_JB 
    234242    pj_oshandle_t           trace_jb_fd;            /**< Jitter tracing file handle.*/ 
     
    16631671 * in the RTP socket. 
    16641672 */ 
    1665 static void on_rx_rtp( void *data, 
    1666                        void *pkt, 
    1667                        pj_ssize_t bytes_read) 
    1668  
    1669 { 
    1670     pjmedia_stream *stream = (pjmedia_stream*) data; 
     1673static void on_rx_rtp( pjmedia_tp_cb_param *param) 
     1674{ 
     1675    pjmedia_stream *stream = (pjmedia_stream*) param->user_data; 
     1676    void *pkt = param->pkt; 
     1677    pj_ssize_t bytes_read = param->size; 
    16711678    pjmedia_channel *channel = stream->dec; 
    16721679    const pjmedia_rtp_hdr *hdr; 
     
    17351742        } 
    17361743 
    1737         if (seq_st.status.flag.badssrc) { 
     1744        if (!stream->si.has_rem_ssrc && seq_st.status.flag.badssrc) { 
    17381745            PJ_LOG(4,(stream->port.info.name.ptr, 
    17391746                      "Changed RTP peer SSRC %d (previously %d)", 
     
    17681775        handle_incoming_dtmf(stream, payload, payloadlen); 
    17691776        goto on_return; 
     1777    } 
     1778 
     1779    /* See if source address of RTP packet is different than the  
     1780     * configured address, and check if we need to tell the 
     1781     * media transport to switch RTP remote address. 
     1782     */ 
     1783    if (param->src_addr) { 
     1784        pj_bool_t badssrc = (stream->si.has_rem_ssrc && 
     1785                             seq_st.status.flag.badssrc); 
     1786 
     1787        if (pj_sockaddr_cmp(&stream->rem_rtp_addr, param->src_addr) == 0) { 
     1788            /* We're still receiving from rem_rtp_addr. */ 
     1789            stream->rtp_src_cnt = 0; 
     1790            stream->rem_rtp_flag = badssrc? 2: 1; 
     1791        } else { 
     1792            stream->rtp_src_cnt++; 
     1793             
     1794            if (stream->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 
     1795                if (stream->rem_rtp_flag == 1 || 
     1796                    (stream->rem_rtp_flag == 2 && badssrc)) 
     1797                { 
     1798                    /* Only discard if: 
     1799                     * - we have ever received packet with good ssrc from 
     1800                     *   remote address (rem_rtp_addr), or 
     1801                     * - we have ever received packet with bad ssrc from 
     1802                     *   remote address and this packet also has bad ssrc. 
     1803                     */ 
     1804                    pkt_discarded = PJ_TRUE; 
     1805                    goto on_return; 
     1806                }                
     1807                if (stream->si.has_rem_ssrc && !seq_st.status.flag.badssrc && 
     1808                    stream->rem_rtp_flag != 1) 
     1809                { 
     1810                    /* Immediately switch if we receive packet with the 
     1811                     * correct ssrc AND we never receive packets with 
     1812                     * good ssrc from rem_rtp_addr. 
     1813                     */ 
     1814                    param->rem_switch = PJ_TRUE; 
     1815                } 
     1816            } else { 
     1817                /* Switch. We no longer receive packets from rem_rtp_addr. */ 
     1818                param->rem_switch = PJ_TRUE; 
     1819            } 
     1820 
     1821            if (param->rem_switch) { 
     1822                /* Set remote RTP address to source address */ 
     1823                pj_sockaddr_cp(&stream->rem_rtp_addr, param->src_addr); 
     1824 
     1825                /* Reset counter and flag */ 
     1826                stream->rtp_src_cnt = 0; 
     1827                stream->rem_rtp_flag = badssrc? 2: 1; 
     1828 
     1829                /* Update RTCP peer ssrc */ 
     1830                stream->rtcp.peer_ssrc = pj_ntohl(hdr->ssrc); 
     1831            } 
     1832        } 
    17701833    } 
    17711834 
     
    24252488    att_param.user_data = stream; 
    24262489    pj_sockaddr_cp(&att_param.rem_addr, &info->rem_addr); 
     2490    pj_sockaddr_cp(&stream->rem_rtp_addr, &info->rem_addr); 
    24272491    if (pj_sockaddr_has_addr(&info->rem_rtcp.addr)) 
    24282492        pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp); 
    24292493    att_param.addr_len = pj_sockaddr_get_len(&info->rem_addr); 
    2430     att_param.rtp_cb = &on_rx_rtp; 
     2494    att_param.rtp_cb2 = &on_rx_rtp; 
    24312495    att_param.rtcp_cb = &on_rx_rtcp; 
    24322496 
Note: See TracChangeset for help on using the changeset viewer.