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/vid_stream.c

    r5748 r5752  
    181181    pj_timestamp             ts_freq;       /**< Timestamp frequency.       */ 
    182182 
     183    pj_sockaddr              rem_rtp_addr;  /**< Remote RTP address         */ 
     184    unsigned                 rem_rtp_flag;  /**< Indicator flag about 
     185                                                 packet from this addr.  
     186                                                 0=no pkt, 1=good ssrc pkts,  
     187                                                 2=bad ssrc pkts            */ 
     188    pj_sockaddr              rtp_src_addr;  /**< Actual packet src addr.    */ 
     189    unsigned                 rtp_src_cnt;   /**< How many pkt from this addr*/ 
     190 
    183191#if TRACE_RC 
    184192    unsigned                 rc_total_sleep; 
     
    599607 * in the RTP socket.  
    600608 */ 
    601 static void on_rx_rtp( void *data,  
    602                        void *pkt, 
    603                        pj_ssize_t bytes_read) 
    604  
    605 { 
    606     pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data; 
     609static void on_rx_rtp( pjmedia_tp_cb_param *param) 
     610{ 
     611    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) param->user_data; 
     612    void *pkt = param->pkt; 
     613    pj_ssize_t bytes_read = param->size; 
    607614    pjmedia_vid_channel *channel = stream->dec; 
    608615    const pjmedia_rtp_hdr *hdr; 
     
    670677        } 
    671678 
    672         if (seq_st.status.flag.badssrc) { 
     679        if (!stream->info.has_rem_ssrc && seq_st.status.flag.badssrc) { 
    673680            PJ_LOG(4,(channel->port.info.name.ptr, 
    674681                      "Changed RTP peer SSRC %d (previously %d)", 
     
    690697        pkt_discarded = PJ_TRUE; 
    691698        goto on_return; 
     699    } 
     700 
     701    /* See if source address of RTP packet is different than the  
     702     * configured address, and check if we need to tell the 
     703     * media transport to switch RTP remote address. 
     704     */ 
     705    if (param->src_addr) { 
     706        pj_bool_t badssrc = (stream->info.has_rem_ssrc && 
     707                             seq_st.status.flag.badssrc); 
     708 
     709        if (pj_sockaddr_cmp(&stream->rem_rtp_addr, param->src_addr) == 0) { 
     710            /* We're still receiving from rem_rtp_addr. */ 
     711            stream->rtp_src_cnt = 0; 
     712            stream->rem_rtp_flag = badssrc? 2: 1; 
     713        } else { 
     714            stream->rtp_src_cnt++; 
     715             
     716            if (stream->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 
     717                if (stream->rem_rtp_flag == 1 || 
     718                    (stream->rem_rtp_flag == 2 && badssrc)) 
     719                { 
     720                    /* Only discard if: 
     721                     * - we have ever received packet with good ssrc from 
     722                     *   remote address (rem_rtp_addr), or 
     723                     * - we have ever received packet with bad ssrc from 
     724                     *   remote address and this packet also has bad ssrc. 
     725                     */ 
     726                    pkt_discarded = PJ_TRUE; 
     727                    goto on_return; 
     728                }                
     729                if (stream->info.has_rem_ssrc && !seq_st.status.flag.badssrc 
     730                    && stream->rem_rtp_flag != 1) 
     731                { 
     732                    /* Immediately switch if we receive packet with the 
     733                     * correct ssrc AND we never receive packets with 
     734                     * good ssrc from rem_rtp_addr. 
     735                     */ 
     736                    param->rem_switch = PJ_TRUE; 
     737                } 
     738            } else { 
     739                /* Switch. We no longer receive packets from rem_rtp_addr. */ 
     740                param->rem_switch = PJ_TRUE; 
     741            } 
     742 
     743            if (param->rem_switch) { 
     744                /* Set remote RTP address to source address */ 
     745                pj_sockaddr_cp(&stream->rem_rtp_addr, param->src_addr); 
     746 
     747                /* Reset counter and flag */ 
     748                stream->rtp_src_cnt = 0; 
     749                stream->rem_rtp_flag = badssrc? 2: 1; 
     750 
     751                /* Update RTCP peer ssrc */ 
     752                stream->rtcp.peer_ssrc = pj_ntohl(hdr->ssrc); 
     753            } 
     754        } 
    692755    } 
    693756 
     
    16731736    att_param.user_data = stream; 
    16741737    pj_sockaddr_cp(&att_param.rem_addr, &info->rem_addr); 
     1738    pj_sockaddr_cp(&stream->rem_rtp_addr, &info->rem_addr); 
    16751739    if (pj_sockaddr_has_addr(&info->rem_rtcp.addr)) 
    16761740        pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp);     
    16771741    att_param.addr_len = pj_sockaddr_get_len(&info->rem_addr); 
    1678     att_param.rtp_cb = &on_rx_rtp; 
     1742    att_param.rtp_cb2 = &on_rx_rtp; 
    16791743    att_param.rtcp_cb = &on_rx_rtcp; 
    16801744 
Note: See TracChangeset for help on using the changeset viewer.