diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2011-12-01 09:06:14 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2011-12-01 09:06:14 +0000 |
commit | fb7ffe37b9ca728f0d3f6bf57b937e114d2f9161 (patch) | |
tree | bf3d2bd71b21ee29d72fd4bb99af186d8b18f064 /pjsip/src | |
parent | 9ad8beaa148c78e04a2aac3c5ad6d85567d31b01 (diff) |
Re #1419, implement media count manipulation per call basis:
- moved the media count setting from account setting to call setting
- introduced pjsua_call_setting, to be used by pjsua_call_make_call() and some new APIs: pjsua_call_answer2(), pjsua_call_reinvite2(), pjsua_call_update2()
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3891 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src')
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_acc.c | 19 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 216 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 1 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 211 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_vid.c | 12 |
5 files changed, 346 insertions, 113 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index 24df6e01..b8f0dd8e 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -383,14 +383,6 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, /* Must have a transport */ PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP); - /* Verify media count */ -#if !defined(PJMEDIA_HAS_VIDEO) || (PJMEDIA_HAS_VIDEO == 0) - /* Enable PJMEDIA_HAS_VIDEO in your config_site.h! */ - PJ_ASSERT_RETURN(cfg->max_video_cnt == 0, PJ_EINVAL); -#endif - PJ_ASSERT_RETURN(cfg->max_audio_cnt + cfg->max_video_cnt <= - PJSUA_MAX_CALL_MEDIA, PJ_ETOOMANY); - PJ_LOG(4,(THIS_FILE, "Adding account: id=%.*s", (int)cfg->id.slen, cfg->id.ptr)); pj_log_push_indent(); @@ -674,13 +666,6 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), PJ_EINVAL); - /* Verify media count */ -#if !defined(PJMEDIA_HAS_VIDEO) || (PJMEDIA_HAS_VIDEO == 0) - PJ_ASSERT_RETURN(cfg->max_video_cnt == 0, PJ_EINVAL); -#endif - PJ_ASSERT_RETURN(cfg->max_audio_cnt + cfg->max_video_cnt <= - PJSUA_MAX_CALL_MEDIA, PJ_ETOOMANY); - PJ_LOG(4,(THIS_FILE, "Modifying accunt %d", acc_id)); pj_log_push_indent(); @@ -1064,10 +1049,6 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, } } - /* Max number of audio and video stream in a call */ - acc->cfg.max_audio_cnt = cfg->max_audio_cnt; - acc->cfg.max_video_cnt = cfg->max_video_cnt; - /* Video settings */ acc->cfg.vid_in_auto_show = cfg->vid_in_auto_show; acc->cfg.vid_out_auto_transmit = cfg->vid_out_auto_transmit; diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 1e337dd6..cec75935 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -116,6 +116,7 @@ static void reset_call(pjsua_call_id id) call_med->idx = i; call_med->tp_auto_del = PJ_TRUE; } + pjsua_call_setting_default(&call->opt); } @@ -341,7 +342,7 @@ on_make_call_med_tp_complete(pjsua_call_id call_id, pjsua_call *call = &pjsua_var.calls[call_id]; pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; pjsip_dialog *dlg = call->async_call.dlg; - unsigned options = call->async_call.call_var.out_call.options; + unsigned options = 0; pjsip_tx_data *tdata; pj_status_t status = (info? info->status: PJ_SUCCESS); @@ -487,14 +488,79 @@ on_error: /* + * Initialize call settings based on account ID. + */ +PJ_DEF(void) pjsua_call_setting_default(pjsua_call_setting *opt) +{ + pj_assert(opt); + + pj_bzero(opt, sizeof(*opt)); + opt->flag = PJSUA_CALL_INCLUDE_DISABLED_MEDIA; + opt->audio_cnt = 1; + +#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) + opt->video_cnt = 1; + //{ + // unsigned i; + // for (i = 0; i < PJ_ARRAY_SIZE(opt->vid_cap_dev); ++i) + // opt->vid_cap_dev[i] = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; + //} +#endif +} + +static pj_status_t apply_call_setting(pjsua_call *call, + const pjsua_call_setting *opt, + const pjmedia_sdp_session *rem_sdp) +{ + pj_assert(call); + + if (!opt) + return PJ_SUCCESS; + +#if !PJMEDIA_HAS_VIDEO + pj_assert(opt->video_cnt == 0); +#endif + + /* If call is established, reinit media channel */ + if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) { + pjsua_call_setting old_opt; + pj_status_t status; + + old_opt = call->opt; + call->opt = *opt; + + /* Reinit media channel when media count is changed */ + if (opt->audio_cnt != old_opt.audio_cnt || + opt->video_cnt != old_opt.video_cnt) + { + pjsip_role_e role = rem_sdp? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC; + status = pjsua_media_channel_init(call->index, role, + call->secure_level, + call->inv->pool_prov, + rem_sdp, NULL, + PJ_FALSE, NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error re-initializing media channel", + status); + return status; + } + } + } else { + call->opt = *opt; + } + + return PJ_SUCCESS; +} + +/* * Make outgoing call to the specified URI using the specified account. */ -PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, - const pj_str_t *dest_uri, - unsigned options, - void *user_data, - const pjsua_msg_data *msg_data, - pjsua_call_id *p_call_id) +PJ_DEF(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id, + const pj_str_t *dest_uri, + const pjsua_call_setting *opt, + void *user_data, + const pjsua_msg_data *msg_data, + pjsua_call_id *p_call_id) { pj_pool_t *tmp_pool = NULL; pjsip_dialog *dlg = NULL; @@ -555,6 +621,13 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, call->acc_id = acc_id; call->call_hold_type = acc->cfg.call_hold_type; + /* Apply call setting */ + status = apply_call_setting(call, opt, NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Failed to apply call setting", status); + goto on_error; + } + /* Create temporary pool */ tmp_pool = pjsua_pool_create("tmpcall10", 512, 256); @@ -622,7 +695,6 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, /* Store variables required for the callback after the async * media transport creation is completed. */ - call->async_call.call_var.out_call.options = options; if (msg_data) { call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone( dlg->pool, msg_data); @@ -1465,6 +1537,9 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, pj_strncpy(&info->call_id, &dlg->call_id->id, sizeof(info->buf_.call_id)); + /* call setting */ + pj_memcpy(&info->setting, &call->opt, sizeof(call->opt)); + /* state, state_text */ info->state = (call->inv? call->inv->state: PJSIP_INV_STATE_DISCONNECTED); info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); @@ -1486,6 +1561,13 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, sizeof(info->buf_.last_status_text)); } + /* Audio & video count offered by remote */ + info->rem_offerer = call->rem_offerer; + if (call->rem_offerer) { + info->rem_audio_cnt = call->rem_aud_cnt; + info->rem_video_cnt = call->rem_vid_cnt; + } + /* Build array of media status and dir */ info->media_cnt = 0; for (mi=0; mi < call->med_cnt && @@ -1760,6 +1842,19 @@ PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, const pj_str_t *reason, const pjsua_msg_data *msg_data) { + return pjsua_call_answer2(call_id, NULL, code, reason, msg_data); +} + + +/* + * Send response to incoming INVITE request. + */ +PJ_DEF(pj_status_t) pjsua_call_answer2(pjsua_call_id call_id, + const pjsua_call_setting *opt, + unsigned code, + const pj_str_t *reason, + const pjsua_msg_data *msg_data) +{ pjsua_call *call; pjsip_dialog *dlg = NULL; pjsip_tx_data *tdata; @@ -1775,6 +1870,13 @@ PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, if (status != PJ_SUCCESS) goto on_return; + /* Apply call setting */ + status = apply_call_setting(call, opt, NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Failed to apply call setting", status); + goto on_return; + } + PJSUA_LOCK(); /* If media transport creation is not yet completed, we will answer * the call in the media transport creation callback instead. @@ -2016,6 +2118,32 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, unsigned options, const pjsua_msg_data *msg_data) { + pjsua_call *call; + pjsip_dialog *dlg = NULL; + pj_status_t status; + + status = acquire_call("pjsua_call_reinvite()", call_id, &call, &dlg); + if (status != PJ_SUCCESS) + goto on_return; + + if (options != call->opt.flag) + call->opt.flag = options; + + status = pjsua_call_reinvite2(call_id, NULL, msg_data); + +on_return: + if (dlg) pjsip_dlg_dec_lock(dlg); + return status; +} + + +/* + * Send re-INVITE (to release hold). + */ +PJ_DEF(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id, + const pjsua_call_setting *opt, + const pjsua_msg_data *msg_data) +{ pjmedia_sdp_session *sdp; pj_str_t *new_contact = NULL; pjsip_tx_data *tdata; @@ -2030,7 +2158,7 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, PJ_LOG(4,(THIS_FILE, "Sending re-INVITE on call %d", call_id)); pj_log_push_indent(); - status = acquire_call("pjsua_call_reinvite()", call_id, &call, &dlg); + status = acquire_call("pjsua_call_reinvite2()", call_id, &call, &dlg); if (status != PJ_SUCCESS) goto on_return; @@ -2040,8 +2168,14 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, goto on_return; } + status = apply_call_setting(call, opt, NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Failed to apply call setting", status); + goto on_return; + } + /* Create SDP */ - if (call->local_hold && (options & PJSUA_CALL_UNHOLD)==0) { + if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) { status = create_sdp_of_call_hold(call, &sdp); } else { status = pjsua_media_channel_create_sdp(call->index, @@ -2055,7 +2189,7 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, goto on_return; } - if ((options & PJSUA_CALL_UPDATE_CONTACT) & + if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) & pjsua_acc_is_valid(call->acc_id)) { new_contact = &pjsua_var.acc[call->acc_id].contact; @@ -2092,6 +2226,32 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id, unsigned options, const pjsua_msg_data *msg_data) { + pjsua_call *call; + pjsip_dialog *dlg = NULL; + pj_status_t status; + + status = acquire_call("pjsua_call_update()", call_id, &call, &dlg); + if (status != PJ_SUCCESS) + goto on_return; + + if (options != call->opt.flag) + call->opt.flag = options; + + status = pjsua_call_update2(call_id, NULL, msg_data); + +on_return: + if (dlg) pjsip_dlg_dec_lock(dlg); + return status; +} + + +/* + * Send UPDATE request. + */ +PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id, + const pjsua_call_setting *opt, + const pjsua_msg_data *msg_data) +{ pjmedia_sdp_session *sdp; pj_str_t *new_contact = NULL; pjsip_tx_data *tdata; @@ -2099,18 +2259,22 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id, pjsip_dialog *dlg = NULL; pj_status_t status; - PJ_UNUSED_ARG(options); - PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id)); pj_log_push_indent(); - status = acquire_call("pjsua_call_update()", call_id, &call, &dlg); + status = acquire_call("pjsua_call_update2()", call_id, &call, &dlg); if (status != PJ_SUCCESS) goto on_return; + status = apply_call_setting(call, opt, NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Failed to apply call setting", status); + goto on_return; + } + /* Create SDP */ status = pjsua_media_channel_create_sdp(call->index, call->inv->pool_prov, @@ -2121,7 +2285,7 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id, goto on_return; } - if ((options & PJSUA_CALL_UPDATE_CONTACT) & + if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) & pjsua_acc_is_valid(call->acc_id)) { new_contact = &pjsua_var.acc[call->acc_id].contact; @@ -3356,6 +3520,7 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, pjsua_call *call; pjmedia_sdp_session *answer; unsigned i; + int vid_idx; pj_status_t status; PJSUA_LOCK(); @@ -3367,6 +3532,27 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, call->index)); pj_log_push_indent(); +#if 0 && PJMEDIA_HAS_VIDEO + /* If current session has no video, let's just stay with no video. + * If application want to enable video, it must send re-INVITE + * with video. + */ + vid_idx = pjsua_call_get_vid_stream_idx(call->index); + if (vid_idx == -1 || call->media[vid_idx].dir == PJMEDIA_DIR_NONE) + call->opt.video_cnt = 0; +#endif + + /* 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); + goto on_return; + } + status = pjsua_media_channel_create_sdp(call->index, call->inv->pool_prov, offer, &answer, NULL); diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 6a80380c..fc47121d 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -216,7 +216,6 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) cfg->timer_setting = pjsua_var.ua_cfg.timer_setting; cfg->ka_interval = 15; cfg->ka_data = pj_str("\r\n"); - cfg->max_audio_cnt = 1; cfg->vid_cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV; pjsua_transport_config_default(&cfg->rtp_cfg); diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 8fe57a11..138f4808 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -1157,15 +1157,18 @@ static void sort_media(const pjmedia_sdp_session *sdp, const pj_str_t *type, pjmedia_srtp_use use_srtp, pj_uint8_t midx[], - unsigned *p_count) + unsigned *p_count, + unsigned *p_total_count) { unsigned i; unsigned count = 0; int score[PJSUA_MAX_CALL_MEDIA]; pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA); + pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA); *p_count = 0; + *p_total_count = 0; for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i) score[i] = 1; @@ -1238,10 +1241,11 @@ static void sort_media(const pjmedia_sdp_session *sdp, /* Don't put media with negative score, that media is unacceptable * for us. */ - if (score[best] >= 0) { - midx[*p_count] = (pj_uint8_t)best; + midx[i] = (pj_uint8_t)best; + if (score[best] >= 0) (*p_count)++; - } + if (score[best] > -22000) + (*p_total_count)++; score[best] = -22000; @@ -1588,11 +1592,13 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); + unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx); pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA]; unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx); - pjmedia_type media_types[PJSUA_MAX_CALL_MEDIA]; + unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx); unsigned mi; pj_bool_t pending_med_tp = PJ_FALSE; + pj_bool_t reinit = PJ_FALSE; pj_status_t status; PJ_UNUSED_ARG(role); @@ -1614,7 +1620,12 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, return status; } - PJ_LOG(4,(THIS_FILE, "Call %d: initializing media..", call_id)); + if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) + reinit = PJ_TRUE; + + PJ_LOG(4,(THIS_FILE, "Call %d: %sinitializing media..", + call_id, (reinit?"re-":"") )); + pj_log_push_indent(); #if DISABLED_FOR_TICKET_1185 @@ -1629,13 +1640,10 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, } #endif + /* Get media count for each media type */ if (rem_sdp) { sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); - // Don't apply media count limitation until SDP negotiation is done. - //if (maudcnt > acc->cfg.max_audio_cnt) - // maudcnt = acc->cfg.max_audio_cnt; - + maudidx, &maudcnt, &mtotaudcnt); if (maudcnt==0) { /* Expecting audio in the offer */ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; @@ -1646,35 +1654,98 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, #if PJMEDIA_HAS_VIDEO sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp, - mvididx, &mvidcnt); - // Don't apply media count limitation until SDP negotiation is done. - //if (mvidcnt > acc->cfg.max_video_cnt) - //mvidcnt = acc->cfg.max_video_cnt; + mvididx, &mvidcnt, &mtotvidcnt); #else - mvidcnt = 0; + mvidcnt = mtotvidcnt = 0; + PJ_UNUSED_ARG(STR_VIDEO); #endif /* Update media count only when remote add any media, this media count - * must never decrease. + * 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); + call->rem_offerer = PJ_TRUE; + call->rem_aud_cnt = maudcnt; + call->rem_vid_cnt = mvidcnt; + } else { - maudcnt = acc->cfg.max_audio_cnt; - for (mi=0; mi<maudcnt; ++mi) { - maudidx[mi] = (pj_uint8_t)mi; - media_types[mi] = PJMEDIA_TYPE_AUDIO; - } + + /* If call already established, calculate media count from current + * local active SDP and call setting. Otherwise, calculate media + * count from the call setting only. + */ + if (reinit) { + pjmedia_sdp_session *sdp; + + status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); + pj_assert(status == PJ_SUCCESS); + + sort_media(sdp, &STR_AUDIO, acc->cfg.use_srtp, + maudidx, &maudcnt, &mtotaudcnt); + pj_assert(maudcnt > 0); + + sort_media(sdp, &STR_VIDEO, acc->cfg.use_srtp, + mvididx, &mvidcnt, &mtotvidcnt); + + /* Call setting may add or remove media. Adding media is done by + * enabling any disabled/port-zeroed media first, then adding new + * media whenever needed. Removing media is done by disabling + * media with the lowest 'quality'. + */ + + /* Check if we need to add new audio */ + if (maudcnt < call->opt.audio_cnt && + mtotaudcnt < call->opt.audio_cnt) + { + for (mi = 0; mi < call->opt.audio_cnt - mtotaudcnt; ++mi) + maudidx[maudcnt++] = (pj_uint8_t)call->med_cnt++; + + mtotaudcnt = call->opt.audio_cnt; + } + maudcnt = call->opt.audio_cnt; + + /* Check if we need to add new video */ + if (mvidcnt < call->opt.video_cnt && + mtotvidcnt < call->opt.video_cnt) + { + for (mi = 0; mi < call->opt.video_cnt - mtotvidcnt; ++mi) + mvididx[mvidcnt++] = (pj_uint8_t)call->med_cnt++; + + mtotvidcnt = call->opt.video_cnt; + } + mvidcnt = call->opt.video_cnt; + + } else { + + maudcnt = mtotaudcnt = call->opt.audio_cnt; + for (mi=0; mi<maudcnt; ++mi) { + maudidx[mi] = (pj_uint8_t)mi; + } + mvidcnt = mtotvidcnt = call->opt.video_cnt; + for (mi=0; mi<mvidcnt; ++mi) { + mvididx[mi] = (pj_uint8_t)(maudcnt + mi); + } + call->med_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++; + } #if PJMEDIA_HAS_VIDEO - mvidcnt = acc->cfg.max_video_cnt; - for (mi=0; mi<mvidcnt; ++mi) { - media_types[maudcnt + mi] = PJMEDIA_TYPE_VIDEO; + if (mtotvidcnt == 0) { + mtotvidcnt = 1; + mvididx[0] = (pj_uint8_t)call->med_cnt++; + } +#endif + } } -#else - mvidcnt = 0; -#endif - call->med_cnt = maudcnt + mvidcnt; + + call->rem_offerer = PJ_FALSE; } if (call->med_cnt == 0) { @@ -1702,28 +1773,22 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, for (mi=0; mi < call->med_cnt; ++mi) { pjsua_call_media *call_med = &call->media[mi]; pj_bool_t enabled = PJ_FALSE; - pjmedia_type media_type = PJMEDIA_TYPE_NONE; - - if (rem_sdp) { - if (mi >= rem_sdp->media_count) { - /* Media has been removed in remote re-offer */ - media_type = call_med->type; - } else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_AUDIO)) { - media_type = PJMEDIA_TYPE_AUDIO; - if (pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) { - enabled = PJ_TRUE; - } + pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN; + + if (pj_memchr(maudidx, mi, mtotaudcnt * sizeof(maudidx[0]))) { + media_type = PJMEDIA_TYPE_AUDIO; + if (call->opt.audio_cnt && + pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) + { + enabled = PJ_TRUE; } - else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_VIDEO)) { - media_type = PJMEDIA_TYPE_VIDEO; - if (pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) { - enabled = PJ_TRUE; - } + } else if (pj_memchr(mvididx, mi, mtotvidcnt * sizeof(mvididx[0]))) { + media_type = PJMEDIA_TYPE_VIDEO; + if (call->opt.video_cnt && + pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) + { + enabled = PJ_TRUE; } - - } else { - enabled = PJ_TRUE; - media_type = media_types[mi]; } if (enabled) { @@ -1807,6 +1872,12 @@ on_error: return status; } + +/* Create SDP based on the current media channel. Note that, this function + * will not modify the media channel, so when receiving new offer or + * updating media count (via call setting), media channel must be reinit'd + * (using pjsua_media_channel_init()) first before calling this function. + */ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, pj_pool_t *pool, const pjmedia_sdp_session *rem_sdp, @@ -1824,6 +1895,8 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, if (pjsua_get_state() != PJSUA_STATE_RUNNING) return PJ_EBUSY; +#if 0 + // This function should not really change the media channel. if (rem_sdp) { /* If this is a re-offer, let's re-initialize media as remote may * add or remove media @@ -1836,24 +1909,6 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, if (status != PJ_SUCCESS) return status; } - -#if 0 - pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; - pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; - unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); - - sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); - - 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); - return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); - } - - call->audio_idx = maudidx[0]; -#endif } else { /* Audio is first in our offer, by convention */ // The audio_idx should not be changed here, as this function may be @@ -1861,6 +1916,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, // can be anywhere. //call->audio_idx = 0; } +#endif #if 0 // Since r3512, old-style hold should have got transport, created by @@ -2084,6 +2140,8 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, } #endif + call->rem_offerer = (rem_sdp != NULL); + *p_sdp = sdp; return PJ_SUCCESS; } @@ -2463,8 +2521,10 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, const pj_str_t STR_VIDEO = { "video", 5 }; pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); + unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx); pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA]; unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx); + unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx); pj_bool_t need_renego_sdp = PJ_FALSE; if (pjsua_get_state() != PJSUA_STATE_RUNNING) @@ -2484,22 +2544,27 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, /* Reset audio_idx first */ call->audio_idx = -1; - /* Apply maximum audio/video count of the account */ + /* Sort audio/video based on "quality" */ sort_media(local_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); + maudidx, &maudcnt, &mtotaudcnt); #if PJMEDIA_HAS_VIDEO sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp, - mvididx, &mvidcnt); + mvididx, &mvidcnt, &mtotvidcnt); #else PJ_UNUSED_ARG(STR_VIDEO); mvidcnt = 0; #endif - if (maudcnt > acc->cfg.max_audio_cnt || mvidcnt > acc->cfg.max_video_cnt) + + /* Applying media count limitation. Note that in generating SDP answer, + * no media count limitation applied, as we didn't know yet which media + * would pass the SDP negotiation. + */ + if (maudcnt > call->opt.audio_cnt || mvidcnt > call->opt.video_cnt) { pjmedia_sdp_session *local_sdp2; - maudcnt = PJ_MIN(maudcnt, acc->cfg.max_audio_cnt); - mvidcnt = PJ_MIN(mvidcnt, acc->cfg.max_video_cnt); + maudcnt = PJ_MIN(maudcnt, call->opt.audio_cnt); + mvidcnt = PJ_MIN(mvidcnt, call->opt.video_cnt); local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp); for (mi=0; mi < local_sdp2->media_count; ++mi) { diff --git a/pjsip/src/pjsua-lib/pjsua_vid.c b/pjsip/src/pjsua-lib/pjsua_vid.c index 38b77f22..81b943e1 100644 --- a/pjsip/src/pjsua-lib/pjsua_vid.c +++ b/pjsip/src/pjsua-lib/pjsua_vid.c @@ -1312,6 +1312,10 @@ PJ_DEF(pj_status_t) pjsua_vid_win_set_show( pjsua_vid_win_id wid, return PJ_EINVAL; } + /* Make sure that renderer gets started before shown up */ + if (show && !pjmedia_vid_port_is_running(w->vp_rend)) + status = pjmedia_vid_port_start(w->vp_rend); + hide = !show; status = pjmedia_vid_dev_stream_set_cap(s, PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, &hide); @@ -1540,17 +1544,12 @@ static pj_status_t call_add_video(pjsua_call *call, pjmedia_sdp_session *sdp; pjmedia_sdp_media *sdp_m; pjmedia_transport_info tpinfo; - unsigned active_cnt; pj_status_t status; /* Verify media slot availability */ if (call->med_cnt == PJSUA_MAX_CALL_MEDIA) return PJ_ETOOMANY; - call_get_vid_strm_info(call, NULL, NULL, &active_cnt, NULL); - if (active_cnt == acc_cfg->max_video_cnt) - return PJ_ETOOMANY; - /* Get active local SDP and clone it */ status = pjmedia_sdp_neg_get_active_local(call->inv->neg, ¤t_sdp); if (status != PJ_SUCCESS) @@ -1617,6 +1616,8 @@ static pj_status_t call_add_video(pjsua_call *call, if (status != PJ_SUCCESS) goto on_error; + call->opt.video_cnt++; + return PJ_SUCCESS; on_error: @@ -1758,6 +1759,7 @@ on_error: /* Deactivate the stream */ pjmedia_sdp_media_deactivate(pool, sdp->media[med_idx]); + call->opt.video_cnt--; } status = call_reoffer_sdp(call->index, sdp); |