]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add auto-jitterbuffer-msec param and auto-disable the jitterbuffer when briding to...
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 5 Jan 2011 22:25:07 +0000 (16:25 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 5 Jan 2011 22:25:14 +0000 (16:25 -0600)
conf/sip_profiles/internal.xml
src/include/switch_channel.h
src/include/switch_rtp.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_channel.c
src/switch_ivr_bridge.c
src/switch_rtp.c

index 3e756a85c0f962c32e2bc895deb2a773dce22e1b..d09ca79dcef127531c0e13373f0ad3ece6cdcf26 100644 (file)
                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>
index ee9b397d2ae72b7f57ceb925f6e8feb52be8970d..368b8950e43d2217a24327d461a1e427522bbd60 100644 (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(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
index a161d2ac0e121049ddfcb599ee77d142176f5b82..27dacc7c18c76aa513e3c5ecc545b3d4971e6659 100644 (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_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
index d3aacca634b0bbfa783cdf4a61fe3ffdb078abf5..98ac80430816f6b5ea3fed87f7c5c225eab781fc 100644 (file)
@@ -1035,6 +1035,8 @@ typedef enum {
        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;
index f7ce6fac76d2c1de39ca1255f948364bb0a041dd..a0bcdbdbd1da56c6322fd20ee1cc66b1872e1003 100644 (file)
@@ -1346,7 +1346,13 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                        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;
@@ -1426,10 +1432,16 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                {
 
                        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);
@@ -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)) {
                        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",
index e1b1ff71e3c9630b9bfbc026e60cfcbe02d3b09c..df267967fa20053c04e888b6c77554f97ae60bf5 100644 (file)
@@ -501,6 +501,7 @@ struct sofia_profile {
        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;
@@ -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_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);
index 61ede0c5c4e21cfab0dd8c08122bb34877e0b133..99c18cbaaa95b045dc1e8db838299aa1663d5b45 100644 (file)
@@ -2351,6 +2351,11 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
                                                } 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);
@@ -3089,6 +3094,11 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                                } 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;
index f4ec094b9ea77fe34b05a3267839a445883732f1..6b8521b10e57b977dab5184d817436f62f68dbce 100644 (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_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);
 
@@ -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"))) {
-                       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;
 
@@ -3162,13 +3164,13 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                                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);
@@ -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_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);
                                }
                                
                        }
@@ -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)
 {
        switch_core_session_message_t *msg;
index e5d30ee5d5846877b14d26d93b39186ed7b8e984..672c47d38b6485683bcb993f9e888a79a57fd632 100644 (file)
@@ -1261,6 +1261,24 @@ SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, swit
        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 };
index 7448125788b8dc599595e7c55e7cad49edd68ab8..6f84de389301a78f9276d7ec73e6f9448384803e 100644 (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) ||
                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) {
index 73c2f45009a601efaf7a88cf7a3ea60c629b6b35..41d5fc98dd0b17e340a8b794071de1b308b5e39a 100644 (file)
@@ -242,6 +242,7 @@ struct switch_rtp {
 
        switch_time_t send_time;
        switch_byte_t auto_adj_used;
+       uint8_t pause_jb;
 };
 
 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)
 {
        
@@ -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);
        
        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;
@@ -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;
 
-       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);
@@ -2217,7 +2238,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
                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);