Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 3849)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 3891)
@@ -117,4 +117,5 @@
 	call_med->tp_auto_del = PJ_TRUE;
     }
+    pjsua_call_setting_default(&call->opt);
 }
 
@@ -342,5 +343,5 @@
     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);
@@ -488,12 +489,77 @@
 
 /*
+ * 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;
@@ -555,4 +621,11 @@
     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 */
@@ -623,5 +696,4 @@
      * 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(
@@ -1466,4 +1538,7 @@
 	       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);
@@ -1487,4 +1562,11 @@
     }
     
+    /* 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;
@@ -1761,4 +1843,17 @@
 				       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;
@@ -1775,4 +1870,11 @@
     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();
@@ -2017,4 +2119,30 @@
 					 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;
@@ -2031,5 +2159,5 @@
     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;
@@ -2041,6 +2169,12 @@
     }
 
+    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 {
@@ -2056,5 +2190,5 @@
     }
 
-    if ((options & PJSUA_CALL_UPDATE_CONTACT) &
+    if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &
 	    pjsua_acc_is_valid(call->acc_id))
     {
@@ -2091,4 +2225,30 @@
 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)
 {
@@ -2100,6 +2260,4 @@
     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);
@@ -2108,7 +2266,13 @@
     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 */
@@ -2122,5 +2286,5 @@
     }
 
-    if ((options & PJSUA_CALL_UPDATE_CONTACT) &
+    if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &
 	    pjsua_acc_is_valid(call->acc_id))
     {
@@ -3357,4 +3521,5 @@
     pjmedia_sdp_session *answer;
     unsigned i;
+    int vid_idx;
     pj_status_t status;
 
@@ -3367,4 +3532,25 @@
 	      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, 
