36 #define NACK_TIME 80000 37 #define RENACK_TIME 100000 38 #define MAX_FRAME_PADDING 2 39 #define MAX_MISSING_SEQ 20 40 #define jb_debug(_jb, _level, _format, ...) if (_jb->debug_level >= _level) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(_jb->session), SWITCH_LOG_ALERT, "JB:%p:%s:%d/%d lv:%d ln:%.4d sz:%.3u/%.3u/%.3u/%.3u c:%.3u %.3u/%.3u/%.3u/%.3u %.2f%% ->" _format, (void *) _jb, (jb->type == SJB_TEXT ? "txt" : (jb->type == SJB_AUDIO ? "aud" : "vid")), _jb->allocated_nodes, _jb->visible_nodes, _level, __LINE__, _jb->min_frame_len, _jb->max_frame_len, _jb->frame_len, _jb->complete_frames, _jb->period_count, _jb->consec_good_count, _jb->period_good_count, _jb->consec_miss_count, _jb->period_miss_count, _jb->period_miss_pct, __VA_ARGS__) 160 int insize, nmerges, psize, qsize, i;
180 for (i = 0; i < insize; i++) {
190 while (psize > 0 || (qsize > 0 && q)) {
195 e = q; q = q->
next; qsize--;
196 }
else if (qsize == 0 || !q) {
198 e = p; p = p->
next; psize--;
199 }
else if (cmp(p,q) <= 0) {
202 e = p; p = p->
next; psize--;
205 e = q; q = q->
next; qsize--;
295 }
else if (node->
prev) {
365 void *payload = packet ? (packet->
ebody ? packet->
ebody : packet->
body) : NULL;
366 uint16_t payload_len =
len;
368 if (payload && payload_len > 0) {
376 &ret_t, (
void *)&ret_p);
439 return lowest ? lowest : NULL;
450 static inline void thin_frames(
switch_jb_t *jb,
int freq,
int max)
459 while (node && dropped <= max) {
469 if ((i % freq) == 0) {
493 return highest ? highest : NULL;
497 static inline uint32_t jb_find_highest_ts(
switch_jb_t *jb)
504 static inline void drop_newest_frame(
switch_jb_t *jb)
506 uint32_t ts = jb_find_highest_ts(jb);
509 jb_debug(jb, 1,
"Dropping highest frame ts:%u\n", ntohl(ts));
524 if (highest) second_highest = highest;
530 return second_highest ? second_highest : highest;
574 jb_debug(jb, 1,
"%d Change framelen from %u to %u\n", line, old_frame_len, jb->
frame_len);
583 #define jb_frame_inc(_jb, _i) jb_frame_inc_line(_jb, _i, __LINE__) 594 static inline int verify_oldest_frame(
switch_jb_t *jb)
609 for (np = lowest->
next; np; np = np->
next) {
611 if (!np->visible)
continue;
613 if (ntohs(np->packet.header.seq) != ntohs(np->prev->packet.header.seq) + 1) {
614 uint32_t val = (uint32_t)htons(ntohs(np->prev->packet.header.seq) + 1);
622 if (np->packet.header.ts != lowest->
packet.
header.
ts || !np->next) {
640 jb_debug(jb, 1,
"Dropping oldest frame ts:%u\n", ntohl(ts));
646 static inline void drop_second_newest_frame(
switch_jb_t *jb)
662 if (a >= b || (b > a && b > USHRT_MAX / 2 && a < USHRT_MAX / 2)) {
674 if (a > b || (b > a && b > UINT_MAX / 2 && a < UINT_MAX / 2)) {
699 jb_debug(jb, (packet->
header.
m ? 2 : 3),
"PUT packet last_ts:%u ts:%u seq:%u%s\n",
703 int seq_diff = 0, ts_diff = 0;
717 if (((seq_diff >= 100) || (ts_diff > (900000 * 5)))) {
806 jb_debug(jb, 2,
"%s",
"DROPPED FRAME DETECTED RESYNCING\n");
821 jb_debug(jb, 1,
"%s",
"No nodes available....\n");
838 for (x = 0; x < 10; x++) {
844 jb_debug(jb, 2,
"%s",
"SAME FRAME DROPPING\n");
889 jb_debug(jb, 1,
"%s",
"No nodes available....\n");
916 uint16_t seq_hs, target_seq_hs;
932 if (target_seq_hs > seq_hs) {
939 l_seq = h_seq = seq_hs;
944 if (seq_hs < l_seq) {
948 if (seq_hs > h_seq) {
964 if (target_seq_hs % 50 == 0) {
991 jb_debug(jb,
SWITCH_LOG_INFO,
"JITTER buffersize %u == %u old[%u] target[%u] seq[%u|%u]\n", count, h_seq - l_seq + 1, old, target_seq_hs, l_seq, h_seq);
1015 packet = &(*nodep)->packet;
1016 seq = ntohs((*nodep)->packet.header.seq);
1017 len = (*nodep)->len;
1044 jb_debug(jb, 2,
"JITTER estimation %dms buffersize %d/%d %dms\n",
1129 int tmp = atoi(var);
1131 if (tmp >= 128 && tmp <= 10240) {
1196 jb_debug(jb, 2,
"%s",
"RESET BUFFER\n");
1226 uint32_t nack_recovered;
1230 return nack_recovered;
1246 uint16_t want_seq = seq + peek;
1273 if (min_frame_len) {
1277 if (max_frame_len) {
1281 if (cur_frame_len) {
1417 seq = ntohs(*((uint16_t *) var));
1418 then = (intptr_t) val;
1421 jb_debug(jb, 3,
"NACKABLE seq %u too soon to repeat\n", seq);
1430 jb_debug(jb, 3,
"NACKABLE seq %u expired\n", seq);
1435 if (!least || seq < least) {
1443 jb_debug(jb, 3,
"Found NACKABLE seq %u\n", least);
1444 nack = (uint32_t) htons(least);
1447 for(i = 0; i < 16; i++) {
1450 jb_debug(jb, 3,
"Found addtl NACKABLE seq %u\n", least + i + 1);
1456 nack |= (uint32_t) blp << 16;
1481 jb_debug(jb, 2,
"%s",
"TS ALREADY DROPPED, DROPPING PACKET\n");
1489 if (!want) want = got;
1497 jb_debug(jb, 2,
"got nacked seq %u too late\n", got);
1501 jb_debug(jb, 2,
"got nacked %u saved the day!\n", got);
1508 jb_debug(jb, 2,
"Missing %u frames, Resetting\n", got - want);
1516 jb_debug(jb, 2,
"GOT %u WANTED %u; MARK SEQS MISSING %u - %u\n", got, want, want, got - 1);
1518 for (i = want; i < got; i++) {
1525 if (got >= want || (want - got) > 1000) {
1554 jb_debug(jb, 2,
"Found buffered seq: %u\n", ntohs(seq));
1560 jb_debug(jb, 2,
"Missing buffered seq: %u\n", ntohs(seq));
1615 jb_debug(jb, 2,
"%s",
"Allow BITRATE changes\n");
1628 msg.
from = __FILE__;
1675 jb_debug(jb, 2,
"%s",
"Error encountered ask for new keyframe\n");
1679 jb_debug(jb, 2,
"%s",
"No frames found wait for more\n");
1685 jb_debug(jb, 2,
"%s",
"Error encountered\n");
1694 jb_debug(jb, 2,
"%s",
"Too many frames not found, RESIZE\n");
1709 jb_debug(jb, 2,
"%s",
"Frame not found suggest PLC\n");
1712 jb_debug(jb, 2,
"%s",
"Frame not found suggest PLC\n");
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
uint32_t highest_wrote_ts
struct switch_jb_jitter_s switch_jb_jitter_t
uint32_t samples_per_frame
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_jb_put_packet(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
switch_status_t switch_core_inthash_init(switch_inthash_t **hash)
static switch_jb_node_t * jb_find_lowest_seq(switch_jb_t *jb, uint32_t ts)
void switch_jb_debug_level(switch_jb_t *jb, uint8_t level)
switch_core_session_message_types_t message_id
#define SWITCH_CHANNEL_LOG
switch_jb_jitter_t jitter
uint32_t highest_read_seq
switch_inthash_t * node_hash
switch_channel_t * channel
switch_inthash_t * node_hash_ts
switch_inthash_t * missing_seq_hash
static void hide_nodes(switch_jb_t *jb)
switch_bool_t complete_frame_mark
struct switch_jb_node_s * next
void switch_jb_ts_mode(switch_jb_t *jb, uint32_t samples_per_frame, uint32_t samples_per_second)
uint32_t nack_saved_the_day
uint32_t switch_jb_pop_nack(switch_jb_t *jb)
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
switch_memory_pool_t * pool
#define jb_debug(_jb, _level, _format,...)
void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key)
switch_status_t switch_jb_create(switch_jb_t **jbp, switch_jb_type_t type, uint32_t min_frame_len, uint32_t max_frame_len, switch_memory_pool_t *pool)
static void decrement_seq(switch_jb_t *jb)
#define jb_frame_inc(_jb, _i)
uint32_t switch_jb_get_nack_success(switch_jb_t *jb)
int switch_jb_frame_count(switch_jb_t *jb)
uint16_t highest_wrote_seq
struct switch_jb_node_s switch_jb_node_t
static uint32_t jb_find_lowest_ts(switch_jb_t *jb)
static void set_read_seq(switch_jb_t *jb, uint16_t seq)
const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
Retrieve a variable from a given channel.
switch_jb_node_t * sort_nodes(switch_jb_node_t *list, int(*cmp)(const void *, const void *))
uint32_t highest_dropped_ts
void switch_jb_set_jitter_estimator(switch_jb_t *jb, double *jitter, uint32_t samples_per_frame, uint32_t samples_per_second)
int switch_jb_poll(switch_jb_t *jb)
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
struct switch_jb_s * parent
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_inthash_destroy(switch_inthash_t **hash)
switch_status_t switch_jb_peek_frame(switch_jb_t *jb, uint32_t ts, uint16_t seq, int peek, switch_frame_t *frame)
static switch_bool_t packet_vad(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
#define SWITCH_MUTEX_NESTED
static switch_jb_node_t * jb_find_lowest_node(switch_jb_t *jb)
uint32_t samples_per_second
static void jb_hit(switch_jb_t *jb)
switch_codec_control_type_t
switch_status_t switch_jb_get_packet_by_seq(switch_jb_t *jb, uint16_t seq, switch_rtp_packet_t *packet, switch_size_t *len)
static void drop_oldest_frame(switch_jb_t *jb)
const switch_codec_implementation_t * implementation
switch_status_t switch_jb_get_packet(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t *len)
static int check_seq(uint16_t a, uint16_t b)
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
static void add_node(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
static void increment_ts(switch_jb_t *jb)
void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key)
uint32_t nack_didnt_save_the_day
static void push_to_top(switch_jb_t *jb, switch_jb_node_t *node)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
#define switch_core_session_request_video_refresh(_s)
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
static void drop_ts(switch_jb_t *jb, uint32_t ts)
switch_status_t switch_core_inthash_insert(switch_inthash_t *hash, uint32_t key, const void *data)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
void switch_jb_clear_flag(switch_jb_t *jb, switch_jb_flag_t flag)
static switch_status_t jb_next_packet_by_ts(switch_jb_t *jb, switch_jb_node_t **nodep)
uint32_t consec_miss_count
void switch_core_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen) const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val)
Gets the key and value of the current hash element.
An abstraction of a data frame.
switch_hash_index_t * switch_core_hash_next(_In_ switch_hash_index_t **hi)
Gets the next element of a hashtable.
static switch_status_t jb_next_packet_by_seq_with_acceleration(switch_jb_t *jb, switch_jb_node_t **nodep)
static int check_jb_size(switch_jb_t *jb)
#define switch_core_session_receive_message(_session, _message)
static void sort_free_nodes(switch_jb_t *jb)
struct fspr_thread_mutex_t switch_mutex_t
#define SWITCH_RTP_HEADER_LEN
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
uint32_t video_low_bitrate
static void increment_seq(switch_jb_t *jb)
uint32_t period_good_count
uint32_t period_miss_count
static int node_cmp(const void *l, const void *r)
switch_status_t switch_jb_destroy(switch_jb_t **jbp)
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
void switch_jb_set_session(switch_jb_t *jb, switch_core_session_t *session)
static void jb_frame_inc_line(switch_jb_t *jb, int i, int line)
char body[SWITCH_RTP_MAX_BUF_LEN+4+sizeof(char *)]
switch_mutex_t * list_mutex
static switch_jb_node_t * new_node(switch_jb_t *jb)
static switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_node_t **nodep)
static void set_read_ts(switch_jb_t *jb, uint32_t ts)
void switch_jb_set_flag(switch_jb_t *jb, switch_jb_flag_t flag)
switch_core_session_t * session
switch_size_t switch_jb_get_last_read_len(switch_jb_t *jb)
struct switch_jb_node_s * prev
static void free_nodes(switch_jb_t *jb)
uint32_t switch_jb_get_packets_per_frame(switch_jb_t *jb)
uint32_t samples_per_second
switch_status_t switch_jb_set_frames(switch_jb_t *jb, uint32_t min_frame_len, uint32_t max_frame_len)
uint32_t highest_frame_len
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
static void jb_miss(switch_jb_t *jb)
switch_memory_pool_t * pool
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
unsigned int switch_hashtable_count(switch_hashtable_t *h)
uint32_t reset_missing_frames
struct fspr_pool_t switch_memory_pool_t
#define SWITCH_RTP_MAX_PACKET_LEN
switch_rtp_packet_t packet
switch_status_t switch_jb_get_frames(switch_jb_t *jb, uint32_t *min_frame_len, uint32_t *max_frame_len, uint32_t *cur_frame_len, uint32_t *highest_frame_len)
switch_time_t switch_time_now(void)
static switch_status_t jb_next_packet(switch_jb_t *jb, switch_jb_node_t **nodep)
uint32_t samples_per_frame
static int check_ts(uint32_t a, uint32_t b)
struct switch_jb_stats_s switch_jb_stats_t
static void hide_node(switch_jb_node_t *node, switch_bool_t pop)
struct switch_jb_node_s * node_list
void switch_jb_reset(switch_jb_t *jb)
uint32_t consec_good_count
switch_hash_index_t * switch_core_hash_first_iter(_In_ switch_hash_t *hash, switch_hash_index_t *hi)
Gets the first element of a hashtable.