add auto-jitterbuffer-msec param and auto-disable the jitterbuffer when briding to another channel who also has a jitterbuffer so both legs will disable during a bridge

This commit is contained in:
Anthony Minessale 2011-01-05 16:25:07 -06:00
parent e06feedd9e
commit 181b543b0c
11 changed files with 104 additions and 13 deletions

View File

@ -337,6 +337,9 @@
A completed transaction is kept around for the duration of T4 in order to catch late responses. A completed transaction is kept around for the duration of T4 in order to catch late responses.
The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. --> The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. -->
<!-- <param name="timer-T4" value="4000" /> --> <!-- <param name="timer-T4" value="4000" /> -->
<!-- Turn on a jitterbuffer for every call -->
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
</settings> </settings>
</profile> </profile>

View File

@ -344,6 +344,7 @@ SWITCH_DECLARE(void) switch_channel_set_cap_value(switch_channel_t *channel, swi
SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap); SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap);
SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap); SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap);
SWITCH_DECLARE(uint32_t) switch_channel_test_cap_partner(switch_channel_t *channel, switch_channel_cap_t cap);
/*! /*!
\brief Set given flag(s) on a given channel's bridge partner \brief Set given flag(s) on a given channel's bridge partner

View File

@ -237,6 +237,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name); SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name);
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session); SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session);
SWITCH_DECLARE(switch_status_t) switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause);
/*! /*!
\brief Set an RTP Flag \brief Set an RTP Flag

View File

@ -1035,6 +1035,8 @@ typedef enum {
CC_MEDIA_ACK = 1, CC_MEDIA_ACK = 1,
CC_BYPASS_MEDIA, CC_BYPASS_MEDIA,
CC_PROXY_MEDIA, CC_PROXY_MEDIA,
CC_JITTERBUFFER,
CC_FS_RTP,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CC_FLAG_MAX CC_FLAG_MAX
} switch_channel_cap_t; } switch_channel_cap_t;

View File

@ -1346,7 +1346,13 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
char *p; char *p;
const char *s; const char *s;
if (!strncasecmp(msg->string_arg, "debug:", 6)) { if (!strcasecmp(msg->string_arg, "pause")) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
goto end;
} else if (!strcasecmp(msg->string_arg, "resume")) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
goto end;
} else if (!strncasecmp(msg->string_arg, "debug:", 6)) {
s = msg->string_arg + 6; s = msg->string_arg + 6;
if (s && !strcmp(s, "off")) { if (s && !strcmp(s, "off")) {
s = NULL; s = NULL;
@ -1426,10 +1432,16 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
{ {
sofia_glue_tech_simplify(tech_pvt); sofia_glue_tech_simplify(tech_pvt);
if (switch_rtp_ready(tech_pvt->rtp_session)) { if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val; const char *val;
int ok = 0; int ok = 0;
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(tech_pvt->channel, CC_FS_RTP)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s PAUSE Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
}
if (sofia_test_flag(tech_pvt, TFLAG_PASS_RFC2833) && switch_channel_test_flag_partner(channel, CF_FS_RTP)) { if (sofia_test_flag(tech_pvt, TFLAG_PASS_RFC2833) && switch_channel_test_flag_partner(channel, CF_FS_RTP)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833); switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833);
@ -1455,6 +1467,12 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_rtp_ready(tech_pvt->rtp_session)) { if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val; const char *val;
int ok = 0; int ok = 0;
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s RESUME Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
}
if (switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833)) { if (switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",

View File

@ -501,6 +501,7 @@ struct sofia_profile {
char *challenge_realm; char *challenge_realm;
char *rtcp_audio_interval_msec; char *rtcp_audio_interval_msec;
char *rtcp_video_interval_msec; char *rtcp_video_interval_msec;
char *jb_msec;
sofia_cid_type_t cid_type; sofia_cid_type_t cid_type;
sofia_dtmf_t dtmf_type; sofia_dtmf_t dtmf_type;
int auto_restart; int auto_restart;
@ -1050,3 +1051,4 @@ void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const
void sofia_glue_check_dtmf_type(private_object_t *tech_pvt); void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str); void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str);
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np); char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np);
void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on);

View File

@ -2351,6 +2351,11 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else { } else {
sofia_clear_pflag(profile, PFLAG_DISABLE_HOLD); sofia_clear_pflag(profile, PFLAG_DISABLE_HOLD);
} }
} else if (!strcasecmp(var, "auto-jitterbuffer-msec")) {
int msec = atoi(val);
if (msec > 19) {
profile->jb_msec = switch_core_strdup(profile->pool, val);
}
} else if (!strcasecmp(var, "sip-trace")) { } else if (!strcasecmp(var, "sip-trace")) {
if (switch_true(val)) { if (switch_true(val)) {
sofia_set_flag(profile, TFLAG_TPORT_LOG); sofia_set_flag(profile, TFLAG_TPORT_LOG);
@ -3089,6 +3094,11 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else { } else {
sofia_clear_pflag(profile, PFLAG_DISABLE_HOLD); sofia_clear_pflag(profile, PFLAG_DISABLE_HOLD);
} }
} else if (!strcasecmp(var, "auto-jitterbuffer-msec")) {
int msec = atoi(val);
if (msec > 19) {
profile->jb_msec = switch_core_strdup(profile->pool, val);
}
} else if (!strcasecmp(var, "dtmf-type")) { } else if (!strcasecmp(var, "dtmf-type")) {
if (!strcasecmp(val, "rfc2833")) { if (!strcasecmp(val, "rfc2833")) {
profile->dtmf_type = DTMF_2833; profile->dtmf_type = DTMF_2833;

View File

@ -832,6 +832,8 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK); switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK);
switch_channel_set_cap(tech_pvt->channel, CC_BYPASS_MEDIA); switch_channel_set_cap(tech_pvt->channel, CC_BYPASS_MEDIA);
switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA); switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
switch_core_session_set_private(session, tech_pvt); switch_core_session_set_private(session, tech_pvt);
@ -3152,8 +3154,8 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
} }
} }
if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) { if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) {
int len = atoi(val); int jb_msec = atoi(val);
int maxlen = 0; int maxlen = 0;
char *p; char *p;
@ -3162,13 +3164,13 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
maxlen = atoi(p); maxlen = atoi(p);
} }
if (len < 20 || len > 10000) { if (jb_msec < 20 || jb_msec > 10000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
"Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", len); "Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec);
} else { } else {
int qlen, maxqlen = 50; int qlen, maxqlen = 50;
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000); qlen = jb_msec / (tech_pvt->read_impl.microseconds_per_packet / 1000);
if (maxlen) { if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000); maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
@ -3178,11 +3180,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
tech_pvt->read_impl.samples_per_packet, tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) { tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", len, qlen); SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
} else { } else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen); SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
} }
} }
@ -6065,6 +6067,19 @@ void sofia_glue_tech_simplify(private_object_t *tech_pvt)
} }
} }
void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on)
{
switch_core_session_message_t *msg;
msg = switch_core_session_alloc(session, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
msg->string_arg = switch_core_session_strdup(session, on ? "pause" : "resume");
msg->from = __FILE__;
switch_core_session_queue_message(session, msg);
}
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl) void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl)
{ {
switch_core_session_message_t *msg; switch_core_session_message_t *msg;

View File

@ -1261,6 +1261,24 @@ SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, swit
return channel->caps[cap] ? 1 : 0; return channel->caps[cap] ? 1 : 0;
} }
SWITCH_DECLARE(uint32_t) switch_channel_test_cap_partner(switch_channel_t *channel, switch_channel_cap_t cap)
{
const char *uuid;
int r = 0;
switch_assert(channel != NULL);
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
switch_core_session_t *session;
if ((session = switch_core_session_locate(uuid))) {
r = switch_channel_test_cap(switch_core_session_get_channel(session), cap);
switch_core_session_rwunlock(session);
}
}
return r;
}
SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel) SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel)
{ {
switch_stream_handle_t stream = { 0 }; switch_stream_handle_t stream = { 0 };

View File

@ -1142,7 +1142,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) || if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) ||
switch_channel_test_flag(peer_channel, CF_RING_READY)) { switch_channel_test_flag(peer_channel, CF_RING_READY)) {
const char *app, *data; const char *app, *data;
switch_channel_set_state(peer_channel, CS_CONSUME_MEDIA); switch_channel_set_state(peer_channel, CS_CONSUME_MEDIA);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {

View File

@ -242,6 +242,7 @@ struct switch_rtp {
switch_time_t send_time; switch_time_t send_time;
switch_byte_t auto_adj_used; switch_byte_t auto_adj_used;
uint8_t pause_jb;
}; };
struct switch_rtcp_senderinfo { struct switch_rtcp_senderinfo {
@ -1640,6 +1641,26 @@ static void jb_callback(stfu_instance_t *i, void *udata)
} }
SWITCH_DECLARE(switch_status_t) switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause)
{
if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
return SWITCH_STATUS_FALSE;
}
if (!!pause == !!rtp_session->pause_jb) {
return SWITCH_STATUS_FALSE;
}
if (rtp_session->pause_jb && !pause) {
stfu_n_reset(rtp_session->jb);
}
rtp_session->pause_jb = pause ? 1 : 0;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session) SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session)
{ {
@ -2174,7 +2195,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
ts = ntohl(rtp_session->recv_msg.header.ts); ts = ntohl(rtp_session->recv_msg.header.ts);
if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) && if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
ts && !rtp_session->jb && ts == rtp_session->last_cng_ts) { ts && !rtp_session->jb && !rtp_session->pause_jb && ts == rtp_session->last_cng_ts) {
/* we already sent this frame..... */ /* we already sent this frame..... */
*bytes = 0; *bytes = 0;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -2204,7 +2225,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
rtp_session->last_read_ts = ts; rtp_session->last_read_ts = ts;
if (rtp_session->jb && rtp_session->recv_msg.header.version == 2 && *bytes) { if (rtp_session->jb && !rtp_session->pause_jb && rtp_session->recv_msg.header.version == 2 && *bytes) {
if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te && if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) { !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
stfu_n_reset(rtp_session->jb); stfu_n_reset(rtp_session->jb);
@ -2217,7 +2238,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
} }
if (rtp_session->jb && !rtp_session->checked_jb) { if (rtp_session->jb && !rtp_session->pause_jb && !rtp_session->checked_jb) {
if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) { if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) {
memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen); memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen);