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:
parent
678c02c7a4
commit
debd48ae0b
|
@ -134,6 +134,7 @@ static struct app_config
|
||||||
pjmedia_port *ring_port;
|
pjmedia_port *ring_port;
|
||||||
|
|
||||||
struct app_vid vid;
|
struct app_vid vid;
|
||||||
|
unsigned aud_cnt;
|
||||||
} app_config;
|
} 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.vcapture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
|
||||||
cfg->vid.vrender_dev = PJMEDIA_VID_DEFAULT_RENDER_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;
|
cfg->udp_cfg.qos_params.dscp_val = 0x18;
|
||||||
break;
|
break;
|
||||||
case OPT_VIDEO:
|
case OPT_VIDEO:
|
||||||
app_config.vid.vid_cnt = 1;
|
cfg->vid.vid_cnt = 1;
|
||||||
app_config.vid.in_auto_show = PJ_TRUE;
|
cfg->vid.in_auto_show = PJ_TRUE;
|
||||||
app_config.vid.out_auto_transmit = PJ_TRUE;
|
cfg->vid.out_auto_transmit = PJ_TRUE;
|
||||||
break;
|
break;
|
||||||
case OPT_EXTRA_AUDIO:
|
case OPT_EXTRA_AUDIO:
|
||||||
++cur_acc->max_audio_cnt;
|
cfg->aud_cnt++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_VCAPTURE_DEV:
|
case OPT_VCAPTURE_DEV:
|
||||||
|
@ -1717,14 +1719,6 @@ static void write_account_settings(int acc_index, pj_str_t *result)
|
||||||
/* MWI */
|
/* MWI */
|
||||||
if (acc_cfg->mwi_enabled)
|
if (acc_cfg->mwi_enabled)
|
||||||
pj_strcat2(result, "--mwi\n");
|
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");
|
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 */
|
/* SRTP */
|
||||||
#if PJMEDIA_HAS_SRTP
|
#if PJMEDIA_HAS_SRTP
|
||||||
if (app_config.cfg.use_srtp != PJSUA_DEFAULT_USE_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);
|
ring_start(call_id);
|
||||||
|
|
||||||
if (app_config.auto_answer > 0) {
|
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) {
|
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,
|
PJ_LOG(3,(THIS_FILE,
|
||||||
"Incoming call for account %d!\n"
|
"Incoming call for account %d!\n"
|
||||||
|
"Media count: %d audio & %d video\n"
|
||||||
|
"%s"
|
||||||
"From: %s\n"
|
"From: %s\n"
|
||||||
"To: %s\n"
|
"To: %s\n"
|
||||||
"Press a to answer or h to reject call",
|
"Press a to answer or h to reject call",
|
||||||
acc_id,
|
acc_id,
|
||||||
|
call_info.rem_audio_cnt,
|
||||||
|
call_info.rem_video_cnt,
|
||||||
|
notif_st,
|
||||||
call_info.remote_info.ptr,
|
call_info.remote_info.ptr,
|
||||||
call_info.local_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");
|
pj_str_t reason = pj_str("Media failed");
|
||||||
pjsua_call_hangup(call_id, 500, &reason, NULL);
|
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)
|
static void vid_show_help(void)
|
||||||
{
|
{
|
||||||
#if PJSUA_HAS_VIDEO
|
#if PJSUA_HAS_VIDEO
|
||||||
|
pj_bool_t vid_enabled = (app_config.vid.vid_cnt > 0);
|
||||||
|
|
||||||
puts("+=============================================================================+");
|
puts("+=============================================================================+");
|
||||||
puts("| Video commands: |");
|
puts("| Video commands: |");
|
||||||
puts("| |");
|
puts("| |");
|
||||||
puts("| vid help Show this help screen |");
|
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 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 autorx on|off Automatically show incoming video on/off |");
|
||||||
puts("| vid acc autotx on|off Automatically offer 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 |");
|
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 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 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 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 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 list List all video devices |");
|
||||||
puts("| vid dev refresh Refresh video device list |");
|
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 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("| vid win resize ID w h Resize window ID to the specified width, height |");
|
||||||
puts("+=============================================================================+");
|
puts("+=============================================================================+");
|
||||||
|
printf("| Video will be %s in the next offer/answer %s |\n",
|
||||||
|
(vid_enabled? "enabled" : "disabled"), (vid_enabled? " " : ""));
|
||||||
|
puts("+=============================================================================+");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3863,7 +3910,6 @@ static void vid_list_devs(void)
|
||||||
|
|
||||||
static void app_config_init_video(pjsua_acc_config *acc_cfg)
|
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_in_auto_show = app_config.vid.in_auto_show;
|
||||||
acc_cfg->vid_out_auto_transmit = app_config.vid.out_auto_transmit;
|
acc_cfg->vid_out_auto_transmit = app_config.vid.out_auto_transmit;
|
||||||
/* Note that normally GUI application will prefer a borderless
|
/* 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,
|
PJ_LOG(3,(THIS_FILE,
|
||||||
"Account %d:\n"
|
"Account %d:\n"
|
||||||
" Video count: %d\n"
|
|
||||||
" RX auto show: %d\n"
|
" RX auto show: %d\n"
|
||||||
" TX auto transmit: %d\n"
|
" TX auto transmit: %d\n"
|
||||||
" Capture dev: %d\n"
|
" Capture dev: %d\n"
|
||||||
" Render dev: %d",
|
" Render dev: %d",
|
||||||
acc_id,
|
acc_id,
|
||||||
acc_cfg->max_video_cnt,
|
|
||||||
acc_cfg->vid_in_auto_show,
|
acc_cfg->vid_in_auto_show,
|
||||||
acc_cfg->vid_out_auto_transmit,
|
acc_cfg->vid_out_auto_transmit,
|
||||||
acc_cfg->vid_cap_dev,
|
acc_cfg->vid_cap_dev,
|
||||||
|
@ -3906,6 +3950,13 @@ static void vid_handle_menu(char *menuin)
|
||||||
|
|
||||||
if (argc == 1 || strcmp(argv[1], "help")==0) {
|
if (argc == 1 || strcmp(argv[1], "help")==0) {
|
||||||
vid_show_help();
|
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) {
|
} else if (strcmp(argv[1], "acc")==0) {
|
||||||
pjsua_acc_config acc_cfg;
|
pjsua_acc_config acc_cfg;
|
||||||
pj_bool_t changed = PJ_FALSE;
|
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) {
|
if (argc == 3 && strcmp(argv[2], "show")==0) {
|
||||||
app_config_show_video(current_acc, &acc_cfg);
|
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) {
|
} else if (argc == 4 && strcmp(argv[2], "autorx")==0) {
|
||||||
int on = (strcmp(argv[3], "on")==0);
|
int on = (strcmp(argv[3], "on")==0);
|
||||||
acc_cfg.vid_in_auto_show = on;
|
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_msg_data msg_data;
|
||||||
pjsua_call_info call_info;
|
pjsua_call_info call_info;
|
||||||
pjsua_acc_info acc_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 user specifies URI to call, then call the URI */
|
||||||
if (uri_to_call->slen) {
|
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();
|
keystroke_help();
|
||||||
|
@ -4204,6 +4248,11 @@ void console_app_main(const pj_str_t *uri_to_call)
|
||||||
printf("%s", menuin);
|
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]) {
|
switch (menuin[0]) {
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
|
@ -4233,7 +4282,7 @@ void console_app_main(const pj_str_t *uri_to_call)
|
||||||
|
|
||||||
pjsua_msg_data_init(&msg_data);
|
pjsua_msg_data_init(&msg_data);
|
||||||
TEST_MULTIPART(&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;
|
break;
|
||||||
|
|
||||||
case 'M':
|
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) {
|
for (i=0; i<my_atoi(menuin); ++i) {
|
||||||
pj_status_t status;
|
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);
|
NULL, NULL);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
@ -4402,7 +4451,7 @@ void console_app_main(const pj_str_t *uri_to_call)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pjsua_call_answer(current_call, st_code, NULL, &msg_data);
|
pjsua_call_answer2(current_call, &call_opt, st_code, NULL, &msg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -4591,7 +4640,8 @@ void console_app_main(const pj_str_t *uri_to_call)
|
||||||
/*
|
/*
|
||||||
* re-INVITE
|
* 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 {
|
} else {
|
||||||
PJ_LOG(3,(THIS_FILE, "No current call"));
|
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) {
|
if (current_call != -1) {
|
||||||
|
|
||||||
pjsua_call_update(current_call, 0, NULL);
|
pjsua_call_update2(current_call, &call_opt, NULL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PJ_LOG(3,(THIS_FILE, "No current call"));
|
PJ_LOG(3,(THIS_FILE, "No current call"));
|
||||||
|
|
|
@ -2696,24 +2696,6 @@ typedef struct pjsua_acc_config
|
||||||
*/
|
*/
|
||||||
pj_str_t ka_data;
|
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.
|
* Specify whether incoming video should be shown to screen by default.
|
||||||
* This applies to incoming call (INVITE), incoming re-INVITE, and
|
* This applies to incoming call (INVITE), incoming re-INVITE, and
|
||||||
|
@ -3388,6 +3370,37 @@ typedef enum pjsua_call_media_status
|
||||||
} 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.
|
* This structure describes the information and current status of a call.
|
||||||
*/
|
*/
|
||||||
|
@ -3417,6 +3430,9 @@ typedef struct pjsua_call_info
|
||||||
/** Dialog Call-ID string. */
|
/** Dialog Call-ID string. */
|
||||||
pj_str_t call_id;
|
pj_str_t call_id;
|
||||||
|
|
||||||
|
/** Call setting */
|
||||||
|
pjsua_call_setting setting;
|
||||||
|
|
||||||
/** Call state */
|
/** Call state */
|
||||||
pjsip_inv_state state;
|
pjsip_inv_state state;
|
||||||
|
|
||||||
|
@ -3490,6 +3506,15 @@ typedef struct pjsua_call_info
|
||||||
/** Total call duration, including set-up time */
|
/** Total call duration, including set-up time */
|
||||||
pj_time_val total_duration;
|
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 */
|
/** Internal */
|
||||||
struct {
|
struct {
|
||||||
char local_info[128];
|
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
|
* session with the new Contact and to inform this new Contact to the
|
||||||
* remote peer with the outgoing re-INVITE or UPDATE
|
* 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;
|
} 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
|
* Add a new video stream. This will add a new m=video line to
|
||||||
* the media, regardless of whether existing video is/are present
|
* the media, regardless of whether existing video is/are present
|
||||||
* or not. This will cause re-INVITE or UPDATE to be sent to remote
|
* 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
|
* party.
|
||||||
* still limited by \a max_video_cnt setting in pjsua_acc_config.
|
|
||||||
*/
|
*/
|
||||||
PJSUA_CALL_VID_STRM_ADD,
|
PJSUA_CALL_VID_STRM_ADD,
|
||||||
|
|
||||||
|
@ -3666,6 +3697,14 @@ typedef struct pjsua_call_vid_strm_op_param
|
||||||
} 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.
|
* 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 acc_id The account to be used.
|
||||||
* @param dst_uri URI to be put in the To header (normally is the same
|
* @param dst_uri URI to be put in the To header (normally is the same
|
||||||
* as the target URI).
|
* 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
|
* @param user_data Arbitrary user data to be attached to the call, and
|
||||||
* can be retrieved later.
|
* can be retrieved later.
|
||||||
* @param msg_data Optional headers etc to be added to outgoing INVITE
|
* @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,
|
PJ_DECL(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
|
||||||
const pj_str_t *dst_uri,
|
const pj_str_t *dst_uri,
|
||||||
unsigned options,
|
const pjsua_call_setting *opt,
|
||||||
void *user_data,
|
void *user_data,
|
||||||
const pjsua_msg_data *msg_data,
|
const pjsua_msg_data *msg_data,
|
||||||
pjsua_call_id *p_call_id);
|
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 pj_str_t *reason,
|
||||||
const pjsua_msg_data *msg_data);
|
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
|
* Hangup call by using method that is appropriate according to the
|
||||||
* call state. This function is different than answering the call with
|
* 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,
|
unsigned options,
|
||||||
const pjsua_msg_data *msg_data);
|
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.
|
* Send UPDATE request.
|
||||||
*
|
*
|
||||||
|
@ -3963,6 +4045,22 @@ PJ_DECL(pj_status_t) pjsua_call_update(pjsua_call_id call_id,
|
||||||
unsigned options,
|
unsigned options,
|
||||||
const pjsua_msg_data *msg_data);
|
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
|
* Initiate call transfer to the specified address. This function will send
|
||||||
* REFER request to instruct remote call party to initiate a new INVITE
|
* 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.
|
* Get the media stream index of the default video stream in the call.
|
||||||
* Typically this will just retrieve the stream index of the first
|
* 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.
|
* @param call_id Call identification.
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,6 +120,7 @@ typedef struct call_answer
|
||||||
struct pjsua_call
|
struct pjsua_call
|
||||||
{
|
{
|
||||||
unsigned index; /**< Index in pjsua array. */
|
unsigned index; /**< Index in pjsua array. */
|
||||||
|
pjsua_call_setting opt; /**< Call setting. */
|
||||||
pjsip_inv_session *inv; /**< The invite session. */
|
pjsip_inv_session *inv; /**< The invite session. */
|
||||||
void *user_data; /**< User/application data. */
|
void *user_data; /**< User/application data. */
|
||||||
pjsip_status_code last_code; /**< Last status code seen. */
|
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? */
|
pj_bool_t med_ch_deinit;/**< Media channel de-init-ed? */
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
unsigned options; /**< Outgoing call options. */
|
|
||||||
pjsua_msg_data *msg_data;/**< Headers for outgoing INVITE. */
|
pjsua_msg_data *msg_data;/**< Headers for outgoing INVITE. */
|
||||||
} out_call;
|
} out_call;
|
||||||
struct {
|
struct {
|
||||||
|
@ -171,6 +171,12 @@ struct pjsua_call
|
||||||
} call_var;
|
} call_var;
|
||||||
} async_call; /**< Temporary storage for async
|
} async_call; /**< Temporary storage for async
|
||||||
outgoing/incoming call. */
|
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. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -383,14 +383,6 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg,
|
||||||
/* Must have a transport */
|
/* Must have a transport */
|
||||||
PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP);
|
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",
|
PJ_LOG(4,(THIS_FILE, "Adding account: id=%.*s",
|
||||||
(int)cfg->id.slen, cfg->id.ptr));
|
(int)cfg->id.slen, cfg->id.ptr));
|
||||||
pj_log_push_indent();
|
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_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),
|
||||||
PJ_EINVAL);
|
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(4,(THIS_FILE, "Modifying accunt %d", acc_id));
|
||||||
pj_log_push_indent();
|
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 */
|
/* Video settings */
|
||||||
acc->cfg.vid_in_auto_show = cfg->vid_in_auto_show;
|
acc->cfg.vid_in_auto_show = cfg->vid_in_auto_show;
|
||||||
acc->cfg.vid_out_auto_transmit = cfg->vid_out_auto_transmit;
|
acc->cfg.vid_out_auto_transmit = cfg->vid_out_auto_transmit;
|
||||||
|
|
|
@ -116,6 +116,7 @@ static void reset_call(pjsua_call_id id)
|
||||||
call_med->idx = i;
|
call_med->idx = i;
|
||||||
call_med->tp_auto_del = PJ_TRUE;
|
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_call *call = &pjsua_var.calls[call_id];
|
||||||
pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
|
pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
|
||||||
pjsip_dialog *dlg = call->async_call.dlg;
|
pjsip_dialog *dlg = call->async_call.dlg;
|
||||||
unsigned options = call->async_call.call_var.out_call.options;
|
unsigned options = 0;
|
||||||
pjsip_tx_data *tdata;
|
pjsip_tx_data *tdata;
|
||||||
pj_status_t status = (info? info->status: PJ_SUCCESS);
|
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.
|
* 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,
|
PJ_DEF(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
|
||||||
const pj_str_t *dest_uri,
|
const pj_str_t *dest_uri,
|
||||||
unsigned options,
|
const pjsua_call_setting *opt,
|
||||||
void *user_data,
|
void *user_data,
|
||||||
const pjsua_msg_data *msg_data,
|
const pjsua_msg_data *msg_data,
|
||||||
pjsua_call_id *p_call_id)
|
pjsua_call_id *p_call_id)
|
||||||
{
|
{
|
||||||
pj_pool_t *tmp_pool = NULL;
|
pj_pool_t *tmp_pool = NULL;
|
||||||
pjsip_dialog *dlg = 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->acc_id = acc_id;
|
||||||
call->call_hold_type = acc->cfg.call_hold_type;
|
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 */
|
/* Create temporary pool */
|
||||||
tmp_pool = pjsua_pool_create("tmpcall10", 512, 256);
|
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
|
/* Store variables required for the callback after the async
|
||||||
* media transport creation is completed.
|
* media transport creation is completed.
|
||||||
*/
|
*/
|
||||||
call->async_call.call_var.out_call.options = options;
|
|
||||||
if (msg_data) {
|
if (msg_data) {
|
||||||
call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone(
|
call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone(
|
||||||
dlg->pool, msg_data);
|
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,
|
pj_strncpy(&info->call_id, &dlg->call_id->id,
|
||||||
sizeof(info->buf_.call_id));
|
sizeof(info->buf_.call_id));
|
||||||
|
|
||||||
|
/* call setting */
|
||||||
|
pj_memcpy(&info->setting, &call->opt, sizeof(call->opt));
|
||||||
|
|
||||||
/* state, state_text */
|
/* state, state_text */
|
||||||
info->state = (call->inv? call->inv->state: PJSIP_INV_STATE_DISCONNECTED);
|
info->state = (call->inv? call->inv->state: PJSIP_INV_STATE_DISCONNECTED);
|
||||||
info->state_text = pj_str((char*)pjsip_inv_state_name(info->state));
|
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));
|
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 */
|
/* Build array of media status and dir */
|
||||||
info->media_cnt = 0;
|
info->media_cnt = 0;
|
||||||
for (mi=0; mi < call->med_cnt &&
|
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,
|
unsigned code,
|
||||||
const pj_str_t *reason,
|
const pj_str_t *reason,
|
||||||
const pjsua_msg_data *msg_data)
|
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;
|
pjsua_call *call;
|
||||||
pjsip_dialog *dlg = NULL;
|
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)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_return;
|
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();
|
PJSUA_LOCK();
|
||||||
/* If media transport creation is not yet completed, we will answer
|
/* If media transport creation is not yet completed, we will answer
|
||||||
* the call in the media transport creation callback instead.
|
* 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,
|
PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
|
||||||
unsigned options,
|
unsigned options,
|
||||||
const pjsua_msg_data *msg_data)
|
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;
|
pjmedia_sdp_session *sdp;
|
||||||
pj_str_t *new_contact = NULL;
|
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(4,(THIS_FILE, "Sending re-INVITE on call %d", call_id));
|
||||||
pj_log_push_indent();
|
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)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_return;
|
goto on_return;
|
||||||
|
|
||||||
|
@ -2040,8 +2168,14 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
|
||||||
goto on_return;
|
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 */
|
/* 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);
|
status = create_sdp_of_call_hold(call, &sdp);
|
||||||
} else {
|
} else {
|
||||||
status = pjsua_media_channel_create_sdp(call->index,
|
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;
|
goto on_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & PJSUA_CALL_UPDATE_CONTACT) &
|
if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &
|
||||||
pjsua_acc_is_valid(call->acc_id))
|
pjsua_acc_is_valid(call->acc_id))
|
||||||
{
|
{
|
||||||
new_contact = &pjsua_var.acc[call->acc_id].contact;
|
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,
|
PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
|
||||||
unsigned options,
|
unsigned options,
|
||||||
const pjsua_msg_data *msg_data)
|
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;
|
pjmedia_sdp_session *sdp;
|
||||||
pj_str_t *new_contact = NULL;
|
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;
|
pjsip_dialog *dlg = NULL;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
PJ_UNUSED_ARG(options);
|
|
||||||
|
|
||||||
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
|
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
|
||||||
PJ_EINVAL);
|
PJ_EINVAL);
|
||||||
|
|
||||||
PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id));
|
PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id));
|
||||||
pj_log_push_indent();
|
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)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_return;
|
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 */
|
/* Create SDP */
|
||||||
status = pjsua_media_channel_create_sdp(call->index,
|
status = pjsua_media_channel_create_sdp(call->index,
|
||||||
call->inv->pool_prov,
|
call->inv->pool_prov,
|
||||||
|
@ -2121,7 +2285,7 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
|
||||||
goto on_return;
|
goto on_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & PJSUA_CALL_UPDATE_CONTACT) &
|
if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &
|
||||||
pjsua_acc_is_valid(call->acc_id))
|
pjsua_acc_is_valid(call->acc_id))
|
||||||
{
|
{
|
||||||
new_contact = &pjsua_var.acc[call->acc_id].contact;
|
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;
|
pjsua_call *call;
|
||||||
pjmedia_sdp_session *answer;
|
pjmedia_sdp_session *answer;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
int vid_idx;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
PJSUA_LOCK();
|
PJSUA_LOCK();
|
||||||
|
@ -3367,6 +3532,27 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
|
||||||
call->index));
|
call->index));
|
||||||
pj_log_push_indent();
|
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,
|
status = pjsua_media_channel_create_sdp(call->index,
|
||||||
call->inv->pool_prov,
|
call->inv->pool_prov,
|
||||||
offer, &answer, NULL);
|
offer, &answer, NULL);
|
||||||
|
|
|
@ -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->timer_setting = pjsua_var.ua_cfg.timer_setting;
|
||||||
cfg->ka_interval = 15;
|
cfg->ka_interval = 15;
|
||||||
cfg->ka_data = pj_str("\r\n");
|
cfg->ka_data = pj_str("\r\n");
|
||||||
cfg->max_audio_cnt = 1;
|
|
||||||
cfg->vid_cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
|
cfg->vid_cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
|
||||||
cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
|
cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
|
||||||
pjsua_transport_config_default(&cfg->rtp_cfg);
|
pjsua_transport_config_default(&cfg->rtp_cfg);
|
||||||
|
|
|
@ -1157,15 +1157,18 @@ static void sort_media(const pjmedia_sdp_session *sdp,
|
||||||
const pj_str_t *type,
|
const pj_str_t *type,
|
||||||
pjmedia_srtp_use use_srtp,
|
pjmedia_srtp_use use_srtp,
|
||||||
pj_uint8_t midx[],
|
pj_uint8_t midx[],
|
||||||
unsigned *p_count)
|
unsigned *p_count,
|
||||||
|
unsigned *p_total_count)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
int score[PJSUA_MAX_CALL_MEDIA];
|
int score[PJSUA_MAX_CALL_MEDIA];
|
||||||
|
|
||||||
pj_assert(*p_count >= 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_count = 0;
|
||||||
|
*p_total_count = 0;
|
||||||
for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i)
|
for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i)
|
||||||
score[i] = 1;
|
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
|
/* Don't put media with negative score, that media is unacceptable
|
||||||
* for us.
|
* for us.
|
||||||
*/
|
*/
|
||||||
if (score[best] >= 0) {
|
midx[i] = (pj_uint8_t)best;
|
||||||
midx[*p_count] = (pj_uint8_t)best;
|
if (score[best] >= 0)
|
||||||
(*p_count)++;
|
(*p_count)++;
|
||||||
}
|
if (score[best] > -22000)
|
||||||
|
(*p_total_count)++;
|
||||||
|
|
||||||
score[best] = -22000;
|
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];
|
pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
|
||||||
pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
|
pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
|
||||||
unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
|
unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
|
||||||
|
unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
|
||||||
pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
|
pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
|
||||||
unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
|
unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
|
||||||
pjmedia_type media_types[PJSUA_MAX_CALL_MEDIA];
|
unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
|
||||||
unsigned mi;
|
unsigned mi;
|
||||||
pj_bool_t pending_med_tp = PJ_FALSE;
|
pj_bool_t pending_med_tp = PJ_FALSE;
|
||||||
|
pj_bool_t reinit = PJ_FALSE;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
PJ_UNUSED_ARG(role);
|
PJ_UNUSED_ARG(role);
|
||||||
|
@ -1614,7 +1620,12 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
|
||||||
return status;
|
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();
|
pj_log_push_indent();
|
||||||
|
|
||||||
#if DISABLED_FOR_TICKET_1185
|
#if DISABLED_FOR_TICKET_1185
|
||||||
|
@ -1629,13 +1640,10 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get media count for each media type */
|
||||||
if (rem_sdp) {
|
if (rem_sdp) {
|
||||||
sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp,
|
sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp,
|
||||||
maudidx, &maudcnt);
|
maudidx, &maudcnt, &mtotaudcnt);
|
||||||
// Don't apply media count limitation until SDP negotiation is done.
|
|
||||||
//if (maudcnt > acc->cfg.max_audio_cnt)
|
|
||||||
// maudcnt = acc->cfg.max_audio_cnt;
|
|
||||||
|
|
||||||
if (maudcnt==0) {
|
if (maudcnt==0) {
|
||||||
/* Expecting audio in the offer */
|
/* Expecting audio in the offer */
|
||||||
if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
|
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
|
#if PJMEDIA_HAS_VIDEO
|
||||||
sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp,
|
sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp,
|
||||||
mvididx, &mvidcnt);
|
mvididx, &mvidcnt, &mtotvidcnt);
|
||||||
// Don't apply media count limitation until SDP negotiation is done.
|
|
||||||
//if (mvidcnt > acc->cfg.max_video_cnt)
|
|
||||||
//mvidcnt = acc->cfg.max_video_cnt;
|
|
||||||
#else
|
#else
|
||||||
mvidcnt = 0;
|
mvidcnt = mtotvidcnt = 0;
|
||||||
|
PJ_UNUSED_ARG(STR_VIDEO);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Update media count only when remote add any media, this media count
|
/* 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)
|
if (call->med_cnt < rem_sdp->media_count)
|
||||||
call->med_cnt = PJ_MIN(rem_sdp->media_count, PJSUA_MAX_CALL_MEDIA);
|
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 {
|
} else {
|
||||||
maudcnt = acc->cfg.max_audio_cnt;
|
|
||||||
for (mi=0; mi<maudcnt; ++mi) {
|
/* If call already established, calculate media count from current
|
||||||
maudidx[mi] = (pj_uint8_t)mi;
|
* local active SDP and call setting. Otherwise, calculate media
|
||||||
media_types[mi] = PJMEDIA_TYPE_AUDIO;
|
* 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
|
#if PJMEDIA_HAS_VIDEO
|
||||||
mvidcnt = acc->cfg.max_video_cnt;
|
if (mtotvidcnt == 0) {
|
||||||
for (mi=0; mi<mvidcnt; ++mi) {
|
mtotvidcnt = 1;
|
||||||
media_types[maudcnt + mi] = PJMEDIA_TYPE_VIDEO;
|
mvididx[0] = (pj_uint8_t)call->med_cnt++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
mvidcnt = 0;
|
call->rem_offerer = PJ_FALSE;
|
||||||
#endif
|
|
||||||
call->med_cnt = maudcnt + mvidcnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call->med_cnt == 0) {
|
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) {
|
for (mi=0; mi < call->med_cnt; ++mi) {
|
||||||
pjsua_call_media *call_med = &call->media[mi];
|
pjsua_call_media *call_med = &call->media[mi];
|
||||||
pj_bool_t enabled = PJ_FALSE;
|
pj_bool_t enabled = PJ_FALSE;
|
||||||
pjmedia_type media_type = PJMEDIA_TYPE_NONE;
|
pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN;
|
||||||
|
|
||||||
if (rem_sdp) {
|
if (pj_memchr(maudidx, mi, mtotaudcnt * sizeof(maudidx[0]))) {
|
||||||
if (mi >= rem_sdp->media_count) {
|
media_type = PJMEDIA_TYPE_AUDIO;
|
||||||
/* Media has been removed in remote re-offer */
|
if (call->opt.audio_cnt &&
|
||||||
media_type = call_med->type;
|
pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0])))
|
||||||
} else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_AUDIO)) {
|
{
|
||||||
media_type = PJMEDIA_TYPE_AUDIO;
|
enabled = PJ_TRUE;
|
||||||
if (pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) {
|
|
||||||
enabled = PJ_TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_VIDEO)) {
|
} else if (pj_memchr(mvididx, mi, mtotvidcnt * sizeof(mvididx[0]))) {
|
||||||
media_type = PJMEDIA_TYPE_VIDEO;
|
media_type = PJMEDIA_TYPE_VIDEO;
|
||||||
if (pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) {
|
if (call->opt.video_cnt &&
|
||||||
enabled = PJ_TRUE;
|
pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0])))
|
||||||
}
|
{
|
||||||
|
enabled = PJ_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
enabled = PJ_TRUE;
|
|
||||||
media_type = media_types[mi];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
@ -1807,6 +1872,12 @@ on_error:
|
||||||
return status;
|
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_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
|
||||||
pj_pool_t *pool,
|
pj_pool_t *pool,
|
||||||
const pjmedia_sdp_session *rem_sdp,
|
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)
|
if (pjsua_get_state() != PJSUA_STATE_RUNNING)
|
||||||
return PJ_EBUSY;
|
return PJ_EBUSY;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// This function should not really change the media channel.
|
||||||
if (rem_sdp) {
|
if (rem_sdp) {
|
||||||
/* If this is a re-offer, let's re-initialize media as remote may
|
/* If this is a re-offer, let's re-initialize media as remote may
|
||||||
* add or remove media
|
* 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)
|
if (status != PJ_SUCCESS)
|
||||||
return status;
|
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 {
|
} else {
|
||||||
/* Audio is first in our offer, by convention */
|
/* Audio is first in our offer, by convention */
|
||||||
// The audio_idx should not be changed here, as this function may be
|
// 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.
|
// can be anywhere.
|
||||||
//call->audio_idx = 0;
|
//call->audio_idx = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Since r3512, old-style hold should have got transport, created by
|
// 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
|
#endif
|
||||||
|
|
||||||
|
call->rem_offerer = (rem_sdp != NULL);
|
||||||
|
|
||||||
*p_sdp = sdp;
|
*p_sdp = sdp;
|
||||||
return PJ_SUCCESS;
|
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 };
|
const pj_str_t STR_VIDEO = { "video", 5 };
|
||||||
pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
|
pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
|
||||||
unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
|
unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
|
||||||
|
unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
|
||||||
pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
|
pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
|
||||||
unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
|
unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
|
||||||
|
unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
|
||||||
pj_bool_t need_renego_sdp = PJ_FALSE;
|
pj_bool_t need_renego_sdp = PJ_FALSE;
|
||||||
|
|
||||||
if (pjsua_get_state() != PJSUA_STATE_RUNNING)
|
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 */
|
/* Reset audio_idx first */
|
||||||
call->audio_idx = -1;
|
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,
|
sort_media(local_sdp, &STR_AUDIO, acc->cfg.use_srtp,
|
||||||
maudidx, &maudcnt);
|
maudidx, &maudcnt, &mtotaudcnt);
|
||||||
#if PJMEDIA_HAS_VIDEO
|
#if PJMEDIA_HAS_VIDEO
|
||||||
sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp,
|
sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp,
|
||||||
mvididx, &mvidcnt);
|
mvididx, &mvidcnt, &mtotvidcnt);
|
||||||
#else
|
#else
|
||||||
PJ_UNUSED_ARG(STR_VIDEO);
|
PJ_UNUSED_ARG(STR_VIDEO);
|
||||||
mvidcnt = 0;
|
mvidcnt = 0;
|
||||||
#endif
|
#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;
|
pjmedia_sdp_session *local_sdp2;
|
||||||
|
|
||||||
maudcnt = PJ_MIN(maudcnt, acc->cfg.max_audio_cnt);
|
maudcnt = PJ_MIN(maudcnt, call->opt.audio_cnt);
|
||||||
mvidcnt = PJ_MIN(mvidcnt, acc->cfg.max_video_cnt);
|
mvidcnt = PJ_MIN(mvidcnt, call->opt.video_cnt);
|
||||||
local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp);
|
local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp);
|
||||||
|
|
||||||
for (mi=0; mi < local_sdp2->media_count; ++mi) {
|
for (mi=0; mi < local_sdp2->media_count; ++mi) {
|
||||||
|
|
|
@ -1312,6 +1312,10 @@ PJ_DEF(pj_status_t) pjsua_vid_win_set_show( pjsua_vid_win_id wid,
|
||||||
return PJ_EINVAL;
|
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;
|
hide = !show;
|
||||||
status = pjmedia_vid_dev_stream_set_cap(s,
|
status = pjmedia_vid_dev_stream_set_cap(s,
|
||||||
PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, &hide);
|
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_session *sdp;
|
||||||
pjmedia_sdp_media *sdp_m;
|
pjmedia_sdp_media *sdp_m;
|
||||||
pjmedia_transport_info tpinfo;
|
pjmedia_transport_info tpinfo;
|
||||||
unsigned active_cnt;
|
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
/* Verify media slot availability */
|
/* Verify media slot availability */
|
||||||
if (call->med_cnt == PJSUA_MAX_CALL_MEDIA)
|
if (call->med_cnt == PJSUA_MAX_CALL_MEDIA)
|
||||||
return PJ_ETOOMANY;
|
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 */
|
/* Get active local SDP and clone it */
|
||||||
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, ¤t_sdp);
|
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, ¤t_sdp);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
|
@ -1617,6 +1616,8 @@ static pj_status_t call_add_video(pjsua_call *call,
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
|
call->opt.video_cnt++;
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
return PJ_SUCCESS;
|
||||||
|
|
||||||
on_error:
|
on_error:
|
||||||
|
@ -1758,6 +1759,7 @@ on_error:
|
||||||
/* Deactivate the stream */
|
/* Deactivate the stream */
|
||||||
pjmedia_sdp_media_deactivate(pool, sdp->media[med_idx]);
|
pjmedia_sdp_media_deactivate(pool, sdp->media[med_idx]);
|
||||||
|
|
||||||
|
call->opt.video_cnt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = call_reoffer_sdp(call->index, sdp);
|
status = call_reoffer_sdp(call->index, sdp);
|
||||||
|
|
Loading…
Reference in New Issue