Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3890)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3891)
@@ -135,4 +135,5 @@
 
     struct app_vid	    vid;
+    unsigned		    aud_cnt;
 } app_config;
 
@@ -403,4 +404,5 @@
     cfg->vid.vcapture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
     cfg->vid.vrender_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
+    cfg->aud_cnt = 1;
 }
 
@@ -1456,10 +1458,10 @@
 	    break;
 	case OPT_VIDEO:
-	    app_config.vid.vid_cnt = 1;
-	    app_config.vid.in_auto_show = PJ_TRUE;
-	    app_config.vid.out_auto_transmit = PJ_TRUE;
+	    cfg->vid.vid_cnt = 1;
+	    cfg->vid.in_auto_show = PJ_TRUE;
+	    cfg->vid.out_auto_transmit = PJ_TRUE;
 	    break;
 	case OPT_EXTRA_AUDIO:
-	    ++cur_acc->max_audio_cnt;
+	    cfg->aud_cnt++;
 	    break;
 
@@ -1718,12 +1720,4 @@
     if (acc_cfg->mwi_enabled)
 	pj_strcat2(result, "--mwi\n");
-
-    /* Video & extra audio */
-    for (i=0; i<acc_cfg->max_video_cnt; ++i) {
-	pj_strcat2(result, "--video\n");
-    }
-    for (i=1; i<acc_cfg->max_audio_cnt; ++i) {
-	pj_strcat2(result, "--extra-audio\n");
-    }
 }
 
@@ -1890,4 +1884,12 @@
 
     pj_strcat2(&cfg, "\n#\n# Media settings:\n#\n");
+
+    /* Video & extra audio */
+    for (i=0; i<config->vid.vid_cnt; ++i) {
+	pj_strcat2(&cfg, "--video\n");
+    }
+    for (i=1; i<config->aud_cnt; ++i) {
+	pj_strcat2(&cfg, "--extra-audio\n");
+    }
 
     /* SRTP */
@@ -2576,14 +2578,37 @@
     
     if (app_config.auto_answer > 0) {
-	pjsua_call_answer(call_id, app_config.auto_answer, NULL, NULL);
-    }
-
+	pjsua_call_setting call_opt;
+
+	pjsua_call_setting_default(&call_opt);
+	call_opt.audio_cnt = app_config.aud_cnt;
+	call_opt.video_cnt = app_config.vid.vid_cnt;
+
+	pjsua_call_answer2(call_id, &call_opt, app_config.auto_answer, NULL, NULL);
+    }
+    
     if (app_config.auto_answer < 200) {
+	char notif_st[80] = {0};
+
+#if PJSUA_HAS_VIDEO
+	if (call_info.rem_offerer && call_info.rem_video_cnt) {
+	    snprintf(notif_st, sizeof(notif_st), 
+		     "To %s the video, type \"vid %s\" first, "
+		     "before answering the call!\n",
+		     (app_config.vid.vid_cnt? "reject":"accept"),
+		     (app_config.vid.vid_cnt? "disable":"enable"));
+	}
+#endif
+
 	PJ_LOG(3,(THIS_FILE,
 		  "Incoming call for account %d!\n"
+		  "Media count: %d audio & %d video\n"
+		  "%s"
 		  "From: %s\n"
 		  "To: %s\n"
 		  "Press a to answer or h to reject call",
 		  acc_id,
+		  call_info.rem_audio_cnt,
+		  call_info.rem_video_cnt,
+		  notif_st,
 		  call_info.remote_info.ptr,
 		  call_info.local_info.ptr));
@@ -2847,4 +2872,21 @@
 	pjsua_call_hangup(call_id, 500, &reason, NULL);
     }
+
+#if PJSUA_HAS_VIDEO
+    /* Check if remote has just tried to enable video */
+    if (call_info.rem_offerer && call_info.rem_video_cnt)
+    {
+	int vid_idx;
+
+	/* Check if there is active video */
+	vid_idx = pjsua_call_get_vid_stream_idx(call_id);
+	if (vid_idx == -1 || call_info.media[vid_idx].dir == PJMEDIA_DIR_NONE) {
+	    PJ_LOG(3,(THIS_FILE,
+		      "Just rejected incoming video offer on call %d"
+		      "use \"vid call add\" to enable video!",
+		      call_id));
+	}
+    }
+#endif
 }
 
