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. -->
<!-- <param name="timer-T4" value="4000" /> -->
+
+ <!-- Turn on a jitterbuffer for every call -->
+ <!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
</settings>
</profile>
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_partner(switch_channel_t *channel, switch_channel_cap_t cap);
/*!
\brief Set given flag(s) on a given channel's bridge partner
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_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause);
/*!
\brief Set an RTP Flag
CC_MEDIA_ACK = 1,
CC_BYPASS_MEDIA,
CC_PROXY_MEDIA,
+ CC_JITTERBUFFER,
+ CC_FS_RTP,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CC_FLAG_MAX
} switch_channel_cap_t;
char *p;
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;
if (s && !strcmp(s, "off")) {
s = NULL;
{
sofia_glue_tech_simplify(tech_pvt);
-
+
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
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)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833);
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
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)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
char *challenge_realm;
char *rtcp_audio_interval_msec;
char *rtcp_video_interval_msec;
+ char *jb_msec;
sofia_cid_type_t cid_type;
sofia_dtmf_t dtmf_type;
int auto_restart;
void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
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);
+void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on);
} else {
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")) {
if (switch_true(val)) {
sofia_set_flag(profile, TFLAG_TPORT_LOG);
} else {
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")) {
if (!strcasecmp(val, "rfc2833")) {
profile->dtmf_type = DTMF_2833;
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_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);
}
}
- if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) {
- int len = atoi(val);
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) {
+ int jb_msec = atoi(val);
int maxlen = 0;
char *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,
- "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 {
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) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
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);
} else {
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);
}
}
}
}
+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)
{
switch_core_session_message_t *msg;
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_stream_handle_t stream = { 0 };
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)) {
const char *app, *data;
-
+
switch_channel_set_state(peer_channel, CS_CONSUME_MEDIA);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_time_t send_time;
switch_byte_t auto_adj_used;
+ uint8_t pause_jb;
};
struct switch_rtcp_senderinfo {
}
+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)
{
ts = ntohl(rtp_session->recv_msg.header.ts);
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..... */
*bytes = 0;
return SWITCH_STATUS_SUCCESS;
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 &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
stfu_n_reset(rtp_session->jb);
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))) {
memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen);