Index: /pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3635)
+++ /pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3636)
@@ -3317,5 +3317,6 @@
     puts("| vid call tx on|off        Enable/disable video tx for current call          |");
     puts("| vid call add              Add video stream for current call                 |");
-    puts("| vid call remove [idx]     Remove video stream #idx for current call         |");
+    puts("| vid call remove N         Remove video stream #N for current call           |");
+    puts("| vid call modify N CAP     Modify capture dev of video stream #N             |");
     puts("| vid dev list              List all video devices                            |");
     puts("| vid dev refresh           Refresh video device list                         |");
@@ -3757,18 +3758,31 @@
     } else if (strcmp(argv[1], "call")==0) {
 	pjsua_call_vid_strm_op_param param;
-	pj_bool_t tx = (strcmp(argv[2], "tx") == 0);
-	if (tx) {
+
+	if (strcmp(argv[2], "rx")==0) {
 	    pj_bool_t on = (strcmp(argv[3], "on") == 0);
-	}
-
-	if (strcmp(argv[2], "add")==0) {
+	    PJ_TODO(vid_enable_disable_video_RX_on_call);
+	    PJ_LOG(1,(THIS_FILE, "Not implemented"));
+	}
+	else if (strcmp(argv[2], "tx")==0) {
+	    pj_bool_t on = (strcmp(argv[3], "on") == 0);
+	    pjsua_call_vid_strm_op op = on? PJSUA_CALL_VID_STRM_START_TRANSMIT :
+					    PJSUA_CALL_VID_STRM_STOP_TRANSMIT;
+	    pjsua_call_set_vid_strm(current_call, op, NULL);
+	}
+	else if (strcmp(argv[2], "add")==0) {
 	    pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_ADD, NULL);
 	}
-	if (strcmp(argv[2], "remove")==0) {
+	else if (strcmp(argv[2], "disable")==0 || strcmp(argv[2], "enable")==0) {
+	    pj_bool_t enable = (strcmp(argv[2], "enable") == 0);
+	    pjsua_call_vid_strm_op op = enable? PJSUA_CALL_VID_STRM_ENABLE :
+						PJSUA_CALL_VID_STRM_DISABLE;
 	    param.med_idx = argc >= 4? atoi(argv[3]) : -1;
-	    pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_REMOVE, &param);
-	}
-	PJ_TODO(vid_enable_disable_video_on_call);
-	PJ_LOG(1,(THIS_FILE, "Not implemented"));
+	    pjsua_call_set_vid_strm(current_call, op, &param);
+	}
+	else if (strcmp(argv[2], "set-cap-dev")==0) {
+	    param.med_idx = argc >= 4? atoi(argv[3]) : -1;
+	    param.cap_dev = argc >= 5? atoi(argv[4]) : PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
+	    pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV, &param);
+	}
     } else if (strcmp(argv[1], "dev")==0) {
 	if (strcmp(argv[2], "list")==0) {
Index: /pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua.h	(revision 3635)
+++ /pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua.h	(revision 3636)
@@ -382,12 +382,17 @@
 
     /**
-     * Remove an existing video stream.
-     */
-    PJSUA_CALL_VID_STRM_REMOVE,
-
-    /**
-     * Modify an existing video stream, such as changing the capture device.
-     */
-    PJSUA_CALL_VID_STRM_MODIFY,
+     * Disable/remove an existing video stream.
+     */
+    PJSUA_CALL_VID_STRM_DISABLE,
+
+    /**
+     * Enable video stream.
+     */
+    PJSUA_CALL_VID_STRM_ENABLE,
+
+    /**
+     * Changing capture device of a video stream.
+     */
+    PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV,
 
     /**
@@ -425,5 +430,5 @@
      *
      * This field is valid for the following video stream operations:
-     * PJSUA_CALL_VID_STRM_ADD, PJSUA_CALL_VID_STRM_MODIFY, and
+     * PJSUA_CALL_VID_STRM_ADD, PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV, and
      * PJSUA_CALL_VID_STRM_START_TRANSMIT.
      */
Index: /pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_vid.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 3635)
+++ /pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 3636)
@@ -573,5 +573,6 @@
 	    unsigned i, j;
 