@@ -3423,10 +3465,12 @@
 {
 #if PJSUA_HAS_VIDEO
+    pj_bool_t vid_enabled = (app_config.vid.vid_cnt > 0);
+
     puts("+=============================================================================+");
     puts("|                            Video commands:                                  |");
     puts("|                                                                             |");
     puts("| vid help                  Show this help screen                             |");
+    puts("| vid enable|disable        Enable or disable video in next offer/answer      |");
     puts("| vid acc show              Show current account video settings               |");
-    puts("| vid acc enable|disable    Enable or disable video on current account        |");
     puts("| vid acc autorx on|off     Automatically show incoming video on/off          |");
     puts("| vid acc autotx on|off     Automatically offer video on/off                  |");
@@ -3436,5 +3480,5 @@
     puts("| vid call tx on|off N      Enable/disable video tx for stream N in curr call |");
     puts("| vid call add              Add video stream for current call                 |");
-    puts("| vid call enable/disable N Enable/disable stream #N in current call          |");
+    puts("| vid call enable|disable N Enable/disable stream #N in current call          |");
     puts("| vid call cap N ID         Set capture dev ID for stream #N in current call  |");
     puts("| vid dev list              List all video devices                            |");
@@ -3448,4 +3492,7 @@
     puts("| vid win move ID X Y       Move window ID to position X,Y                    |");
     puts("| vid win resize ID w h     Resize window ID to the specified width, height   |");
+    puts("+=============================================================================+");
+    printf("| Video will be %s in the next offer/answer %s                            |\n",
+	   (vid_enabled? "enabled" : "disabled"), (vid_enabled? " " : ""));
     puts("+=============================================================================+");
 #endif
@@ -3864,5 +3911,4 @@
 static void app_config_init_video(pjsua_acc_config *acc_cfg)
 {
-    acc_cfg->max_video_cnt = app_config.vid.vid_cnt;
     acc_cfg->vid_in_auto_show = app_config.vid.in_auto_show;
     acc_cfg->vid_out_auto_transmit = app_config.vid.out_auto_transmit;
@@ -3880,5 +3926,4 @@
     PJ_LOG(3,(THIS_FILE,
 	      "Account %d:\n"
-	      "  Video count:      %d\n"
 	      "  RX auto show:     %d\n"
 	      "  TX auto transmit: %d\n"
@@ -3886,5 +3931,4 @@
 	      "  Render dev:       %d",
 	      acc_id,
-	      acc_cfg->max_video_cnt,
 	      acc_cfg->vid_in_auto_show,
 	      acc_cfg->vid_out_auto_transmit,
@@ -3907,4 +3951,11 @@
     if (argc == 1 || strcmp(argv[1], "help")==0) {
 	vid_show_help();
+    } else if (argc == 2 && (strcmp(argv[1], "enable")==0 ||
+			     strcmp(argv[1], "disable")==0))
+    {
+	pj_bool_t enabled = (strcmp(argv[1], "enable")==0);
+	app_config.vid.vid_cnt = (enabled ? 1 : 0);
+	PJ_LOG(3,(THIS_FILE, "Video will be %s in next offer/answer",
+		  (enabled?"enabled":"disabled")));
     } else if (strcmp(argv[1], "acc")==0) {
 	pjsua_acc_config acc_cfg;
@@ -3915,15 +3966,4 @@
 	if (argc == 3 && strcmp(argv[2], "show")==0) {
 	    app_config_show_video(current_acc, &acc_cfg);
-
-	} else if (argc == 3 && (strcmp(argv[2], "enable")==0 ||
-			         strcmp(argv[2], "disable")==0))
-        {
-	    int enabled = (strcmp(argv[2], "enable")==0);
-	    acc_cfg.max_video_cnt = (enabled ? 1 : 0);
-	    if (enabled) {
-		app_config_init_video(&acc_cfg);
-		acc_cfg.max_video_cnt = (enabled ? 1 : 0);
-	    }
-	    changed = PJ_TRUE;
 	} else if (argc == 4 && strcmp(argv[2], "autorx")==0) {
 	    int on = (strcmp(argv[3], "on")==0);
@@ -4166,9 +4206,13 @@
     pjsua_call_info call_info;
     pjsua_acc_info acc_info;
-
+    pjsua_call_setting call_opt;
+
+    pjsua_call_setting_default(&call_opt);
+    call_opt.audio_cnt = app_config.aud_cnt;
+    call_opt.video_cnt = app_config.vid.vid_cnt;
 
     /* If user specifies URI to call, then call the URI */
     if (uri_to_call->slen) {
-	pjsua_call_make_call( current_acc, uri_to_call, 0, NULL, NULL, NULL);
+	pjsua_call_make_call( current_acc, uri_to_call, &call_opt, NULL, NULL, NULL);
     }
 
@@ -4205,4 +4249,9 @@
 	}
 
+	/* Update call setting */
+	pjsua_call_setting_default(&call_opt);
+	call_opt.audio_cnt = app_config.aud_cnt;
+	call_opt.video_cnt = app_config.vid.vid_cnt;
+
 	switch (menuin[0]) {
 
@@ -4234,5 +4283,5 @@
 	    pjsua_msg_data_init(&msg_data);
 	    TEST_MULTIPART(&msg_data);
-	    pjsua_call_make_call( current_acc, &tmp, 0, NULL, &msg_data, NULL);
+	    pjsua_call_make_call( current_acc, &tmp, &call_opt, NULL, &msg_data, NULL);
 	    break;
 
@@ -4266,5 +4315,5 @@
 		pj_status_t status;
 	    
-		status = pjsua_call_make_call(current_acc, &tmp, 0, NULL,
+		status = pjsua_call_make_call(current_acc, &tmp, &call_opt, NULL,
 					      NULL, NULL);
 		if (status != PJ_SUCCESS)
@@ -4403,5 +4452,5 @@
 		}
 
-		pjsua_call_answer(current_call, st_code, NULL, &msg_data);
+		pjsua_call_answer2(current_call, &call_opt, st_code, NULL, &msg_data);
 	    }
 
@@ -4592,5 +4641,6 @@
 		 * re-INVITE
 		 */
-		pjsua_call_reinvite(current_call, PJ_TRUE, NULL);
+		call_opt.flag |= PJSUA_CALL_UNHOLD;
+		pjsua_call_reinvite2(current_call, &call_opt, NULL);
 
 	    } else {
@@ -4605,5 +4655,5 @@
 	    if (current_call != -1) {
 		
-		pjsua_call_update(current_call, 0, NULL);
+		pjsua_call_update2(current_call, &call_opt, NULL);
 
 	    } else {
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 3890)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 3891)
@@ -2698,22 +2698,4 @@
 
     /**
-     * Maximum number of simultaneous active audio streams to be allowed
-     * for calls on this account. Setting this to zero will disable audio
-     * in calls on this account.
-     *
-     * Default: 1
-     */
-    unsigned         max_audio_cnt;
-
-    /**
-     * Maximum number of simultaneous active video streams to be allowed
-     * for calls on this account. Setting this to zero will disable video
-     * in calls on this account, regardless of other video settings.
-     *
-     * Default: 1
-     */
-    unsigned         max_video_cnt;
-
-    /**
      * Specify whether incoming video should be shown to screen by default.
      * This applies to incoming call (INVITE), incoming re-INVITE, and
@@ -3390,4 +3372,35 @@
 
 /**
+ * Call settings.
+ */
+typedef struct pjsua_call_setting
+{
+    /**
+     * Bitmask of pjsua_call_flag constants.
+     *
+     * Default: 0
+     */
+    unsigned	     flag;
+
+    /**
+     * Number of simultaneous active audio streams for this call. Setting
+     * this to zero will disable audio in this call.
+     *
+     * Default: 1
+     */
+    unsigned         audio_cnt;
+
+    /**
+     * Number of simultaneous active video streams for this call. Setting
+     * this to zero will disable video in this call.
+     *
+     * Default: 1 (if video feature is enabled, otherwise it is zero)
+     */
+    unsigned         video_cnt;
+
+} pjsua_call_setting;
+
+
+/**
  * This structure describes the information and current status of a call.
  */
@@ -3417,4 +3430,7 @@
     /** Dialog Call-ID string. */
     pj_str_t		call_id;
+
+    /** Call setting */
+    pjsua_call_setting	setting;
 
     /** Call state */
@@ -3490,4 +3506,13 @@
     /** Total call duration, including set-up time */
     pj_time_val		total_duration;
+
+    /** Flag if remote was SDP offerer */
+    pj_bool_t		rem_offerer;
+
+    /** Number of audio streams offered by remote */
+    unsigned		rem_audio_cnt;
+
+    /** Number of video streams offered by remote */
+    unsigned		rem_video_cnt;
 
     /** Internal */
@@ -3526,5 +3551,12 @@
      * remote peer with the outgoing re-INVITE or UPDATE
      */
-    PJSUA_CALL_UPDATE_CONTACT = 2
+    PJSUA_CALL_UPDATE_CONTACT = 2,
+
+    /**
+     * Include SDP "m=" line with port set to zero for each disabled media
+     * (i.e when aud_cnt or vid_cnt is set to zero). This flag is only valid
+     * for #pjsua_call_make_call().
+     */
+    PJSUA_CALL_INCLUDE_DISABLED_MEDIA = 4
 
 } pjsua_call_flag;
@@ -3579,6 +3611,5 @@
      * the media, regardless of whether existing video is/are present
      * or not.  This will cause re-INVITE or UPDATE to be sent to remote
-     * party. The number of maximum active video streams in a call is
-     * still limited by \a max_video_cnt setting in pjsua_acc_config.
+     * party.
      */
     PJSUA_CALL_VID_STRM_ADD,
@@ -3668,4 +3699,12 @@
 
 /**
+ * Initialize call settings.
+ *
+ * @param opt		The call setting to be initialized.
+ */
+PJ_DECL(void) pjsua_call_setting_default(pjsua_call_setting *opt);
+
+
+/**
  * Initialize video stream operation param with default values.
  *
@@ -3710,5 +3749,6 @@
  * @param dst_uri	URI to be put in the To header (normally is the same
  *			as the target URI).
- * @param options	Options (must be zero at the moment).
+ * @param opt		Optional call setting. This should be initialized
+ *			using #pjsua_call_setting_default().
  * @param user_data	Arbitrary user data to be attached to the call, and
  *			can be retrieved later.
@@ -3721,5 +3761,5 @@
 PJ_DECL(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
 					  const pj_str_t *dst_uri,
-					  unsigned options,
+					  const pjsua_call_setting *opt,
 					  void *user_data,
 					  const pjsua_msg_data *msg_data,
@@ -3863,4 +3903,27 @@
 				       const pjsua_msg_data *msg_data);
 
+
+/**
+ * Send response to incoming INVITE request. Depending on the status
+ * code specified as parameter, this function may send provisional
+ * response, establish the call, or terminate the call.
+ *
+ * @param call_id	Incoming call identification.
+ * @param opt		Optional call setting.
+ * @param code		Status code, (100-699).
+ * @param reason	Optional reason phrase. If NULL, default text
+ *			will be used.
+ * @param msg_data	Optional list of headers etc to be added to outgoing
+ *			response message.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(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);
+
+
 /**
  * Hangup call by using method that is appropriate according to the
@@ -3950,4 +4013,23 @@
 					 const pjsua_msg_data *msg_data);
 
+
+/**
+ * Send re-INVITE to release hold.
+ * The final status of the request itself will be reported on the
+ * \a on_call_media_state() callback, which inform the application that
+ * the media state of the call has changed.
+ *
+ * @param call_id	Call identification.
+ * @param opt		Optional call setting.
+ * @param msg_data	Optional message components to be sent with
+ *			the request.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id,
+					  const pjsua_call_setting *opt,
+					  const pjsua_msg_data *msg_data);
+
+
 /**
  * Send UPDATE request.
@@ -3963,4 +4045,20 @@
 				       unsigned options,
 				       const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send UPDATE request.
+ *
+ * @param call_id	Call identification.
+ * @param opt		Optional call setting.
+ * @param msg_data	Optional message components to be sent with
+ *			the request.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,
+				        const pjsua_call_setting *opt,
+				        const pjsua_msg_data *msg_data);
+
 
 /**
@@ -4107,5 +4205,6 @@
  * Get the media stream index of the default video stream in the call.
  * Typically this will just retrieve the stream index of the first
- * activated video stream in the call.
+ * activated video stream in the call. If none is active, it will return
+ * the first inactive video stream.
  *
  * @param call_id	Call identification.
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 3890)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 3891)
@@ -121,4 +121,5 @@
 {
     unsigned		 index;	    /**< Index in pjsua array.		    */
+    pjsua_call_setting	 opt;	    /**< Call setting.			    */
     pjsip_inv_session	*inv;	    /**< The invite session.		    */
     void		*user_data; /**< User/application data.		    */
@@ -163,5 +164,4 @@
         union {
             struct {
-                unsigned         options; /**< Outgoing call options.       */
                 pjsua_msg_data  *msg_data;/**< Headers for outgoing INVITE. */
             } out_call;
@@ -172,4 +172,10 @@
     } async_call;                      /**< Temporary storage for async
                                             outgoing/incoming call.         */
+
+    pj_bool_t		 rem_offerer;  /**< Was remote SDP offerer?	    */
+    unsigned		 rem_aud_cnt;  /**< No of active audio in last remote
+					    offer.			    */
+    unsigned		 rem_vid_cnt;  /**< No of active video in last remote
+					    offer.			    */
 };
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 3890)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 3891)
@@ -384,12 +384,4 @@
     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));
