summaryrefslogtreecommitdiff
path: root/pjsip/src
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_acc.c19
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c216
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c1
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c211
-rw-r--r--pjsip/src/pjsua-lib/pjsua_vid.c12
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, &current_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);