diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 787fd9c3d9..7ca036fc64 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -402,7 +402,7 @@ static void stfu_n_swap(stfu_instance_t *i) i->out_queue->last_jitter = 0; } -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last) +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint16_t seq, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last) { uint32_t index = 0; stfu_frame_t *frame; @@ -569,6 +569,7 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void frame->pt = pt; frame->ts = ts; + frame->seq = seq; frame->dlen = cplen; frame->was_read = 0; diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index 045b644009..e3d05bcbc1 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -163,6 +163,7 @@ typedef enum { struct stfu_frame { uint32_t ts; + uint16_t seq; uint32_t pt; uint8_t data[STFU_DATALEN]; size_t dlen; @@ -188,7 +189,7 @@ void stfu_n_report(stfu_instance_t *i, stfu_report_t *r); void stfu_n_destroy(stfu_instance_t **i); stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second, uint32_t max_drift_ms); stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen); -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last); +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint16_t seq, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last); stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i); void stfu_n_reset(stfu_instance_t *i); stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets); @@ -197,8 +198,8 @@ void stfu_n_debug(stfu_instance_t *i, const char *name); int32_t stfu_n_get_drift(stfu_instance_t *i); int32_t stfu_n_get_most_qlen(stfu_instance_t *i); -#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 0, 1) -#define stfu_n_eat(i,t,p,d,l,tt) stfu_n_add_data(i, t, p, d, l, tt, 0) +#define stfu_im_done(i) stfu_n_add_data(i, 0, 0, NULL, 0, 0, 1) +#define stfu_n_eat(i,t,s,p,d,l,tt) stfu_n_add_data(i, t, s, p, d, l, tt, 0) #ifdef __cplusplus } diff --git a/src/include/switch.h b/src/include/switch.h index 1eb45ae48a..3cfa271be4 100644 --- a/src/include/switch.h +++ b/src/include/switch.h @@ -106,6 +106,7 @@ #include #include +#include "../../../libs/stfu/stfu.h" #include "switch_platform.h" #include "switch_types.h" #include "switch_apr.h" @@ -138,9 +139,9 @@ #include "switch_pgsql.h" #include "switch_json.h" #include "switch_limit.h" - #include + /** \mainpage FreeSWITCH * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3cb4dc8116..a3898d9d64 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -741,7 +741,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_loglevel(switch_core_ses */ SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_session_t *session); - +SWITCH_DECLARE(stfu_instance_t *) switch_core_session_get_jb(switch_core_session_t *session, switch_media_type_t type); SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec); SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h index 91910f85dd..812aa5d413 100644 --- a/src/include/switch_frame.h +++ b/src/include/switch_frame.h @@ -70,6 +70,7 @@ SWITCH_BEGIN_EXTERN_C switch_bool_t m; /*! frame flags */ switch_frame_flag_t flags; + void *user_data; }; SWITCH_END_EXTERN_C diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index e92e1a1366..deb96e4d47 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -118,6 +118,7 @@ typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *); typedef switch_status_t (*switch_io_state_run_t) (switch_core_session_t *); typedef switch_status_t (*switch_io_read_video_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int); typedef switch_status_t (*switch_io_write_video_frame_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int); +typedef stfu_instance_t *(*switch_io_get_jb_t) (switch_core_session_t *, switch_media_type_t); typedef enum { SWITCH_IO_OUTGOING_CHANNEL, @@ -130,6 +131,7 @@ typedef enum { SWITCH_IO_STATE_CHANGE, SWITCH_IO_READ_VIDEO_FRAME, SWITCH_IO_WRITE_VIDEO_FRAME, + SWITCH_IO_GET_JB, } switch_io_routine_name_t; /*! \brief A table of i/o routines that an endpoint interface can implement */ @@ -156,6 +158,8 @@ struct switch_io_routines { switch_io_write_video_frame_t write_video_frame; /*! change a sessions channel run state */ switch_io_state_run_t state_run; + /*! get sessions jitterbuffer */ + switch_io_get_jb_t get_jb; void *padding[10]; }; @@ -613,6 +617,7 @@ struct switch_codec { switch_payload_t agreed_pt; switch_mutex_t *mutex; struct switch_codec *next; + switch_core_session_t *session; }; /*! \brief A table of settings and callbacks that define a paticular implementation of a codec */ diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 602889f3d6..0a4ac93643 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -240,6 +240,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp 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); +SWITCH_DECLARE(stfu_instance_t *) switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session); /*! \brief Set an RTP Flag diff --git a/src/include/switch_types.h b/src/include/switch_types.h index f1c5f1b65a..c4c2ed7190 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1427,6 +1427,11 @@ typedef enum { SWITCH_CODEC_TYPE_APP } switch_codec_type_t; +typedef enum { + SWITCH_MEDIA_TYPE_AUDIO, + SWITCH_MEDIA_TYPE_VIDEO +} switch_media_type_t; + /*! \enum switch_timer_flag_t diff --git a/src/mod/codecs/mod_silk/mod_silk.c b/src/mod/codecs/mod_silk/mod_silk.c index 5c32b72969..af32332de2 100644 --- a/src/mod/codecs/mod_silk/mod_silk.c +++ b/src/mod/codecs/mod_silk/mod_silk.c @@ -320,9 +320,20 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec, struct silk_context *context = codec->private_info; SKP_int16 ret, len; int16_t *target = decoded_data; + switch_core_session_t *session = codec->session; + stfu_instance_t *jb; *decoded_data_len = 0; + if (session) { + jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO); + } + + if (jb) { + /* to allow compile */ + jb = NULL; + } + do { ret = SKP_Silk_SDK_Decode(context->dec_state, &context->decoder_object, diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 3f26a26fff..20bff868de 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -306,6 +306,24 @@ char *generate_pai_str(private_object_t *tech_pvt) return pai; } +static stfu_instance_t *sofia_get_jb(switch_core_session_t *session, switch_media_type_t type) +{ + private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session); + switch_rtp_t *rtp; + + if (type == SWITCH_MEDIA_TYPE_AUDIO) { + rtp = tech_pvt->rtp_session; + } else { + rtp = tech_pvt->video_rtp_session; + } + + if (rtp && switch_rtp_ready(rtp)) { + return switch_rtp_get_jitter_buffer(rtp); + } + + return NULL; +} + /* map QSIG cause codes to SIP from RFC4497 section 8.4.1 */ static int hangup_cause_to_sip(switch_call_cause_t cause) { @@ -4501,7 +4519,9 @@ switch_io_routines_t sofia_io_routines = { /*.receive_event */ sofia_receive_event, /*.state_change */ NULL, /*.read_video_frame */ sofia_read_video_frame, - /*.write_video_frame */ sofia_write_video_frame + /*.write_video_frame */ sofia_write_video_frame, + /*.state_run*/ NULL, + /*.get_jb*/ sofia_get_jb }; switch_state_handler_table_t sofia_event_handlers = { diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 7b9580c0bb..7dbfdb2ac8 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -373,14 +373,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen); status = SWITCH_STATUS_SUCCESS; } else { + switch_codec_t *codec = use_codec->implementation?use_codec:read_frame->codec; switch_thread_rwlock_rdlock(session->bug_rwlock); - status = switch_core_codec_decode(use_codec->implementation?use_codec:read_frame->codec, + codec->session = session; + status = switch_core_codec_decode(codec, session->read_codec, read_frame->data, read_frame->datalen, session->read_impl.actual_samples_per_second, session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, &read_frame->flags); + codec->session = NULL; switch_thread_rwlock_unlock(session->bug_rwlock); } @@ -623,14 +626,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_assert(session->read_codec != NULL); switch_assert(enc_frame != NULL); switch_assert(enc_frame->data != NULL); - + session->read_codec->session = session; status = switch_core_codec_encode(session->read_codec, enc_frame->codec, enc_frame->data, enc_frame->datalen, session->read_impl.actual_samples_per_second, session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag); - + session->read_codec->session = NULL; switch (status) { case SWITCH_STATUS_RESAMPLE: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n"); @@ -904,12 +907,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess if (frame->codec) { session->raw_write_frame.datalen = session->raw_write_frame.buflen; + frame->codec->session = session; status = switch_core_codec_decode(frame->codec, session->write_codec, frame->data, frame->datalen, session->write_impl.actual_samples_per_second, session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags); + frame->codec->session = NULL; if (do_resample && status == SWITCH_STATUS_SUCCESS) { status = SWITCH_STATUS_RESAMPLE; @@ -1089,14 +1094,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess enc_frame = write_frame; session->enc_write_frame.datalen = session->enc_write_frame.buflen; - + session->write_codec->session = session; status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, session->write_impl.actual_samples_per_second, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); - + session->write_codec->session = NULL; @@ -1193,14 +1198,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess } else { rate = session->write_impl.actual_samples_per_second; } - + session->write_codec->session = session; status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, rate, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); - + session->write_codec->session = NULL; switch (status) { case SWITCH_STATUS_RESAMPLE: diff --git a/src/switch_core_session.c b/src/switch_core_session.c index b0ccbb866f..4c16fadc51 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -62,6 +62,16 @@ SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_ return NULL; } + +SWITCH_DECLARE(stfu_instance_t *) switch_core_session_get_jb(switch_core_session_t *session, switch_media_type_t type) +{ + if (session->endpoint_interface->io_routines->get_jb) { + return session->endpoint_interface->io_routines->get_jb(session, type); + } + + return NULL; +} + SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec) { session->soft_lock = sec; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 63721e66fd..b6c1127b31 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2820,7 +2820,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3 break; } - stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen, 0); + stfu_n_eat(jb, ts, 0, read_frame->payload, read_frame->data, read_frame->datalen, 0); ts += read_impl.samples_per_packet; if ((jb_frame = stfu_n_read_a_frame(jb))) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 93eb42c695..1b5925c23b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -53,7 +53,7 @@ #define WRITE_INC(rtp_session) switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++ #define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing-- -#include "stfu.h" + #define rtp_header_len 12 #define RTP_START_PORT 16384 @@ -2148,6 +2148,15 @@ static void jb_callback(stfu_instance_t *i, void *udata) } +SWITCH_DECLARE(stfu_instance_t *) switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session) +{ + if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) { + return NULL; + } + + return rtp_session->jb; +} + SWITCH_DECLARE(switch_status_t) switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause) { @@ -3019,6 +3028,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t } if (stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts, + ntohs((uint16_t) rtp_session->recv_msg.header.seq), rtp_session->recv_msg.header.pt, rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount) == STFU_ITS_TOO_LATE) {