@@ -674,11 +666,4 @@
     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));
@@ -1064,8 +1049,4 @@
 	}
     }
-
-    /* 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 */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 3890)
+++ 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, 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 3890)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 3891)
@@ -217,5 +217,4 @@
     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;
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3890)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3891)
@@ -1158,5 +1158,6 @@
 		       pjmedia_srtp_use	use_srtp,
 		       pj_uint8_t midx[],
-		       unsigned *p_count)
+		       unsigned *p_count,
+		       unsigned *p_total_count)
 {
     unsigned i;
@@ -1165,6 +1166,8 @@
 
     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;
@@ -1239,8 +1242,9 @@
 	 * 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;
@@ -1589,9 +1593,11 @@
     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;
 
@@ -1615,5 +1621,10 @@
     }
 
-    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();
 
@@ -1630,11 +1641,8 @@
 #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 */
@@ -1647,33 +1655,96 @@
 #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;
-	}
-#else
-	mvidcnt = 0;
-#endif	
-	call->med_cnt = maudcnt + mvidcnt;
+		if (mtotvidcnt == 0) {
+		    mtotvidcnt = 1;
+		    mvididx[0] = (pj_uint8_t)call->med_cnt++;
+		}
+#endif
+	    }
+	}
+
+	call->rem_offerer = PJ_FALSE;
     }
 
