]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add a fixed jitterbuffer to rtp (settable from a channel variable) (libSTFU)
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 4 May 2007 23:29:35 +0000 (23:29 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 4 May 2007 23:29:35 +0000 (23:29 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5090 d0543943-73ff-0310-b7d9-9358b9ac24b2

Makefile.am
conf/default_context.xml
libs/stfu/stfu.c
src/include/switch_rtp.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_rtp.c

index a672871d5ef040edad2033aea19dab6a9625c6f9..ef9a2ef712efe78f0d8172c2ba146603bbe38bc2 100644 (file)
@@ -57,6 +57,7 @@ src/switch_ivr.c \
 src/switch_stun.c\
 src/switch_log.c\
 src/switch_xml.c\
+libs/stfu/stfu.c\
 libs/libteletone/src/libteletone_detect.c\
 libs/libteletone/src/libteletone_generate.c
 
@@ -95,6 +96,7 @@ libs/libteletone/src/libteletone.h
 
 CORE_CFLAGS     = `$(switch_srcdir)/libs/apr/apr-1-config --cflags --cppflags --includes`
 CORE_CFLAGS    += `$(switch_srcdir)/libs/apr-util/apu-1-config --includes`
+CORE_CFLAGS    += -I$(switch_srcdir)/libs/stfu
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/sqlite
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/pcre
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/srtp/include
index 047d2c363747b4875570ff9663224b0ba396254c..7b8b2688a5985bf51efa40bd729c9ee3e7749a0b 100644 (file)
@@ -53,6 +53,7 @@
       <!-- Request a certain tone/file to be played while you wait for the call to be answered-->
       <action application="set" data="ringback=${us-ring}"/>
       <!--<action application="set" data="ringback=/home/ring.wav"/>-->
+      <!--<action application="set" data="jitterbuffer_msec=400"/>-->
       <action application="bridge" data="sofia/$${sip_profile}/1234@conference.freeswitch.org"/>
     </condition>
   </extension>
index 326fabb9854daa7ad6f4f88308030026509ec320..08683a99fa73edf0af9fe2d3ee386a752e84025c 100644 (file)
@@ -163,7 +163,6 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, void *data, size_
                cplen = sizeof(frame->data);
        }
 
-
        memcpy(frame->data, data, cplen);
        frame->ts = ts;
        frame->dlen = cplen;
@@ -185,7 +184,9 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
 
        if (i->running) {
                should_have = i->last_ts + i->interval;
-       } 
+       } else {
+               should_have = i->out_queue->array[0].ts;
+       }
 
        for(index = 0; index < i->out_queue->array_len; index++) {
                if (i->out_queue->array[index].was_read) {
@@ -220,11 +221,12 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
 
                        i->miss_count++;
 
-                       if (i->miss_count > 10) {
+                       if (i->miss_count > 10 || i->in_queue->array_len == i->in_queue->array_size ) {
                                i->out_queue->wr_len = i->out_queue->array_len;
                                i->last_ts = should_have = frame->ts;
                                return NULL;
                        }
+
                        i->last_ts = should_have;
                        rframe = &i->out_queue->int_frame;
                        rframe->dlen = i->out_queue->array[i->out_queue->last_index].dlen;
@@ -248,6 +250,7 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
                i->last_ts = rframe->ts;
                rframe->was_read = 1;
                i->running = 1;
+               i->miss_count = 0;
        }
 
        return rframe;
index 3cfcd8a15470ea0b2bd64adc99d4be6dd91b702f..224a932e9e9107cd7583f0aaaf7a975734374a82 100644 (file)
@@ -165,6 +165,14 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session);
 */
 SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin);
 
