Changeset 5989


Ignore:
Timestamp:
May 15, 2019 12:09:57 AM (10 months ago)
Author:
ming
Message:

Fixed #2107: Add option to use loopback media transport in pjsua

Location:
pjproject/trunk
Files:
5 edited

Legend:

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

    r5901 r5989  
    485485     */ 
    486486    PJMEDIA_TRANSPORT_TYPE_SRTP, 
     487 
     488    /** Loopback media transport */ 
     489    PJMEDIA_TRANSPORT_TYPE_LOOP, 
    487490 
    488491    /** 
  • pjproject/trunk/pjmedia/include/pjmedia/transport_loop.h

    r3553 r5989  
    5151 
    5252/** 
     53 * Settings to be given when creating loopback media transport. Application 
     54 * should call #pjmedia_loop_tp_setting_default() to initialize this 
     55 * structure with its default values. 
     56 */ 
     57typedef struct pjmedia_loop_tp_setting 
     58{ 
     59    /* Address family, which can be pj_AF_INET() for IPv4 or 
     60     * pj_AF_INET6() for IPv6. Default is IPv4 (pj_AF_INET()). 
     61     */ 
     62    int         af; 
     63 
     64    /* Optional local address which will be returned in the transport info. 
     65     * If the string is empty, the address will be the default loopback 
     66     * address (127.0.0.1 or ::1). 
     67     * 
     68     * Note that the address is used for info purpose only and no actual 
     69     * resource will be allocated. 
     70     * 
     71     * Default is empty string. 
     72     */ 
     73    pj_str_t    addr; 
     74 
     75    /* The port number for the RTP socket. The RTCP port number will be 
     76     * set to one above RTP port. If zero, it will use the default port 
     77     * number (4000). 
     78     * 
     79     * Note that no actual port will be allocated. Default is 4000. 
     80     */ 
     81    int         port; 
     82     
     83    /* Setting whether attached streams will receive incoming packets. 
     84     * Application can further customize the setting of a particular setting 
     85     * using the API pjmedia_transport_loop_disable_rx(). 
     86     * 
     87     * Default: PJ_FALSE; 
     88     */ 
     89    pj_bool_t   disable_rx; 
     90 
     91} pjmedia_loop_tp_setting; 
     92 
     93 
     94/** 
     95 * Initialize loopback media transport setting with its default values. 
     96 * 
     97 * @param opt   SRTP setting to be initialized. 
     98 */ 
     99PJ_DECL(void) pjmedia_loop_tp_setting_default(pjmedia_loop_tp_setting *opt); 
     100 
     101 
     102/** 
    53103 * Create the loopback transport. 
    54104 * 
     
    63113 
    64114/** 
    65  * Set this stream as the receiver of incoming packets. 
     115 * Create the loopback transport. 
     116 * 
     117 * @param endpt     The media endpoint instance. 
     118 * @param opt       Optional settings. If NULL is given, default 
     119 *                  settings will be used. 
     120 * @param p_tp      Pointer to receive the transport instance. 
     121 * 
     122 * @return          PJ_SUCCESS on success. 
     123 */ 
     124PJ_DECL(pj_status_t) 
     125pjmedia_transport_loop_create2(pjmedia_endpt *endpt, 
     126                               const pjmedia_loop_tp_setting *opt, 
     127                               pjmedia_transport **p_tp); 
     128 
     129 
     130/** 
     131 * Set the configuration of whether a stream will become the receiver of 
     132 * incoming packets. 
     133 * 
     134 * @param tp        The transport. 
     135 * @param user      The stream. 
     136 * @param disabled  PJ_TRUE to disable the receiving of packets, or 
     137 *                  PJ_FALSE to enable it. 
    66138 */ 
    67139PJ_DECL(pj_status_t) pjmedia_transport_loop_disable_rx(pjmedia_transport *tp, 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_loop.c

    r3553 r5989  
    3636                        void*, 
    3737                        pj_ssize_t); 
     38    void  (*rtp_cb2)(   pjmedia_tp_cb_param*); 
    3839    void  (*rtcp_cb)(   void*,          /**< To report incoming RTCP.       */ 
    3940                        void*, 
     
    4849    unsigned            user_cnt;       /**< Number of attachments          */ 
    4950    struct user         users[4];       /**< Array of users.                */ 
     51    pj_bool_t           disable_rx;     /**< Disable RX.                    */ 
     52 
     53    pjmedia_loop_tp_setting setting;    /**< Setting.                       */ 
    5054 
    5155    unsigned            tx_drop_pct;    /**< Percent of tx pkts to drop.    */ 
     
    7276                                                       void*, 
    7377                                                       pj_ssize_t)); 
     78static pj_status_t transport_attach2  (pjmedia_transport *tp, 
     79                                       pjmedia_transport_attach_param 
     80                                           *att_param); 
    7481static void        transport_detach   (pjmedia_transport *tp, 
    7582                                       void *strm); 
     
    120127    &transport_media_stop, 
    121128    &transport_simulate_lost, 
    122     &transport_destroy 
     129    &transport_destroy, 
     130    &transport_attach2 
    123131}; 
     132 
     133 
     134/** 
     135 * Initialize loopback media transport setting with its default values. 
     136 */ 
     137PJ_DEF(void) pjmedia_loop_tp_setting_default(pjmedia_loop_tp_setting *opt) 
     138{ 
     139    pj_bzero(opt, sizeof(pjmedia_loop_tp_setting)); 
     140     
     141    opt->af = pj_AF_INET(); 
     142} 
    124143 
    125144 
     
    130149                                                  pjmedia_transport **p_tp) 
    131150{ 
     151    pjmedia_loop_tp_setting opt; 
     152     
     153    pj_bzero(&opt, sizeof(opt)); 
     154    opt.af = pj_AF_INET(); 
     155 
     156    return pjmedia_transport_loop_create2(endpt, &opt, p_tp); 
     157} 
     158 
     159 
     160PJ_DEF(pj_status_t) 
     161pjmedia_transport_loop_create2(pjmedia_endpt *endpt, 
     162                               const pjmedia_loop_tp_setting *opt, 
     163                               pjmedia_transport **p_tp) 
     164{ 
    132165    struct transport_loop *tp; 
    133166    pj_pool_t *pool; 
     
    147180    tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP; 
    148181 
     182    if (opt) { 
     183        tp->setting = *opt; 
     184    } else { 
     185        pjmedia_loop_tp_setting_default(&tp->setting); 
     186    } 
     187    if (tp->setting.addr.slen) { 
     188        pj_strdup(pool, &tp->setting.addr, &opt->addr); 
     189    } else { 
     190        pj_strset2(&tp->setting.addr, (opt->af == pj_AF_INET())? 
     191                                       "127.0.0.1": "::1"); 
     192    } 
     193    if (tp->setting.port == 0) 
     194        tp->setting.port = 4000; 
     195 
    149196    /* Done */ 
    150197    *p_tp = &tp->base; 
     
    190237                                      pjmedia_transport_info *info) 
    191238{ 
    192     PJ_ASSERT_RETURN(tp && info, PJ_EINVAL); 
     239    struct transport_loop *loop = (struct transport_loop*) tp; 
    193240 
    194241    info->sock_info.rtp_sock = 1; 
    195     pj_sockaddr_in_init(&info->sock_info.rtp_addr_name.ipv4, 0, 0); 
     242    pj_sockaddr_init(loop->setting.af, &info->sock_info.rtp_addr_name,  
     243                     &loop->setting.addr, loop->setting.port); 
    196244    info->sock_info.rtcp_sock = 2; 
    197     pj_sockaddr_in_init(&info->sock_info.rtcp_addr_name.ipv4, 0, 0); 
     245    pj_sockaddr_init(loop->setting.af, &info->sock_info.rtcp_addr_name, 
     246                     &loop->setting.addr, loop->setting.port + 1); 
    198247 
    199248    return PJ_SUCCESS; 
     
    202251 
    203252/* Called by application to initialize the transport */ 
     253static pj_status_t tp_attach(   pjmedia_transport *tp, 
     254                                       void *user_data, 
     255                                       const pj_sockaddr_t *rem_addr, 
     256                                       const pj_sockaddr_t *rem_rtcp, 
     257                                       unsigned addr_len, 
     258                                       void (*rtp_cb)(void*, 
     259                                                      void*, 
     260                                                      pj_ssize_t), 
     261                                       void (*rtp_cb2)(pjmedia_tp_cb_param*), 
     262                                       void (*rtcp_cb)(void*, 
     263                                                       void*, 
     264                                                       pj_ssize_t)) 
     265{ 
     266    struct transport_loop *loop = (struct transport_loop*) tp; 
     267    unsigned i; 
     268    const pj_sockaddr *rtcp_addr; 
     269 
     270    /* Validate arguments */ 
     271    PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL); 
     272 
     273    /* Must not be "attached" to same user */ 
     274    for (i=0; i<loop->user_cnt; ++i) { 
     275        PJ_ASSERT_RETURN(loop->users[i].user_data != user_data, 
     276                         PJ_EINVALIDOP); 
     277    } 
     278    PJ_ASSERT_RETURN(loop->user_cnt != PJ_ARRAY_SIZE(loop->users),  
     279                     PJ_ETOOMANY); 
     280 
     281    PJ_UNUSED_ARG(rem_rtcp); 
     282    PJ_UNUSED_ARG(rtcp_addr); 
     283 
     284    /* "Attach" the application: */ 
     285 
     286    /* Save the new user */ 
     287    loop->users[loop->user_cnt].rtp_cb = rtp_cb; 
     288    loop->users[loop->user_cnt].rtp_cb2 = rtp_cb2; 
     289    loop->users[loop->user_cnt].rtcp_cb = rtcp_cb; 
     290    loop->users[loop->user_cnt].user_data = user_data; 
     291    loop->users[loop->user_cnt].rx_disabled = loop->disable_rx; 
     292    ++loop->user_cnt; 
     293 
     294    return PJ_SUCCESS; 
     295} 
     296 
    204297static pj_status_t transport_attach(   pjmedia_transport *tp, 
    205298                                       void *user_data, 
     
    214307                                                       pj_ssize_t)) 
    215308{ 
    216     struct transport_loop *loop = (struct transport_loop*) tp; 
    217     unsigned i; 
    218     const pj_sockaddr *rtcp_addr; 
    219  
    220     /* Validate arguments */ 
    221     PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL); 
    222  
    223     /* Must not be "attached" to same user */ 
    224     for (i=0; i<loop->user_cnt; ++i) { 
    225         PJ_ASSERT_RETURN(loop->users[i].user_data != user_data, 
    226                          PJ_EINVALIDOP); 
    227     } 
    228     PJ_ASSERT_RETURN(loop->user_cnt != PJ_ARRAY_SIZE(loop->users),  
    229                      PJ_ETOOMANY); 
    230  
    231     PJ_UNUSED_ARG(rem_rtcp); 
    232     PJ_UNUSED_ARG(rtcp_addr); 
    233  
    234     /* "Attach" the application: */ 
    235  
    236     /* Save the new user */ 
    237     loop->users[loop->user_cnt].rtp_cb = rtp_cb; 
    238     loop->users[loop->user_cnt].rtcp_cb = rtcp_cb; 
    239     loop->users[loop->user_cnt].user_data = user_data; 
    240     ++loop->user_cnt; 
    241  
    242     return PJ_SUCCESS; 
     309    return tp_attach(tp, user_data, rem_addr, rem_rtcp, addr_len, 
     310                     rtp_cb, NULL, rtcp_cb); 
     311} 
     312 
     313static pj_status_t transport_attach2(pjmedia_transport *tp, 
     314                                     pjmedia_transport_attach_param *att_param) 
     315{ 
     316    return tp_attach(tp, att_param->user_data,  
     317                            (pj_sockaddr_t*)&att_param->rem_addr,  
     318                            (pj_sockaddr_t*)&att_param->rem_rtcp,  
     319                            att_param->addr_len, att_param->rtp_cb, 
     320                            att_param->rtp_cb2,  
     321                            att_param->rtcp_cb); 
    243322} 
    244323 
     
    297376    /* Distribute to users */ 
    298377    for (i=0; i<loop->user_cnt; ++i) { 
    299         if (!loop->users[i].rx_disabled && loop->users[i].rtp_cb) 
     378        if (loop->users[i].rx_disabled) continue; 
     379        if (loop->users[i].rtp_cb2) { 
     380            pjmedia_tp_cb_param param; 
     381 
     382            pj_bzero(&param, sizeof(param)); 
     383            param.user_data = loop->users[i].user_data; 
     384            param.pkt = (void *)pkt; 
     385            param.size = size; 
     386            (*loop->users[i].rtp_cb2)(&param); 
     387        } else if (loop->users[i].rtp_cb) { 
    300388            (*loop->users[i].rtp_cb)(loop->users[i].user_data, (void*)pkt,  
    301389                                     size); 
     390        } 
    302391    } 
    303392 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5956 r5989  
    38593859 
    38603860    /** 
     3861     * Use loopback media transport. This may be useful if application 
     3862     * doesn't want PJSIP to create real media transports/sockets, such as 
     3863     * when using third party media. 
     3864     * 
     3865     * Default: PJ_FALSE 
     3866     */ 
     3867    pj_bool_t                   use_loop_med_tp; 
     3868 
     3869    /** 
     3870     * Enable local loopback when loop_med_tp_use is set to PJ_TRUE. 
     3871     * If enabled, packets sent to the transport will be sent back to 
     3872     * the streams attached to the transport. 
     3873     * 
     3874     * Default: PJ_FALSE 
     3875     */ 
     3876    pj_bool_t                   enable_loopback; 
     3877 
     3878    /** 
    38613879     * Control the use of ICE in the account. By default, the settings in the 
    38623880     * \a pjsua_media_config will be used. 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r5979 r5989  
    630630    if (status != PJ_SUCCESS) { 
    631631        pjsua_perror(THIS_FILE, "Unable to create media transport", 
     632                     status); 
     633        goto on_error; 
     634    } 
     635 
     636    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING, 
     637                                    pjsua_var.media_cfg.tx_drop_pct); 
     638 
     639    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING, 
     640                                    pjsua_var.media_cfg.rx_drop_pct); 
     641 
     642    call_med->tp_ready = PJ_SUCCESS; 
     643 
     644    return PJ_SUCCESS; 
     645 
     646on_error: 
     647    if (call_med->tp) 
     648        pjmedia_transport_close(call_med->tp); 
     649 
     650    return status; 
     651} 
     652 
     653/* Create loop media transport */ 
     654static pj_status_t create_loop_media_transport( 
     655                       const pjsua_transport_config *cfg, 
     656                       pjsua_call_media *call_med) 
     657{ 
     658    pj_status_t status; 
     659    pjmedia_loop_tp_setting opt; 
     660    pj_bool_t use_ipv6, use_nat64; 
     661    int af; 
     662    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 
     663 
     664    use_ipv6 = (acc->cfg.ipv6_media_use != PJSUA_IPV6_DISABLED); 
     665    use_nat64 = (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED); 
     666    af = (use_ipv6 || use_nat64) ? pj_AF_INET6() : pj_AF_INET(); 
     667 
     668    pjmedia_loop_tp_setting_default(&opt); 
     669    opt.af = af; 
     670    if (cfg->bound_addr.slen) 
     671        opt.addr = cfg->bound_addr; 
     672    opt.port = cfg->port; 
     673    opt.disable_rx=!pjsua_var.acc[call_med->call->acc_id].cfg.enable_loopback; 
     674    status = pjmedia_transport_loop_create2(pjsua_var.med_endpt, &opt, 
     675                                            &call_med->tp); 
     676    if (status != PJ_SUCCESS) { 
     677        pjsua_perror(THIS_FILE, "Unable to create loop media transport", 
    632678                     status); 
    633679        goto on_error; 
     
    17551801     */ 
    17561802    if (call_med->tp == NULL) { 
     1803        pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 
     1804 
    17571805        /* Initializations. If media transport creation completes immediately,  
    17581806         * we don't need to call the callbacks. 
     
    17721820        pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_CREATING); 
    17731821 
    1774         if (pjsua_var.acc[call_med->call->acc_id].cfg.ice_cfg.enable_ice) { 
     1822        if (acc->cfg.use_loop_med_tp) { 
     1823            status = create_loop_media_transport(tcfg, call_med); 
     1824        } else if (acc->cfg.ice_cfg.enable_ice) { 
    17751825            status = create_ice_media_transport(tcfg, call_med, async); 
    17761826            if (async && status == PJ_EPENDING) { 
     
    33023352                        goto on_check_med_status; 
    33033353                    } 
     3354 
     3355                    if (pjmedia_transport_info_get_spc_info( 
     3356                                    &tp_info, PJMEDIA_TRANSPORT_TYPE_LOOP)) 
     3357                    { 
     3358                        pjmedia_transport_loop_disable_rx( 
     3359                                call_med->tp, call_med->strm.a.stream, 
     3360                                !acc->cfg.enable_loopback); 
     3361                    } 
    33043362                } 
    33053363            } 
Note: See TracChangeset for help on using the changeset viewer.