- Renamed API pjsua_call_set_vid_out() with pjsua_call_set_vid_strm().
 - Implemented initial version of the function, features covered:
   - add, remove video media stream during the call
   - change which device to use during the call
   - start/stop video stream transmission




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/2.0-dev@3634 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Nanang Izzuddin 2011-07-13 08:51:10 +00:00
parent 06dffff4a7
commit b4d4dade23
5 changed files with 623 additions and 44 deletions

View File

@ -1451,7 +1451,7 @@ static pj_status_t parse_args(int argc, char *argv[],
++cur_acc->max_video_cnt;
cur_acc->vid_in_auto_show = PJ_TRUE;
cur_acc->vid_out_auto_transmit = PJ_TRUE;
PJ_TODO(implement_pjsua_option_for_vid_auto_show_transmit);
PJ_TODO(implement_pjsua_option_for_vid_auto_show_and_transmit);
break;
case OPT_EXTRA_AUDIO:
++cur_acc->max_audio_cnt;
@ -3315,6 +3315,8 @@ static void vid_show_help(void)
puts("| vid help Show this help screen |");
puts("| vid call rx on|off Enable/disable incoming video for current call |");
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 dev list List all video devices |");
puts("| vid dev refresh Refresh video device list |");
puts("| vid dev prev on|off ID Enable/disable preview for specified device ID |");
@ -3753,9 +3755,19 @@ static void vid_handle_menu(char *menuin)
if (strcmp(argv[1], "help")==0 || argc == 1) {
vid_show_help();
} else if (strcmp(argv[1], "call")==0) {
pjsua_call_vid_strm_op_param param;
pj_bool_t tx = (strcmp(argv[2], "tx") == 0);
pj_bool_t on = (strcmp(argv[3], "on") == 0);
if (tx) {
pj_bool_t on = (strcmp(argv[3], "on") == 0);
}
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) {
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"));
} else if (strcmp(argv[1], "dev")==0) {

View File

@ -369,6 +369,69 @@ typedef enum pjsua_state
} pjsua_state;
/**
* This enumeration represents video stream operation on a call.
* See also #pjsua_call_vid_strm_op_param for further info.
*/
typedef enum pjsua_call_vid_strm_op
{
/**
* Add a new video stream.
*/
PJSUA_CALL_VID_STRM_ADD,
/**
* 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,
/**
* Start transmitting video stream.
*/
PJSUA_CALL_VID_STRM_START_TRANSMIT,
/**
* Stop transmitting video stream.
*/
PJSUA_CALL_VID_STRM_STOP_TRANSMIT,
} pjsua_call_vid_strm_op;
/**
* Parameters for video stream operation on a call.
*/
typedef struct pjsua_call_vid_strm_op_param
{
/**
* Specify the media stream index. This can be set to -1 to denote
* the default video stream in the call, which is the first active
* video stream or any first video stream if none is active.
*
* This field is valid for all video stream operations, except
* PJSUA_CALL_VID_STRM_ADD.
*/
int med_idx;
/**
* Specify the video capture device ID. This can be set to
* PJMEDIA_VID_DEFAULT_CAPTURE_DEV to specify the default capture
* device as configured in the account.
*
* 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_START_TRANSMIT.
*/
pjmedia_vid_dev_index cap_dev;
} pjsua_call_vid_strm_op_param;
/**
* Logging configuration, which can be (optionally) specified when calling
* #pjsua_init(). Application must call #pjsua_logging_config_default() to
@ -3680,43 +3743,24 @@ PJ_DECL(pj_status_t) pjsua_call_dump(pjsua_call_id call_id,
*/
PJ_DECL(int) pjsua_call_get_vid_stream_idx(pjsua_call_id call_id);
/**
* Start, stop, and/or manipulate video transmission for the specified
* call. This would trigger a re-INVITE or UPDATE to be sent for the
* call. This function may add, remove, or modify existing video media
* stream, depending on the media index specified (the \a med_idx argument).
*
* To add a new or edit existing video stream (for transmission), specify
* a valid video capture device ID or PJMEDIA_VID_DEFAULT_CAPTURE_DEV in
* the \a cap_dev argument. If \a med_idx is set to default stream (-1),
* then the function will modify existing video stream if one exists, or
* add a new one if it doesn't. If \a med_idx is set to a specific stream
* index, the function will modify that video stream. Otherwise if \a med_idx
* is set to value larger than the current media count, a new video stream
* will be added to the call.
*
* To remove an existing video stream, specify PJMEDIA_VID_INVALID_DEV in
* \a cap_dev argument. If \a med_idx is set to default stream (-1), this
* will remove the default/first video stream in the call, otherwise
* application can put a specific value to request removal of that particular
* video stream.
* Add, remove, modify, and/or manipulate video media stream for the
* specified call. This may trigger a re-INVITE or UPDATE to be sent
* for the call.
*
* @param call_id Call identification.
* @param med_idx The media stream index. Currently the value MUST
* be -1 to denote the default video stream in the
* call.
* @param cap_dev To add or modify existing video media stream,
* specify PJMEDIA_VID_DEFAULT_CAPTURE_DEV to use
* the default capture device as configured in the
* account, or specify a specific capture device ID.
* To disable an existing video stream, specify
* PJMEDIA_VID_INVALID_DEV for this parameter.
* @param op The video stream operation to be performed,
* possible values are #pjsua_call_vid_strm_op.
* @param param The parameters for the video stream operation.
*
* @return PJ_SUCCESS on success or the appropriate error.
*/
PJ_DECL(pj_status_t) pjsua_call_set_vid_out(pjsua_call_id call_id,
int med_idx,
pjmedia_vid_dev_index cap_dev);
PJ_DECL(pj_status_t) pjsua_call_set_vid_strm (
pjsua_call_id call_id,
pjsua_call_vid_strm_op op,
const pjsua_call_vid_strm_op_param *param);
/**
* Get media stream info for the specified media index.

View File

@ -74,6 +74,8 @@ typedef struct pjsua_call_media
pjmedia_vid_stream *stream; /**< The video stream. */
pjsua_vid_win_id cap_win_id;/**< The video capture window */
pjsua_vid_win_id rdr_win_id;/**< The video render window */
pjmedia_vid_dev_index cap_dev; /**< The video capture device */
pjmedia_vid_dev_index rdr_dev; /**< The video-in render device */
} v;
} strm;

