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;
frame->pt = pt;
frame->ts = ts;
+ frame->seq = seq;
frame->dlen = cplen;
frame->was_read = 0;
struct stfu_frame {
uint32_t ts;
+ uint16_t seq;
uint32_t pt;
uint8_t data[STFU_DATALEN];
size_t dlen;
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);
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
}
#include <signal.h>
#include <errno.h>
+#include "../../../libs/stfu/stfu.h"
#include "switch_platform.h"
#include "switch_types.h"
#include "switch_apr.h"
#include "switch_pgsql.h"
#include "switch_json.h"
#include "switch_limit.h"
-
#include <libteletone.h>
+
/** \mainpage FreeSWITCH
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*/
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);
switch_bool_t m;
/*! frame flags */
switch_frame_flag_t flags;
+ void *user_data;
};
SWITCH_END_EXTERN_C
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,
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 */
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];
};
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 */
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
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
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,
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)
{
/*.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 = {
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);
}
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");
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;
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;
} 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:
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;
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))) {
#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
}
+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)
{
}
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) {