Re #1419, implement media count manipulation per call basis:

- moved the media count setting from account setting to call setting
 - introduced pjsua_call_setting, to be used by pjsua_call_make_call() and some new APIs: pjsua_call_answer2(), pjsua_call_reinvite2(), pjsua_call_update2() 




git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@3891 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Nanang Izzuddin 2011-12-01 09:06:14 +00:00
parent 678c02c7a4
commit debd48ae0b
8 changed files with 561 additions and 173 deletions

View File

@ -134,6 +134,7 @@ static struct app_config
pjmedia_port *ring_port;
struct app_vid vid;
unsigned aud_cnt;
} app_config;
@ -402,6 +403,7 @@ static void default_config(struct app_config *cfg)
cfg->vid.vcapture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
cfg->vid.vrender_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
cfg->aud_cnt = 1;
}
@ -1455,12 +1457,12 @@ static pj_status_t parse_args(int argc, char *argv[],
cfg->udp_cfg.qos_params.dscp_val = 0x18;
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;
case OPT_VCAPTURE_DEV:
@ -1717,14 +1719,6 @@ static void write_account_settings(int acc_index, pj_str_t *result)
/* MWI */
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,6 +1884,14 @@ static int write_settings(const struct app_config *config,
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 */
#if PJMEDIA_HAS_SRTP
if (app_config.cfg.use_srtp != PJSUA_DEFAULT_USE_SRTP) {
@ -2575,16 +2577,39 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
ring_start(call_id);
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));
}
@ -2846,6 +2871,23 @@ static void on_call_media_state(pjsua_call_id call_id)
pj_str_t reason = pj_str("Media failed");
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
}
/*
@ -3422,12 +3464,14 @@ static void keystroke_help(void)
static void vid_show_help(void)
{
#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 |");
puts("| vid acc cap ID Set default capture device for current acc |");
@ -3435,7 +3479,7 @@ static void vid_show_help(void)
puts("| vid call rx on|off N Enable/disable video rx for stream N in curr call |");
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 |");
puts("| vid dev refresh Refresh video device list |");
@ -3448,6 +3492,9 @@ static void vid_show_help(void)
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
}
@ -3863,7 +3910,6 @@ static void vid_list_devs(void)
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;
/* Note that normally GUI application will prefer a borderless
@ -3879,13 +3925,11 @@ static void app_config_show_video(int acc_id, const pjsua_acc_config *acc_cfg)
{
PJ_LOG(3,(THIS_FILE,
"Account %d:\n"
" Video count: %d\n"
" RX auto show: %d\n"
" TX auto transmit: %d\n"
" Capture dev: %d\n"
" Render dev: %d",
acc_id,
acc_cfg->max_video_cnt,
acc_cfg->vid_in_auto_show,
acc_cfg->vid_out_auto_transmit,
acc_cfg->vid_cap_dev,
@ -3906,6 +3950,13 @@ static void vid_handle_menu(char *menuin)
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;
pj_bool_t changed = PJ_FALSE;
@ -3914,17 +3965,6 @@ static void vid_handle_menu(char *menuin)
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);
acc_cfg.vid_in_auto_show = on;
@ -4165,11 +4205,15 @@ void console_app_main(const pj_str_t *uri_to_call)
pjsua_msg_data msg_data;
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);
}
keystroke_help();
@ -4204,6 +4248,11 @@ void console_app_main(const pj_str_t *uri_to_call)
printf("%s", menuin);
}
/* 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]) {
case 'm':
@ -4233,7 +4282,7 @@ void console_app_main(const pj_str_t *uri_to_call)
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;
case 'M':
@ -4265,7 +4314,7 @@ void console_app_main(const pj_str_t *uri_to_call)
for (i=0; i<my_atoi(menuin); ++i) {
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)
break;
@ -4402,7 +4451,7 @@ void console_app_main(const pj_str_t *uri_to_call)
continue;
}
pjsua_call_answer(current_call, st_code, NULL, &msg_data);
pjsua_call_answer2(current_call, &call_opt, st_code, NULL, &msg_data);
}
break;
@ -4591,7 +4640,8 @@ void console_app_main(const pj_str_t *uri_to_call)
/*
* 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 {
PJ_LOG(3,(THIS_FILE, "No current call"));
@ -4604,7 +4654,7 @@ void console_app_main(const pj_str_t *uri_to_call)
*/
if (current_call != -1) {
pjsua_call_update(current_call, 0, NULL);
pjsua_call_update2(current_call, &call_opt, NULL);
} else {
PJ_LOG(3,(THIS_FILE, "No current call"));

View File

@ -2696,24 +2696,6 @@ typedef struct pjsua_acc_config
*/
pj_str_t ka_data;
/**
* 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
@ -3388,6 +3370,37 @@ typedef enum pjsua_call_media_status
} pjsua_call_media_status;
/**
* 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,6 +3430,9 @@ typedef struct pjsua_call_info
/** Dialog Call-ID string. */
pj_str_t call_id;
/** Call setting */
pjsua_call_setting setting;
/** Call state */
pjsip_inv_state state;
@ -3490,6 +3506,15 @@ typedef struct pjsua_call_info
/** 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 */
struct {
char local_info[128];
@ -3525,7 +3550,14 @@ typedef enum pjsua_call_flag
* session with the new Contact and to inform this new Contact to the
* 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;
@ -3578,8 +3610,7 @@ typedef enum pjsua_call_vid_strm_op
* Add a new video stream. This will add a new m=video line to
* 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,
@ -3666,6 +3697,14 @@ typedef struct pjsua_call_vid_strm_op_param
} pjsua_call_vid_strm_op_param;
/**
* 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.
*
@ -3709,7 +3748,8 @@ PJ_DECL(pj_status_t) pjsua_enum_calls(pjsua_call_id ids[],
* @param acc_id The account to be used.
* @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.
* @param msg_data Optional headers etc to be added to outgoing INVITE
@ -3720,7 +3760,7 @@ PJ_DECL(pj_status_t) pjsua_enum_calls(pjsua_call_id ids[],
*/
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,
pjsua_call_id *p_call_id);
@ -3862,6 +3902,29 @@ PJ_DECL(pj_status_t) pjsua_call_answer(pjsua_call_id call_id,
const pj_str_t *reason,
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
* call state. This function is different than answering the call with
@ -3949,6 +4012,25 @@ PJ_DECL(pj_status_t) pjsua_call_reinvite(pjsua_call_id call_id,
unsigned options,
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,6 +4045,22 @@ PJ_DECL(pj_status_t) pjsua_call_update(pjsua_call_id call_id,
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);
/**
* Initiate call transfer to the specified address. This function will send
* REFER request to instruct remote call party to initiate a new INVITE
@ -4106,7 +4204,8 @@ PJ_DECL(pj_status_t) pjsua_call_dump(pjsua_call_id call_id,
/**
* 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.
*

View File

@ -120,6 +120,7 @@ typedef struct call_answer
struct pjsua_call
{
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. */
pjsip_status_code last_code; /**< Last status code seen. */
@ -162,7 +163,6 @@ struct pjsua_call
pj_bool_t med_ch_deinit;/**< Media channel de-init-ed? */
union {
struct {
unsigned options; /**< Outgoing call options. */
pjsua_msg_data *msg_data;/**< Headers for outgoing INVITE. */
} out_call;
struct {
@ -171,6 +171,12 @@ struct pjsua_call
} call_var;
} 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. */
};

View File

@ -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;

View File

@ -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);
@ -486,15 +487,80 @@ 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 &&
@ -1759,6 +1841,19 @@ PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id,
unsigned code,
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;
@ -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.
@ -2015,6 +2117,32 @@ on_return:
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;
@ -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;
@ -2091,6 +2225,32 @@ on_return:
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;
@ -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);

View File

@ -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);

View File

@ -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;
pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN;
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;
}
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) {

View File

@ -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);