Ignore:
Timestamp:
Mar 8, 2018 2:01:26 AM (6 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/transport_ice.c

    r5635 r5752  
    7777    pj_sockaddr          remote_rtcp; 
    7878    unsigned             addr_len;      /**< Length of addresses.           */ 
    79     unsigned             rem_rtp_cnt;   /**< How many pkt from this addr.   */ 
    8079 
    8180    pj_bool_t            use_ice; 
    8281    pj_sockaddr          rtp_src_addr;  /**< Actual source RTP address.     */ 
    8382    pj_sockaddr          rtcp_src_addr; /**< Actual source RTCP address.    */ 
    84     unsigned             rtp_src_cnt;   /**< How many pkt from this addr.   */ 
    8583    unsigned             rtcp_src_cnt;  /**< How many pkt from this addr.   */ 
    8684 
     
    9189                                 void*, 
    9290                                 pj_ssize_t); 
     91    void               (*rtp_cb2)(pjmedia_tp_cb_param*); 
    9392    void               (*rtcp_cb)(void*, 
    9493                                  void*, 
     
    113112                                                       void*, 
    114113                                                       pj_ssize_t)); 
     114static pj_status_t transport_attach2  (pjmedia_transport *tp, 
     115                                       pjmedia_transport_attach_param 
     116                                           *att_param); 
    115117static void        transport_detach   (pjmedia_transport *tp, 
    116118                                       void *strm); 
     
    178180    &transport_media_stop, 
    179181    &transport_simulate_lost, 
    180     &transport_destroy 
     182    &transport_destroy, 
     183    &transport_attach2 
    181184}; 
    182185 
     
    16631666     * ICE activated or received any packets. 
    16641667     */ 
    1665     if (tp_ice->use_ice || tp_ice->rtp_src_cnt) { 
     1668    if (tp_ice->use_ice) { 
    16661669        info->src_rtp_name  = tp_ice->rtp_src_addr; 
    16671670    } 
     
    17241727                                                      pj_ssize_t)) 
    17251728{ 
     1729    pjmedia_transport_attach_param param; 
     1730     
     1731    pj_bzero(&param, sizeof(param)); 
     1732    param.user_data = stream; 
     1733    pj_sockaddr_cp(&param.rem_addr, rem_addr); 
     1734    pj_sockaddr_cp(&param.rem_rtcp, rem_rtcp); 
     1735    param.addr_len = addr_len; 
     1736    param.rtp_cb = rtp_cb; 
     1737    return transport_attach2(tp, &param); 
     1738} 
     1739 
     1740 
     1741static pj_status_t transport_attach2  (pjmedia_transport *tp, 
     1742                                       pjmedia_transport_attach_param 
     1743                                           *att_param) 
     1744{ 
    17261745    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    17271746 
    1728     tp_ice->stream = stream; 
    1729     tp_ice->rtp_cb = rtp_cb; 
    1730     tp_ice->rtcp_cb = rtcp_cb; 
    1731  
    1732     pj_memcpy(&tp_ice->remote_rtp, rem_addr, addr_len); 
    1733     pj_memcpy(&tp_ice->remote_rtcp, rem_rtcp, addr_len); 
    1734     tp_ice->addr_len = addr_len; 
    1735     tp_ice->rem_rtp_cnt = 0; 
     1747    tp_ice->stream = att_param->user_data; 
     1748    tp_ice->rtp_cb = att_param->rtp_cb; 
     1749    tp_ice->rtp_cb2 = att_param->rtp_cb2; 
     1750    tp_ice->rtcp_cb = att_param->rtcp_cb; 
     1751 
     1752    pj_memcpy(&tp_ice->remote_rtp, &att_param->rem_addr, att_param->addr_len); 
     1753    pj_memcpy(&tp_ice->remote_rtcp, &att_param->rem_rtcp, att_param->addr_len); 
     1754    tp_ice->addr_len = att_param->addr_len; 
    17361755 
    17371756    /* Init source RTP & RTCP addresses and counter */ 
    17381757    tp_ice->rtp_src_addr = tp_ice->remote_rtp; 
    1739     tp_ice->rtcp_src_addr = tp_ice->remote_rtcp; 
    1740     tp_ice->rtp_src_cnt = 0; 
     1758    pj_bzero(&tp_ice->rtcp_src_addr, sizeof(tp_ice->rtcp_src_addr)); 
    17411759    tp_ice->rtcp_src_cnt = 0; 
    17421760 
     
    17531771 
    17541772    tp_ice->rtp_cb = NULL; 
     1773    tp_ice->rtp_cb2 = NULL; 
    17551774    tp_ice->rtcp_cb = NULL; 
    17561775    tp_ice->stream = NULL; 
     
    18231842    } 
    18241843 
    1825     if (comp_id==1 && tp_ice->rtp_cb) { 
     1844    if (comp_id==1 && (tp_ice->rtp_cb || tp_ice->rtp_cb2)) { 
     1845        pj_bool_t rem_switch = PJ_FALSE; 
    18261846 
    18271847        /* Simulate packet lost on RX direction */ 
     
    18351855        } 
    18361856 
    1837         /* See if source address of RTP packet is different than the  
    1838          * configured address, and switch RTP remote address to  
    1839          * source packet address after several consecutive packets 
    1840          * have been received. 
    1841          */ 
    1842         if (!tp_ice->use_ice) { 
    1843             pj_bool_t enable_switch = 
    1844                     ((tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING)==0); 
    1845  
    1846             if (!enable_switch || 
    1847                 pj_sockaddr_cmp(&tp_ice->remote_rtp, src_addr) == 0) 
    1848             { 
    1849                 /* Don't switch while we're receiving from remote_rtp */ 
    1850                 tp_ice->rtp_src_cnt = 0; 
    1851                 tp_ice->rem_rtp_cnt++; 
     1857        if (!discard) { 
     1858            if (tp_ice->rtp_cb2) { 
     1859                pjmedia_tp_cb_param param; 
     1860 
     1861                param.user_data = tp_ice->stream; 
     1862                param.pkt = pkt; 
     1863                param.size = size; 
     1864                param.src_addr = (tp_ice->use_ice? NULL: 
     1865                                  (pj_sockaddr_t *)src_addr); 
     1866                param.rem_switch = PJ_FALSE; 
     1867                (*tp_ice->rtp_cb2)(&param); 
     1868                rem_switch = param.rem_switch; 
    18521869            } else { 
    1853  
    1854                 ++tp_ice->rtp_src_cnt; 
    1855  
    1856                 /* Check if the source address is recognized. */ 
    1857                 if (pj_sockaddr_cmp(src_addr, &tp_ice->rtp_src_addr) != 0) { 
    1858                     /* Remember the new source address. */ 
    1859                     pj_sockaddr_cp(&tp_ice->rtp_src_addr, src_addr); 
    1860                     /* Reset counter */ 
    1861                     tp_ice->rtp_src_cnt = 0; 
    1862                     discard = PJ_TRUE; 
    1863                 } 
    1864  
    1865                 if (tp_ice->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 
    1866                     /* Only discard if we have ever received packet from 
    1867                      * remote address (remote_rtp). 
    1868                      */ 
    1869                     discard = (tp_ice->rem_rtp_cnt != 0); 
    1870                 } else { 
    1871                     char addr_text[80]; 
    1872  
    1873                     /* Set remote RTP address to source address */ 
    1874                     pj_sockaddr_cp(&tp_ice->remote_rtp, &tp_ice->rtp_src_addr); 
    1875                     tp_ice->addr_len = pj_sockaddr_get_len(&tp_ice->remote_rtp); 
    1876  
    1877                     /* Reset counter */ 
    1878                     tp_ice->rtp_src_cnt = 0; 
    1879  
    1880                     PJ_LOG(4,(tp_ice->base.name, 
    1881                               "Remote RTP address switched to %s", 
    1882                               pj_sockaddr_print(&tp_ice->remote_rtp, addr_text, 
    1883                                                 sizeof(addr_text), 3))); 
    1884  
    1885                     /* Also update remote RTCP address if actual RTCP source 
    1886                      * address is not heard yet. 
    1887                      */ 
    1888                     if (!pj_sockaddr_has_addr(&tp_ice->rtcp_src_addr)) { 
    1889                         pj_uint16_t port; 
    1890  
    1891                         pj_sockaddr_cp(&tp_ice->remote_rtcp,  
    1892                                        &tp_ice->remote_rtp); 
    1893  
    1894                         port = (pj_uint16_t) 
    1895                                (pj_sockaddr_get_port(&tp_ice->remote_rtp)+1); 
    1896                         pj_sockaddr_set_port(&tp_ice->remote_rtcp, port); 
    1897  
    1898                         PJ_LOG(4,(tp_ice->base.name, 
    1899                                   "Remote RTCP address switched to predicted " 
    1900                                   "address %s", 
    1901                                   pj_sockaddr_print(&tp_ice->remote_rtcp,  
    1902                                                     addr_text, 
    1903                                                     sizeof(addr_text), 3))); 
    1904                     } 
    1905                 } 
     1870                (*tp_ice->rtp_cb)(tp_ice->stream, pkt, size); 
    19061871            } 
    19071872        } 
    1908  
    1909         if (!discard) 
    1910             (*tp_ice->rtp_cb)(tp_ice->stream, pkt, size); 
     1873         
     1874#if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ 
     1875    (PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR == 1) 
     1876        if (rem_switch && 
     1877            (tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING)==0) 
     1878        { 
     1879            char addr_text[PJ_INET6_ADDRSTRLEN+10]; 
     1880 
     1881            /* Set remote RTP address to source address */ 
     1882            pj_sockaddr_cp(&tp_ice->rtp_src_addr, src_addr); 
     1883            pj_sockaddr_cp(&tp_ice->remote_rtp, src_addr); 
     1884            tp_ice->addr_len = pj_sockaddr_get_len(&tp_ice->remote_rtp); 
     1885 
     1886            PJ_LOG(4,(tp_ice->base.name, 
     1887                      "Remote RTP address switched to %s", 
     1888                      pj_sockaddr_print(&tp_ice->remote_rtp, addr_text, 
     1889                                        sizeof(addr_text), 3))); 
     1890 
     1891            /* Also update remote RTCP address if actual RTCP source 
     1892             * address is not heard yet. 
     1893             */ 
     1894            if (!pj_sockaddr_has_addr(&tp_ice->rtcp_src_addr)) { 
     1895                pj_uint16_t port; 
     1896 
     1897                pj_sockaddr_cp(&tp_ice->remote_rtcp, &tp_ice->remote_rtp); 
     1898 
     1899                port = (pj_uint16_t) 
     1900                       (pj_sockaddr_get_port(&tp_ice->remote_rtp)+1); 
     1901                pj_sockaddr_set_port(&tp_ice->remote_rtcp, port); 
     1902 
     1903                PJ_LOG(4,(tp_ice->base.name, 
     1904                          "Remote RTCP address switched to predicted " 
     1905                          "address %s", 
     1906                          pj_sockaddr_print(&tp_ice->remote_rtcp,  
     1907                                            addr_text, 
     1908                                            sizeof(addr_text), 3))); 
     1909            } 
     1910        } 
     1911#endif 
    19111912 
    19121913    } else if (comp_id==2 && tp_ice->rtcp_cb) { 
    19131914 
     1915#if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ 
     1916    (PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR == 1) 
    19141917        /* Check if RTCP source address is the same as the configured 
    19151918         * remote address, and switch the address when they are 
     
    19221925                tp_ice->rtcp_src_cnt = 0; 
    19231926            } else { 
    1924                 char addr_text[80]; 
     1927                char addr_text[PJ_INET6_ADDRSTRLEN+10]; 
    19251928 
    19261929                ++tp_ice->rtcp_src_cnt; 
     
    19421945            } 
    19431946        } 
     1947#endif 
    19441948 
    19451949        if (!discard) 
     
    20192023    tp_ice->base.user_data = NULL; 
    20202024    tp_ice->rtp_cb = NULL; 
     2025    tp_ice->rtp_cb2 = NULL; 
    20212026    tp_ice->rtcp_cb = NULL; 
    20222027 
Note: See TracChangeset for help on using the changeset viewer.