-	    status = pjmedia_vid_dev_get_info(acc->cfg.vid_cap_dev, &dev_info);
+	    status = pjmedia_vid_dev_get_info(call_med->strm.v.cap_dev,
+					      &dev_info);
 	    if (status != PJ_SUCCESS)
 		return status;
@@ -740,5 +741,5 @@
     }
 
-    if (acc->cfg.vid_out_auto_transmit) {
+    if (!acc->cfg.vid_out_auto_transmit) {
 	status = pjmedia_vid_stream_pause(call_med->strm.v.stream,
 					  PJMEDIA_DIR_ENCODING);
@@ -1113,5 +1114,4 @@
     pjmedia_sdp_media *sdp_m;
     pjmedia_transport_info tpinfo;
-    pjmedia_vid_dev_info vinfo;
     unsigned active_cnt;
     pj_status_t status;
@@ -1124,14 +1124,4 @@
     if (active_cnt == acc_cfg->max_video_cnt)
 	return PJ_ETOOMANY;
-
-    /* Verify the capture device */
-    status = pjmedia_vid_dev_get_info(cap_dev, &vinfo);
-    if (status != PJ_SUCCESS)
-	return status;
-
-    if (vinfo.dir != PJMEDIA_DIR_CAPTURE)
-	return PJ_EINVAL;
-
-    cap_dev = vinfo.id;
 
     /* Get active local SDP */
@@ -1194,7 +1184,8 @@
 
 
-/* Remove a video stream from a call */
-static pj_status_t call_remove_video(pjsua_call *call,
-				     int med_idx)
+/* Modify a video stream from a call, i.e: enable/disable */
+static pj_status_t call_modify_video(pjsua_call *call,
+				     int med_idx,
+				     pj_bool_t enable)
 {
     pjsua_call_media *call_med;
@@ -1219,12 +1210,8 @@
 	return PJ_EINVAL;
 
-    /* Verify if the stream already disabled */
-    if (call_med->dir != PJMEDIA_DIR_NONE)
+    /* Verify if the stream already enabled/disabled */
+    if (( enable && call_med->dir != PJMEDIA_DIR_NONE) ||
+	(!enable && call_med->dir == PJMEDIA_DIR_NONE))
 	return PJ_SUCCESS;
-
-    /* Mark media transport to disabled */
-    // Don't close this here, as SDP negotiation has not been
-    // done and stream may be still active.
-    call_med->tp_st = PJSUA_MED_TP_DISABLED;
 
     /* Get active local SDP */
@@ -1234,5 +1221,60 @@
 
     pj_assert(med_idx < (int)sdp->media_count);
-    sdp->media[med_idx]->desc.port = 0;
+
+    if (enable) {
+	pjsua_acc_config *acc_cfg = &pjsua_var.acc[call->acc_id].cfg;
+	pj_pool_t *pool = call->inv->pool_prov;
+	pjmedia_sdp_media *sdp_m;
+	pjmedia_transport_info tpinfo;
+
+	status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO,
+				       &acc_cfg->rtp_cfg, call->secure_level,
+				       NULL);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	/* Init transport media */
+	status = pjmedia_transport_media_create(call_med->tp, pool, 0,
+						NULL, call_med->idx);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	call_med->tp_st = PJSUA_MED_TP_INIT;
+
+	/* Get transport address info */
+	pjmedia_transport_info_init(&tpinfo);
+	pjmedia_transport_get_info(call_med->tp, &tpinfo);
+
+	/* Create SDP media line */
+	status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool,
+						&tpinfo.sock_info, 0, &sdp_m);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	sdp->media[med_idx] = sdp_m;
+
+	/* Update SDP media line by media transport */
+	status = pjmedia_transport_encode_sdp(call_med->tp, pool,
+					      sdp, NULL, call_med->idx);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+on_error:
+	if (status != PJ_SUCCESS) {
+	    if (call_med->tp) {
+		pjmedia_transport_close(call_med->tp);
+		call_med->tp = call_med->tp_orig = NULL;
+	    }
+	    return status;
+	}
+    } else {
+	/* Mark media transport to disabled */
+	// Don't close this here, as SDP negotiation has not been
+	// done and stream may be still active.
+	call_med->tp_st = PJSUA_MED_TP_DISABLED;
+
+	/* Disable the stream in SDP by setting port to 0 */
+	sdp->media[med_idx]->desc.port = 0;
+    }
 
     status = call_reoffer_sdp(call->index, sdp);
@@ -1244,8 +1286,8 @@
 
 
-/* Modify a video stream in a call */
-static pj_status_t call_modify_video(pjsua_call *call,
-				     int med_idx,
-				     pjmedia_vid_dev_index cap_dev)
+/* Change capture device of a video stream in a call */
+static pj_status_t call_change_cap_dev(pjsua_call *call,
+				       int med_idx,
+				       pjmedia_vid_dev_index cap_dev)
 {
     pjsua_call_media *call_med;
@@ -1275,11 +1317,6 @@
     /* Verify the capture device */
     status = pjmedia_vid_dev_get_info(cap_dev, &info);
-    if (status != PJ_SUCCESS)
-	return status;
-
-    if (info.dir != PJMEDIA_DIR_CAPTURE)
+    if (status != PJ_SUCCESS || info.dir != PJMEDIA_DIR_CAPTURE)
 	return PJ_EINVAL;
-
-    cap_dev = info.id;
 
     /* The specified capture device is being used already */
@@ -1401,6 +1438,6 @@
     }
 
-    /* Apply the new capture device */
-    status = call_modify_video(call, med_idx, cap_dev);
+    /* Apply the capture device, it may be changed! */
+    status = call_change_cap_dev(call, med_idx, cap_dev);
     if (status != PJ_SUCCESS)
 	return status;
@@ -1479,9 +1516,21 @@
     }
 