@@ -1703,26 +1774,20 @@
 	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;
-		}
-	    }
-	    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 {
-	    enabled = PJ_TRUE;
-	    media_type = media_types[mi];
+	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_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;
+	    }
 	}
 
@@ -1808,4 +1873,10 @@
 }
 
+
+/* 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,
@@ -1825,4 +1896,6 @@
 	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
@@ -1837,22 +1910,4 @@
 		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 */
@@ -1862,4 +1917,5 @@
 	//call->audio_idx = 0;
     }
+#endif
 
 #if 0
@@ -2085,4 +2141,6 @@
 #endif
 
+    call->rem_offerer = (rem_sdp != NULL);
+
     *p_sdp = sdp;
     return PJ_SUCCESS;
@@ -2464,6 +2522,8 @@
     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;
 
@@ -2485,20 +2545,25 @@
     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);
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 3890)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 3891)
@@ -1313,4 +1313,8 @@
     }
 
+    /* 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,
@@ -1541,13 +1545,8 @@
     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;
 
@@ -1617,4 +1616,6 @@
     if (status != PJ_SUCCESS)
 	goto on_error;
+
+    call->opt.video_cnt++;
 
     return PJ_SUCCESS;
@@ -1759,4 +1760,5 @@
 	pjmedia_sdp_media_deactivate(pool, sdp->media[med_idx]);
 
+	call->opt.video_cnt--;
     }
 
