Changeset 5752 for pjproject


Ignore:
Timestamp:
Mar 8, 2018 2:01:26 AM (19 months 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).
Location:
pjproject/trunk/pjmedia
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r5702 r5752  
    11081108 
    11091109 
     1110/* Setting to determine if media transport should switch RTP and RTCP 
     1111 * remote address to the source address of the packets it receives. 
     1112 * 
     1113 * By default it is enabled. 
     1114 */ 
     1115#ifndef PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR 
     1116#   define PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR     1 
     1117#endif 
     1118 
     1119 
    11101120/** 
    11111121 * Transport info (pjmedia_transport_info) contains a socket info and list 
  • pjproject/trunk/pjmedia/include/pjmedia/transport.h

    r5750 r5752  
    564564}; 
    565565 
     566/** 
     567 * This structure describes the data passed when calling #rtp_cb2(). 
     568 */ 
     569typedef struct pjmedia_tp_cb_param 
     570{ 
     571    /** 
     572     * User data. 
     573     */ 
     574    void               *user_data; 
     575 
     576    /** 
     577     * Packet buffer. 
     578     */ 
     579    void               *pkt; 
     580 
     581    /** 
     582     * Packet size. 
     583     */ 
     584    pj_ssize_t          size; 
     585 
     586    /** 
     587     * Packet's source address. 
     588     */ 
     589    pj_sockaddr        *src_addr; 
     590 
     591    /** 
     592     * Should media transport switch remote address to \a rtp_src_addr? 
     593     * Media transport should initialize it to PJ_FALSE, and application 
     594     * can change the value as necessary. 
     595     */ 
     596    pj_bool_t           rem_switch; 
     597 
     598} pjmedia_tp_cb_param; 
    566599 
    567600/** 
     
    613646     */ 
    614647    void (*rtcp_cb)(void *user_data, void *pkt, pj_ssize_t); 
     648 
     649    /** 
     650     * Callback to be called when RTP packet is received on the transport. 
     651     */ 
     652    void (*rtp_cb2)(pjmedia_tp_cb_param *param); 
     653 
    615654}; 
    616655 
  • pjproject/trunk/pjmedia/src/pjmedia/rtp.c

    r5748 r5752  
    247247    if (pj_ntohl(hdr->ssrc) != ses->peer_ssrc) { 
    248248        seq_st.status.flag.badssrc = 1; 
    249         ses->peer_ssrc = pj_ntohl(hdr->ssrc); 
     249        if (!ses->has_peer_ssrc) 
     250            ses->peer_ssrc = pj_ntohl(hdr->ssrc); 
    250251    } 
    251252 
  • 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 
  • 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 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c

    r5746 r5752  
    257257                                   void *pkt, 
    258258                                   pj_ssize_t size); 
     259    void                (*rtp_cb2)(pjmedia_tp_cb_param*); 
    259260    void                (*rtcp_cb)(void *user_data, 
    260261                                   void *pkt, 
     
    305306 * This callback is called by transport when incoming rtp is received 
    306307 */ 
    307 static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size); 
     308static void srtp_rtp_cb(pjmedia_tp_cb_param *param); 
    308309 
    309310/* 
     
    10651066    pj_lock_acquire(srtp->mutex); 
    10661067    srtp->rtp_cb = param->rtp_cb; 
     1068    srtp->rtp_cb2 = param->rtp_cb2; 
    10671069    srtp->rtcp_cb = param->rtcp_cb; 
    10681070    srtp->user_data = param->user_data; 
     
    10721074    member_param = *param; 
    10731075    member_param.user_data = srtp; 
    1074     member_param.rtp_cb = &srtp_rtp_cb; 
     1076    member_param.rtp_cb = NULL; 
     1077    member_param.rtp_cb2 = &srtp_rtp_cb; 
    10751078    member_param.rtcp_cb = &srtp_rtcp_cb; 
    10761079    status = pjmedia_transport_attach2(srtp->member_tp, &member_param); 
     
    11021105    pj_lock_acquire(srtp->mutex); 
    11031106    srtp->rtp_cb = NULL; 
     1107    srtp->rtp_cb2 = NULL; 
    11041108    srtp->rtcp_cb = NULL; 
    11051109    srtp->user_data = NULL; 
     
    12331237 * This callback is called by transport when incoming rtp is received 
    12341238 */ 
    1235 static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size) 
    1236 { 
    1237     transport_srtp *srtp = (transport_srtp *) user_data; 
     1239static void srtp_rtp_cb(pjmedia_tp_cb_param *param) 
     1240{ 
     1241    transport_srtp *srtp = (transport_srtp *) param->user_data; 
     1242    void *pkt = param->pkt; 
     1243    pj_ssize_t size = param->size; 
    12381244    int len = (int)size; 
    12391245    srtp_err_status_t err; 
    12401246    void (*cb)(void*, void*, pj_ssize_t) = NULL; 
     1247    void (*cb2)(pjmedia_tp_cb_param*) = NULL; 
    12411248    void *cb_data = NULL; 
    12421249 
    12431250    if (srtp->bypass_srtp) { 
    1244         srtp->rtp_cb(srtp->user_data, pkt, size); 
     1251        if (srtp->rtp_cb2) { 
     1252            pjmedia_tp_cb_param param2 = *param; 
     1253            param2.user_data = srtp->user_data; 
     1254            srtp->rtp_cb2(&param2); 
     1255            param->rem_switch = param2.rem_switch; 
     1256        } else if (srtp->rtp_cb) { 
     1257            srtp->rtp_cb(srtp->user_data, pkt, size); 
     1258        } 
    12451259        return; 
    12461260    } 
     
    13141328    } else { 
    13151329        cb = srtp->rtp_cb; 
     1330        cb2 = srtp->rtp_cb2; 
    13161331        cb_data = srtp->user_data; 
    13171332    } 
     
    13191334    pj_lock_release(srtp->mutex); 
    13201335 
    1321     if (cb) { 
     1336    if (cb2) { 
     1337        pjmedia_tp_cb_param param2 = *param; 
     1338        param2.user_data = cb_data; 
     1339        param2.pkt = pkt; 
     1340        param2.size = len; 
     1341        (*cb2)(&param2); 
     1342        param->rem_switch = param2.rem_switch; 
     1343    } else if (cb) { 
    13221344        (*cb)(cb_data, pkt, len); 
    13231345    } 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c

    r5750 r5752  
    5959    pj_bool_t           started;        /**< Has started?                   */ 
    6060    pj_sockaddr         rem_rtp_addr;   /**< Remote RTP address             */ 
    61     unsigned            rem_rtp_cnt;    /**< How many pkt from this addr.   */ 
    6261    pj_sockaddr         rem_rtcp_addr;  /**< Remote RTCP address            */ 
    6362    int                 addr_len;       /**< Length of addresses.           */ 
     
    6564                        void*, 
    6665                        pj_ssize_t); 
     66    void  (*rtp_cb2)(pjmedia_tp_cb_param*); /**< To report incoming RTP.    */ 
    6767    void  (*rtcp_cb)(   void*,          /**< To report incoming RTCP.       */ 
    6868                        void*, 
     
    8080    pending_write       rtp_pending_write[MAX_PENDING];  /**< Pending write */ 
    8181    pj_sockaddr         rtp_src_addr;   /**< Actual packet src addr.        */ 
    82     unsigned            rtp_src_cnt;    /**< How many pkt from this addr.   */ 
    8382    int                 rtp_addrlen;    /**< Address length.                */ 
    8483    char                rtp_pkt[RTP_LEN];/**< Incoming RTP packet buffer    */ 
     
    120119                                                       void*, 
    121120                                                       pj_ssize_t)); 
     121static pj_status_t transport_attach2  (pjmedia_transport *tp, 
     122                                       pjmedia_transport_attach_param 
     123                                           *att_param); 
    122124static void        transport_detach   (pjmedia_transport *tp, 
    123125                                       void *strm); 
     
    171173    &transport_media_stop, 
    172174    &transport_simulate_lost, 
    173     &transport_destroy 
     175    &transport_destroy, 
     176    &transport_attach2 
    174177}; 
    175178 
     
    456459    struct transport_udp *udp; 
    457460    pj_status_t status; 
     461    pj_bool_t rem_switch = PJ_FALSE; 
    458462 
    459463    PJ_UNUSED_ARG(op_key); 
     
    479483    do { 
    480484        void (*cb)(void*,void*,pj_ssize_t); 
     485        void (*cb2)(pjmedia_tp_cb_param*); 
    481486        void *user_data; 
    482487        pj_bool_t discard = PJ_FALSE; 
    483488 
    484489        cb = udp->rtp_cb; 
     490        cb2 = udp->rtp_cb2; 
    485491        user_data = udp->user_data; 
    486492 
     
    495501        } 
    496502 
    497         /* See if source address of RTP packet is different than the  
    498          * configured address, and switch RTP remote address to  
    499          * source packet address after several consecutive packets 
    500          * have been received. 
    501          */ 
    502         if (bytes_read>0 &&  
    503             (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0)  
     503        //if (!discard && udp->attached && cb) 
     504        if (!discard) { 
     505            if (cb2) { 
     506                pjmedia_tp_cb_param param; 
     507 
     508                param.user_data = user_data; 
     509                param.pkt = udp->rtp_pkt; 
     510                param.size = bytes_read; 
     511                param.src_addr = &udp->rtp_src_addr; 
     512                param.rem_switch = PJ_FALSE; 
     513                (*cb2)(&param); 
     514                rem_switch = param.rem_switch; 
     515            } else if (cb) { 
     516                (*cb)(user_data, udp->rtp_pkt, bytes_read); 
     517            } 
     518        } 
     519 
     520#if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ 
     521    (PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR == 1) 
     522        if (rem_switch && 
     523            (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0) 
    504524        { 
    505             if (pj_sockaddr_cmp(&udp->rem_rtp_addr, &udp->rtp_src_addr) == 0) { 
    506                 /* We're still receiving from rem_rtp_addr. Don't switch. */ 
    507                 udp->rtp_src_cnt = 0; 
    508                 udp->rem_rtp_cnt++; 
    509             } else { 
    510                 udp->rtp_src_cnt++; 
    511  
    512                 if (udp->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 
    513                     /* Only discard if we have ever received packet from 
    514                      * remote address (rem_rtp_addr). 
    515                      */ 
    516                     //discard = PJ_TRUE; 
    517                     discard = (udp->rem_rtp_cnt != 0); 
    518                 } else { 
    519                  
    520                     char addr_text[80]; 
    521  
    522                     /* Set remote RTP address to source address */ 
    523                     pj_memcpy(&udp->rem_rtp_addr, &udp->rtp_src_addr, 
    524                               sizeof(pj_sockaddr)); 
    525  
    526                     /* Reset counter */ 
    527                     udp->rtp_src_cnt = 0; 
    528  
    529                     PJ_LOG(4,(udp->base.name, 
    530                               "Remote RTP address switched to %s", 
    531                               pj_sockaddr_print(&udp->rtp_src_addr, addr_text, 
    532                                                 sizeof(addr_text), 3))); 
    533  
    534                     /* Also update remote RTCP address if actual RTCP source 
    535                      * address is not heard yet. 
    536                      */ 
    537                     if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) { 
    538                         pj_uint16_t port; 
    539  
    540                         pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr,  
    541                                   sizeof(pj_sockaddr)); 
    542                         pj_sockaddr_copy_addr(&udp->rem_rtcp_addr, 
    543                                               &udp->rem_rtp_addr); 
    544                         port = (pj_uint16_t) 
    545                                (pj_sockaddr_get_port(&udp->rem_rtp_addr)+1); 
    546                         pj_sockaddr_set_port(&udp->rem_rtcp_addr, port); 
    547  
    548                         pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr,  
    549                                   sizeof(pj_sockaddr)); 
    550  
    551                         PJ_LOG(4,(udp->base.name, 
    552                                   "Remote RTCP address switched to predicted" 
    553                                   " address %s", 
    554                                   pj_sockaddr_print(&udp->rtcp_src_addr,  
    555                                                     addr_text, 
    556                                                     sizeof(addr_text), 3))); 
    557  
    558                     } 
    559                 } 
     525            char addr_text[PJ_INET6_ADDRSTRLEN+10]; 
     526 
     527            /* Set remote RTP address to source address */ 
     528            pj_sockaddr_cp(&udp->rem_rtp_addr, &udp->rtp_src_addr); 
     529 
     530            PJ_LOG(4,(udp->base.name, 
     531                      "Remote RTP address switched to %s", 
     532                      pj_sockaddr_print(&udp->rtp_src_addr, addr_text, 
     533                                        sizeof(addr_text), 3))); 
     534 
     535            /* Also update remote RTCP address if actual RTCP source 
     536             * address is not heard yet. 
     537             */ 
     538            if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) { 
     539                pj_uint16_t port; 
     540 
     541                pj_sockaddr_cp(&udp->rem_rtcp_addr, &udp->rem_rtp_addr); 
     542                port = (pj_uint16_t) 
     543                       (pj_sockaddr_get_port(&udp->rem_rtp_addr)+1); 
     544                pj_sockaddr_set_port(&udp->rem_rtcp_addr, port); 
     545 
     546                pj_sockaddr_cp(&udp->rtcp_src_addr, &udp->rem_rtcp_addr); 
     547 
     548                PJ_LOG(4,(udp->base.name, 
     549                          "Remote RTCP address switched to predicted" 
     550                          " address %s", 
     551                          pj_sockaddr_print(&udp->rtcp_src_addr, addr_text, 
     552                                            sizeof(addr_text), 3))); 
    560553            } 
    561554        } 
    562  
    563         //if (!discard && udp->attached && cb) 
    564         if (!discard && cb) 
    565             (*cb)(user_data, udp->rtp_pkt, bytes_read); 
     555#endif 
    566556 
    567557        bytes_read = sizeof(udp->rtp_pkt); 
     
    619609            (*cb)(user_data, udp->rtcp_pkt, bytes_read); 
    620610 
     611#if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ 
     612    (PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR == 1) 
    621613        /* Check if RTCP source address is the same as the configured 
    622614         * remote address, and switch the address when they are 
     
    633625 
    634626                if (udp->rtcp_src_cnt >= PJMEDIA_RTCP_NAT_PROBATION_CNT ) { 
    635                     char addr_text[80]; 
     627                    char addr_text[PJ_INET6_ADDRSTRLEN+10]; 
    636628 
    637629                    udp->rtcp_src_cnt = 0; 
     
    646638            } 
    647639        } 
     640#endif 
    648641 
    649642        bytes_read = sizeof(udp->rtcp_pkt); 
     
    681674 
    682675 
    683 /* Called by application to initialize the transport */ 
    684 static pj_status_t transport_attach(   pjmedia_transport *tp, 
     676static pj_status_t tp_attach          (pjmedia_transport *tp, 
    685677                                       void *user_data, 
    686678                                       const pj_sockaddr_t *rem_addr, 
     
    690682                                                      void*, 
    691683                                                      pj_ssize_t), 
     684                                       void (*rtp_cb2)(pjmedia_tp_cb_param*), 
    692685                                       void (*rtcp_cb)(void*, 
    693686                                                       void*, 
     
    751744    /* Save the callbacks */ 
    752745    udp->rtp_cb = rtp_cb; 
     746    udp->rtp_cb2 = rtp_cb2; 
    753747    udp->rtcp_cb = rtcp_cb; 
    754748    udp->user_data = user_data; 
     
    763757    pj_bzero(&udp->rtp_src_addr, sizeof(udp->rtp_src_addr)); 
    764758    pj_bzero(&udp->rtcp_src_addr, sizeof(udp->rtcp_src_addr)); 
    765     udp->rtp_src_cnt = 0; 
    766759    udp->rtcp_src_cnt = 0; 
    767     udp->rem_rtp_cnt = 0; 
    768760 
    769761    /* Set buffer size for RTP socket */ 
     
    817809 
    818810 
     811/* Called by application to initialize the transport */ 
     812static pj_status_t transport_attach(   pjmedia_transport *tp, 
     813                                       void *user_data, 
     814                                       const pj_sockaddr_t *rem_addr, 
     815                                       const pj_sockaddr_t *rem_rtcp, 
     816                                       unsigned addr_len, 
     817                                       void (*rtp_cb)(void*, 
     818                                                      void*, 
     819                                                      pj_ssize_t), 
     820                                       void (*rtcp_cb)(void*, 
     821                                                       void*, 
     822                                                       pj_ssize_t)) 
     823{ 
     824    return tp_attach(tp, user_data, rem_addr, rem_rtcp, addr_len, 
     825                     rtp_cb, NULL, rtcp_cb); 
     826} 
     827 
     828 
     829static pj_status_t transport_attach2(pjmedia_transport *tp, 
     830                                     pjmedia_transport_attach_param *att_param) 
     831{ 
     832    return tp_attach(tp, att_param->user_data,  
     833                            (pj_sockaddr_t*)&att_param->rem_addr,  
     834                            (pj_sockaddr_t*)&att_param->rem_rtcp,  
     835                            att_param->addr_len, att_param->rtp_cb, 
     836                            att_param->rtp_cb2,  
     837                            att_param->rtcp_cb); 
     838} 
     839 
     840 
    819841/* Called by application when it no longer needs the transport */ 
    820842static void transport_detach( pjmedia_transport *tp, 
     
    846868        /* Clear up application infos from transport */ 
    847869        udp->rtp_cb = NULL; 
     870        udp->rtp_cb2 = NULL; 
    848871        udp->rtcp_cb = NULL; 
    849872        udp->user_data = NULL; 
  • 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.