+/*! 
+  \brief Acvite a jitter buffer on an RTP session
+  \param rtp_session the rtp session
+  \param queue_frames the number of frames to delay
+  \return SWITCH_STATUS_SUCCESS
+*/
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames);
+
 /*!
   \brief Set an RTP Flag
   \param rtp_session the RTP session
index 87332140658cbee402f3cfb38be56dfa1bcd39d6..27885a061db4cd5113e787260e1a45dec27465f3 100644 (file)
@@ -589,16 +589,18 @@ typedef enum {
   \brief Frame Flags
 
 <pre>
-SFF_CNG       = (1 <<  0) - Frame represents comfort noise
-SFF_RAW_RTP   = (1 <<  1) - Frame has raw rtp accessible
-SFF_RTP_HEADER = (1 << 2) - Get the rtp header from the frame header
+SFF_CNG        = (1 <<  0) - Frame represents comfort noise
+SFF_RAW_RTP    = (1 <<  1) - Frame has raw rtp accessible
+SFF_RTP_HEADER = (1 << 2)  - Get the rtp header from the frame header
+SFF_PLC        = (1 << 3)  - Frame has generated PLC data
 </pre>
  */
 typedef enum {
        SFF_NONE = 0,
        SFF_CNG = (1 << 0),
        SFF_RAW_RTP = (1 << 1),
-       SFF_RTP_HEADER = (1 << 2)
+       SFF_RTP_HEADER = (1 << 2),
+       SFF_PLC = (1 << 3)
 } switch_frame_flag_t;
 
 
index 99076bc908d44932fdb80bcffe7834c91a00ce4b..d7a3f5e18df35b65166203a76aa0000fa9169690 100644 (file)
@@ -949,6 +949,23 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt)
                                                          switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
                }
 
+               if ((val = switch_channel_get_variable(channel, "jitterbuffer_msec"))) {
+                       int len = atoi(val);
+                       
+                       if (len < 100 || len > 1000) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Jitterbuffer spec [%d] myst be between 100 and 1000\n", len);
+                       } else {
+                               int qlen;
+
+                               qlen = len / (tech_pvt->read_codec.implementation->microseconds_per_frame / 1000);
+                               
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
+                               switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen);
+                       }
+               }
+
+
+
                if (tech_pvt->te) {
                        switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te);
                }
index 05e5295025627ba98176bf747adac25db4bc0875..12ac302411190a08b63c1fae84f3ecf776d91e09 100644 (file)
@@ -42,7 +42,7 @@
 #undef inline
 #include <datatypes.h>
 #include <srtp.h>
-
+#include "stfu.h"
 #define MAX_KEY_LEN      64
 #define rtp_header_len 12
 #define RTP_START_PORT 16384
@@ -164,6 +164,7 @@ struct switch_rtp {
        uint8_t ready;
        uint8_t cn;
        switch_time_t last_time;
+       stfu_instance_t *jb;
 };
 
 static int global_init = 0;
@@ -586,6 +587,13 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
 
 }
 
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames)
+{
+       rtp_session->jb = stfu_n_init(queue_frames);    
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin)
 {
        char ice_user[80];
@@ -632,6 +640,10 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
 
        switch_mutex_lock((*rtp_session)->flag_mutex);
 
+       if ((*rtp_session)->jb) {
+               stfu_n_destroy(&(*rtp_session)->jb);
+       }
+
        if ((*rtp_session)->dtmf_data.dtmf_buffer) {
                switch_buffer_destroy(&(*rtp_session)->dtmf_data.dtmf_buffer);
        }
@@ -821,6 +833,24 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        return -1;
                }
 
+               if (rtp_session->jb && bytes) {
+                       stfu_frame_t *frame;
+                       
+                       stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.body, bytes - rtp_header_len);
+                       if ((frame = stfu_n_read_a_frame(rtp_session->jb))) {
+                               memcpy(rtp_session->recv_msg.body, frame->data, frame->dlen);
+                               if (frame->plc) {
+                                       *flags |= SFF_PLC;
+                               }
+                               bytes = frame->dlen + rtp_header_len;
+                               rtp_session->recv_msg.header.ts = htonl(frame->ts);
+                       } else {
+                               bytes = 0;
+                               continue;
+                       }
+                       
+               }
+
                if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) {
                        switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
 
@@ -907,6 +937,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        bytes = sbytes;
                }
 
+
                if (status == SWITCH_STATUS_BREAK || bytes == 0) {
                        if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) {
                                if (rtp_session->ms_per_packet) {
@@ -996,6 +1027,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        
                        continue;
                }
+       
 
                break;
        }