Changeset 3763


Ignore:
Timestamp:
Sep 21, 2011 10:20:01 AM (13 years ago)
Author:
ming
Message:

Re #1266: Asynchronous media transport creation

  • Add feature that allows ICE media transport to be created asynchronously.
  • Add new callback, e.g. on_call_media_transport_state(call_id, state_struct) to report media transport status.
  • Handle outgoing calls while creating media transport asynchronously.
Location:
pjproject/trunk/pjsip
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3756 r3763  
    462462                                                 registration callback. */ 
    463463} pjsua_reg_info; 
     464 
     465 
     466/**  
     467 * Enumeration of media transport state types. 
     468 */ 
     469typedef enum pjsua_med_tp_st 
     470{ 
     471    /** Null, this is the state before media transport is created. */ 
     472    PJSUA_MED_TP_NULL, 
     473 
     474    /** 
     475     * Just before media transport is created, which can finish 
     476     * asynchronously later. 
     477     */ 
     478    PJSUA_MED_TP_CREATING, 
     479 
     480    /** Media transport creation is completed, but not initialized yet. */ 
     481    PJSUA_MED_TP_IDLE, 
     482 
     483    /** Initialized (media_create() has been called). */ 
     484    PJSUA_MED_TP_INIT, 
     485 
     486    /** Running (media_start() has been called). */ 
     487    PJSUA_MED_TP_RUNNING, 
     488 
     489    /** Disabled (transport is initialized, but media is being disabled). */ 
     490    PJSUA_MED_TP_DISABLED 
     491 
     492} pjsua_med_tp_st; 
     493 
     494 
     495/** 
     496 * Structure to be passed on media transport state callback. 
     497 */ 
     498typedef struct pjsua_med_tp_state_info 
     499{ 
     500    /** 
     501     * The media index. 
     502     */ 
     503    unsigned             med_idx; 
     504 
     505    /** 
     506     * The media transport state 
     507     */ 
     508    pjsua_med_tp_st      state; 
     509 
     510    /** 
     511     * The last error code related to the media transport state. 
     512     */ 
     513    pj_status_t          status; 
     514 
     515    /** 
     516     * Optional SIP error code. 
     517     */ 
     518    int                  sip_err_code; 
     519 
     520    /** 
     521     * Optional extended info, the content is specific for each transport type. 
     522     */ 
     523    void                *ext_info; 
     524 
     525} pjsua_med_tp_state_info; 
     526 
     527 
     528/** 
     529  * Type of callback to be called when media transport state is changed. 
     530  * 
     531  * @param call_id      The call ID. 
     532  * @param info         The media transport state info. 
     533  */ 
     534typedef void (*pjsua_med_tp_state_cb)(pjsua_call_id call_id, 
     535                                      const pjsua_med_tp_state_info *info); 
    464536 
    465537 
     
    9501022 
    9511023    /** 
     1024     * This callback is called when media transport state is changed. See 
     1025     * also #pjsua_med_tp_state_cb. 
     1026     */ 
     1027    pjsua_med_tp_state_cb on_call_media_transport_state; 
     1028 
     1029    /** 
    9521030     * This callback is called to report error in ICE media transport. 
    9531031     * Currently it is used to report TURN Refresh error. 
     
    13631441 */ 
    13641442PJ_DECL(void) pjsua_msg_data_init(pjsua_msg_data *msg_data); 
     1443 
     1444 
     1445/** 
     1446 * Clone message data. 
     1447 * 
     1448 * @param pool      Pool to allocate memory for the new message data. 
     1449 * @param rhs       Message data to be cloned. 
     1450 * 
     1451 * @return          The new message data. 
     1452 */ 
     1453PJ_DECL(pjsua_msg_data*) pjsua_msg_data_clone(pj_pool_t *pool, 
     1454                                              const pjsua_msg_data *rhs); 
    13651455 
    13661456 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3758 r3763  
    2828PJ_BEGIN_DECL 
    2929 
    30 /**  
    31  * Media transport state. 
    32  */ 
    33 typedef enum pjsua_med_tp_st 
    34 { 
    35     /** Not initialized */ 
    36     PJSUA_MED_TP_IDLE, 
    37  
    38     /** Initialized (media_create() has been called) */ 
    39     PJSUA_MED_TP_INIT, 
    40  
    41     /** Running (media_start() has been called) */ 
    42     PJSUA_MED_TP_RUNNING, 
    43  
    44     /** Disabled (transport is initialized, but media is being disabled) */ 
    45     PJSUA_MED_TP_DISABLED 
    46  
    47 } pjsua_med_tp_st; 
    48  
    4930/** Forward decl of pjsua call */ 
    5031typedef struct pjsua_call pjsua_call; 
     32 
     33/** Forward decl of pjsua call media */ 
     34typedef struct pjsua_call_media pjsua_call_media; 
    5135 
    5236 
     
    9377    pj_status_t          tp_ready;  /**< Media transport status.            */ 
    9478    pjmedia_transport   *tp_orig;   /**< Original media transport           */ 
    95     pj_bool_t            tp_auto_del; /**< May delete media transport   */ 
     79    pj_bool_t            tp_auto_del; /**< May delete media transport       */ 
    9680    pjsua_med_tp_st      tp_st;     /**< Media transport state              */ 
    9781    pj_sockaddr          rtp_addr;  /**< Current RTP source address 
     
    10084    pjmedia_srtp_use     rem_srtp_use; /**< Remote's SRTP usage policy.     */ 
    10185 
    102     pjmedia_event_subscription esub_rend;/**< Subscribe renderer events.     */ 
     86    pjmedia_event_subscription esub_rend;/**< Subscribe renderer events.    */ 
    10387    pjmedia_event_subscription esub_cap;/**< Subscribe capture events.      */ 
     88 
     89    pjsua_med_tp_state_cb      med_init_cb;/**< Media transport 
     90                                                initialization callback.    */ 
     91 
     92    /** Media transport creation callback. */ 
     93    pj_status_t (*med_create_cb)(pjsua_call_media *call_med, 
     94                                 pj_status_t status, int security_level, 
     95                                 int *sip_err_code); 
    10496} pjsua_call_media; 
    10597 
     
    133125    pjsua_call_media     media[PJSUA_MAX_CALL_MEDIA]; /**< Array of media   */ 
    134126    int                  audio_idx; /**< First active audio media.          */ 
     127    pj_mutex_t          *med_ch_mutex;/**< Media channel callback's mutex.  */ 
     128    pjsua_med_tp_state_cb   med_ch_cb;/**< Media channel callback.          */ 
     129    pjsua_med_tp_state_info med_ch_info;/**< Media channel info.            */ 
    135130 
    136131    pjsip_evsub         *xfer_sub;  /**< Xfer server subscription, if this 
     
    148143                                          contains multiple codecs.         */ 
    149144 
     145    struct { 
     146        pjsip_dialog        *dlg;    /**< Call dialog.                      */ 
     147        pjmedia_sdp_session *rem_sdp;/**< Remote SDP.                       */ 
     148        union { 
     149            struct { 
     150                unsigned         options; /**< Outgoing call options.       */ 
     151                pjsua_msg_data  *msg_data;/**< Headers for outgoing INVITE. */ 
     152            } out_call; 
     153        } call_var; 
     154    } async_call;                      /**< Temporary storage for async 
     155                                            outgoing/incoming call.         */ 
    150156}; 
    151157 
     
    509515                                     pj_pool_t *tmp_pool, 
    510516                                     const pjmedia_sdp_session *rem_sdp, 
    511                                      int *sip_err_code); 
     517                                     int *sip_err_code, 
     518                                     pj_bool_t async, 
     519                                     pjsua_med_tp_state_cb cb); 
    512520pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,  
    513521                                           pj_pool_t *pool, 
     
    524532                                  const pjsua_transport_config *tcfg, 
    525533                                  int security_level, 
    526                                   int *sip_err_code); 
     534                                  int *sip_err_code, 
     535                                  pj_bool_t async, 
     536                                  pjsua_med_tp_state_cb cb); 
    527537pj_status_t video_channel_update(pjsua_call_media *call_med, 
    528538                                 pj_pool_t *tmp_pool, 
     
    530540                                 const pjmedia_sdp_session *remote_sdp); 
    531541void stop_video_stream(pjsua_call_media *call_med); 
     542void set_media_tp_state(pjsua_call_media *call_med, pjsua_med_tp_st tp_st); 
    532543 
    533544 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r3753 r3763  
    332332*/ 
    333333 
     334static pj_status_t 
     335on_make_call_med_tp_complete(pjsua_call_id call_id, 
     336                             const pjsua_med_tp_state_info *info) 
     337{ 
     338    pjmedia_sdp_session *offer; 
     339    pjsip_inv_session *inv = NULL; 
     340    pjsua_call *call = &pjsua_var.calls[call_id]; 
     341    pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 
     342    pjsip_dialog *dlg = call->async_call.dlg; 
     343    unsigned options = call->async_call.call_var.out_call.options; 
     344    pjsip_tx_data *tdata; 
     345    pj_status_t status = (info? info->status: PJ_SUCCESS); 
     346 
     347    PJSUA_LOCK(); 
     348 
     349    /* Increment the dialog's lock otherwise when invite session creation 
     350     * fails the dialog will be destroyed prematurely. 
     351     */ 
     352    pjsip_dlg_inc_lock(dlg); 
     353 
     354    if (status != PJ_SUCCESS) { 
     355        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     356        goto on_error; 
     357    } 
     358 
     359    /* Create offer */ 
     360    status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, 
     361                                            &offer, NULL); 
     362    if (status != PJ_SUCCESS) { 
     363        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     364        goto on_error; 
     365    } 
     366 
     367    /* Create the INVITE session: */ 
     368    options |= PJSIP_INV_SUPPORT_100REL; 
     369    if (acc->cfg.require_100rel) 
     370        options |= PJSIP_INV_REQUIRE_100REL; 
     371    if (acc->cfg.use_timer != PJSUA_SIP_TIMER_INACTIVE) { 
     372        options |= PJSIP_INV_SUPPORT_TIMER; 
     373        if (acc->cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED) 
     374            options |= PJSIP_INV_REQUIRE_TIMER; 
     375        else if (acc->cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS) 
     376            options |= PJSIP_INV_ALWAYS_USE_TIMER; 
     377    } 
     378 
     379    status = pjsip_inv_create_uac( dlg, offer, options, &inv); 
     380    if (status != PJ_SUCCESS) { 
     381        pjsua_perror(THIS_FILE, "Invite session creation failed", status); 
     382        goto on_error; 
     383    } 
     384 
     385    /* Init Session Timers */ 
     386    status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting); 
     387    if (status != PJ_SUCCESS) { 
     388        pjsua_perror(THIS_FILE, "Session Timer init failed", status); 
     389        goto on_error; 
     390    } 
     391 
     392    /* Create and associate our data in the session. */ 
     393    call->inv = inv; 
     394 
     395    dlg->mod_data[pjsua_var.mod.id] = call; 
     396    inv->mod_data[pjsua_var.mod.id] = call; 
     397 
     398    /* If account is locked to specific transport, then lock dialog 
     399     * to this transport too. 
     400     */ 
     401    if (acc->cfg.transport_id != PJSUA_INVALID_ID) { 
     402        pjsip_tpselector tp_sel; 
     403 
     404        pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); 
     405        pjsip_dlg_set_transport(dlg, &tp_sel); 
     406    } 
     407 
     408    /* Set dialog Route-Set: */ 
     409    if (!pj_list_empty(&acc->route_set)) 
     410        pjsip_dlg_set_route_set(dlg, &acc->route_set); 
     411 
     412 
     413    /* Set credentials: */ 
     414    if (acc->cred_cnt) { 
     415        pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
     416                                        acc->cred_cnt, acc->cred); 
     417    } 
     418 
     419    /* Set authentication preference */ 
     420    pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 
     421 
     422    /* Create initial INVITE: */ 
     423 
     424    status = pjsip_inv_invite(inv, &tdata); 
     425    if (status != PJ_SUCCESS) { 
     426        pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",  
     427                     status); 
     428        goto on_error; 
     429    } 
     430 
     431 
     432    /* Add additional headers etc */ 
     433 
     434    pjsua_process_msg_data( tdata, 
     435                            call->async_call.call_var.out_call.msg_data); 
     436 
     437    /* Must increment call counter now */ 
     438    ++pjsua_var.call_cnt; 
     439 
     440    /* Send initial INVITE: */ 
     441 
     442    status = pjsip_inv_send_msg(inv, tdata); 
     443    if (status != PJ_SUCCESS) { 
     444        pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",  
     445                     status); 
     446 
     447        /* Upon failure to send first request, the invite  
     448         * session would have been cleared. 
     449         */ 
     450        inv = NULL; 
     451        goto on_error; 
     452    } 
     453 
     454    /* Done. */ 
     455 
     456    pjsip_dlg_dec_lock(dlg); 
     457    PJSUA_UNLOCK(); 
     458 
     459    return PJ_SUCCESS; 
     460 
     461on_error: 
     462    if (dlg) { 
     463        /* This may destroy the dialog */ 
     464        pjsip_dlg_dec_lock(dlg); 
     465    } 
     466 
     467    if (inv != NULL) { 
     468        pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 
     469    } 
     470 
     471    if (call_id != -1) { 
     472        reset_call(call_id); 
     473        pjsua_media_channel_deinit(call_id); 
     474    } 
     475 
     476    PJSUA_UNLOCK(); 
     477    return status; 
     478} 
     479 
    334480 
    335481/* 
     
    345491    pj_pool_t *tmp_pool = NULL; 
    346492    pjsip_dialog *dlg = NULL; 
    347     pjmedia_sdp_session *offer; 
    348     pjsip_inv_session *inv = NULL; 
    349493    pjsua_acc *acc; 
    350494    pjsua_call *call; 
    351495    int call_id = -1; 
    352496    pj_str_t contact; 
    353     pjsip_tx_data *tdata; 
    354497    pj_status_t status; 
    355498 
     
    377520        pjsua_var.null_snd==NULL && !pjsua_var.no_snd)  
    378521    { 
    379         pj_status_t status; 
    380  
    381522        status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); 
    382523        if (status != PJ_SUCCESS) 
     
    463604     * fails the dialog will be destroyed prematurely. 
    464605     */ 
    465     pjsip_dlg_inc_lock(dlg); 
     606//    pjsip_dlg_inc_lock(dlg); 
    466607 
    467608    /* Calculate call's secure level */ 
    468609    call->secure_level = get_secure_level(acc_id, dest_uri); 
     610 
     611    /* Attach user data */ 
     612    call->user_data = user_data; 
     613     
     614    call->async_call.call_var.out_call.options = options; 
     615    call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone( 
     616                                                      dlg->pool, msg_data); 
     617    call->async_call.dlg = dlg; 
    469618 
    470619    /* Init media channel */ 
    471620    status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,  
    472621                                      call->secure_level, dlg->pool, 
    473                                       NULL, NULL); 
    474     if (status != PJ_SUCCESS) { 
     622                                      NULL, NULL, PJ_TRUE, 
     623                                      (pjsua_med_tp_state_cb) 
     624                                      &on_make_call_med_tp_complete); 
     625    if (status == PJ_SUCCESS) { 
     626        status = on_make_call_med_tp_complete(call->index, NULL); 
     627        if (status != PJ_SUCCESS) 
     628            goto on_error; 
     629    } else if (status != PJ_EPENDING) { 
    475630        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    476631        goto on_error; 
    477632    } 
    478633 
    479     /* Create offer */ 
    480     status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, 
    481                                             &offer, NULL); 
    482     if (status != PJ_SUCCESS) { 
    483         pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    484         goto on_error; 
    485     } 
    486  
    487     /* Create the INVITE session: */ 
    488     options |= PJSIP_INV_SUPPORT_100REL; 
    489     if (acc->cfg.require_100rel) 
    490         options |= PJSIP_INV_REQUIRE_100REL; 
    491     if (acc->cfg.use_timer != PJSUA_SIP_TIMER_INACTIVE) { 
    492         options |= PJSIP_INV_SUPPORT_TIMER; 
    493         if (acc->cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED) 
    494             options |= PJSIP_INV_REQUIRE_TIMER; 
    495         else if (acc->cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS) 
    496             options |= PJSIP_INV_ALWAYS_USE_TIMER; 
    497     } 
    498  
    499     status = pjsip_inv_create_uac( dlg, offer, options, &inv); 
    500     if (status != PJ_SUCCESS) { 
    501         pjsua_perror(THIS_FILE, "Invite session creation failed", status); 
    502         goto on_error; 
    503     } 
    504  
    505     /* Init Session Timers */ 
    506     status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting); 
    507     if (status != PJ_SUCCESS) { 
    508         pjsua_perror(THIS_FILE, "Session Timer init failed", status); 
    509         goto on_error; 
    510     } 
    511  
    512     /* Create and associate our data in the session. */ 
    513     call->inv = inv; 
    514  
    515     dlg->mod_data[pjsua_var.mod.id] = call; 
    516     inv->mod_data[pjsua_var.mod.id] = call; 
    517  
    518     /* Attach user data */ 
    519     call->user_data = user_data; 
    520  
    521     /* If account is locked to specific transport, then lock dialog 
    522      * to this transport too. 
    523      */ 
    524     if (acc->cfg.transport_id != PJSUA_INVALID_ID) { 
    525         pjsip_tpselector tp_sel; 
    526  
    527         pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); 
    528         pjsip_dlg_set_transport(dlg, &tp_sel); 
    529     } 
    530  
    531     /* Set dialog Route-Set: */ 
    532     if (!pj_list_empty(&acc->route_set)) 
    533         pjsip_dlg_set_route_set(dlg, &acc->route_set); 
    534  
    535  
    536     /* Set credentials: */ 
    537     if (acc->cred_cnt) { 
    538         pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
    539                                         acc->cred_cnt, acc->cred); 
    540     } 
    541  
    542     /* Set authentication preference */ 
    543     pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 
    544  
    545     /* Create initial INVITE: */ 
    546  
    547     status = pjsip_inv_invite(inv, &tdata); 
    548     if (status != PJ_SUCCESS) { 
    549         pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",  
    550                      status); 
    551         goto on_error; 
    552     } 
    553  
    554  
    555     /* Add additional headers etc */ 
    556  
    557     pjsua_process_msg_data( tdata, msg_data); 
    558  
    559     /* Must increment call counter now */ 
    560     ++pjsua_var.call_cnt; 
    561  
    562     /* Send initial INVITE: */ 
    563  
    564     status = pjsip_inv_send_msg(inv, tdata); 
    565     if (status != PJ_SUCCESS) { 
    566         pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",  
    567                      status); 
    568  
    569         /* Upon failure to send first request, the invite  
    570          * session would have been cleared. 
    571          */ 
    572         inv = NULL; 
    573         goto on_error; 
    574     } 
    575  
    576634    /* Done. */ 
    577635 
     
    579637        *p_call_id = call_id; 
    580638 
    581     pjsip_dlg_dec_lock(dlg); 
    582639    pj_pool_release(tmp_pool); 
    583640    PJSUA_UNLOCK(); 
     
    590647on_error: 
    591648    if (dlg) { 
     649        pjsip_dlg_inc_lock(dlg); 
    592650        /* This may destroy the dialog */ 
    593651        pjsip_dlg_dec_lock(dlg); 
    594     } 
    595  
    596     if (inv != NULL) { 
    597         pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 
    598652    } 
    599653 
     
    816870                                      rdata->tp_info.pool, 
    817871                                      offer, 
    818                                       &sip_err_code); 
     872                                      &sip_err_code, PJ_FALSE, 
     873                                      NULL); 
    819874    if (status != PJ_SUCCESS) { 
    820875        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     
    833888        goto on_return; 
    834889    } 
    835  
    836890 
    837891    /* Verify that we can handle the request. */ 
     
    10151069 
    10161070    ++pjsua_var.call_cnt; 
    1017  
    10181071 
    10191072    /* Check if this request should replace existing call */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3756 r3763  
    149149    pjsip_media_type_init(&msg_data->multipart_ctype, NULL, NULL); 
    150150    pj_list_init(&msg_data->multipart_parts); 
     151} 
     152 
     153PJ_DEF(pjsua_msg_data*) pjsua_msg_data_clone(pj_pool_t *pool, 
     154                                             const pjsua_msg_data *rhs) 
     155{ 
     156    pjsua_msg_data *msg_data; 
     157    const pjsip_hdr *hdr; 
     158    const pjsip_multipart_part *mpart; 
     159 
     160    PJ_ASSERT_RETURN(pool && rhs, NULL); 
     161 
     162    msg_data = PJ_POOL_ZALLOC_T(pool, pjsua_msg_data); 
     163    PJ_ASSERT_RETURN(msg_data != NULL, NULL); 
     164 
     165    pj_list_init(&msg_data->hdr_list); 
     166    hdr = rhs->hdr_list.next; 
     167    while (hdr != &rhs->hdr_list) { 
     168        pj_list_push_back(&msg_data->hdr_list, pjsip_hdr_clone(pool, hdr)); 
     169        hdr = hdr->next; 
     170    } 
     171 
     172    pj_strdup(pool, &msg_data->content_type, &rhs->content_type); 
     173    pj_strdup(pool, &msg_data->msg_body, &rhs->msg_body); 
     174 
     175    pjsip_media_type_cp(pool, &msg_data->multipart_ctype, 
     176                        &rhs->multipart_ctype); 
     177 
     178    pj_list_init(&msg_data->multipart_parts); 
     179    mpart = rhs->multipart_parts.next; 
     180    while (mpart != &rhs->multipart_parts) { 
     181        pj_list_push_back(&msg_data->multipart_parts, 
     182                          pjsip_multipart_clone_part(pool, mpart)); 
     183        mpart = mpart->next; 
     184    } 
     185 
     186    return msg_data; 
    151187} 
    152188 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3753 r3763  
    711711                                    pjsua_var.media_cfg.rx_drop_pct); 
    712712 
     713    call_med->tp_ready = PJ_SUCCESS; 
     714 
    713715    return PJ_SUCCESS; 
    714716 
     
    772774    switch (op) { 
    773775    case PJ_ICE_STRANS_OP_INIT: 
    774         call_med->tp_ready = result; 
     776        call_med->tp_ready = result; 
     777        if (call_med->med_create_cb) 
     778            (*call_med->med_create_cb)(call_med, result, 
     779                                       call_med->call->secure_level, NULL); 
    775780        break; 
    776781    case PJ_ICE_STRANS_OP_NEGOTIATION: 
     
    832837                         call_med->call->index, call_med->idx)); 
    833838        } 
     839        if (pjsua_var.ua_cfg.cb.on_call_media_transport_state) { 
     840            pjsua_med_tp_state_info info; 
     841 
     842            pj_bzero(&info, sizeof(info)); 
     843            info.med_idx = call_med->idx; 
     844            info.state = call_med->tp_st; 
     845            info.status = result; 
     846            info.ext_info = &op; 
     847            (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)( 
     848                call_med->call->index, &info); 
     849        } 
    834850        if (pjsua_var.ua_cfg.cb.on_ice_transport_error) { 
    835851            pjsua_call_id id = call_med->call->index; 
     
    871887static pj_status_t create_ice_media_transport( 
    872888                                const pjsua_transport_config *cfg, 
    873                                 pjsua_call_media *call_med) 
     889                                pjsua_call_media *call_med, 
     890                                pj_bool_t async) 
    874891{ 
    875892    char stunip[PJ_INET6_ADDRSTRLEN]; 
     
    953970 
    954971    /* Wait until transport is initialized, or time out */ 
    955     PJSUA_UNLOCK(); 
    956     while (call_med->tp_ready == PJ_EPENDING) { 
    957         pjsua_handle_events(100); 
    958     } 
    959     PJSUA_LOCK(); 
    960     if (call_med->tp_ready != PJ_SUCCESS) { 
     972    if (!async) { 
     973        PJSUA_UNLOCK(); 
     974        while (call_med->tp_ready == PJ_EPENDING) { 
     975            pjsua_handle_events(100); 
     976        } 
     977        PJSUA_LOCK(); 
     978    } 
     979 
     980    if (async && call_med->tp_ready == PJ_EPENDING) { 
     981        return PJ_EPENDING; 
     982    } else if (call_med->tp_ready != PJ_SUCCESS) { 
    961983        pjsua_perror(THIS_FILE, "Error initializing ICE media transport", 
    962984                     call_med->tp_ready); 
     
    12361258} 
    12371259 
     1260/* Set media transport state and notify the application via the callback. */ 
     1261void set_media_tp_state(pjsua_call_media *call_med, 
     1262                        pjsua_med_tp_st tp_st) 
     1263{ 
     1264    if (pjsua_var.ua_cfg.cb.on_call_media_transport_state && 
     1265        call_med->tp_st != tp_st) 
     1266    { 
     1267        pjsua_med_tp_state_info info; 
     1268 
     1269        pj_bzero(&info, sizeof(info)); 
     1270        info.med_idx = call_med->idx; 
     1271        info.state = tp_st; 
     1272        info.status = call_med->tp_ready; 
     1273        (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)( 
     1274            call_med->call->index, &info); 
     1275    } 
     1276 
     1277    call_med->tp_st = tp_st; 
     1278} 
     1279 
     1280/* Callback to resume pjsua_call_media_init() after media transport 
     1281 * creation is completed. 
     1282 */ 
     1283static pj_status_t call_media_init_cb(pjsua_call_media *call_med, 
     1284                                      pj_status_t status, 
     1285                                      int security_level, 
     1286                                      int *sip_err_code) 
     1287{ 
     1288    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 
     1289    int err_code = 0; 
     1290 
     1291    if (status != PJ_SUCCESS) 
     1292        goto on_error; 
     1293 
     1294    if (call_med->tp_st == PJSUA_MED_TP_CREATING) 
     1295        set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); 
     1296 
     1297#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     1298    /* This function may be called when SRTP transport already exists 
     1299     * (e.g: in re-invite, update), don't need to destroy/re-create. 
     1300     */ 
     1301    if (!call_med->tp_orig || call_med->tp == call_med->tp_orig) { 
     1302        pjmedia_srtp_setting srtp_opt; 
     1303        pjmedia_transport *srtp = NULL; 
     1304 
     1305        /* Check if SRTP requires secure signaling */ 
     1306        if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) { 
     1307            if (security_level < acc->cfg.srtp_secure_signaling) { 
     1308                err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     1309                status = PJSIP_ESESSIONINSECURE; 
     1310                goto on_error; 
     1311            } 
     1312        } 
     1313 
     1314        /* Always create SRTP adapter */ 
     1315        pjmedia_srtp_setting_default(&srtp_opt); 
     1316        srtp_opt.close_member_tp = PJ_TRUE; 
     1317        /* If media session has been ever established, let's use remote's 
     1318         * preference in SRTP usage policy, especially when it is stricter. 
     1319         */ 
     1320        if (call_med->rem_srtp_use > acc->cfg.use_srtp) 
     1321            srtp_opt.use = call_med->rem_srtp_use; 
     1322        else 
     1323            srtp_opt.use = acc->cfg.use_srtp; 
     1324 
     1325        status = pjmedia_transport_srtp_create(pjsua_var.med_endpt, 
     1326                                               call_med->tp, 
     1327                                               &srtp_opt, &srtp); 
     1328        if (status != PJ_SUCCESS) { 
     1329            err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; 
     1330            goto on_error; 
     1331        } 
     1332 
     1333        /* Set SRTP as current media transport */ 
     1334        call_med->tp_orig = call_med->tp; 
     1335        call_med->tp = srtp; 
     1336    } 
     1337#else 
     1338    call_med->tp_orig = call_med->tp; 
     1339    PJ_UNUSED_ARG(security_level); 
     1340#endif 
     1341 
     1342    pjmedia_event_subscription_init(&call_med->esub_rend, &call_media_on_event, 
     1343                                    call_med); 
     1344    pjmedia_event_subscription_init(&call_med->esub_cap, &call_media_on_event, 
     1345                                    call_med); 
     1346 
     1347on_error: 
     1348    if (status != PJ_SUCCESS && call_med->tp) { 
     1349        pjmedia_transport_close(call_med->tp); 
     1350        call_med->tp = NULL; 
     1351    } 
     1352 
     1353    if (sip_err_code) 
     1354        *sip_err_code = err_code; 
     1355 
     1356    if (call_med->med_init_cb) { 
     1357        pjsua_med_tp_state_info info; 
     1358 
     1359        pj_bzero(&info, sizeof(info)); 
     1360        info.status = status; 
     1361        info.state = call_med->tp_st; 
     1362        info.med_idx = call_med->idx; 
     1363        info.sip_err_code = err_code; 
     1364        (*call_med->med_init_cb)(call_med->call->index, &info); 
     1365    } 
     1366 
     1367    return status; 
     1368} 
     1369 
    12381370/* Initialize the media line */ 
    12391371pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, 
     
    12411373                                  const pjsua_transport_config *tcfg, 
    12421374                                  int security_level, 
    1243                                   int *sip_err_code) 
     1375                                  int *sip_err_code, 
     1376                                  pj_bool_t async, 
     1377                                  pjsua_med_tp_state_cb cb) 
    12441378{ 
    12451379    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 
    1246     pj_status_t status; 
     1380    pj_status_t status = PJ_SUCCESS; 
    12471381 
    12481382    /* 
     
    12521386    call_med->type = type; 
    12531387 
    1254     /* Create the media transport for initial call. This is blocking for now */ 
     1388    /* Create the media transport for initial call. */ 
    12551389    if (call_med->tp == NULL) { 
    1256         if (pjsua_var.media_cfg.enable_ice) { 
    1257             status = create_ice_media_transport(tcfg, call_med); 
    1258         } else { 
    1259             status = create_udp_media_transport(tcfg, call_med); 
    1260         } 
    1261  
    1262         if (status != PJ_SUCCESS) { 
    1263             PJ_PERROR(1,(THIS_FILE, status, "Error creating media transport")); 
    1264             return status; 
    1265         } 
    1266          
    1267         call_med->tp_st = PJSUA_MED_TP_IDLE; 
    1268  
    12691390#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 
    12701391        /* While in initial call, set default video devices */ 
     
    12851406#endif 
    12861407 
     1408        set_media_tp_state(call_med, PJSUA_MED_TP_CREATING); 
     1409 
     1410        if (async) { 
     1411            call_med->med_create_cb = &call_media_init_cb; 
     1412            call_med->med_init_cb = cb; 
     1413        } 
     1414 
     1415        if (pjsua_var.media_cfg.enable_ice) { 
     1416            status = create_ice_media_transport(tcfg, call_med, async); 
     1417        } else { 
     1418            status = create_udp_media_transport(tcfg, call_med); 
     1419        } 
     1420 
     1421        if (status == PJ_EPENDING) { 
     1422            /* We will resume call media initialization in the 
     1423             * on_ice_complete() callback. 
     1424             */ 
     1425            return PJ_EPENDING; 
     1426        } else if (status != PJ_SUCCESS) { 
     1427            PJ_PERROR(1,(THIS_FILE, status, "Error creating media transport")); 
     1428            return status; 
     1429        } 
     1430 
     1431        /* Media transport creation completed immediately, so  
     1432         * we don't need to call the callback. 
     1433         */ 
     1434        call_med->med_init_cb = NULL; 
     1435 
    12871436    } else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) { 
    12881437        /* Media is being reenabled. */ 
    1289         call_med->tp_st = PJSUA_MED_TP_INIT; 
    1290     } 
    1291  
    1292 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    1293     /* This function may be called when SRTP transport already exists 
    1294      * (e.g: in re-invite, update), don't need to destroy/re-create. 
    1295      */ 
    1296     if (!call_med->tp_orig || call_med->tp == call_med->tp_orig) { 
    1297         pjmedia_srtp_setting srtp_opt; 
    1298         pjmedia_transport *srtp = NULL; 
    1299  
    1300         /* Check if SRTP requires secure signaling */ 
    1301         if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) { 
    1302             if (security_level < acc->cfg.srtp_secure_signaling) { 
    1303                 if (sip_err_code) 
    1304                     *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
    1305                 status = PJSIP_ESESSIONINSECURE; 
     1438        set_media_tp_state(call_med, PJSUA_MED_TP_INIT); 
     1439    } 
     1440 
     1441    return call_media_init_cb(call_med, status, security_level, 
     1442                              sip_err_code); 
     1443} 
     1444 
     1445/* Callback to resume pjsua_media_channel_init() after media transport 
     1446 * initialization is completed. 
     1447 */ 
     1448static pj_status_t media_channel_init_cb(pjsua_call_id call_id, 
     1449                                         const pjsua_med_tp_state_info *info) 
     1450{ 
     1451    pjsua_call *call = &pjsua_var.calls[call_id]; 
     1452    pj_status_t status = (info? info->status : PJ_SUCCESS); 
     1453    unsigned mi; 
     1454 
     1455    if (info) { 
     1456        pj_mutex_lock(call->med_ch_mutex); 
     1457 
     1458        /* Set the callback to NULL to indicate that the async operation 
     1459         * has completed. 
     1460         */ 
     1461        call->media[info->med_idx].med_init_cb = NULL; 
     1462 
     1463        /* In case of failure, save the information to be returned 
     1464         * by the last media transport to finish. 
     1465         */ 
     1466        if (info->status != PJ_SUCCESS) 
     1467            pj_memcpy(&call->med_ch_info, info, sizeof(info)); 
     1468 
     1469        /* Check whether all the call's medias have finished calling their 
     1470         * callbacks. 
     1471         */ 
     1472        for (mi=0; mi < call->med_cnt; ++mi) { 
     1473            pjsua_call_media *call_med = &call->media[mi]; 
     1474 
     1475            if (call_med->med_init_cb) { 
     1476                pj_mutex_unlock(call->med_ch_mutex); 
     1477                return PJ_SUCCESS; 
     1478            } 
     1479 
     1480            if (call_med->tp_ready != PJ_SUCCESS) 
     1481                status = call_med->tp_ready; 
     1482        } 
     1483 
     1484        /* OK, we are called by the last media transport finished. */ 
     1485        pj_mutex_unlock(call->med_ch_mutex); 
     1486    } 
     1487 
     1488    if (call->med_ch_mutex) { 
     1489        pj_mutex_destroy(call->med_ch_mutex); 
     1490        call->med_ch_mutex = NULL; 
     1491    } 
     1492 
     1493    if (status != PJ_SUCCESS) { 
     1494        pjsua_media_channel_deinit(call_id); 
     1495        goto on_error; 
     1496    } 
     1497 
     1498    /* Tell the media transport of a new offer/answer session */ 
     1499    for (mi=0; mi < call->med_cnt; ++mi) { 
     1500        pjsua_call_media *call_med = &call->media[mi]; 
     1501 
     1502        /* Note: tp may be NULL if this media line is disabled */ 
     1503        if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) { 
     1504            pj_pool_t *tmp_pool = (call->inv? call->inv->pool_prov: 
     1505                                   call->async_call.dlg->pool); 
     1506 
     1507            status = pjmedia_transport_media_create( 
     1508                         call_med->tp, tmp_pool, 
     1509                         0, call->async_call.rem_sdp, mi); 
     1510            if (status != PJ_SUCCESS) { 
     1511                call->med_ch_info.status = status; 
     1512                call->med_ch_info.med_idx = mi; 
     1513                call->med_ch_info.state = call_med->tp_st; 
     1514                call->med_ch_info.sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     1515                pjsua_media_channel_deinit(call_id); 
    13061516                goto on_error; 
    13071517            } 
    1308         } 
    1309  
    1310         /* Always create SRTP adapter */ 
    1311         pjmedia_srtp_setting_default(&srtp_opt); 
    1312         srtp_opt.close_member_tp = PJ_TRUE; 
    1313         /* If media session has been ever established, let's use remote's 
    1314          * preference in SRTP usage policy, especially when it is stricter. 
    1315          */ 
    1316         if (call_med->rem_srtp_use > acc->cfg.use_srtp) 
    1317             srtp_opt.use = call_med->rem_srtp_use; 
    1318         else 
    1319             srtp_opt.use = acc->cfg.use_srtp; 
    1320  
    1321         status = pjmedia_transport_srtp_create(pjsua_var.med_endpt, 
    1322                                                call_med->tp, 
    1323                                                &srtp_opt, &srtp); 
    1324         if (status != PJ_SUCCESS) { 
    1325             if (sip_err_code) 
    1326                 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; 
    1327             goto on_error; 
    1328         } 
    1329  
    1330         /* Set SRTP as current media transport */ 
    1331         call_med->tp_orig = call_med->tp; 
    1332         call_med->tp = srtp; 
    1333     } 
    1334 #else 
    1335     call_med->tp_orig = call_med->tp; 
    1336     PJ_UNUSED_ARG(security_level); 
    1337 #endif 
    1338  
    1339     pjmedia_event_subscription_init(&call_med->esub_rend, &call_media_on_event, 
    1340                                     call_med); 
    1341     pjmedia_event_subscription_init(&call_med->esub_cap, &call_media_on_event, 
    1342                                         call_med); 
    1343  
    1344     return PJ_SUCCESS; 
     1518 
     1519            set_media_tp_state(call_med, PJSUA_MED_TP_INIT); 
     1520        } 
     1521    } 
     1522 
     1523    call->med_ch_info.status = PJ_SUCCESS; 
    13451524 
    13461525on_error: 
    1347     if (call_med->tp) { 
    1348         pjmedia_transport_close(call_med->tp); 
    1349         call_med->tp = NULL; 
    1350     } 
     1526    if (call->med_ch_cb) 
     1527        (*call->med_ch_cb)(call->index, &call->med_ch_info); 
     1528 
    13511529    return status; 
    13521530} 
     
    13571535                                     pj_pool_t *tmp_pool, 
    13581536                                     const pjmedia_sdp_session *rem_sdp, 
    1359                                      int *sip_err_code) 
     1537                                     int *sip_err_code, 
     1538                                     pj_bool_t async, 
     1539                                     pjsua_med_tp_state_cb cb) 
    13601540{ 
    13611541    const pj_str_t STR_AUDIO = { "audio", 5 }; 
     
    13691549    pjmedia_type media_types[PJSUA_MAX_CALL_MEDIA]; 
    13701550    unsigned mi; 
     1551    pj_bool_t pending_med_tp = PJ_FALSE; 
    13711552    pj_status_t status; 
    13721553 
    13731554    PJ_UNUSED_ARG(role); 
     1555    PJ_UNUSED_ARG(tmp_pool); 
    13741556 
    13751557    /* 
     
    13801562    if (pjsua_get_state() != PJSUA_STATE_RUNNING) 
    13811563        return PJ_EBUSY; 
     1564 
     1565    if (async) { 
     1566        pj_pool_t *tmppool = (call->inv? call->inv->pool_prov: 
     1567                              call->async_call.dlg->pool); 
     1568 
     1569        status = pj_mutex_create_simple(tmppool, NULL, &call->med_ch_mutex); 
     1570        if (status != PJ_SUCCESS) 
     1571            return status; 
     1572    } 
    13821573 
    13831574    PJ_LOG(4,(THIS_FILE, "Call %d: initializing media..", call_id)); 
     
    14501641        status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); 
    14511642        goto on_error; 
     1643    } 
     1644 
     1645    if (async) { 
     1646        call->med_ch_cb = cb; 
     1647        if (rem_sdp) { 
     1648            /* TODO: change rem_sdp to non-const parameter. */ 
     1649            call->async_call.rem_sdp = 
     1650                pjmedia_sdp_session_clone(call->inv->pool_prov, rem_sdp); 
     1651        } 
    14521652    } 
    14531653 
     
    14831683            status = pjsua_call_media_init(call_med, media_type, 
    14841684                                           &acc->cfg.rtp_cfg, 
    1485                                            security_level, sip_err_code); 
    1486             if (status != PJ_SUCCESS) { 
    1487                 pjsua_media_channel_deinit(call_id); 
     1685                                           security_level, sip_err_code, 
     1686                                           async, 
     1687                                           (async? (pjsua_med_tp_state_cb) 
     1688                                           &media_channel_init_cb: NULL)); 
     1689            if (status == PJ_EPENDING) { 
     1690                pending_med_tp = PJ_TRUE; 
     1691            } else if (status != PJ_SUCCESS) { 
     1692                if (pending_med_tp) { 
     1693                    /* Save failure information. */ 
     1694                    call_med->tp_ready = status; 
     1695                    pj_bzero(&call->med_ch_info, sizeof(call->med_ch_info)); 
     1696                    call->med_ch_info.status = status; 
     1697                    call->med_ch_info.state = call_med->tp_st; 
     1698                    call->med_ch_info.med_idx = call_med->idx; 
     1699                    if (sip_err_code) 
     1700                        call->med_ch_info.sip_err_code = *sip_err_code; 
     1701 
     1702                    /* We will return failure in the callback later. */ 
     1703                    return PJ_EPENDING; 
     1704                } 
     1705 
     1706                pjsua_media_channel_deinit(call_id); 
    14881707                goto on_error; 
    14891708            } 
     
    14991718                pj_assert(call_med->tp_st == PJSUA_MED_TP_INIT ||  
    15001719                          call_med->tp_st == PJSUA_MED_TP_RUNNING); 
    1501                 call_med->tp_st = PJSUA_MED_TP_DISABLED; 
     1720                set_media_tp_state(call_med, PJSUA_MED_TP_DISABLED); 
    15021721            } 
    15031722 
     
    15121731              call->audio_idx, call->index)); 
    15131732 
    1514     /* Tell the media transport of a new offer/answer session */ 
    1515     for (mi=0; mi < call->med_cnt; ++mi) { 
    1516         pjsua_call_media *call_med = &call->media[mi]; 
    1517  
    1518         /* Note: tp may be NULL if this media line is disabled */ 
    1519         if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) { 
    1520             status = pjmedia_transport_media_create(call_med->tp, 
    1521                                                     tmp_pool, 0, 
    1522                                                     rem_sdp, mi); 
    1523             if (status != PJ_SUCCESS) { 
    1524                 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
    1525                 pjsua_media_channel_deinit(call_id); 
    1526                 goto on_error; 
    1527             } 
    1528  
    1529             call_med->tp_st = PJSUA_MED_TP_INIT; 
    1530         } 
    1531     } 
     1733    if (pending_med_tp) { 
     1734        /* We have a pending media transport initialization. */ 
     1735        pj_log_pop_indent(); 
     1736        return PJ_EPENDING; 
     1737    } 
     1738 
     1739    /* Media transport initialization completed immediately, so  
     1740     * we don't need to call the callback. 
     1741     */ 
     1742    call->med_ch_cb = NULL; 
     1743 
     1744    status = media_channel_init_cb(call_id, NULL); 
     1745    if (status != PJ_SUCCESS && sip_err_code) 
     1746        *sip_err_code = call->med_ch_info.sip_err_code; 
    15321747 
    15331748    pj_log_pop_indent(); 
    1534     return PJ_SUCCESS; 
     1749    return status; 
    15351750 
    15361751on_error: 
     1752    if (call->med_ch_mutex) { 
     1753        pj_mutex_destroy(call->med_ch_mutex); 
     1754        call->med_ch_mutex = NULL; 
     1755    } 
     1756 
    15371757    pj_log_pop_indent(); 
    15381758    return status; 
     
    15631783            status = pjsua_media_channel_init(call_id, PJSIP_ROLE_UAS, 
    15641784                                              call->secure_level, pool, 
    1565                                               rem_sdp, sip_err_code); 
     1785                                              rem_sdp, sip_err_code, 
     1786                                              PJ_FALSE, NULL); 
    15661787            if (status != PJ_SUCCESS) 
    15671788                return status; 
     
    18862107        pjsua_call_media *call_med = &call->media[mi]; 
    18872108 
    1888         if (call_med->tp_st != PJSUA_MED_TP_IDLE) { 
     2109        if (call_med->tp_st > PJSUA_MED_TP_IDLE) { 
    18892110            pjmedia_transport_media_stop(call_med->tp); 
    1890             call_med->tp_st = PJSUA_MED_TP_IDLE; 
     2111            set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); 
    18912112        } 
    18922113 
     
    19722193            goto on_return; 
    19732194 
    1974         call_med->tp_st = PJSUA_MED_TP_RUNNING; 
     2195        set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING); 
    19752196 
    19762197        /* Get remote SRTP usage policy */ 
     
    22642485            pjmedia_transport_close(call_med->tp); 
    22652486            call_med->tp = call_med->tp_orig = NULL; 
    2266             call_med->tp_st = PJSUA_MED_TP_IDLE; 
     2487            set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); 
    22672488        } 
    22682489 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r3758 r3763  
    676676            goto on_error; 
    677677 
    678         call_med->tp_st = PJSUA_MED_TP_RUNNING; 
     678        set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING); 
    679679 
    680680        /* Get remote SRTP usage policy */ 
     
    14731473    status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, 
    14741474                                   &acc_cfg->rtp_cfg, call->secure_level, 
    1475                                    NULL); 
     1475                                   NULL, PJ_FALSE, NULL); 
    14761476    if (status != PJ_SUCCESS) 
    14771477        goto on_error; 
     
    14861486        goto on_error; 
    14871487 
    1488     call_med->tp_st = PJSUA_MED_TP_INIT; 
     1488    set_media_tp_state(call_med, PJSUA_MED_TP_INIT); 
    14891489 
    14901490    /* Get transport address info */ 
     
    15931593        status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, 
    15941594                                       &acc_cfg->rtp_cfg, call->secure_level, 
    1595                                        NULL); 
     1595                                       NULL, PJ_FALSE, NULL); 
    15961596        if (status != PJ_SUCCESS) 
    15971597            goto on_error; 
     
    16631663        // Don't close this here, as SDP negotiation has not been 
    16641664        // done and stream may be still active. 
    1665         call_med->tp_st = PJSUA_MED_TP_DISABLED; 
     1665        set_media_tp_state(call_med, PJSUA_MED_TP_DISABLED); 
    16661666 
    16671667        /* Deactivate the stream */ 
Note: See TracChangeset for help on using the changeset viewer.