add a fixed jitterbuffer to rtp (settable from a channel variable) (libSTFU)

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5090 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-05-04 23:29:35 +00:00
parent 5d628cda03
commit af97953adc
7 changed files with 73 additions and 8 deletions

View File

@ -57,6 +57,7 @@ src/switch_ivr.c \
src/switch_stun.c\ src/switch_stun.c\
src/switch_log.c\ src/switch_log.c\
src/switch_xml.c\ src/switch_xml.c\
libs/stfu/stfu.c\
libs/libteletone/src/libteletone_detect.c\ libs/libteletone/src/libteletone_detect.c\
libs/libteletone/src/libteletone_generate.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/apr-1-config --cflags --cppflags --includes`
CORE_CFLAGS += `$(switch_srcdir)/libs/apr-util/apu-1-config --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/sqlite
CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include

View File

@ -53,6 +53,7 @@
<!-- Request a certain tone/file to be played while you wait for the call to be answered--> <!-- 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=${us-ring}"/>
<!--<action application="set" data="ringback=/home/ring.wav"/>--> <!--<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"/> <action application="bridge" data="sofia/$${sip_profile}/1234@conference.freeswitch.org"/>
</condition> </condition>
</extension> </extension>

View 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); cplen = sizeof(frame->data);
} }
memcpy(frame->data, data, cplen); memcpy(frame->data, data, cplen);
frame->ts = ts; frame->ts = ts;
frame->dlen = cplen; frame->dlen = cplen;
@ -185,6 +184,8 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
if (i->running) { if (i->running) {
should_have = i->last_ts + i->interval; 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++) { for(index = 0; index < i->out_queue->array_len; index++) {
@ -220,11 +221,12 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
i->miss_count++; 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->out_queue->wr_len = i->out_queue->array_len;
i->last_ts = should_have = frame->ts; i->last_ts = should_have = frame->ts;
return NULL; return NULL;
} }
i->last_ts = should_have; i->last_ts = should_have;
rframe = &i->out_queue->int_frame; rframe = &i->out_queue->int_frame;
rframe->dlen = i->out_queue->array[i->out_queue->last_index].dlen; 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; i->last_ts = rframe->ts;
rframe->was_read = 1; rframe->was_read = 1;
i->running = 1; i->running = 1;
i->miss_count = 0;
} }
return rframe; return rframe;

View 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); 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 \brief Set an RTP Flag
\param rtp_session the RTP session \param rtp_session the RTP session

View File

@ -592,13 +592,15 @@ typedef enum {
SFF_CNG = (1 << 0) - Frame represents comfort noise SFF_CNG = (1 << 0) - Frame represents comfort noise
SFF_RAW_RTP = (1 << 1) - Frame has raw rtp accessible SFF_RAW_RTP = (1 << 1) - Frame has raw rtp accessible
SFF_RTP_HEADER = (1 << 2) - Get the rtp header from the frame header SFF_RTP_HEADER = (1 << 2) - Get the rtp header from the frame header
SFF_PLC = (1 << 3) - Frame has generated PLC data
</pre> </pre>
*/ */
typedef enum { typedef enum {
SFF_NONE = 0, SFF_NONE = 0,
SFF_CNG = (1 << 0), SFF_CNG = (1 << 0),
SFF_RAW_RTP = (1 << 1), SFF_RAW_RTP = (1 << 1),
SFF_RTP_HEADER = (1 << 2) SFF_RTP_HEADER = (1 << 2),
SFF_PLC = (1 << 3)
} switch_frame_flag_t; } switch_frame_flag_t;

View 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" : ""); 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) { if (tech_pvt->te) {
switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te);
} }

View File

@ -42,7 +42,7 @@
#undef inline #undef inline
#include <datatypes.h> #include <datatypes.h>
#include <srtp.h> #include <srtp.h>
#include "stfu.h"
#define MAX_KEY_LEN 64 #define MAX_KEY_LEN 64
#define rtp_header_len 12 #define rtp_header_len 12
#define RTP_START_PORT 16384 #define RTP_START_PORT 16384
@ -164,6 +164,7 @@ struct switch_rtp {
uint8_t ready; uint8_t ready;
uint8_t cn; uint8_t cn;
switch_time_t last_time; switch_time_t last_time;
stfu_instance_t *jb;
}; };
static int global_init = 0; 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) SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin)
{ {
char ice_user[80]; 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); switch_mutex_lock((*rtp_session)->flag_mutex);
if ((*rtp_session)->jb) {
stfu_n_destroy(&(*rtp_session)->jb);
}
if ((*rtp_session)->dtmf_data.dtmf_buffer) { if ((*rtp_session)->dtmf_data.dtmf_buffer) {
switch_buffer_destroy(&(*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; 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)) { if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) {
switch_clear_flag_locked(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; bytes = sbytes;
} }
if (status == SWITCH_STATUS_BREAK || bytes == 0) { if (status == SWITCH_STATUS_BREAK || bytes == 0) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) {
if (rtp_session->ms_per_packet) { if (rtp_session->ms_per_packet) {
@ -997,6 +1028,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
continue; continue;
} }
break; break;
} }