-    /* Get real capture ID, if set to PJMEDIA_VID_DEFAULT_CAPTURE_DEV */
+    /* If set to PJMEDIA_VID_DEFAULT_CAPTURE_DEV, replace it with
+     * account default video capture device.
+     */
     if (param_.cap_dev == PJMEDIA_VID_DEFAULT_CAPTURE_DEV) {
-	pjmedia_vid_dev_info info;
-	pjmedia_vid_dev_get_info(param_.cap_dev, &info);
-	param_.cap_dev = info.id;
+	pjsua_acc_config *acc_cfg = &pjsua_var.acc[call->acc_id].cfg;
+	param_.cap_dev = acc_cfg->vid_cap_dev;
+	
+	/* If the account default video capture device is
+	 * PJMEDIA_VID_DEFAULT_CAPTURE_DEV, replace it with
+	 * global default video capture device.
+	 */
+	if (param_.cap_dev == PJMEDIA_VID_DEFAULT_CAPTURE_DEV) {
+	    pjmedia_vid_dev_info info;
+	    pjmedia_vid_dev_get_info(param_.cap_dev, &info);
+	    pj_assert(info.dir == PJMEDIA_DIR_CAPTURE);
+	    param_.cap_dev = info.id;
+	}
     }
 
@@ -1490,9 +1539,12 @@
 	status = call_add_video(call, param_.cap_dev);
 	break;
-    case PJSUA_CALL_VID_STRM_REMOVE:
-	status = call_remove_video(call, param_.med_idx);
+    case PJSUA_CALL_VID_STRM_ENABLE:
+	status = call_modify_video(call, param_.med_idx, PJ_TRUE);
 	break;
-    case PJSUA_CALL_VID_STRM_MODIFY:
-	status = call_modify_video(call, param_.med_idx, param_.cap_dev);
+    case PJSUA_CALL_VID_STRM_DISABLE:
+	status = call_modify_video(call, param_.med_idx, PJ_FALSE);
+	break;
+    case PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV:
+	status = call_change_cap_dev(call, param_.med_idx, param_.cap_dev);
 	break;
     case PJSUA_CALL_VID_STRM_START_TRANSMIT:
