diff options
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua_internal.h | 6 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 26 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 53 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 180 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_vid.c | 23 |
5 files changed, 214 insertions, 74 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index 646c8d7c..61007d8a 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -136,6 +136,10 @@ struct pjsua_call unsigned med_cnt; /**< Number of media in SDP. */ pjsua_call_media media[PJSUA_MAX_CALL_MEDIA]; /**< Array of media */ + unsigned med_prov_cnt;/**< Number of provisional media. */ + pjsua_call_media media_prov[PJSUA_MAX_CALL_MEDIA]; + /**< Array of provisional media. */ + int audio_idx; /**< First active audio media. */ pj_mutex_t *med_ch_mutex;/**< Media channel callback's mutex. */ pjsua_med_tp_state_cb med_ch_cb;/**< Media channel callback. */ @@ -603,6 +607,8 @@ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, pjsua_med_tp_state_cb cb); void pjsua_set_media_tp_state(pjsua_call_media *call_med, pjsua_med_tp_st tp_st); +void pjsua_media_prov_clean_up(pjsua_call_id call_id); + /* Callback to receive media events */ pj_status_t call_media_on_event(pjmedia_event *event, void *user_data); diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index b8cf6b37..6dc49fdf 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -544,9 +544,12 @@ static pj_status_t apply_call_setting(pjsua_call *call, old_opt = call->opt; call->opt = *opt; - /* Reinit media channel when media count is changed */ - if (opt->aud_cnt != old_opt.aud_cnt || - opt->vid_cnt != old_opt.vid_cnt) + /* Reinit media channel when media count is changed or we are the + * answerer (as remote offer may 'extremely' modify the existing + * media session, e.g: media type order). + */ + if (rem_sdp || + opt->aud_cnt!=old_opt.aud_cnt || opt->vid_cnt!=old_opt.vid_cnt) { pjsip_role_e role = rem_sdp? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC; status = pjsua_media_channel_init(call->index, role, @@ -1198,7 +1201,6 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) /* Can't terminate dialog because transaction is in progress. pjsip_dlg_terminate(dlg); */ - pjsua_media_channel_deinit(call->index); goto on_return; } @@ -1317,6 +1319,7 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) status = pjsip_inv_send_msg(inv, response); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send 100 response", status); + pjsua_media_channel_deinit(call->index); goto on_return; } } @@ -3224,6 +3227,9 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv, pjsua_perror(THIS_FILE, "SDP negotiation has failed", status); + /* Clean up provisional media */ + pjsua_media_prov_clean_up(call->index); + /* Do not deinitialize media since this may be a re-INVITE or * UPDATE (which in this case the media should not get affected * by the failed re-INVITE/UPDATE). The media will be shutdown @@ -3427,17 +3433,11 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, call->opt = opt; } - + /* Re-init media for the new remote offer before creating SDP */ - status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, - call->secure_level, - call->inv->pool_prov, - offer, NULL, - PJ_FALSE, NULL); - if (status != PJ_SUCCESS) { - pjsua_perror(THIS_FILE, "Error re-initializing media channel", status); + status = apply_call_setting(call, &call->opt, offer); + if (status != PJ_SUCCESS) goto on_return; - } status = pjsua_media_channel_create_sdp(call->index, call->inv->pool_prov, diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index aeb85ebf..8b6dc46e 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -2770,26 +2770,47 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail) pjmedia_endpt_dump(pjsua_get_pjmedia_endpt()); PJ_LOG(3,(THIS_FILE, "Dumping media transports:")); - // Suppress compile warning caused by unreferenced var. - PJ_UNUSED_ARG(i); -#if DISABLED_FOR_TICKET_1185 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { pjsua_call *call = &pjsua_var.calls[i]; - pjmedia_transport_info tpinfo; - char addr_buf[80]; - - /* MSVC complains about tpinfo not being initialized */ - //pj_bzero(&tpinfo, sizeof(tpinfo)); - - pjmedia_transport_info_init(&tpinfo); - pjmedia_transport_get_info(call->med_tp, &tpinfo); + pjmedia_transport *tp[PJSUA_MAX_CALL_MEDIA*2]; + unsigned tp_cnt = 0; + unsigned j; + + /* Collect media transports in this call */ + for (j = 0; j < call->med_cnt; ++j) { + if (call->media[j].tp != NULL) + tp[tp_cnt++] = call->media[j].tp; + } + for (j = 0; j < call->med_prov_cnt; ++j) { + pjmedia_transport *med_tp = call->media_prov[j].tp; + if (med_tp) { + unsigned k; + pj_bool_t used = PJ_FALSE; + for (k = 0; k < tp_cnt; ++k) { + if (med_tp == tp[k]) { + used = PJ_TRUE; + break; + } + } + if (!used) + tp[tp_cnt++] = med_tp; + } + } - PJ_LOG(3,(THIS_FILE, " %s: %s", - (pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"), - pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name, addr_buf, - sizeof(addr_buf), 3))); + /* Dump the media transports in this call */ + for (j = 0; j < tp_cnt; ++j) { + pjmedia_transport_info tpinfo; + char addr_buf[80]; + + pjmedia_transport_info_init(&tpinfo); + pjmedia_transport_get_info(tp[j], &tpinfo); + PJ_LOG(3,(THIS_FILE, " %s: %s", + (pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"), + pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name, + addr_buf, + sizeof(addr_buf), 3))); + } } -#endif pjsip_tsx_layer_dump(detail); pjsip_ua_dump(detail); diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index db36b236..394ac0b4 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -1145,6 +1145,7 @@ static pj_status_t call_media_init_cb(pjsua_call_media *call_med, /* Always create SRTP adapter */ pjmedia_srtp_setting_default(&srtp_opt); srtp_opt.close_member_tp = PJ_TRUE; + /* If media session has been ever established, let's use remote's * preference in SRTP usage policy, especially when it is stricter. */ @@ -1179,6 +1180,7 @@ static pj_status_t call_media_init_cb(pjsua_call_media *call_med, on_return: if (status != PJ_SUCCESS && call_med->tp) { + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); pjmedia_transport_close(call_med->tp); call_med->tp = NULL; } @@ -1217,7 +1219,14 @@ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, */ call_med->type = type; - /* Create the media transport for initial call. */ + /* Create the media transport for initial call. Here are the possible + * media transport state and the action needed: + * - PJSUA_MED_TP_NULL or call_med->tp==NULL, create one. + * - PJSUA_MED_TP_RUNNING, do nothing. + * - PJSUA_MED_TP_DISABLED, re-init (media_create(), etc). Currently, + * this won't happen as media_channel_update() will always clean up + * the unused transport of a disabled media. + */ if (call_med->tp == NULL) { #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) /* While in initial call, set default video devices */ @@ -1257,7 +1266,9 @@ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, } else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) { /* Media is being reenabled. */ - pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_INIT); + //pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); + + pj_assert(!"Currently no media transport reuse"); } return call_media_init_cb(call_med, status, security_level, @@ -1280,7 +1291,7 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id, /* Set the callback to NULL to indicate that the async operation * has completed. */ - call->media[info->med_idx].med_init_cb = NULL; + call->media_prov[info->med_idx].med_init_cb = NULL; /* In case of failure, save the information to be returned * by the last media transport to finish. @@ -1291,8 +1302,8 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id, /* Check whether all the call's medias have finished calling their * callbacks. */ - for (mi=0; mi < call->med_cnt; ++mi) { - pjsua_call_media *call_med = &call->media[mi]; + for (mi=0; mi < call->med_prov_cnt; ++mi) { + pjsua_call_media *call_med = &call->media_prov[mi]; if (call_med->med_init_cb) { pj_mutex_unlock(call->med_ch_mutex); @@ -1313,13 +1324,13 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id, } if (status != PJ_SUCCESS) { - pjsua_media_channel_deinit(call_id); + pjsua_media_prov_clean_up(call_id); goto on_return; } /* Tell the media transport of a new offer/answer session */ - for (mi=0; mi < call->med_cnt; ++mi) { - pjsua_call_media *call_med = &call->media[mi]; + for (mi=0; mi < call->med_prov_cnt; ++mi) { + pjsua_call_media *call_med = &call->media_prov[mi]; /* Note: tp may be NULL if this media line is disabled */ if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) { @@ -1354,7 +1365,7 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id, call->med_ch_info.med_idx = mi; call->med_ch_info.state = call_med->tp_st; call->med_ch_info.sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; - pjsua_media_channel_deinit(call_id); + pjsua_media_prov_clean_up(call_id); goto on_return; } @@ -1371,6 +1382,43 @@ on_return: return status; } + +/* Clean up media transports in provisional media that is not used + * by call media. + */ +void pjsua_media_prov_clean_up(pjsua_call_id call_id) +{ + pjsua_call *call = &pjsua_var.calls[call_id]; + unsigned i; + + for (i = 0; i < call->med_prov_cnt; ++i) { + pjsua_call_media *call_med = &call->media_prov[i]; + unsigned j; + pj_bool_t used = PJ_FALSE; + + if (call_med->tp == NULL) + continue; + + for (j = 0; j < call->med_cnt; ++j) { + if (call->media[j].tp == call_med->tp) { + used = PJ_TRUE; + break; + } + } + + if (!used) { + if (call_med->tp_st > PJSUA_MED_TP_IDLE) { + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); + pjmedia_transport_media_stop(call_med->tp); + } + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); + pjmedia_transport_close(call_med->tp); + call_med->tp = call_med->tp_orig = NULL; + } + } +} + + pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, pjsip_role_e role, int security_level, @@ -1422,6 +1470,24 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, pj_log_push_indent(); + /* Init provisional media state */ + if (call->med_cnt == 0) { + /* New media session, just copy whole from call media state. */ + pj_memcpy(call->media_prov, call->media, sizeof(call->media)); + } else { + /* Clean up any unused transports. Note that when local SDP reoffer + * is rejected by remote, there may be any initialized transports that + * are not used by call media and currently there is no notification + * from PJSIP level regarding the reoffer rejection. + */ + pjsua_media_prov_clean_up(call_id); + + /* Updating media session, copy from call media state. */ + pj_memcpy(call->media_prov, call->media, + sizeof(call->media[0]) * call->med_cnt); + } + call->med_prov_cnt = call->med_cnt; + #if DISABLED_FOR_TICKET_1185 /* Return error if media transport has not been created yet * (e.g. application is starting) @@ -1441,7 +1507,6 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, if (maudcnt==0) { /* Expecting audio in the offer */ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; - pjsua_media_channel_deinit(call_id); status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); goto on_error; } @@ -1458,8 +1523,9 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, * must never decrease. Also note that we shouldn't apply the media * count setting (of the call setting) before the SDP negotiation. */ - if (call->med_cnt < rem_sdp->media_count) - call->med_cnt = PJ_MIN(rem_sdp->media_count, PJSUA_MAX_CALL_MEDIA); + if (call->med_prov_cnt < rem_sdp->media_count) + call->med_prov_cnt = PJ_MIN(rem_sdp->media_count, + PJSUA_MAX_CALL_MEDIA); call->rem_offerer = PJ_TRUE; call->rem_aud_cnt = maudcnt; @@ -1495,7 +1561,7 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, mtotaudcnt < call->opt.aud_cnt) { for (mi = 0; mi < call->opt.aud_cnt - mtotaudcnt; ++mi) - maudidx[maudcnt++] = (pj_uint8_t)call->med_cnt++; + maudidx[maudcnt++] = (pj_uint8_t)call->med_prov_cnt++; mtotaudcnt = call->opt.aud_cnt; } @@ -1506,7 +1572,7 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, mtotvidcnt < call->opt.vid_cnt) { for (mi = 0; mi < call->opt.vid_cnt - mtotvidcnt; ++mi) - mvididx[mvidcnt++] = (pj_uint8_t)call->med_cnt++; + mvididx[mvidcnt++] = (pj_uint8_t)call->med_prov_cnt++; mtotvidcnt = call->opt.vid_cnt; } @@ -1522,18 +1588,18 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, for (mi=0; mi<mvidcnt; ++mi) { mvididx[mi] = (pj_uint8_t)(maudcnt + mi); } - call->med_cnt = maudcnt + mvidcnt; + call->med_prov_cnt = maudcnt + mvidcnt; /* Need to publish supported media? */ if (call->opt.flag & PJSUA_CALL_INCLUDE_DISABLED_MEDIA) { if (mtotaudcnt == 0) { mtotaudcnt = 1; - maudidx[0] = (pj_uint8_t)call->med_cnt++; + maudidx[0] = (pj_uint8_t)call->med_prov_cnt++; } #if PJMEDIA_HAS_VIDEO if (mtotvidcnt == 0) { mtotvidcnt = 1; - mvididx[0] = (pj_uint8_t)call->med_cnt++; + mvididx[0] = (pj_uint8_t)call->med_prov_cnt++; } #endif } @@ -1542,10 +1608,9 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, call->rem_offerer = PJ_FALSE; } - if (call->med_cnt == 0) { + if (call->med_prov_cnt == 0) { /* Expecting at least one media */ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; - pjsua_media_channel_deinit(call_id); status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); goto on_error; } @@ -1564,8 +1629,8 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, call->async_call.pool_prov = tmp_pool; /* Initialize each media line */ - for (mi=0; mi < call->med_cnt; ++mi) { - pjsua_call_media *call_med = &call->media[mi]; + for (mi=0; mi < call->med_prov_cnt; ++mi) { + pjsua_call_media *call_med = &call->media_prov[mi]; pj_bool_t enabled = PJ_FALSE; pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN; @@ -1609,7 +1674,7 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, return PJ_EPENDING; } - pjsua_media_channel_deinit(call_id); + pjsua_media_prov_clean_up(call_id); goto on_error; } } else { @@ -1618,7 +1683,9 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, */ if (call_med->tp) { // Don't close transport here, as SDP negotiation has not been - // done and stream may be still active. + // done and stream may be still active. Once SDP negotiation + // is done (channel_update() invoked), this transport will be + // closed there. //pjmedia_transport_close(call_med->tp); //call_med->tp = NULL; pj_assert(call_med->tp_st == PJSUA_MED_TP_INIT || @@ -1735,14 +1802,14 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, /* Get one address to use in the origin field */ pj_bzero(&origin, sizeof(origin)); - for (mi=0; mi<call->med_cnt; ++mi) { + for (mi=0; mi<call->med_prov_cnt; ++mi) { pjmedia_transport_info tpinfo; - if (call->media[mi].tp == NULL) + if (call->media_prov[mi].tp == NULL) continue; pjmedia_transport_info_init(&tpinfo); - pjmedia_transport_get_info(call->media[mi].tp, &tpinfo); + pjmedia_transport_get_info(call->media_prov[mi].tp, &tpinfo); pj_sockaddr_cp(&origin, &tpinfo.sock_info.rtp_addr_name); break; } @@ -1754,8 +1821,8 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, return status; /* Process each media line */ - for (mi=0; mi<call->med_cnt; ++mi) { - pjsua_call_media *call_med = &call->media[mi]; + for (mi=0; mi<call->med_prov_cnt; ++mi) { + pjsua_call_media *call_med = &call->media_prov[mi]; pjmedia_sdp_media *m = NULL; pjmedia_transport_info tpinfo; unsigned i; @@ -1998,6 +2065,34 @@ static void stop_media_session(pjsua_call_id call_id) call_id, mi)); call_med->prev_state = call_med->state; call_med->state = PJSUA_CALL_MEDIA_NONE; + + /* Try to sync recent changes to provisional media */ + if (mi<call->med_prov_cnt && call->media_prov[mi].tp==call_med->tp) + { + pjsua_call_media *prov_med = &call->media_prov[mi]; + + /* Media state */ + prov_med->prev_state = call_med->prev_state; + prov_med->state = call_med->state; + + /* RTP seq/ts */ + prov_med->rtp_tx_seq_ts_set = call_med->rtp_tx_seq_ts_set; + prov_med->rtp_tx_seq = call_med->rtp_tx_seq; + prov_med->rtp_tx_ts = call_med->rtp_tx_ts; + + /* Stream */ + if (call_med->type == PJMEDIA_TYPE_AUDIO) { + prov_med->strm.a.conf_slot = call_med->strm.a.conf_slot; + prov_med->strm.a.stream = call_med->strm.a.stream; + } +#if PJMEDIA_HAS_VIDEO + else if (call_med->type == PJMEDIA_TYPE_VIDEO) { + prov_med->strm.v.cap_win_id = call_med->strm.v.cap_win_id; + prov_med->strm.v.rdr_win_id = call_med->strm.v.rdr_win_id; + prov_med->strm.v.stream = call_med->strm.v.stream; + } +#endif + } } pj_log_pop_indent(); @@ -2028,21 +2123,19 @@ pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) stop_media_session(call_id); + /* Clean up media transports */ + pjsua_media_prov_clean_up(call_id); + call->med_prov_cnt = 0; for (mi=0; mi<call->med_cnt; ++mi) { pjsua_call_media *call_med = &call->media[mi]; if (call_med->tp_st > PJSUA_MED_TP_IDLE) { - pjmedia_transport_media_stop(call_med->tp); pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); + pjmedia_transport_media_stop(call_med->tp); } - //if (call_med->tp_orig && call_med->tp && - // call_med->tp != call_med->tp_orig) - //{ - // pjmedia_transport_close(call_med->tp); - // call_med->tp = call_med->tp_orig; - //} if (call_med->tp) { + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); pjmedia_transport_close(call_med->tp); call_med->tp = call_med->tp_orig = NULL; } @@ -2088,7 +2181,7 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, /* Call media count must be at least equal to SDP media. Note that * it may not be equal when remote removed any SDP media line. */ - pj_assert(call->med_cnt >= local_sdp->media_count); + pj_assert(call->med_prov_cnt >= local_sdp->media_count); /* Reset audio_idx first */ call->audio_idx = -1; @@ -2135,8 +2228,8 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, } /* Process each media stream */ - for (mi=0; mi < call->med_cnt; ++mi) { - pjsua_call_media *call_med = &call->media[mi]; + for (mi=0; mi < call->med_prov_cnt; ++mi) { + pjsua_call_media *call_med = &call->media_prov[mi]; if (mi >= local_sdp->media_count || mi >= remote_sdp->media_count) @@ -2287,10 +2380,8 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, /* Check if no media is active */ if (si->dir == PJMEDIA_DIR_NONE) { - /* Call media state */ + /* Update call media state and direction */ call_med->state = PJSUA_CALL_MEDIA_NONE; - - /* Call media direction */ call_med->dir = PJMEDIA_DIR_NONE; } else { @@ -2393,9 +2484,9 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, * (account) setting. */ if (local_sdp->media[mi]->desc.port==0 && call_med->tp) { + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); pjmedia_transport_close(call_med->tp); call_med->tp = call_med->tp_orig = NULL; - pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); } if (status != PJ_SUCCESS) { @@ -2406,6 +2497,11 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, } } + /* Update call media from provisional media */ + call->med_cnt = call->med_prov_cnt; + pj_memcpy(call->media, call->media_prov, + sizeof(call->media_prov[0]) * call->med_prov_cnt); + /* Perform SDP re-negotiation if needed. */ if (got_media && need_renego_sdp) { pjmedia_sdp_neg *neg = call->inv->neg; diff --git a/pjsip/src/pjsua-lib/pjsua_vid.c b/pjsip/src/pjsua-lib/pjsua_vid.c index 5b5f83a2..6e5a83e9 100644 --- a/pjsip/src/pjsua-lib/pjsua_vid.c +++ b/pjsip/src/pjsua-lib/pjsua_vid.c @@ -1532,9 +1532,16 @@ static pj_status_t call_add_video(pjsua_call *call, sdp = pjmedia_sdp_session_clone(call->inv->pool_prov, current_sdp); - /* Initialize call media */ - call_med = &call->media[call->med_cnt++]; + /* Clean up provisional media before using it */ + pjsua_media_prov_clean_up(call->index); + + /* Update provisional media from call media */ + call->med_prov_cnt = call->med_cnt; + pj_memcpy(call->media_prov, call->media, + sizeof(call->media[0]) * call->med_cnt); + /* Initialize call media */ + call_med = &call->media_prov[call->med_prov_cnt++]; status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, &acc_cfg->rtp_cfg, call->secure_level, NULL, PJ_FALSE, NULL); @@ -1597,6 +1604,7 @@ static pj_status_t call_add_video(pjsua_call *call, on_error: if (call_med->tp) { + pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); pjmedia_transport_close(call_med->tp); call_med->tp = call_med->tp_orig = NULL; } @@ -1629,7 +1637,15 @@ static pj_status_t call_modify_video(pjsua_call *call, med_idx = first_active; } - call_med = &call->media[med_idx]; + /* Clean up provisional media before using it */ + pjsua_media_prov_clean_up(call->index); + + /* Update provisional media from call media */ + call->med_prov_cnt = call->med_cnt; + pj_memcpy(call->media_prov, call->media, + sizeof(call->media[0]) * call->med_cnt); + + call_med = &call->media_prov[med_idx]; /* Verify if the stream media type is video */ if (call_med->type != PJMEDIA_TYPE_VIDEO) @@ -1735,6 +1751,7 @@ static pj_status_t call_modify_video(pjsua_call *call, on_error: if (status != PJ_SUCCESS) { + pjsua_media_prov_clean_up(call->index); return status; } |