View File

@ -1313,11 +1313,11 @@ static void sort_media(const pjmedia_sdp_session *sdp,
}
/* Initialize the media line */
static pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
const pjsua_transport_config *tcfg,
int security_level,
int *sip_err_code)
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
const pjsua_transport_config *tcfg,
int security_level,
int *sip_err_code)
{
pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
pj_status_t status;
@ -1342,6 +1342,22 @@ static pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
}
call_med->tp_st = PJSUA_MED_TP_IDLE;
/* While in initial call, set default video devices */
if (type == PJMEDIA_TYPE_VIDEO) {
call_med->strm.v.rdr_dev = acc->cfg.vid_rend_dev;
call_med->strm.v.cap_dev = acc->cfg.vid_cap_dev;
if (call_med->strm.v.rdr_dev == PJMEDIA_VID_DEFAULT_RENDER_DEV) {
pjmedia_vid_dev_info info;
pjmedia_vid_dev_get_info(call_med->strm.v.rdr_dev, &info);
call_med->strm.v.rdr_dev = info.id;
}
if (call_med->strm.v.cap_dev == PJMEDIA_VID_DEFAULT_CAPTURE_DEV) {
pjmedia_vid_dev_info info;
pjmedia_vid_dev_get_info(call_med->strm.v.cap_dev, &info);
call_med->strm.v.cap_dev = info.id;
}
}
} else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) {
/* Media is being reenabled. */
call_med->tp_st = PJSUA_MED_TP_INIT;

View File

@ -607,7 +607,8 @@ pj_status_t video_channel_update(pjsua_call_media *call_med,
return status;
/* Setup decoding direction */
if (si->dir & PJMEDIA_DIR_DECODING) {
if (si->dir & PJMEDIA_DIR_DECODING)
{
pjsua_vid_win_id wid;
pjsua_vid_win *w;
@ -620,7 +621,8 @@ pj_status_t video_channel_update(pjsua_call_media *call_med,
/* Create stream video window */
status = create_vid_win(PJSUA_WND_TYPE_STREAM,
&media_port->info.fmt,
acc->cfg.vid_rend_dev,
call_med->strm.v.rdr_dev,
//acc->cfg.vid_rend_dev,
PJSUA_INVALID_ID,
acc->cfg.vid_in_auto_show,
&wid);
@ -646,8 +648,7 @@ pj_status_t video_channel_update(pjsua_call_media *call_med,
}
/* Setup encoding direction */
if (si->dir & PJMEDIA_DIR_ENCODING && !call->local_hold &&
acc->cfg.vid_out_auto_transmit)
if (si->dir & PJMEDIA_DIR_ENCODING && !call->local_hold)
{
pjsua_vid_win *w;
pjsua_vid_win_id wid;
@ -661,8 +662,10 @@ pj_status_t video_channel_update(pjsua_call_media *call_med,
/* Create preview video window */
status = create_vid_win(PJSUA_WND_TYPE_PREVIEW,
&media_port->info.fmt,
acc->cfg.vid_rend_dev,
acc->cfg.vid_cap_dev,
call_med->strm.v.rdr_dev,
call_med->strm.v.cap_dev,
//acc->cfg.vid_rend_dev,
//acc->cfg.vid_cap_dev,
PJ_FALSE,
&wid);
if (status != PJ_SUCCESS)
@ -736,6 +739,13 @@ pj_status_t video_channel_update(pjsua_call_media *call_med,
PJ_LOG(4,(THIS_FILE,"Media updates%s", info));
}
if (acc->cfg.vid_out_auto_transmit) {
status = pjmedia_vid_stream_pause(call_med->strm.v.stream,
PJMEDIA_DIR_ENCODING);
if (status != PJ_SUCCESS)
return status;
}
return PJ_SUCCESS;
}
@ -1006,6 +1016,501 @@ PJ_DEF(pj_status_t) pjsua_vid_win_set_size( pjsua_vid_win_id wid,
}
static void call_get_vid_strm_info(pjsua_call *call,
int *first_active,
int *first_inactive,
unsigned *active_cnt,
unsigned *cnt)
{
unsigned i, var_cnt = 0;
if (first_active && ++var_cnt)
*first_active = -1;
if (first_inactive && ++var_cnt)
*first_inactive = -1;
if (active_cnt && ++var_cnt)
*active_cnt = 0;
if (cnt && ++var_cnt)
*cnt = 0;
for (i = 0; i < call->med_cnt && var_cnt; ++i) {
if (call->media[i].type == PJMEDIA_TYPE_VIDEO) {
if (call->media[i].dir != PJMEDIA_DIR_NONE)
{
if (first_active && *first_active == -1) {
*first_active = i;
--var_cnt;
}
if (active_cnt)
++(*active_cnt);
} else if (first_inactive && *first_inactive == -1) {
*first_inactive = i;
--var_cnt;
}
if (cnt)
++(*cnt);
}
}
}
/* Send SDP reoffer. */
static pj_status_t call_reoffer_sdp(pjsua_call_id call_id,
const pjmedia_sdp_session *sdp)
{
pjsua_call *call;
pjsip_tx_data *tdata;
pjsip_dialog *dlg;
pj_status_t status;
status = acquire_call("call_reoffer_sdp()", call_id, &call, &dlg);
if (status != PJ_SUCCESS)
return status;
if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed"));
pjsip_dlg_dec_lock(dlg);
return PJSIP_ESESSIONSTATE;
}
/* Create re-INVITE with new offer */
status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
pjsip_dlg_dec_lock(dlg);
return status;
}
/* Send the request */
status = pjsip_inv_send_msg( call->inv, tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
pjsip_dlg_dec_lock(dlg);
return status;
}
pjsip_dlg_dec_lock(dlg);
return PJ_SUCCESS;
}
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
const pjsua_transport_config *tcfg,
int security_level,
int *sip_err_code);
/* Add a new video stream into a call */
static pj_status_t call_add_video(pjsua_call *call,
pjmedia_vid_dev_index cap_dev)
{
pj_pool_t *pool = call->inv->pool_prov;
pjsua_acc_config *acc_cfg = &pjsua_var.acc[call->acc_id].cfg;
pjsua_call_media *call_med;
pjmedia_sdp_session *sdp;
pjmedia_sdp_media *sdp_m;
pjmedia_transport_info tpinfo;
pjmedia_vid_dev_info vinfo;
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;
/* 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 */
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp);
if (status != PJ_SUCCESS)
return status;
/* Initialize call media */
call_med = &call->media[call->med_cnt++];
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;
/* Override default capture device setting */
call_med->strm.v.cap_dev = cap_dev;
/* 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[sdp->media_count++] = 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;
status = call_reoffer_sdp(call->index, sdp);
if (status != PJ_SUCCESS)
goto on_error;
return PJ_SUCCESS;
on_error:
if (call_med->tp) {
pjmedia_transport_close(call_med->tp);
call_med->tp = call_med->tp_orig = NULL;
}
return status;
}
/* Remove a video stream from a call */
static pj_status_t call_remove_video(pjsua_call *call,
int med_idx)
{
pjsua_call_media *call_med;
pjmedia_sdp_session *sdp;
pj_status_t status;
/* Verify and normalize media index */
if (med_idx == -1) {
int first_active;
call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL);
if (first_active == -1)
return PJ_ENOTFOUND;
med_idx = first_active;
}
call_med = &call->media[med_idx];
/* Verify if the stream media type is video */
if (call_med->type != PJMEDIA_TYPE_VIDEO)
return PJ_EINVAL;
/* Verify if the stream already disabled */
if (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 */
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp);
if (status != PJ_SUCCESS)
return status;
pj_assert(med_idx < (int)sdp->media_count);
sdp->media[med_idx]->desc.port = 0;
status = call_reoffer_sdp(call->index, sdp);
if (status != PJ_SUCCESS)
return status;
return PJ_SUCCESS;
}
/* 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)
{
pjsua_call_media *call_med;
pjmedia_vid_dev_info info;
pjsua_vid_win *w, *new_w = NULL;
pjsua_vid_win_id wid, new_wid;
pjmedia_port *media_port;
pj_status_t status;
/* Verify and normalize media index */
if (med_idx == -1) {
int first_active;
call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL);
if (first_active == -1)
return PJ_ENOTFOUND;
med_idx = first_active;
}
call_med = &call->media[med_idx];
/* Verify if the stream media type is video */
if (call_med->type != PJMEDIA_TYPE_VIDEO)
return PJ_EINVAL;
/* 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)
return PJ_EINVAL;
cap_dev = info.id;
/* The specified capture device is being used already */
if (call_med->strm.v.cap_dev == cap_dev)
return PJ_SUCCESS;
/* == Apply the new capture device == */
wid = call_med->strm.v.cap_win_id;
w = &pjsua_var.win[wid];
pj_assert(w->type == PJSUA_WND_TYPE_PREVIEW && w->vp_cap);
status = pjmedia_vid_stream_get_port(call_med->strm.v.stream,
PJMEDIA_DIR_ENCODING, &media_port);
if (status != PJ_SUCCESS)
return status;
/* = Detach stream port from the old capture device = */
status = pjmedia_vid_port_disconnect(w->vp_cap);
if (status != PJ_SUCCESS)
return status;
status = pjmedia_vid_tee_remove_dst_port(w->tee, media_port);
if (status != PJ_SUCCESS) {
/* Connect back the old capturer */
pjmedia_vid_port_connect(w->vp_cap, media_port, PJ_FALSE);
return status;
}
/* = Attach stream port to the new capture device = */
/* Create preview video window */
status = create_vid_win(PJSUA_WND_TYPE_PREVIEW,
&media_port->info.fmt,
call_med->strm.v.rdr_dev,
cap_dev,
PJ_FALSE,
&new_wid);
if (status != PJ_SUCCESS)
goto on_error;
inc_vid_win(new_wid);
new_w = &pjsua_var.win[new_wid];
/* Connect stream to capturer (via video window tee) */
status = pjmedia_vid_tee_add_dst_port2(new_w->tee, 0, media_port);
if (status != PJ_SUCCESS)
goto on_error;
/* Connect capturer to tee */
status = pjmedia_vid_port_connect(new_w->vp_cap, new_w->tee, PJ_FALSE);
if (status != PJ_SUCCESS)
return status;
/* Start renderer */
status = pjmedia_vid_port_start(new_w->vp_rend);
if (status != PJ_SUCCESS)
goto on_error;
/* Start capturer */
status = pjmedia_vid_port_start(new_w->vp_cap);
if (status != PJ_SUCCESS)
goto on_error;
/* Finally */
call_med->strm.v.cap_dev = cap_dev;
call_med->strm.v.cap_win_id = new_wid;
dec_vid_win(wid);
return PJ_SUCCESS;
on_error:
if (new_w) {
/* Disconnect media port from the new capturer */
pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port);
/* Release the new capturer */
dec_vid_win(new_wid);
}
/* Revert back to the old capturer */
status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port);
if (status != PJ_SUCCESS)
return status;
status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE);
if (status != PJ_SUCCESS)
return status;
return status;
}
/* Start transmitting video stream in a call */
static pj_status_t call_start_tx_video(pjsua_call *call,
int med_idx,
pjmedia_vid_dev_index cap_dev)
{
pjsua_call_media *call_med;
pj_status_t status;
/* Verify and normalize media index */
if (med_idx == -1) {
int first_active;
call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL);
if (first_active == -1)
return PJ_ENOTFOUND;
med_idx = first_active;
}
call_med = &call->media[med_idx];
/* Verify if the stream is transmitting video */
if (call_med->type != PJMEDIA_TYPE_VIDEO ||
(call_med->dir & PJMEDIA_DIR_ENCODING) == 0)
{
return PJ_EINVAL;
}
/* Apply the new capture device */
status = call_modify_video(call, med_idx, cap_dev);
if (status != PJ_SUCCESS)
return status;
/* Start stream in encoding direction */
status = pjmedia_vid_stream_resume(call_med->strm.v.stream,
PJMEDIA_DIR_ENCODING);
if (status != PJ_SUCCESS)
return status;
return PJ_SUCCESS;
}
/* Stop transmitting video stream in a call */
static pj_status_t call_stop_tx_video(pjsua_call *call,
int med_idx)
{
pjsua_call_media *call_med;
pj_status_t status;
/* Verify and normalize media index */
if (med_idx == -1) {
int first_active;
call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL);
if (first_active == -1)
return PJ_ENOTFOUND;
med_idx = first_active;
}
call_med = &call->media[med_idx];
/* Verify if the stream is transmitting video */
if (call_med->type != PJMEDIA_TYPE_VIDEO ||
(call_med->dir & PJMEDIA_DIR_ENCODING) == 0)
{
return PJ_EINVAL;
}
/* Pause stream in encoding direction */
status = pjmedia_vid_stream_pause( call_med->strm.v.stream,
PJMEDIA_DIR_ENCODING);
if (status != PJ_SUCCESS)
return status;
return PJ_SUCCESS;
}
/*
* Start, stop, and/or manipulate video transmission for the specified call.
*/
PJ_DEF(pj_status_t) pjsua_call_set_vid_strm (
pjsua_call_id call_id,
pjsua_call_vid_strm_op op,
const pjsua_call_vid_strm_op_param *param)
{
pjsua_call *call;
pjsua_call_vid_strm_op_param param_;
pj_status_t status;
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
PJ_EINVAL);
PJSUA_LOCK();
call = &pjsua_var.calls[call_id];
if (param) {
param_ = *param;
} else {
param_.med_idx = -1;
param_.cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
}
/* Get real capture ID, if set to PJMEDIA_VID_DEFAULT_CAPTURE_DEV */
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;
}
switch (op) {
case PJSUA_CALL_VID_STRM_ADD:
status = call_add_video(call, param_.cap_dev);
break;
case PJSUA_CALL_VID_STRM_REMOVE:
status = call_remove_video(call, param_.med_idx);
break;
case PJSUA_CALL_VID_STRM_MODIFY:
status = call_modify_video(call, param_.med_idx, param_.cap_dev);
break;
case PJSUA_CALL_VID_STRM_START_TRANSMIT:
status = call_start_tx_video(call, param_.med_idx, param_.cap_dev);
break;
case PJSUA_CALL_VID_STRM_STOP_TRANSMIT:
status = call_stop_tx_video(call, param_.med_idx);
break;
default:
status = PJ_EINVALIDOP;
break;
}
PJSUA_UNLOCK();
return status;
}
#endif /* PJSUA_HAS_VIDEO */