RTS API Documentation  1.10.11
Data Structures | Macros | Typedefs | Functions
switch_jitterbuffer.c File Reference
#include <switch.h>
#include <switch_jitterbuffer.h>
#include "private/switch_hashtable_private.h"
+ Include dependency graph for switch_jitterbuffer.c:

Go to the source code of this file.

Data Structures

struct  switch_jb_node_s
 
struct  switch_jb_stats_s
 
struct  switch_jb_jitter_s
 
struct  switch_jb_s
 

Macros

#define NACK_TIME   80000
 
#define RENACK_TIME   100000
 
#define MAX_FRAME_PADDING   2
 
#define MAX_MISSING_SEQ   20
 
#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__)
 
#define jb_frame_inc(_jb, _i)   jb_frame_inc_line(_jb, _i, __LINE__)
 

Typedefs

typedef struct switch_jb_node_s switch_jb_node_t
 
typedef struct switch_jb_stats_s switch_jb_stats_t
 
typedef struct switch_jb_jitter_s switch_jb_jitter_t
 

Functions

static int check_jb_size (switch_jb_t *jb)
 
static int node_cmp (const void *l, const void *r)
 
switch_jb_node_tsort_nodes (switch_jb_node_t *list, int(*cmp)(const void *, const void *))
 
static switch_jb_node_tnew_node (switch_jb_t *jb)
 
static void push_to_top (switch_jb_t *jb, switch_jb_node_t *node)
 
static void hide_node (switch_jb_node_t *node, switch_bool_t pop)
 
static void sort_free_nodes (switch_jb_t *jb)
 
static void hide_nodes (switch_jb_t *jb)
 
static switch_bool_t packet_vad (switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
 
static void drop_ts (switch_jb_t *jb, uint32_t ts)
 
static switch_jb_node_tjb_find_lowest_seq (switch_jb_t *jb, uint32_t ts)
 
static switch_jb_node_tjb_find_lowest_node (switch_jb_t *jb)
 
static uint32_t jb_find_lowest_ts (switch_jb_t *jb)
 
static void jb_hit (switch_jb_t *jb)
 
static void jb_frame_inc_line (switch_jb_t *jb, int i, int line)
 
static void jb_miss (switch_jb_t *jb)
 
static void drop_oldest_frame (switch_jb_t *jb)
 
static int check_seq (uint16_t a, uint16_t b)
 
static int check_ts (uint32_t a, uint32_t b)
 
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)
 
static void set_read_ts (switch_jb_t *jb, uint32_t ts)
 
static void increment_seq (switch_jb_t *jb)
 
static void decrement_seq (switch_jb_t *jb)
 
static void set_read_seq (switch_jb_t *jb, uint16_t seq)
 
static switch_status_t jb_next_packet_by_seq (switch_jb_t *jb, switch_jb_node_t **nodep)
 
static switch_status_t jb_next_packet_by_ts (switch_jb_t *jb, switch_jb_node_t **nodep)
 
static switch_status_t jb_next_packet_by_seq_with_acceleration (switch_jb_t *jb, switch_jb_node_t **nodep)
 
static switch_status_t jb_next_packet (switch_jb_t *jb, switch_jb_node_t **nodep)
 
static void free_nodes (switch_jb_t *jb)
 
void switch_jb_ts_mode (switch_jb_t *jb, uint32_t samples_per_frame, uint32_t samples_per_second)
 
void switch_jb_set_jitter_estimator (switch_jb_t *jb, double *jitter, uint32_t samples_per_frame, uint32_t samples_per_second)
 
void switch_jb_set_session (switch_jb_t *jb, switch_core_session_t *session)
 
void switch_jb_set_flag (switch_jb_t *jb, switch_jb_flag_t flag)
 
void switch_jb_clear_flag (switch_jb_t *jb, switch_jb_flag_t flag)
 
int switch_jb_poll (switch_jb_t *jb)
 
int switch_jb_frame_count (switch_jb_t *jb)
 
void switch_jb_debug_level (switch_jb_t *jb, uint8_t level)
 
void switch_jb_reset (switch_jb_t *jb)
 
uint32_t switch_jb_get_nack_success (switch_jb_t *jb)
 
uint32_t switch_jb_get_packets_per_frame (switch_jb_t *jb)
 
switch_status_t switch_jb_peek_frame (switch_jb_t *jb, uint32_t ts, uint16_t seq, int peek, switch_frame_t *frame)
 
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_status_t switch_jb_set_frames (switch_jb_t *jb, uint32_t min_frame_len, uint32_t max_frame_len)
 
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)
 
switch_status_t switch_jb_destroy (switch_jb_t **jbp)
 
uint32_t switch_jb_pop_nack (switch_jb_t *jb)
 
switch_status_t switch_jb_put_packet (switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
 
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)
 
switch_size_t switch_jb_get_last_read_len (switch_jb_t *jb)
 
switch_status_t switch_jb_get_packet (switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t *len)
 

Macro Definition Documentation

◆ jb_debug

#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__)

◆ jb_frame_inc

#define jb_frame_inc (   _jb,
  _i 
)    jb_frame_inc_line(_jb, _i, __LINE__)

◆ MAX_FRAME_PADDING

#define MAX_FRAME_PADDING   2

Definition at line 38 of file switch_jitterbuffer.c.

◆ MAX_MISSING_SEQ

#define MAX_MISSING_SEQ   20

Definition at line 39 of file switch_jitterbuffer.c.

◆ NACK_TIME

#define NACK_TIME   80000

Definition at line 36 of file switch_jitterbuffer.c.

◆ RENACK_TIME

#define RENACK_TIME   100000

Definition at line 37 of file switch_jitterbuffer.c.

Referenced by switch_jb_pop_nack().

Typedef Documentation

◆ switch_jb_jitter_t

◆ switch_jb_node_t

◆ switch_jb_stats_t

Function Documentation

◆ add_node()

static void add_node ( switch_jb_t jb,
switch_rtp_packet_t packet,
switch_size_t  len 
)
inlinestatic

Definition at line 681 of file switch_jitterbuffer.c.

References check_seq(), check_ts(), switch_jb_node_s::complete_frame_mark, switch_jb_s::complete_frames, switch_jb_s::frame_len, switch_rtp_packet_t::header, switch_jb_s::highest_wrote_seq, switch_jb_s::highest_wrote_ts, jb_debug, switch_jb_s::jitter, switch_jb_node_s::len, switch_rtp_hdr_t::m, switch_jb_s::max_packet_len, new_node(), switch_jb_s::node_hash, switch_jb_s::node_hash_ts, switch_jb_node_s::packet, switch_jb_s::packet_count, switch_jb_stats_s::reset_ts_jump, switch_rtp_hdr_t::seq, SJB_AUDIO, SJB_TEXT, SJB_VIDEO, switch_jb_jitter_s::stats, switch_core_inthash_insert(), switch_jb_reset(), TRUE, switch_rtp_hdr_t::ts, switch_jb_s::type, switch_jb_s::visible_nodes, and switch_jb_s::write_init.

Referenced by switch_jb_put_packet().

682 {
683  switch_jb_node_t *node = new_node(jb);
684 
685  if (!node) {
686  return;
687  }
688 
689 
690  node->packet = *packet;
691  node->len = len;
692 
694 
695  if (jb->node_hash_ts) {
697  }
698 
699  jb_debug(jb, (packet->header.m ? 2 : 3), "PUT packet last_ts:%u ts:%u seq:%u%s\n",
700  ntohl(jb->highest_wrote_ts), ntohl(node->packet.header.ts), ntohs(node->packet.header.seq), packet->header.m ? " <MARK>" : "");
701 
702  if (jb->write_init && jb->type == SJB_VIDEO) {
703  int seq_diff = 0, ts_diff = 0;
704 
705  if (ntohs(jb->highest_wrote_seq) > (USHRT_MAX - 100) && ntohs(packet->header.seq) < 100) {
706  seq_diff = (USHRT_MAX - ntohs(jb->highest_wrote_seq)) + ntohs(packet->header.seq);
707  } else {
708  seq_diff = abs(((int)ntohs(packet->header.seq) - ntohs(jb->highest_wrote_seq)));
709  }
710 
711  if (ntohl(jb->highest_wrote_ts) > (UINT_MAX - 1000) && ntohl(node->packet.header.ts) < 1000) {
712  ts_diff = (UINT_MAX - ntohl(node->packet.header.ts)) + ntohl(node->packet.header.ts);
713  } else {
714  ts_diff = abs((int)((int64_t)ntohl(node->packet.header.ts) - (int64_t)ntohl(jb->highest_wrote_ts)));
715  }
716 
717  if (((seq_diff >= 100) || (ts_diff > (900000 * 5)))) {
718  jb_debug(jb, 2, "CHANGE DETECTED, PUNT %u\n", abs(((int)ntohs(packet->header.seq) - ntohs(jb->highest_wrote_seq))));
719  jb->jitter.stats.reset_ts_jump++;
720  switch_jb_reset(jb);
721  }
722  }
723 
724  if (!jb->write_init || ntohs(packet->header.seq) > ntohs(jb->highest_wrote_seq) ||
725  (ntohs(jb->highest_wrote_seq) > USHRT_MAX - 100 && ntohs(packet->header.seq) < 100) ) {
726  jb->highest_wrote_seq = packet->header.seq;
727  }
728 
729  if (jb->type == SJB_VIDEO) {
730  jb->packet_count++;
731 
732  if (jb->write_init && check_seq(packet->header.seq, jb->highest_wrote_seq) && check_ts(node->packet.header.ts, jb->highest_wrote_ts)) {
733  jb_debug(jb, 2, "WRITE frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
734  jb->highest_wrote_ts = packet->header.ts;
735  jb->complete_frames++;
736 
737  jb->packet_count--;
738  if (jb->packet_count > jb->max_packet_len) {
739  jb->max_packet_len = jb->packet_count;
740  }
741  jb->packet_count = 1;
742  node->complete_frame_mark = TRUE;
743  } else if (!jb->write_init) {
744  jb->highest_wrote_ts = packet->header.ts;
745  }
746  } else {
747  if (jb->write_init || jb->type == SJB_TEXT || jb->type == SJB_AUDIO) {
748  jb_debug(jb, 2, "WRITE frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
749  jb->complete_frames++;
750  } else {
751  jb->highest_wrote_ts = packet->header.ts;
752  }
753  }
754 
755  if (!jb->write_init) jb->write_init = 1;
756 }
uint32_t highest_wrote_ts
switch_jb_type_t type
switch_jb_jitter_t jitter
switch_inthash_t * node_hash
switch_inthash_t * node_hash_ts
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
switch_bool_t complete_frame_mark
uint32_t complete_frames
#define jb_debug(_jb, _level, _format,...)
uint16_t highest_wrote_seq
uint32_t max_packet_len
static int check_seq(uint16_t a, uint16_t b)
switch_status_t switch_core_inthash_insert(switch_inthash_t *hash, uint32_t key, const void *data)
uint32_t visible_nodes
static switch_jb_node_t * new_node(switch_jb_t *jb)
switch_jb_stats_t stats
#define TRUE
switch_rtp_packet_t packet
static int check_ts(uint32_t a, uint32_t b)
void switch_jb_reset(switch_jb_t *jb)

◆ check_jb_size()

static int check_jb_size ( switch_jb_t jb)
inlinestatic

Definition at line 913 of file switch_jitterbuffer.c.

References switch_jb_stats_s::acceleration, switch_jb_s::channel, count, switch_jb_jitter_s::estimate, switch_jb_stats_s::estimate_ms, switch_jb_stats_s::expand, switch_rtp_packet_t::header, hide_node(), if(), jb_debug, switch_jb_s::jitter, switch_jb_stats_s::jitter_max_ms, switch_jb_s::list_mutex, switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::packet, switch_jb_jitter_s::samples_per_frame, switch_jb_jitter_s::samples_per_second, switch_rtp_hdr_t::seq, switch_jb_stats_s::size_est, switch_jb_stats_s::size_max, sort_free_nodes(), switch_jb_jitter_s::stats, switch_channel_set_variable_printf(), SWITCH_FALSE, SWITCH_LOG_INFO, switch_mutex_lock(), switch_mutex_unlock(), switch_jb_s::target_seq, and switch_jb_node_s::visible.

Referenced by jb_next_packet_by_seq_with_acceleration(), and switch_jb_get_packet().

914 {
915  switch_jb_node_t *np;
916  uint16_t seq_hs, target_seq_hs;
917  uint16_t l_seq = 0;
918  uint16_t h_seq = 0;
919  uint16_t count = 0;
920  uint16_t old = 0;
921 
923 
924  target_seq_hs = ntohs(jb->target_seq);
925 
926  for (np = jb->node_list; np; np = np->next) {
927  if (!np->visible) {
928  continue;
929  }
930 
931  seq_hs = ntohs(np->packet.header.seq);
932  if (target_seq_hs > seq_hs) {
933  hide_node(np, SWITCH_FALSE);
934  old++;
935  continue;
936  }
937 
938  if (count == 0) {
939  l_seq = h_seq = seq_hs;
940  }
941 
942  count++;
943 
944  if (seq_hs < l_seq) {
945  l_seq = seq_hs;
946  }
947 
948  if (seq_hs > h_seq) {
949  h_seq = seq_hs;
950  }
951  }
952 
953  if (count > jb->jitter.stats.size_max) {
954  jb->jitter.stats.size_max = count;
955  }
956 
957  if (jb->jitter.stats.size_est == 0) {
958  jb->jitter.stats.size_est = count;
959  } else {
960  jb->jitter.stats.size_est = ((99 * jb->jitter.stats.size_est) + (1 * count)) / 100;
961  }
962 
963  /* update the stats every x packets */
964  if (target_seq_hs % 50 == 0) {
965  int packet_ms = jb->jitter.samples_per_frame / (jb->jitter.samples_per_second / 1000);
966 
967  jb->jitter.stats.estimate_ms = (*jb->jitter.estimate) / jb->jitter.samples_per_second * 1000;
968  if (jb->channel) {
969  switch_channel_set_variable_printf(jb->channel, "rtp_jb_size_max_ms", "%u", jb->jitter.stats.size_max * packet_ms);
970  switch_channel_set_variable_printf(jb->channel, "rtp_jb_size_est_ms", "%u", jb->jitter.stats.size_est * packet_ms);
971  switch_channel_set_variable_printf(jb->channel, "rtp_jb_acceleration_ms", "%u", jb->jitter.stats.acceleration * packet_ms);
972  switch_channel_set_variable_printf(jb->channel, "rtp_jb_expand_ms", "%u", jb->jitter.stats.expand * packet_ms);
973  }
974 
977  }
978 
979  if (jb->channel) {
980  switch_channel_set_variable_printf(jb->channel, "rtp_jb_jitter_max_ms", "%u", jb->jitter.stats.jitter_max_ms);
981  switch_channel_set_variable_printf(jb->channel, "rtp_jb_jitter_est_ms", "%u", jb->jitter.stats.estimate_ms);
982  }
983  }
984 
985  if (old) {
986  sort_free_nodes(jb);
987  }
988 
990 
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);
992 
993  return count;
994 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
switch_jb_jitter_t jitter
switch_channel_t * channel
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
struct switch_jb_node_s * next
#define jb_debug(_jb, _level, _format,...)
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
static void sort_free_nodes(switch_jb_t *jb)
switch_mutex_t * list_mutex
switch_jb_stats_t stats
int count
Definition: switch_cJSON.h:204
switch_rtp_packet_t packet
static void hide_node(switch_jb_node_t *node, switch_bool_t pop)
struct switch_jb_node_s * node_list

◆ check_seq()

static int check_seq ( uint16_t  a,
uint16_t  b 
)
inlinestatic

Definition at line 657 of file switch_jitterbuffer.c.

Referenced by add_node(), and switch_jb_get_packet().

658 {
659  a = ntohs(a);
660  b = ntohs(b);
661 
662  if (a >= b || (b > a && b > USHRT_MAX / 2 && a < USHRT_MAX / 2)) {
663  return 1;
664  }
665 
666  return 0;
667 }
const cJSON *const b
Definition: switch_cJSON.h:243

◆ check_ts()

static int check_ts ( uint32_t  a,
uint32_t  b 
)
inlinestatic

Definition at line 669 of file switch_jitterbuffer.c.

Referenced by add_node(), and switch_jb_get_packet().

670 {
671  a = ntohl(a);
672  b = ntohl(b);
673 
674  if (a > b || (b > a && b > UINT_MAX / 2 && a < UINT_MAX / 2)) {
675  return 1;
676  }
677 
678  return 0;
679 }
const cJSON *const b
Definition: switch_cJSON.h:243

◆ decrement_seq()

static void decrement_seq ( switch_jb_t jb)
inlinestatic

Definition at line 785 of file switch_jitterbuffer.c.

References switch_jb_s::last_target_seq, and switch_jb_s::target_seq.

Referenced by switch_jb_get_packet().

786 {
787  jb->last_target_seq = jb->target_seq;
788  jb->target_seq = htons((ntohs(jb->target_seq) - 1));
789 }
uint32_t last_target_seq

◆ drop_oldest_frame()

static void drop_oldest_frame ( switch_jb_t jb)
inlinestatic

Definition at line 635 of file switch_jitterbuffer.c.

References drop_ts(), switch_rtp_packet_t::header, jb_debug, jb_find_lowest_ts(), switch_jb_node_s::packet, and switch_rtp_hdr_t::ts.

Referenced by switch_jb_put_packet().

636 {
637  uint32_t ts = jb_find_lowest_ts(jb);
638 
639  drop_ts(jb, ts);
640  jb_debug(jb, 1, "Dropping oldest frame ts:%u\n", ntohl(ts));
641 }
#define jb_debug(_jb, _level, _format,...)
static uint32_t jb_find_lowest_ts(switch_jb_t *jb)
static void drop_ts(switch_jb_t *jb, uint32_t ts)

◆ drop_ts()

static void drop_ts ( switch_jb_t jb,
uint32_t  ts 
)
inlinestatic

Definition at line 384 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::header, hide_node(), switch_jb_s::list_mutex, switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::packet, sort_free_nodes(), SWITCH_FALSE, switch_mutex_lock(), switch_mutex_unlock(), switch_rtp_hdr_t::ts, and switch_jb_node_s::visible.

Referenced by drop_oldest_frame(), jb_find_lowest_ts(), and jb_next_packet_by_seq().

385 {
386  switch_jb_node_t *np;
387  int x = 0;
388 
390  for (np = jb->node_list; np; np = np->next) {
391  if (!np->visible) continue;
392 
393  if (ts == np->packet.header.ts) {
394  hide_node(np, SWITCH_FALSE);
395  x++;
396  }
397  }
398 
399  if (x) {
400  sort_free_nodes(jb);
401  }
402 
404 }
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
struct switch_jb_node_s * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
static void sort_free_nodes(switch_jb_t *jb)
switch_mutex_t * list_mutex
switch_rtp_packet_t packet
static void hide_node(switch_jb_node_t *node, switch_bool_t pop)
struct switch_jb_node_s * node_list

◆ free_nodes()

static void free_nodes ( switch_jb_t jb)
inlinestatic

Definition at line 1065 of file switch_jitterbuffer.c.

References switch_jb_s::list_mutex, switch_jb_s::node_list, switch_mutex_lock(), and switch_mutex_unlock().

Referenced by switch_jb_destroy().

1066 {
1068  jb->node_list = NULL;
1070 }
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_mutex_t * list_mutex
struct switch_jb_node_s * node_list

◆ hide_node()

static void hide_node ( switch_jb_node_t node,
switch_bool_t  pop 
)
inlinestatic

Definition at line 316 of file switch_jitterbuffer.c.

References switch_jb_node_s::bad_hits, switch_jb_node_s::complete_frame_mark, switch_jb_s::complete_frames, FALSE, switch_rtp_packet_t::header, switch_jb_s::list_mutex, switch_jb_s::node_hash, switch_jb_s::node_hash_ts, switch_jb_node_s::packet, switch_jb_node_s::parent, push_to_top(), switch_rtp_hdr_t::seq, SJB_VIDEO, switch_core_inthash_delete(), switch_mutex_lock(), switch_mutex_unlock(), switch_rtp_hdr_t::ts, switch_jb_s::type, switch_jb_node_s::visible, and switch_jb_s::visible_nodes.

Referenced by check_jb_size(), drop_ts(), hide_nodes(), and switch_jb_get_packet().

317 {
318  switch_jb_t *jb = node->parent;
319 
321 
322  if (node->visible) {
323  node->visible = 0;
324  node->bad_hits = 0;
325  jb->visible_nodes--;
326 
327  if (pop) {
328  push_to_top(jb, node);
329  }
330  }
331 
332  if (jb->node_hash_ts) {
334  }
335 
337  if (node->complete_frame_mark && jb->type == SJB_VIDEO) {
338  jb->complete_frames--;
339  node->complete_frame_mark = FALSE;
340  }
341  }
342 
344 }
switch_jb_type_t type
switch_inthash_t * node_hash
switch_inthash_t * node_hash_ts
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
switch_bool_t complete_frame_mark
uint32_t complete_frames
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
struct switch_jb_s * parent
void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key)
static void push_to_top(switch_jb_t *jb, switch_jb_node_t *node)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
uint32_t visible_nodes
#define FALSE
switch_mutex_t * list_mutex
switch_rtp_packet_t packet

◆ hide_nodes()

static void hide_nodes ( switch_jb_t jb)
inlinestatic

Definition at line 353 of file switch_jitterbuffer.c.

References hide_node(), switch_jb_s::list_mutex, switch_jb_node_s::next, switch_jb_s::node_list, SWITCH_FALSE, switch_mutex_lock(), and switch_mutex_unlock().

Referenced by switch_jb_reset().

354 {
355  switch_jb_node_t *np;
356 
358  for (np = jb->node_list; np; np = np->next) {
359  hide_node(np, SWITCH_FALSE);
360  }
362 }
struct switch_jb_node_s * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_mutex_t * list_mutex
static void hide_node(switch_jb_node_t *node, switch_bool_t pop)
struct switch_jb_node_s * node_list

◆ increment_seq()

static void increment_seq ( switch_jb_t jb)
inlinestatic

Definition at line 779 of file switch_jitterbuffer.c.

References switch_jb_s::last_target_seq, and switch_jb_s::target_seq.

Referenced by jb_next_packet_by_seq().

780 {
781  jb->last_target_seq = jb->target_seq;
782  jb->target_seq = htons((ntohs(jb->target_seq) + 1));
783 }
uint32_t last_target_seq

◆ increment_ts()

static void increment_ts ( switch_jb_t jb)
inlinestatic

Definition at line 758 of file switch_jitterbuffer.c.

References switch_jb_s::last_psuedo_seq, switch_jb_s::last_target_ts, switch_jb_s::psuedo_seq, switch_jb_s::samples_per_frame, and switch_jb_s::target_ts.

Referenced by jb_next_packet_by_ts().

759 {
760  if (!jb->target_ts) return;
761 
762  jb->last_psuedo_seq = jb->psuedo_seq;
763  jb->last_target_ts = jb->target_ts;
764  jb->target_ts = htonl((ntohl(jb->target_ts) + jb->samples_per_frame));
765  jb->psuedo_seq++;
766 }
uint32_t last_target_ts
uint16_t last_psuedo_seq
uint32_t samples_per_frame

◆ jb_find_lowest_node()

static switch_jb_node_t* jb_find_lowest_node ( switch_jb_t jb)
inlinestatic

Definition at line 425 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::header, switch_jb_s::list_mutex, switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::packet, switch_mutex_lock(), switch_mutex_unlock(), switch_rtp_hdr_t::ts, and switch_jb_node_s::visible.

Referenced by jb_find_lowest_ts(), jb_miss(), and jb_next_packet_by_ts().

426 {
427  switch_jb_node_t *np, *lowest = NULL;
428 
430  for (np = jb->node_list; np; np = np->next) {
431  if (!np->visible) continue;
432 
433  if (!lowest || ntohl(lowest->packet.header.ts) > ntohl(np->packet.header.ts)) {
434  lowest = np;
435  }
436  }
438 
439  return lowest ? lowest : NULL;
440 }
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
struct switch_jb_node_s * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_mutex_t * list_mutex
switch_rtp_packet_t packet
struct switch_jb_node_s * node_list

◆ jb_find_lowest_seq()

static switch_jb_node_t* jb_find_lowest_seq ( switch_jb_t jb,
uint32_t  ts 
)
inlinestatic

Definition at line 406 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::header, switch_jb_s::list_mutex, switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::packet, switch_rtp_hdr_t::seq, switch_mutex_lock(), switch_mutex_unlock(), switch_rtp_hdr_t::ts, and switch_jb_node_s::visible.

Referenced by jb_miss(), and jb_next_packet_by_seq().

407 {
408  switch_jb_node_t *np, *lowest = NULL;
409 
411  for (np = jb->node_list; np; np = np->next) {
412  if (!np->visible) continue;
413 
414  if (ts && ts != np->packet.header.ts) continue;
415 
416  if (!lowest || ntohs(lowest->packet.header.seq) > ntohs(np->packet.header.seq)) {
417  lowest = np;
418  }
419  }
421 
422  return lowest;
423 }
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
struct switch_jb_node_s * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_mutex_t * list_mutex
switch_rtp_packet_t packet
struct switch_jb_node_s * node_list

◆ jb_find_lowest_ts()

static uint32_t jb_find_lowest_ts ( switch_jb_t jb)
inlinestatic

◆ jb_frame_inc_line()

static void jb_frame_inc_line ( switch_jb_t jb,
int  i,
int  line 
)
static

Definition at line 541 of file switch_jitterbuffer.c.

References switch_jb_s::frame_len, switch_jb_s::highest_frame_len, jb_debug, switch_jb_s::max_frame_len, and switch_jb_s::min_frame_len.

542 {
543  uint32_t old_frame_len = jb->frame_len;
544 
545  if (i == 0) {
546  jb->frame_len = jb->min_frame_len;
547  goto end;
548  }
549 
550  if (i > 0) {
551  if ((jb->frame_len + i) < jb->max_frame_len) {
552  jb->frame_len += i;
553  } else {
554  jb->frame_len = jb->max_frame_len;
555  }
556 
557  goto end;
558  }
559 
560  /* i < 0 */
561  if ((jb->frame_len + i) > jb->min_frame_len) {
562  jb->frame_len += i;
563  } else {
564  jb->frame_len = jb->min_frame_len;
565  }
566 
567  end:
568 
569  if (jb->frame_len > jb->highest_frame_len) {
570  jb->highest_frame_len = jb->frame_len;
571  }
572 
573  if (old_frame_len != jb->frame_len) {
574  jb_debug(jb, 1, "%d Change framelen from %u to %u\n", line, old_frame_len, jb->frame_len);
575 
576  //if (jb->session) {
577  // switch_core_session_request_video_refresh(jb->session);
578  //}
579  }
580 
581 }
uint32_t min_frame_len
#define jb_debug(_jb, _level, _format,...)
uint32_t max_frame_len
uint32_t highest_frame_len

◆ jb_hit()

static void jb_hit ( switch_jb_t jb)
inlinestatic

◆ jb_miss()

static void jb_miss ( switch_jb_t jb)
inlinestatic

◆ jb_next_packet()

static switch_status_t jb_next_packet ( switch_jb_t jb,
switch_jb_node_t **  nodep 
)
inlinestatic

Definition at line 1052 of file switch_jitterbuffer.c.

References switch_jb_s::elastic, switch_jb_jitter_s::estimate, jb_next_packet_by_seq(), jb_next_packet_by_seq_with_acceleration(), jb_next_packet_by_ts(), switch_jb_s::jitter, and switch_jb_s::samples_per_frame.

Referenced by switch_jb_get_packet().

1053 {
1054  if (jb->samples_per_frame) {
1055  return jb_next_packet_by_ts(jb, nodep);
1056  }
1057 
1058  if (jb->elastic && jb->jitter.estimate) {
1059  return jb_next_packet_by_seq_with_acceleration(jb, nodep);
1060  }
1061 
1062  return jb_next_packet_by_seq(jb, nodep);
1063 }
switch_jb_jitter_t jitter
switch_bool_t elastic
static switch_status_t jb_next_packet_by_ts(switch_jb_t *jb, switch_jb_node_t **nodep)
static switch_status_t jb_next_packet_by_seq_with_acceleration(switch_jb_t *jb, switch_jb_node_t **nodep)
static switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_node_t **nodep)
uint32_t samples_per_frame

◆ jb_next_packet_by_seq()

static switch_status_t jb_next_packet_by_seq ( switch_jb_t jb,
switch_jb_node_t **  nodep 
)
inlinestatic

Definition at line 797 of file switch_jitterbuffer.c.

References drop_ts(), switch_jb_s::dropped, switch_rtp_packet_t::header, switch_jb_s::highest_dropped_ts, switch_jb_s::highest_read_ts, increment_seq(), jb_debug, jb_find_lowest_seq(), jb_frame_inc, jb_hit(), jb_miss(), switch_rtp_hdr_t::m, switch_jb_s::node_hash, switch_jb_node_s::packet, switch_jb_s::period_miss_count, switch_jb_s::period_miss_inc, switch_rtp_hdr_t::seq, switch_jb_s::session, set_read_seq(), SJB_VIDEO, switch_core_inthash_find(), switch_core_session_request_video_refresh, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, switch_jb_s::target_seq, switch_rtp_hdr_t::ts, and switch_jb_s::type.

Referenced by jb_next_packet(), and jb_next_packet_by_seq_with_acceleration().

798 {
799  switch_jb_node_t *node = NULL;
800 
801  top:
802 
803  if (jb->type == SJB_VIDEO) {
804  if (jb->dropped) {
805  jb->dropped = 0;
806  jb_debug(jb, 2, "%s", "DROPPED FRAME DETECTED RESYNCING\n");
807  jb->target_seq = 0;
808 
809  if (jb->session) {
811  }
812  }
813  }
814 
815  if (!jb->target_seq) {
816  if ((node = switch_core_inthash_find(jb->node_hash, jb->target_seq))) {
817  jb_debug(jb, 2, "FOUND rollover seq: %u\n", ntohs(jb->target_seq));
818  } else if ((node = jb_find_lowest_seq(jb, 0))) {
819  jb_debug(jb, 2, "No target seq using seq: %u as a starting point\n", ntohs(node->packet.header.seq));
820  } else {
821  jb_debug(jb, 1, "%s", "No nodes available....\n");
822  }
823  jb_hit(jb);
824  } else if ((node = switch_core_inthash_find(jb->node_hash, jb->target_seq))) {
825  jb_debug(jb, 2, "FOUND desired seq: %u\n", ntohs(jb->target_seq));
826  jb_hit(jb);
827  } else {
828  jb_debug(jb, 2, "MISSING desired seq: %u\n", ntohs(jb->target_seq));
829  jb_miss(jb);
830 
831  if (jb->type == SJB_VIDEO) {
832  int x;
833 
834  if (jb->session) {
836  }
837 
838  for (x = 0; x < 10; x++) {
839  increment_seq(jb);
840  if ((node = switch_core_inthash_find(jb->node_hash, jb->target_seq))) {
841  jb_debug(jb, 2, "FOUND incremental seq: %u\n", ntohs(jb->target_seq));
842 
843  if (node->packet.header.m || node->packet.header.ts == jb->highest_read_ts) {
844  jb_debug(jb, 2, "%s", "SAME FRAME DROPPING\n");
845  jb->dropped++;
846  drop_ts(jb, node->packet.header.ts);
847  jb->highest_dropped_ts = ntohl(node->packet.header.ts);
848 
849 
850  if (jb->period_miss_count > 2 && jb->period_miss_inc < 1) {
851  jb->period_miss_inc++;
852  jb_frame_inc(jb, 1);
853  }
854 
855  node = NULL;
856  goto top;
857  }
858  break;
859  } else {
860  jb_debug(jb, 2, "MISSING incremental seq: %u\n", ntohs(jb->target_seq));
861  }
862  }
863 
864  } else {
865  increment_seq(jb);
866  }
867  }
868 
869  *nodep = node;
870 
871  if (node) {
872  set_read_seq(jb, node->packet.header.seq);
873  return SWITCH_STATUS_SUCCESS;
874  }
875 
876  return SWITCH_STATUS_NOTFOUND;
877 
878 }
switch_jb_type_t type
static switch_jb_node_t * jb_find_lowest_seq(switch_jb_t *jb, uint32_t ts)
switch_inthash_t * node_hash
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
uint32_t highest_read_ts
#define jb_debug(_jb, _level, _format,...)
void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key)
#define jb_frame_inc(_jb, _i)
static void set_read_seq(switch_jb_t *jb, uint16_t seq)
uint32_t highest_dropped_ts
static void jb_hit(switch_jb_t *jb)
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2892
static void drop_ts(switch_jb_t *jb, uint32_t ts)
static void increment_seq(switch_jb_t *jb)
uint32_t period_miss_inc
uint32_t period_miss_count
switch_core_session_t * session
static void jb_miss(switch_jb_t *jb)
switch_rtp_packet_t packet

◆ jb_next_packet_by_seq_with_acceleration()

static switch_status_t jb_next_packet_by_seq_with_acceleration ( switch_jb_t jb,
switch_jb_node_t **  nodep 
)
inlinestatic

Definition at line 996 of file switch_jitterbuffer.c.

References switch_jb_stats_s::acceleration, switch_jb_stats_s::buffer_size_ms, check_jb_size(), switch_jb_s::complete_frames, switch_jb_jitter_s::drop_gap, switch_jb_s::elastic, switch_jb_jitter_s::estimate, switch_jb_stats_s::estimate_ms, switch_jb_s::frame_len, jb_debug, jb_next_packet_by_seq(), switch_jb_s::jitter, switch_jb_node_s::len, switch_jb_node_s::packet, packet_vad(), switch_jb_jitter_s::samples_per_frame, switch_jb_jitter_s::samples_per_second, switch_jb_jitter_s::stats, SWITCH_FALSE, SWITCH_LOG_INFO, SWITCH_STATUS_SUCCESS, switch_jb_s::target_seq, and switch_jb_s::visible_nodes.

Referenced by jb_next_packet().

997 {
998  switch_status_t status = jb_next_packet_by_seq(jb, nodep);
999  switch_rtp_packet_t *packet;
1000  uint32_t len;
1001  uint16_t seq = ntohs(jb->target_seq);
1002 
1003  /* When using a Codec that provides voice activity detection ex. Opus, use it to
1004  select packet to drop/accelerate. */
1005 
1006  if (jb->elastic && jb->jitter.estimate && (jb->visible_nodes * jb->jitter.samples_per_frame) > 0 && jb->jitter.samples_per_second) {
1007  int visible_not_old = check_jb_size(jb);
1008 
1009  jb->jitter.stats.estimate_ms = (int)((*jb->jitter.estimate) / ((jb->jitter.samples_per_second)) * 1000);
1010  jb->jitter.stats.buffer_size_ms = (int)((visible_not_old * jb->jitter.samples_per_frame) / (jb->jitter.samples_per_second / 1000));
1011 
1012  /* We try to accelerate in order to remove delay when the jitter buffer is 3x larger than the estimation. */
1013  if (jb->jitter.stats.buffer_size_ms > (3 * jb->jitter.stats.estimate_ms) && jb->jitter.stats.buffer_size_ms > 60) {
1014  if (status == SWITCH_STATUS_SUCCESS) {
1015  packet = &(*nodep)->packet;
1016  seq = ntohs((*nodep)->packet.header.seq);
1017  len = (*nodep)->len;
1018  }
1019 
1020  if (jb->jitter.drop_gap > 0) {
1021  jb_debug(jb, SWITCH_LOG_INFO, "JITTER estimation %dms buffersize %d/%d %dms seq:%u [drop-gap][%d]\n",
1023  jb->jitter.drop_gap--;
1024  } else {
1025  if (status != SWITCH_STATUS_SUCCESS || packet_vad(jb, packet, len) == SWITCH_FALSE) {
1026  jb->jitter.drop_gap = 3;
1027  if (status != SWITCH_STATUS_SUCCESS) {
1028  jb_debug(jb, SWITCH_LOG_INFO, "JITTER estimation n/a buffersize %d/%d %dms seq:%u [drop-missing/no-plc]\n",
1029  jb->complete_frames, jb->frame_len, jb->jitter.stats.buffer_size_ms, seq);
1030  } else {
1031  jb_debug(jb, SWITCH_LOG_INFO, "JITTER estimation %dms buffersize %d/%d %dms seq:%u ACCELERATE [drop]\n",
1033  }
1034 
1035  jb->jitter.stats.acceleration++;
1036 
1037  return jb_next_packet_by_seq(jb, nodep);
1038  } else {
1039  jb_debug(jb, SWITCH_LOG_INFO, "JITTER estimation %dms buffersize %d/%d %dms seq:%u [drop-skip-vad]\n",
1041  }
1042  }
1043  } else {
1044  jb_debug(jb, 2, "JITTER estimation %dms buffersize %d/%d %dms\n",
1046  }
1047  }
1048 
1049  return status;
1050 }
switch_jb_jitter_t jitter
switch_bool_t elastic
uint32_t complete_frames
#define jb_debug(_jb, _level, _format,...)
static switch_bool_t packet_vad(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
uint32_t visible_nodes
static int check_jb_size(switch_jb_t *jb)
switch_status_t
Common return values.
static switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_node_t **nodep)
switch_jb_stats_t stats

◆ jb_next_packet_by_ts()

static switch_status_t jb_next_packet_by_ts ( switch_jb_t jb,
switch_jb_node_t **  nodep 
)
inlinestatic

Definition at line 881 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::header, increment_ts(), jb_debug, jb_find_lowest_node(), jb_hit(), jb_miss(), switch_jb_s::node_hash_ts, switch_jb_node_s::packet, switch_jb_s::psuedo_seq, switch_rtp_hdr_t::seq, set_read_ts(), switch_core_inthash_find(), SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, switch_jb_s::target_ts, and switch_rtp_hdr_t::ts.

Referenced by jb_next_packet().

882 {
883  switch_jb_node_t *node = NULL;
884 
885  if (!jb->target_ts) {
886  if ((node = jb_find_lowest_node(jb))) {
887  jb_debug(jb, 2, "No target ts using ts: %u as a starting point\n", ntohl(node->packet.header.ts));
888  } else {
889  jb_debug(jb, 1, "%s", "No nodes available....\n");
890  }
891  jb_hit(jb);
892  } else if ((node = switch_core_inthash_find(jb->node_hash_ts, jb->target_ts))) {
893  jb_debug(jb, 2, "FOUND desired ts: %u\n", ntohl(jb->target_ts));
894  jb_hit(jb);
895  } else {
896  jb_debug(jb, 2, "MISSING desired ts: %u\n", ntohl(jb->target_ts));
897  jb_miss(jb);
898  increment_ts(jb);
899  }
900 
901  *nodep = node;
902 
903  if (node) {
904  set_read_ts(jb, node->packet.header.ts);
905  node->packet.header.seq = htons(jb->psuedo_seq);
906  return SWITCH_STATUS_SUCCESS;
907  }
908 
909  return SWITCH_STATUS_NOTFOUND;
910 
911 }
switch_inthash_t * node_hash_ts
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
#define jb_debug(_jb, _level, _format,...)
void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key)
static switch_jb_node_t * jb_find_lowest_node(switch_jb_t *jb)
static void jb_hit(switch_jb_t *jb)
static void increment_ts(switch_jb_t *jb)
static void set_read_ts(switch_jb_t *jb, uint32_t ts)
static void jb_miss(switch_jb_t *jb)
switch_rtp_packet_t packet

◆ new_node()

static switch_jb_node_t* new_node ( switch_jb_t jb)
inlinestatic

Definition at line 239 of file switch_jitterbuffer.c.

References switch_jb_s::allocated_nodes, switch_jb_node_s::bad_hits, jb_debug, switch_jb_s::jitter, switch_jb_s::list_mutex, switch_jb_s::max_frame_len, switch_jb_s::max_packet_len, switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::parent, switch_jb_s::pool, switch_jb_node_s::prev, switch_jb_stats_s::reset_too_big, SJB_VIDEO, switch_jb_jitter_s::stats, switch_assert, switch_core_alloc, switch_jb_reset(), switch_mutex_lock(), switch_mutex_unlock(), switch_jb_s::type, switch_jb_node_s::visible, and switch_jb_s::visible_nodes.

Referenced by add_node().

240 {
241  switch_jb_node_t *np;
242 
244 
245  for (np = jb->node_list; np; np = np->next) {
246  if (!np->visible) {
247  break;
248  }
249  }
250 
251  if (!np) {
252  int mult = 2;
253 
254  if (jb->type != SJB_VIDEO) {
255  mult = 2;
256  } else {
257  if (jb->max_packet_len > mult) {
258  mult = jb->max_packet_len;
259  }
260  }
261 
262  if (jb->allocated_nodes > jb->max_frame_len * mult) {
263  jb_debug(jb, 2, "ALLOCATED FRAMES TOO HIGH! %d\n", jb->allocated_nodes);
264  jb->jitter.stats.reset_too_big++;
265  switch_jb_reset(jb);
267  return NULL;
268  }
269 
270  np = switch_core_alloc(jb->pool, sizeof(*np));
271  jb->allocated_nodes++;
272  np->next = jb->node_list;
273  if (np->next) {
274  np->next->prev = np;
275  }
276  jb->node_list = np;
277 
278  }
279 
280  switch_assert(np);
281  np->bad_hits = 0;
282  np->visible = 1;
283  jb->visible_nodes++;
284  np->parent = jb;
285 
287 
288  return np;
289 }
switch_jb_type_t type
switch_jb_jitter_t jitter
struct switch_jb_node_s * next
#define jb_debug(_jb, _level, _format,...)
uint32_t max_frame_len
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
struct switch_jb_s * parent
uint32_t max_packet_len
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
uint32_t visible_nodes
switch_mutex_t * list_mutex
uint32_t allocated_nodes
struct switch_jb_node_s * prev
switch_memory_pool_t * pool
switch_jb_stats_t stats
#define switch_assert(expr)
struct switch_jb_node_s * node_list
void switch_jb_reset(switch_jb_t *jb)

◆ node_cmp()

static int node_cmp ( const void *  l,
const void *  r 
)
static

Definition at line 146 of file switch_jitterbuffer.c.

References b, switch_rtp_packet_t::header, switch_jb_node_s::packet, switch_rtp_hdr_t::seq, and switch_jb_node_s::visible.

Referenced by jb_miss(), and sort_free_nodes().

147 {
150 
151  if (!a->visible) return 0;
152  if (!b->visible) return 1;
153 
154  return ntohs(a->packet.header.seq) - ntohs(b->packet.header.seq);
155 }
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
const cJSON *const b
Definition: switch_cJSON.h:243
switch_rtp_packet_t packet

◆ packet_vad()

static switch_bool_t packet_vad ( switch_jb_t jb,
switch_rtp_packet_t packet,
switch_size_t  len 
)
inlinestatic

Definition at line 364 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::body, switch_rtp_packet_t::ebody, switch_jb_node_s::len, SCC_AUDIO_VAD, SCCT_INT, SCCT_STRING, switch_jb_s::session, switch_core_media_codec_control(), SWITCH_FALSE, SWITCH_IO_WRITE, SWITCH_MEDIA_TYPE_AUDIO, and SWITCH_TRUE.

Referenced by jb_next_packet_by_seq_with_acceleration().

364  {
365  void *payload = packet ? (packet->ebody ? packet->ebody : packet->body) : NULL;
366  uint16_t payload_len = len;
367 
368  if (payload && payload_len > 0) {
369  switch_bool_t ret = SWITCH_FALSE, *ret_p = &ret;
371 
374  SCCT_STRING, (void *)payload,
375  SCCT_INT, (void *)&payload_len,
376  &ret_t, (void *)&ret_p);
377 
378  return ret;
379  }
380 
381  return SWITCH_TRUE;
382 }
switch_bool_t
Definition: switch_types.h:441
switch_codec_control_type_t
switch_status_t switch_core_media_codec_control(switch_core_session_t *session, switch_media_type_t mtype, switch_io_type_t iotype, switch_codec_control_command_t cmd, switch_codec_control_type_t ctype, void *cmd_data, switch_codec_control_type_t atype, void *cmd_arg, switch_codec_control_type_t *rtype, void **ret_data)
char body[SWITCH_RTP_MAX_BUF_LEN+4+sizeof(char *)]
Definition: switch_rtp.h:57
switch_core_session_t * session

◆ push_to_top()

static void push_to_top ( switch_jb_t jb,
switch_jb_node_t node 
)
inlinestatic

Definition at line 291 of file switch_jitterbuffer.c.

References switch_jb_node_s::next, switch_jb_s::node_list, switch_jb_node_s::prev, and switch_assert.

Referenced by hide_node().

292 {
293  if (node == jb->node_list) {
294  jb->node_list = node->next;
295  } else if (node->prev) {
296  node->prev->next = node->next;
297  }
298 
299  if (node->next) {
300  node->next->prev = node->prev;
301  }
302 
303  node->next = jb->node_list;
304  node->prev = NULL;
305 
306  if (node->next) {
307  node->next->prev = node;
308  }
309 
310  jb->node_list = node;
311 
312  switch_assert(node->next != node);
313  switch_assert(node->prev != node);
314 }
struct switch_jb_node_s * next
struct switch_jb_node_s * prev
#define switch_assert(expr)
struct switch_jb_node_s * node_list

◆ set_read_seq()

static void set_read_seq ( switch_jb_t jb,
uint16_t  seq 
)
inlinestatic

Definition at line 791 of file switch_jitterbuffer.c.

References switch_jb_s::last_target_seq, and switch_jb_s::target_seq.

Referenced by jb_next_packet_by_seq().

792 {
793  jb->last_target_seq = seq;
794  jb->target_seq = htons((ntohs(jb->last_target_seq) + 1));
795 }
uint32_t last_target_seq

◆ set_read_ts()

static void set_read_ts ( switch_jb_t jb,
uint32_t  ts 
)
inlinestatic

Definition at line 768 of file switch_jitterbuffer.c.

References switch_jb_s::last_psuedo_seq, switch_jb_s::last_target_ts, switch_jb_s::psuedo_seq, switch_jb_s::samples_per_frame, and switch_jb_s::target_ts.

Referenced by jb_next_packet_by_ts().

769 {
770  if (!ts) return;
771 
772  jb->last_psuedo_seq = jb->psuedo_seq;
773  jb->last_target_ts = ts;
774  jb->target_ts = htonl((ntohl(jb->last_target_ts) + jb->samples_per_frame));
775  jb->psuedo_seq++;
776 }
uint32_t last_target_ts
uint16_t last_psuedo_seq
uint32_t samples_per_frame

◆ sort_free_nodes()

static void sort_free_nodes ( switch_jb_t jb)
inlinestatic

Definition at line 346 of file switch_jitterbuffer.c.

References switch_jb_s::list_mutex, node_cmp(), switch_jb_s::node_list, sort_nodes(), switch_mutex_lock(), and switch_mutex_unlock().

Referenced by check_jb_size(), drop_ts(), and jb_find_lowest_ts().

347 {
351 }
switch_jb_node_t * sort_nodes(switch_jb_node_t *list, int(*cmp)(const void *, const void *))
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
static int node_cmp(const void *l, const void *r)
switch_mutex_t * list_mutex
struct switch_jb_node_s * node_list

◆ sort_nodes()

switch_jb_node_t* sort_nodes ( switch_jb_node_t list,
int(*)(const void *, const void *)  cmp 
)

Definition at line 158 of file switch_jitterbuffer.c.

References switch_jb_node_s::next, and switch_jb_node_s::prev.

Referenced by jb_miss(), and sort_free_nodes().

158  {
159  switch_jb_node_t *p, *q, *e, *tail;
160  int insize, nmerges, psize, qsize, i;
161 
162  if (!list) {
163  return NULL;
164  }
165 
166  insize = 1;
167 
168  while (1) {
169  p = list;
170  list = NULL;
171  tail = NULL;
172 
173  nmerges = 0; /* count number of merges we do in this pass */
174 
175  while (p) {
176  nmerges++; /* there exists a merge to be done */
177  /* step `insize' places along from p */
178  q = p;
179  psize = 0;
180  for (i = 0; i < insize; i++) {
181  psize++;
182  q = q->next;
183  if (!q) break;
184  }
185 
186  /* if q hasn't fallen off end, we have two lists to merge */
187  qsize = insize;
188 
189  /* now we have two lists; merge them */
190  while (psize > 0 || (qsize > 0 && q)) {
191 
192  /* decide whether next switch_jb_node_t of merge comes from p or q */
193  if (psize == 0) {
194  /* p is empty; e must come from q. */
195  e = q; q = q->next; qsize--;
196  } else if (qsize == 0 || !q) {
197  /* q is empty; e must come from p. */
198  e = p; p = p->next; psize--;
199  } else if (cmp(p,q) <= 0) {
200  /* First switch_jb_node_t of p is lower (or same);
201  * e must come from p. */
202  e = p; p = p->next; psize--;
203  } else {
204  /* First switch_jb_node_t of q is lower; e must come from q. */
205  e = q; q = q->next; qsize--;
206  }
207 
208  /* add the next switch_jb_node_t to the merged list */
209  if (tail) {
210  tail->next = e;
211  } else {
212  list = e;
213  }
214 
215  /* Maintain reverse pointers in a doubly linked list. */
216  e->prev = tail;
217 
218  tail = e;
219  }
220 
221  /* now p has stepped `insize' places along, and q has too */
222  p = q;
223  }
224 
225  tail->next = NULL;
226 
227  /* If we have done only one merge, we're finished. */
228  if (nmerges <= 1) /* allow for nmerges==0, the empty list case */
229  return list;
230 
231  /* Otherwise repeat, merging lists twice the size */
232  insize *= 2;
233  }
234 }
struct switch_jb_node_s * next
struct switch_jb_node_s * prev

◆ switch_jb_clear_flag()

void switch_jb_clear_flag ( switch_jb_t jb,
switch_jb_flag_t  flag 
)

Definition at line 1143 of file switch_jitterbuffer.c.

References switch_clear_flag.

1144 {
1145  switch_clear_flag(jb, flag);
1146 }
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724

◆ switch_jb_create()

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 
)

Definition at line 1322 of file switch_jitterbuffer.c.

References switch_jb_s::frame_len, switch_jb_s::free_pool, switch_jb_s::highest_frame_len, switch_jb_s::list_mutex, switch_jb_s::max_frame_len, switch_jb_s::min_frame_len, switch_jb_s::missing_seq_hash, switch_jb_s::mutex, switch_jb_s::node_hash, switch_jb_s::period_len, pool, switch_jb_s::pool, SJB_VIDEO, switch_core_alloc, switch_core_inthash_init(), switch_core_new_memory_pool, switch_mutex_init(), SWITCH_MUTEX_NESTED, SWITCH_STATUS_SUCCESS, and switch_jb_s::type.

Referenced by rtp_common_write(), switch_ivr_delay_echo(), switch_rtp_activate_jitter_buffer(), and switch_rtp_set_video_buffer_size().

1324 {
1325  switch_jb_t *jb;
1326  int free_pool = 0;
1327 
1328  if (!pool) {
1330  free_pool = 1;
1331  }
1332 
1333  jb = switch_core_alloc(pool, sizeof(*jb));
1334  jb->free_pool = free_pool;
1335  jb->min_frame_len = jb->frame_len = min_frame_len;
1336  jb->max_frame_len = max_frame_len;
1337  jb->pool = pool;
1338  jb->type = type;
1339  jb->highest_frame_len = jb->frame_len;
1340 
1341  if (jb->type == SJB_VIDEO) {
1343  jb->period_len = 2500;
1344  } else {
1345  jb->period_len = 250;
1346  }
1347 
1351 
1352  *jbp = jb;
1353 
1354  return SWITCH_STATUS_SUCCESS;
1355 }
switch_jb_type_t type
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
switch_status_t switch_core_inthash_init(switch_inthash_t **hash)
switch_inthash_t * node_hash
uint32_t min_frame_len
switch_inthash_t * missing_seq_hash
switch_memory_pool_t * pool
uint32_t max_frame_len
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_mutex_t * mutex
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
switch_mutex_t * list_mutex
uint32_t highest_frame_len
switch_memory_pool_t * pool

◆ switch_jb_debug_level()

void switch_jb_debug_level ( switch_jb_t jb,
uint8_t  level 
)

Definition at line 1169 of file switch_jitterbuffer.c.

References switch_jb_s::debug_level.

Referenced by switch_ivr_delay_echo(), and switch_rtp_debug_jitter_buffer().

1170 {
1171  jb->debug_level = level;
1172 }

◆ switch_jb_destroy()

switch_status_t switch_jb_destroy ( switch_jb_t **  jbp)

Definition at line 1357 of file switch_jitterbuffer.c.

References free_nodes(), switch_jb_s::free_pool, jb_debug, switch_jb_s::missing_seq_hash, switch_jb_s::nack_didnt_save_the_day, switch_jb_s::nack_saved_the_day, switch_jb_s::node_hash, switch_jb_s::node_hash_ts, switch_jb_s::pool, SJB_QUEUE_ONLY, SJB_VIDEO, switch_core_destroy_memory_pool, switch_core_inthash_destroy(), switch_hashtable_count(), SWITCH_STATUS_SUCCESS, switch_test_flag, and switch_jb_s::type.

Referenced by read_rtp_packet(), switch_ivr_delay_echo(), and switch_rtp_destroy().

1358 {
1359  switch_jb_t *jb = *jbp;
1360  *jbp = NULL;
1361 
1362  if (jb->type == SJB_VIDEO && !switch_test_flag(jb, SJB_QUEUE_ONLY)) {
1363  jb_debug(jb, 3, "Stats: NACK saved the day: %u\n", jb->nack_saved_the_day);
1364  jb_debug(jb, 3, "Stats: NACK was late: %u\n", jb->nack_didnt_save_the_day);
1365  jb_debug(jb, 3, "Stats: Hash entrycount: missing_seq_hash %u\n", switch_hashtable_count(jb->missing_seq_hash));
1366  }
1367  if (jb->type == SJB_VIDEO) {
1369  }
1371 
1372  if (jb->node_hash_ts) {
1374  }
1375 
1376  free_nodes(jb);
1377 
1378  if (jb->free_pool) {
1380  }
1381 
1382  return SWITCH_STATUS_SUCCESS;
1383 }
switch_jb_type_t type
switch_inthash_t * node_hash
switch_inthash_t * node_hash_ts
switch_inthash_t * missing_seq_hash
uint32_t nack_saved_the_day
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
#define jb_debug(_jb, _level, _format,...)
switch_status_t switch_core_inthash_destroy(switch_inthash_t **hash)
uint32_t nack_didnt_save_the_day
static void free_nodes(switch_jb_t *jb)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
switch_memory_pool_t * pool
unsigned int switch_hashtable_count(switch_hashtable_t *h)

◆ switch_jb_frame_count()

int switch_jb_frame_count ( switch_jb_t jb)

Definition at line 1164 of file switch_jitterbuffer.c.

References switch_jb_s::complete_frames.

1165 {
1166  return jb->complete_frames;
1167 }
uint32_t complete_frames

◆ switch_jb_get_frames()

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 
)

Definition at line 1268 of file switch_jitterbuffer.c.

References switch_jb_s::frame_len, switch_jb_s::max_frame_len, switch_jb_s::min_frame_len, switch_jb_s::mutex, switch_mutex_lock(), switch_mutex_unlock(), and SWITCH_STATUS_SUCCESS.

Referenced by switch_rtp_get_stats(), and switch_rtp_get_video_buffer_size().

1269 {
1270 
1271  switch_mutex_lock(jb->mutex);
1272 
1273  if (min_frame_len) {
1274  *min_frame_len = jb->min_frame_len;
1275  }
1276 
1277  if (max_frame_len) {
1278  *max_frame_len = jb->max_frame_len;
1279  }
1280 
1281  if (cur_frame_len) {
1282  *cur_frame_len = jb->frame_len;
1283  }
1284 
1286 
1287  return SWITCH_STATUS_SUCCESS;
1288 }
uint32_t min_frame_len
uint32_t max_frame_len
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308

◆ switch_jb_get_last_read_len()

switch_size_t switch_jb_get_last_read_len ( switch_jb_t jb)

Definition at line 1567 of file switch_jitterbuffer.c.

References switch_jb_s::last_len.

Referenced by read_rtp_packet().

1568 {
1569  return jb->last_len;
1570 }
switch_size_t last_len

◆ switch_jb_get_nack_success()

uint32_t switch_jb_get_nack_success ( switch_jb_t jb)

Definition at line 1224 of file switch_jitterbuffer.c.

References switch_jb_s::mutex, switch_jb_s::nack_didnt_save_the_day, switch_jb_s::nack_saved_the_day, switch_mutex_lock(), and switch_mutex_unlock().

Referenced by switch_rtp_destroy().

1225 {
1226  uint32_t nack_recovered; /*count*/
1227  switch_mutex_lock(jb->mutex);
1228  nack_recovered = jb->nack_saved_the_day + jb->nack_didnt_save_the_day;
1230  return nack_recovered;
1231 }
uint32_t nack_saved_the_day
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_mutex_t * mutex
uint32_t nack_didnt_save_the_day
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308

◆ switch_jb_get_packet()

switch_status_t switch_jb_get_packet ( switch_jb_t jb,
switch_rtp_packet_t packet,
switch_size_t len 
)

Definition at line 1572 of file switch_jitterbuffer.c.

References switch_jb_s::bitrate_control, switch_jb_stats_s::buffer_size_ms, CF_VIDEO_BITRATE_UNMANAGABLE, switch_jb_s::channel, check_jb_size(), check_seq(), check_ts(), switch_jb_s::complete_frames, switch_jb_s::consec_good_count, switch_jb_s::consec_miss_count, decrement_seq(), switch_jb_s::elastic, switch_jb_jitter_s::estimate, switch_jb_stats_s::estimate_ms, switch_jb_stats_s::expand, switch_jb_s::flush, switch_jb_s::frame_len, switch_core_session_message::from, switch_rtp_packet_t::header, hide_node(), switch_jb_s::highest_read_seq, switch_jb_s::highest_read_ts, jb_debug, jb_frame_inc, jb_next_packet(), switch_jb_s::jitter, switch_jb_s::last_len, switch_jb_s::last_psuedo_seq, switch_jb_s::last_target_seq, switch_jb_s::last_target_ts, switch_jb_node_s::len, switch_rtp_hdr_t::m, switch_jb_s::max_frame_len, switch_core_session_message::message_id, switch_jb_s::min_frame_len, switch_jb_s::mutex, switch_core_session_message::numeric_arg, switch_jb_node_s::packet, switch_jb_s::period_count, switch_jb_s::period_good_count, switch_jb_s::period_len, switch_jb_s::period_miss_count, switch_jb_s::period_miss_inc, switch_jb_s::period_miss_pct, switch_jb_s::read_init, switch_jb_stats_s::reset_error, switch_jb_jitter_s::samples_per_frame, switch_jb_s::samples_per_frame, switch_jb_jitter_s::samples_per_second, switch_rtp_hdr_t::seq, switch_jb_s::session, SJB_VIDEO, switch_jb_jitter_s::stats, switch_channel_clear_flag_recursive(), switch_channel_set_flag_recursive(), switch_channel_test_flag(), switch_core_session_receive_message, switch_core_session_request_video_refresh, switch_goto_status, switch_jb_poll(), switch_jb_reset(), SWITCH_LOG_INFO, SWITCH_MESSAGE_INDICATE_BITRATE_REQ, switch_mutex_lock(), switch_mutex_unlock(), SWITCH_STATUS_BREAK, SWITCH_STATUS_MORE_DATA, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_RESTART, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, SWITCH_TRUE, switch_rtp_hdr_t::ts, switch_jb_s::type, switch_rtp_hdr_t::version, switch_jb_s::video_low_bitrate, and switch_jb_s::visible_nodes.

Referenced by read_rtp_packet(), and switch_ivr_delay_echo().

1573 {
1574  switch_jb_node_t *node = NULL;
1575  switch_status_t status;
1576  int plc = 0;
1577 
1578  switch_mutex_lock(jb->mutex);
1579 
1580  if (jb->complete_frames == 0) {
1581  jb->flush = 0;
1583  }
1584 
1585  if (jb->complete_frames < jb->frame_len) {
1586 
1587  switch_jb_poll(jb);
1588 
1589  if (!jb->flush) {
1590  jb_debug(jb, 2, "BUFFERING %u/%u\n", jb->complete_frames , jb->frame_len);
1592  }
1593  }
1594 
1595  jb_debug(jb, 2, "GET PACKET %u/%u n:%d\n", jb->complete_frames , jb->frame_len, jb->visible_nodes);
1596 
1597  if (++jb->period_count >= jb->period_len) {
1598 
1599  if (jb->consec_good_count >= (jb->period_len - 5)) {
1600  jb_frame_inc(jb, -1);
1601  }
1602 
1603  jb->period_count = 1;
1604  jb->period_miss_inc = 0;
1605  jb->period_miss_count = 0;
1606  jb->period_good_count = 0;
1607  jb->consec_miss_count = 0;
1608  jb->consec_good_count = 0;
1609 
1610  if (jb->type == SJB_VIDEO && jb->channel && jb->video_low_bitrate) {
1611  //switch_time_t now = switch_time_now();
1612  //int ok = (now - jb->last_bitrate_change) > 10000;
1613 
1615  jb_debug(jb, 2, "%s", "Allow BITRATE changes\n");
1617  jb->bitrate_control = 0;
1618  if (jb->session) {
1620  }
1622  switch_core_session_message_t msg = { 0 };
1623 
1625 
1627  msg.numeric_arg = jb->bitrate_control * 1024;
1628  msg.from = __FILE__;
1629 
1630  jb_debug(jb, 2, "Force BITRATE to %d\n", jb->bitrate_control);
1631 
1634  if (jb->session) {
1636  }
1637  }
1638  }
1639  }
1640 
1641 
1642  jb->period_miss_pct = ((double)jb->period_miss_count / jb->period_count) * 100;
1643 
1644  //if (jb->period_miss_pct > 60.0f) {
1645  // jb_debug(jb, 2, "Miss percent %02f too high, resetting buffer.\n", jb->period_miss_pct);
1646  // switch_jb_reset(jb);
1647  //}
1648 
1649  if ((status = jb_next_packet(jb, &node)) == SWITCH_STATUS_SUCCESS) {
1650  jb_debug(jb, 2, "Found next frame cur ts: %u seq: %u\n", htonl(node->packet.header.ts), htons(node->packet.header.seq));
1651 
1652  if (!jb->read_init || check_seq(node->packet.header.seq, jb->highest_read_seq)) {
1653  jb->highest_read_seq = node->packet.header.seq;
1654  }
1655 
1656  if (jb->type != SJB_VIDEO ||
1658 
1659  if (jb->type != SJB_VIDEO) {
1660  jb->complete_frames--;
1661  }
1662  jb_debug(jb, 2, "READ frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
1663  jb->highest_read_ts = node->packet.header.ts;
1664  } else if (!jb->read_init) {
1665  jb->highest_read_ts = node->packet.header.ts;
1666  }
1667 
1668  if (!jb->read_init) jb->read_init = 1;
1669  } else {
1670  if (jb->type == SJB_VIDEO) {
1671  //switch_jb_reset(jb);
1672 
1673  switch(status) {
1674  case SWITCH_STATUS_RESTART:
1675  jb_debug(jb, 2, "%s", "Error encountered ask for new keyframe\n");
1678  default:
1679  jb_debug(jb, 2, "%s", "No frames found wait for more\n");
1681  }
1682  } else {
1683  switch(status) {
1684  case SWITCH_STATUS_RESTART:
1685  jb_debug(jb, 2, "%s", "Error encountered\n");
1686  jb->jitter.stats.reset_error++;
1687  switch_jb_reset(jb);
1690  default:
1691  if (jb->consec_miss_count > jb->frame_len) {
1692  //switch_jb_reset(jb);
1693  jb_frame_inc(jb, 1);
1694  jb_debug(jb, 2, "%s", "Too many frames not found, RESIZE\n");
1696  } else {
1697  if (jb->elastic) {
1698  int visible_not_old = check_jb_size(jb);
1699 
1700  jb->jitter.stats.estimate_ms = (int)((*jb->jitter.estimate) / ((jb->jitter.samples_per_second)) * 1000);
1701  jb->jitter.stats.buffer_size_ms = (int)((visible_not_old * jb->jitter.samples_per_frame) / (jb->jitter.samples_per_second / 1000));
1702  /* When playing PLC, we take the oportunity to expand the buffer if the jitter buffer is smaller than the 3x the estimated jitter. */
1703  if (jb->jitter.stats.buffer_size_ms < (3 * jb->jitter.stats.estimate_ms)) {
1704  jb_debug(jb, SWITCH_LOG_INFO, "JITTER estimation %dms buffersize %d/%d %dms EXPAND [plc]\n",
1706  jb->jitter.stats.expand++;
1707  decrement_seq(jb);
1708  } else {
1709  jb_debug(jb, 2, "%s", "Frame not found suggest PLC\n");
1710  }
1711  } else {
1712  jb_debug(jb, 2, "%s", "Frame not found suggest PLC\n");
1713  }
1714 
1715  plc = 1;
1717  }
1718  }
1719  }
1720  }
1721 
1722  *packet = node->packet;
1723  *len = node->len;
1724  jb->last_len = *len;
1725  packet->header.version = 2;
1726  hide_node(node, SWITCH_TRUE);
1727 
1728  jb_debug(jb, 2, "GET packet ts:%u seq:%u %s\n", ntohl(packet->header.ts), ntohs(packet->header.seq), packet->header.m ? " <MARK>" : "");
1729 
1730  end:
1731 
1732  if (plc) {
1733  uint16_t seq;
1734  uint32_t ts = 0;
1735 
1736  if (jb->samples_per_frame) {
1737  seq = htons(jb->last_psuedo_seq);
1738  ts = jb->last_target_ts;
1739  } else {
1740  seq = jb->last_target_seq;
1741  }
1742 
1743  packet->header.seq = seq;
1744  packet->header.ts = ts;
1745  }
1746 
1748 
1749  if (jb->type == SJB_VIDEO) {
1750  if (jb->complete_frames > jb->max_frame_len * 2) {
1751  jb_debug(jb, 2, "JB TOO BIG (%d), RESET\n", jb->complete_frames);
1752  switch_jb_reset(jb);
1753  }
1754  } else {
1755  int too_big = (int)(jb->max_frame_len * 1.5);
1756  if (jb->visible_nodes > too_big && status == SWITCH_STATUS_SUCCESS) {
1757  status = SWITCH_STATUS_TIMEOUT;
1758  }
1759  }
1760 
1761  return status;
1762 }
switch_jb_type_t type
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
switch_jb_jitter_t jitter
uint32_t highest_read_seq
switch_channel_t * channel
uint32_t min_frame_len
uint32_t last_target_ts
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
uint32_t highest_read_ts
switch_bool_t elastic
uint32_t complete_frames
#define jb_debug(_jb, _level, _format,...)
static void decrement_seq(switch_jb_t *jb)
#define jb_frame_inc(_jb, _i)
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.
uint32_t max_frame_len
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
uint32_t bitrate_control
static int check_seq(uint16_t a, uint16_t b)
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2892
switch_size_t last_len
uint32_t visible_nodes
uint32_t consec_miss_count
static int check_jb_size(switch_jb_t *jb)
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
uint32_t video_low_bitrate
uint32_t period_miss_inc
uint32_t period_good_count
uint32_t period_miss_count
uint16_t last_psuedo_seq
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
switch_core_session_t * session
uint32_t last_target_seq
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_jb_stats_t stats
switch_rtp_packet_t packet
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)
static void hide_node(switch_jb_node_t *node, switch_bool_t pop)
void switch_jb_reset(switch_jb_t *jb)
uint32_t consec_good_count

◆ switch_jb_get_packet_by_seq()

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 
)

Definition at line 1547 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::header, jb_debug, switch_jb_node_s::len, switch_jb_s::mutex, switch_jb_s::node_hash, switch_jb_node_s::packet, switch_core_inthash_find(), switch_mutex_lock(), switch_mutex_unlock(), SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, and switch_rtp_hdr_t::version.

Referenced by handle_nack().

1548 {
1549  switch_jb_node_t *node;
1551 
1552  switch_mutex_lock(jb->mutex);
1553  if ((node = switch_core_inthash_find(jb->node_hash, seq))) {
1554  jb_debug(jb, 2, "Found buffered seq: %u\n", ntohs(seq));
1555  *packet = node->packet;
1556  *len = node->len;
1557  packet->header.version = 2;
1558  status = SWITCH_STATUS_SUCCESS;
1559  } else {
1560  jb_debug(jb, 2, "Missing buffered seq: %u\n", ntohs(seq));
1561  }
1563 
1564  return status;
1565 }
switch_inthash_t * node_hash
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
#define jb_debug(_jb, _level, _format,...)
void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key)
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_status_t
Common return values.
switch_rtp_packet_t packet

◆ switch_jb_get_packets_per_frame()

uint32_t switch_jb_get_packets_per_frame ( switch_jb_t jb)

Definition at line 1233 of file switch_jitterbuffer.c.

References switch_jb_s::mutex, switch_jb_s::packet_count, switch_mutex_lock(), and switch_mutex_unlock().

1234 {
1235  uint32_t ppf;
1236  switch_mutex_lock(jb->mutex);
1237  ppf = jb->packet_count; /* get current packets per frame */
1239  return ppf;
1240 }
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308

◆ switch_jb_peek_frame()

switch_status_t switch_jb_peek_frame ( switch_jb_t jb,
uint32_t  ts,
uint16_t  seq,
int  peek,
switch_frame_t frame 
)

Definition at line 1242 of file switch_jitterbuffer.c.

References switch_rtp_packet_t::body, switch_frame::buflen, switch_frame::data, switch_frame::datalen, switch_rtp_packet_t::header, switch_jb_node_s::len, switch_frame::m, switch_rtp_hdr_t::m, switch_jb_s::node_hash, switch_jb_s::node_hash_ts, switch_jb_node_s::packet, switch_jb_s::samples_per_frame, switch_frame::seq, switch_rtp_hdr_t::seq, switch_core_inthash_find(), SWITCH_RTP_HEADER_LEN, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_frame::timestamp, and switch_rtp_hdr_t::ts.

Referenced by switch_core_media_read_frame().

1243 {
1244  switch_jb_node_t *node = NULL;
1245  if (seq) {
1246  uint16_t want_seq = seq + peek;
1247  node = switch_core_inthash_find(jb->node_hash, htons(want_seq));
1248  } else if (ts && jb->samples_per_frame) {
1249  uint32_t want_ts = ts + (peek * jb->samples_per_frame);
1250  node = switch_core_inthash_find(jb->node_hash_ts, htonl(want_ts));
1251  }
1252 
1253  if (node) {
1254  frame->seq = ntohs(node->packet.header.seq);
1255  frame->timestamp = ntohl(node->packet.header.ts);
1256  frame->m = node->packet.header.m;
1257  frame->datalen = node->len - SWITCH_RTP_HEADER_LEN;
1258 
1259  if (frame->data && frame->buflen > node->len - SWITCH_RTP_HEADER_LEN) {
1260  memcpy(frame->data, node->packet.body, node->len - SWITCH_RTP_HEADER_LEN);
1261  }
1262  return SWITCH_STATUS_SUCCESS;
1263  }
1264 
1265  return SWITCH_STATUS_FALSE;
1266 }
switch_bool_t m
Definition: switch_frame.h:83
switch_inthash_t * node_hash
switch_inthash_t * node_hash_ts
uint32_t timestamp
Definition: switch_frame.h:80
void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key)
uint16_t seq
Definition: switch_frame.h:81
uint32_t buflen
Definition: switch_frame.h:70
uint32_t datalen
Definition: switch_frame.h:68
#define SWITCH_RTP_HEADER_LEN
Definition: switch_rtp.h:44
uint32_t samples_per_frame

◆ switch_jb_poll()

int switch_jb_poll ( switch_jb_t jb)

Definition at line 1148 of file switch_jitterbuffer.c.

References switch_jb_s::buffer_lag, switch_jb_s::complete_frames, switch_jb_s::flush, switch_jb_s::frame_len, SJB_TEXT, and switch_jb_s::type.

Referenced by rtp_common_read(), and switch_jb_get_packet().

1149 {
1150  if (jb->type == SJB_TEXT) {
1151  if (jb->complete_frames < jb->frame_len) {
1152  if (jb->complete_frames && !jb->buffer_lag) {
1153  jb->buffer_lag = 10;
1154  }
1155  if (jb->buffer_lag && --jb->buffer_lag == 0) {
1156  jb->flush = 1;
1157  }
1158  }
1159  }
1160 
1161  return (jb->complete_frames >= jb->frame_len) || jb->flush;
1162 }
switch_jb_type_t type
uint32_t complete_frames

◆ switch_jb_pop_nack()

uint32_t switch_jb_pop_nack ( switch_jb_t jb)

Definition at line 1385 of file switch_jitterbuffer.c.

References switch_jb_s::frame_len, jb_debug, switch_jb_s::missing_seq_hash, switch_jb_s::mutex, RENACK_TIME, SJB_VIDEO, switch_core_hash_first_iter(), switch_core_hash_next(), switch_core_hash_this(), switch_core_inthash_delete(), switch_core_inthash_insert(), switch_mutex_lock(), switch_mutex_unlock(), switch_safe_free, switch_time_now(), switch_jb_s::target_seq, and switch_jb_s::type.

Referenced by check_rtcp_and_ice().

1386 {
1387  switch_hash_index_t *hi = NULL;
1388  uint32_t nack = 0;
1389  uint16_t blp = 0;
1390  uint16_t least = 0;
1391  int i = 0;
1392  void *val;
1393  const void *var;
1394 
1395  if (jb->type != SJB_VIDEO) {
1396  return 0;
1397  }
1398 
1399  switch_mutex_lock(jb->mutex);
1400 
1401  top:
1402 
1403  for (hi = switch_core_hash_first_iter(jb->missing_seq_hash, hi); hi; hi = switch_core_hash_next(&hi)) {
1404  uint16_t seq;
1405  //const char *token;
1406  switch_time_t then = 0;
1407 
1408  switch_core_hash_this(hi, &var, NULL, &val);
1409  //token = (const char *) val;
1410 
1411  //if (token == TOKEN_2) {
1412  //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SKIP %u %s\n", ntohs(*((uint16_t *) var)), token);
1413  //printf("WTf\n");
1414  // continue;
1415  //}
1416 
1417  seq = ntohs(*((uint16_t *) var));
1418  then = (intptr_t) val;
1419 
1420  if (then != 1 && ((uint32_t)(switch_time_now() - then)) < RENACK_TIME) {
1421  jb_debug(jb, 3, "NACKABLE seq %u too soon to repeat\n", seq);
1422  continue;
1423  }
1424 
1425  //if (then != 1) {
1426  // jb_debug(jb, 3, "NACKABLE seq %u not too soon to repeat %lu\n", seq, switch_time_now() - then);
1427  //}
1428 
1429  if (seq < ntohs(jb->target_seq) - jb->frame_len) {
1430  jb_debug(jb, 3, "NACKABLE seq %u expired\n", seq);
1431  switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(seq));
1432  goto top;
1433  }
1434 
1435  if (!least || seq < least) {
1436  least = seq;
1437  }
1438  }
1439 
1440  switch_safe_free(hi);
1441 
1442  if (least && switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(least))) {
1443  jb_debug(jb, 3, "Found NACKABLE seq %u\n", least);
1444  nack = (uint32_t) htons(least);
1445  switch_core_inthash_insert(jb->missing_seq_hash, nack, (void *) (intptr_t)switch_time_now());
1446 
1447  for(i = 0; i < 16; i++) {
1448  if (switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(least + i + 1))) {
1449  switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(least + i + 1), (void *)(intptr_t)switch_time_now());
1450  jb_debug(jb, 3, "Found addtl NACKABLE seq %u\n", least + i + 1);
1451  blp |= (1 << i);
1452  }
1453  }
1454 
1455  blp = htons(blp);
1456  nack |= (uint32_t) blp << 16;
1457 
1458  //jb_frame_inc(jb, 1);
1459  }
1460 
1462 
1463 
1464  return nack;
1465 }
switch_jb_type_t type
switch_inthash_t * missing_seq_hash
#define jb_debug(_jb, _level, _format,...)
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
int64_t switch_time_t
Definition: switch_apr.h:188
switch_mutex_t * mutex
void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
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.
Definition: switch_utils.h:885
#define RENACK_TIME
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.
switch_hash_index_t * switch_core_hash_next(_In_ switch_hash_index_t **hi)
Gets the next element of a hashtable.
switch_time_t switch_time_now(void)
Definition: switch_apr.c:325
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.

◆ switch_jb_put_packet()

switch_status_t switch_jb_put_packet ( switch_jb_t jb,
switch_rtp_packet_t packet,
switch_size_t  len 
)

Definition at line 1467 of file switch_jitterbuffer.c.

References add_node(), switch_jb_s::allocated_nodes, drop_oldest_frame(), switch_jb_s::frame_len, switch_rtp_packet_t::header, switch_jb_s::highest_dropped_ts, jb_debug, jb_frame_inc, switch_jb_s::jitter, switch_jb_s::max_frame_len, switch_jb_s::max_packet_len, switch_jb_s::missing_seq_hash, switch_jb_s::mutex, switch_jb_s::nack_didnt_save_the_day, switch_jb_s::nack_saved_the_day, switch_jb_s::next_seq, switch_jb_stats_s::reset_missing_frames, switch_rtp_hdr_t::seq, SJB_AUDIO, SJB_QUEUE_ONLY, SJB_TEXT, SJB_VIDEO, switch_jb_jitter_s::stats, SWITCH_CHANNEL_LOG, switch_core_inthash_delete(), switch_core_inthash_insert(), switch_jb_reset(), switch_log_printf(), SWITCH_LOG_WARNING, switch_mutex_lock(), switch_mutex_unlock(), SWITCH_RTP_MAX_PACKET_LEN, SWITCH_SIZE_T_FMT, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_jb_s::target_seq, switch_rtp_hdr_t::ts, switch_jb_s::type, and switch_jb_s::visible_nodes.

Referenced by read_bundle_rtp_packet(), read_rtp_packet(), rtp_common_write(), and switch_ivr_delay_echo().

1468 {
1469  uint32_t i;
1470  uint16_t want = ntohs(jb->next_seq), got = ntohs(packet->header.seq);
1471 
1472  if (len >= SWITCH_RTP_MAX_PACKET_LEN) {
1473  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "trying to put %" SWITCH_SIZE_T_FMT " bytes exceeding buffer, truncate to %" SWITCH_SIZE_T_FMT "\n", len, SWITCH_RTP_MAX_PACKET_LEN);
1475  }
1476 
1477  switch_mutex_lock(jb->mutex);
1478 
1479  if (jb->highest_dropped_ts) {
1480  if (ntohl(packet->header.ts) < jb->highest_dropped_ts) {
1481  jb_debug(jb, 2, "%s", "TS ALREADY DROPPED, DROPPING PACKET\n");
1483  return SWITCH_STATUS_SUCCESS;
1484  }
1485  jb->highest_dropped_ts = 0;
1486  }
1487 
1488 
1489  if (!want) want = got;
1490 
1491  if (switch_test_flag(jb, SJB_QUEUE_ONLY) || jb->type == SJB_AUDIO || jb->type == SJB_TEXT) {
1492  jb->next_seq = htons(got + 1);
1493  } else {
1494 
1495  if (switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(got))) {
1496  if (got < ntohs(jb->target_seq)) {
1497  jb_debug(jb, 2, "got nacked seq %u too late\n", got);
1498  jb_frame_inc(jb, 1);
1500  } else {
1501  jb_debug(jb, 2, "got nacked %u saved the day!\n", got);
1502  jb->nack_saved_the_day++;
1503  }
1504  }
1505 
1506  if (got > want) {
1507  if (got - want > jb->max_frame_len && got - want > 17) {
1508  jb_debug(jb, 2, "Missing %u frames, Resetting\n", got - want);
1510  switch_jb_reset(jb);
1511  } else {
1512  if (jb->type != SJB_VIDEO && jb->frame_len < got - want) {
1513  jb_frame_inc(jb, 1);
1514  }
1515 
1516  jb_debug(jb, 2, "GOT %u WANTED %u; MARK SEQS MISSING %u - %u\n", got, want, want, got - 1);
1517 
1518  for (i = want; i < got; i++) {
1519  jb_debug(jb, 2, "MARK MISSING %u ts:%u\n", i, ntohl(packet->header.ts));
1520  switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(i), (void *)(intptr_t)1);
1521  }
1522  }
1523  }
1524 
1525  if (got >= want || (want - got) > 1000) {
1526  jb->next_seq = htons(got + 1);
1527  }
1528  }
1529 
1530  add_node(jb, packet, len);
1531 
1532  if (switch_test_flag(jb, SJB_QUEUE_ONLY) && jb->max_packet_len && jb->max_frame_len * 2 > jb->max_packet_len &&
1533  jb->allocated_nodes > jb->max_frame_len * 2 - 1) {
1534  while ((jb->max_frame_len * 2 - jb->visible_nodes) < jb->max_packet_len) {
1535  drop_oldest_frame(jb);
1536  }
1537  } else if (switch_test_flag(jb, SJB_QUEUE_ONLY) && jb->max_packet_len && jb->max_frame_len * 2 < jb->max_packet_len) {
1538  /* rtp_nack_buffer_size less than initial max_packet_len */
1539  drop_oldest_frame(jb);
1540  }
1541 
1543 
1544  return SWITCH_STATUS_SUCCESS;
1545 }
switch_jb_type_t type
#define SWITCH_CHANNEL_LOG
switch_jb_jitter_t jitter
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
switch_inthash_t * missing_seq_hash
uint32_t nack_saved_the_day
#define jb_debug(_jb, _level, _format,...)
#define jb_frame_inc(_jb, _i)
uint32_t highest_dropped_ts
uint32_t max_frame_len
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
static void drop_oldest_frame(switch_jb_t *jb)
uint32_t max_packet_len
static void add_node(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
switch_mutex_t * mutex
void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key)
uint32_t nack_didnt_save_the_day
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_status_t switch_core_inthash_insert(switch_inthash_t *hash, uint32_t key, const void *data)
uint32_t visible_nodes
#define SWITCH_SIZE_T_FMT
uint32_t allocated_nodes
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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.
switch_jb_stats_t stats
#define SWITCH_RTP_MAX_PACKET_LEN
Definition: switch_rtp.h:48
void switch_jb_reset(switch_jb_t *jb)

◆ switch_jb_reset()

void switch_jb_reset ( switch_jb_t jb)

Definition at line 1174 of file switch_jitterbuffer.c.

References switch_jb_s::channel, switch_jb_s::complete_frames, switch_jb_s::consec_good_count, switch_jb_s::consec_miss_count, switch_jb_s::drop_flag, hide_nodes(), switch_jb_s::highest_read_seq, switch_jb_s::highest_read_ts, switch_jb_s::highest_wrote_seq, switch_jb_s::highest_wrote_ts, jb_debug, switch_jb_s::jitter, switch_jb_s::last_target_seq, switch_jb_s::last_target_ts, switch_jb_s::missing_seq_hash, switch_jb_s::mutex, switch_jb_s::next_seq, switch_jb_s::period_count, switch_jb_s::period_good_count, switch_jb_s::period_miss_count, switch_jb_s::period_miss_inc, switch_jb_s::period_miss_pct, switch_jb_s::read_init, switch_jb_stats_s::reset, switch_jb_stats_s::reset_error, switch_jb_stats_s::reset_missing_frames, switch_jb_stats_s::reset_too_big, switch_jb_stats_s::reset_ts_jump, switch_jb_s::session, SJB_VIDEO, switch_jb_jitter_s::stats, switch_channel_set_variable_printf(), switch_core_inthash_destroy(), switch_core_inthash_init(), switch_core_session_request_video_refresh, switch_mutex_lock(), switch_mutex_unlock(), switch_jb_s::target_seq, switch_jb_s::target_ts, switch_jb_s::type, and switch_jb_s::write_init.

Referenced by add_node(), do_flush(), handle_rfc2833(), new_node(), read_rtp_packet(), switch_jb_get_packet(), switch_jb_put_packet(), switch_rtp_del_dtls(), switch_rtp_pause_jitter_buffer(), switch_rtp_reset_jb(), switch_rtp_reset_vb(), and switch_rtp_set_flag().

1175 {
1176  jb->jitter.stats.reset++;
1177  if (jb->channel) {
1178  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_count", "%u", jb->jitter.stats.reset);
1179  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_too_big", "%u", jb->jitter.stats.reset_too_big);
1180  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_missing_frames", "%u", jb->jitter.stats.reset_missing_frames);
1181  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_ts_jump", "%u", jb->jitter.stats.reset_ts_jump);
1182  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_error", "%u", jb->jitter.stats.reset_error);
1183  }
1184 
1185  if (jb->type == SJB_VIDEO) {
1186  switch_mutex_lock(jb->mutex);
1190 
1191  if (jb->session) {
1193  }
1194  }
1195 
1196  jb_debug(jb, 2, "%s", "RESET BUFFER\n");
1197 
1198  switch_mutex_lock(jb->mutex);
1199  hide_nodes(jb);
1201 
1202  jb->drop_flag = 0;
1203  jb->last_target_seq = 0;
1204  jb->target_seq = 0;
1205  jb->write_init = 0;
1206  jb->highest_wrote_seq = 0;
1207  jb->highest_wrote_ts = 0;
1208  jb->next_seq = 0;
1209  jb->highest_read_ts = 0;
1210  jb->highest_read_seq = 0;
1211  jb->read_init = 0;
1212  jb->complete_frames = 0;
1213  jb->period_miss_count = 0;
1214  jb->consec_miss_count = 0;
1215  jb->period_miss_pct = 0;
1216  jb->period_good_count = 0;
1217  jb->consec_good_count = 0;
1218  jb->period_count = 0;
1219  jb->period_miss_inc = 0;
1220  jb->target_ts = 0;
1221  jb->last_target_ts = 0;
1222 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
uint32_t highest_wrote_ts
switch_jb_type_t type
switch_status_t switch_core_inthash_init(switch_inthash_t **hash)
switch_jb_jitter_t jitter
uint32_t highest_read_seq
switch_channel_t * channel
uint32_t last_target_ts
switch_inthash_t * missing_seq_hash
static void hide_nodes(switch_jb_t *jb)
uint32_t highest_read_ts
uint32_t complete_frames
#define jb_debug(_jb, _level, _format,...)
uint16_t highest_wrote_seq
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_core_inthash_destroy(switch_inthash_t **hash)
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2892
uint32_t consec_miss_count
uint32_t period_miss_inc
uint32_t period_good_count
uint32_t period_miss_count
switch_core_session_t * session
uint32_t last_target_seq
switch_jb_stats_t stats
uint32_t consec_good_count

◆ switch_jb_set_flag()

void switch_jb_set_flag ( switch_jb_t jb,
switch_jb_flag_t  flag 
)

Definition at line 1138 of file switch_jitterbuffer.c.

References switch_set_flag.

Referenced by rtp_common_write().

1139 {
1140  switch_set_flag(jb, flag);
1141 }
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700

◆ switch_jb_set_frames()

switch_status_t switch_jb_set_frames ( switch_jb_t jb,
uint32_t  min_frame_len,
uint32_t  max_frame_len 
)

Definition at line 1290 of file switch_jitterbuffer.c.

References switch_jb_s::frame_len, switch_jb_s::highest_frame_len, switch_jb_s::max_frame_len, switch_jb_s::min_frame_len, switch_jb_s::mutex, switch_mutex_lock(), switch_mutex_unlock(), and SWITCH_STATUS_SUCCESS.

Referenced by switch_rtp_activate_jitter_buffer(), and switch_rtp_set_video_buffer_size().

1291 {
1292  int lowest = 0;
1293 
1294  switch_mutex_lock(jb->mutex);
1295 
1296  if (jb->frame_len == jb->min_frame_len) lowest = 1;
1297 
1298  jb->min_frame_len = min_frame_len;
1299  jb->max_frame_len = max_frame_len;
1300 
1301  if (jb->frame_len > jb->max_frame_len) {
1302  jb->frame_len = jb->max_frame_len;
1303  }
1304 
1305  if (jb->frame_len < jb->min_frame_len) {
1306  jb->frame_len = jb->min_frame_len;
1307  }
1308 
1309  if (jb->frame_len > jb->highest_frame_len) {
1310  jb->highest_frame_len = jb->frame_len;
1311  }
1312 
1313  if (lowest) {
1314  jb->frame_len = jb->min_frame_len;
1315  }
1316 
1318 
1319  return SWITCH_STATUS_SUCCESS;
1320 }
uint32_t min_frame_len
uint32_t max_frame_len
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_mutex_t * mutex
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
uint32_t highest_frame_len

◆ switch_jb_set_jitter_estimator()

void switch_jb_set_jitter_estimator ( switch_jb_t jb,
double *  jitter,
uint32_t  samples_per_frame,
uint32_t  samples_per_second 
)

Definition at line 1079 of file switch_jitterbuffer.c.

References switch_jb_s::channel, switch_jb_jitter_s::drop_gap, switch_jb_jitter_s::estimate, switch_jb_s::jitter, memset(), switch_jb_jitter_s::samples_per_frame, switch_jb_jitter_s::samples_per_second, and switch_channel_set_variable_printf().

Referenced by switch_rtp_activate_jitter_buffer().

1080 {
1081  if (jb && jitter) {
1082  memset(&jb->jitter, 0, sizeof(switch_jb_jitter_t));
1083  if (jb->channel) {
1084  switch_channel_set_variable_printf(jb->channel, "rtp_jb_max_ms", "%u", 0);
1085  switch_channel_set_variable_printf(jb->channel, "rtp_jb_size_ms", "%u", 0);
1086  switch_channel_set_variable_printf(jb->channel, "rtp_jb_acceleration_ms", "%u", 0);
1087  switch_channel_set_variable_printf(jb->channel, "rtp_jb_expand_ms", "%u", 0);
1088  switch_channel_set_variable_printf(jb->channel, "rtp_jb_jitter_max_ms", "%u", 0);
1089  switch_channel_set_variable_printf(jb->channel, "rtp_jb_jitter_ms", "%u", 0);
1090  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_count", "%u", 0);
1091  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_too_big", "%u", 0);
1092  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_missing_frames", "%u", 0);
1093  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_ts_jump", "%u", 0);
1094  switch_channel_set_variable_printf(jb->channel, "rtp_jb_reset_error", "%u", 0);
1095  }
1096 
1097  jb->jitter.estimate = jitter;
1098  jb->jitter.samples_per_frame = samples_per_frame;
1099  jb->jitter.samples_per_second = samples_per_second;
1100  jb->jitter.drop_gap = 5;
1101  }
1102 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
switch_jb_jitter_t jitter
switch_channel_t * channel
memset(buf, 0, buflen)

◆ switch_jb_set_session()

void switch_jb_set_session ( switch_jb_t jb,
switch_core_session_t session 
)

Definition at line 1104 of file switch_jitterbuffer.c.

References switch_jb_s::channel, switch_jb_s::codec, switch_jb_s::elastic, switch_codec_implementation::iananame, switch_codec::implementation, switch_jb_s::session, SJB_AUDIO, SJB_QUEUE_ONLY, SJB_VIDEO, switch_channel_get_variable_dup(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_var_true(), switch_core_session_get_channel(), switch_core_session_get_read_codec(), SWITCH_FALSE, SWITCH_LOG_DEBUG, SWITCH_LOG_DEBUG1, switch_log_printf(), switch_test_flag, SWITCH_TRUE, switch_jb_s::type, and switch_jb_s::video_low_bitrate.

Referenced by switch_rtp_activate_jitter_buffer(), and switch_rtp_set_video_buffer_size().

1105 {
1106  const char *var;
1107 
1108  if (session) {
1110  jb->session = session;
1112  if (jb->type == SJB_AUDIO) {
1113  if (!strcmp(jb->codec->implementation->iananame, "opus")) {
1114  if (switch_channel_var_true(jb->channel, "rtp_jitter_buffer_accelerate")) {
1115  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "audio codec is %s, accelerate on\n", jb->codec->implementation->iananame);
1116  jb->elastic = SWITCH_TRUE;
1117  } else {
1118  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "audio codec is %s, accelerate off\n", jb->codec->implementation->iananame);
1119  jb->elastic = SWITCH_FALSE;
1120  }
1121  } else {
1122  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "audio codec is not Opus: %s\n", jb->codec->implementation->iananame);
1123  jb->elastic = SWITCH_FALSE;
1124  }
1125  }
1126 
1127  if (jb->type == SJB_VIDEO && !switch_test_flag(jb, SJB_QUEUE_ONLY) &&
1128  (var = switch_channel_get_variable_dup(jb->channel, "jb_video_low_bitrate", SWITCH_FALSE, -1))) {
1129  int tmp = atoi(var);
1130 
1131  if (tmp >= 128 && tmp <= 10240) {
1132  jb->video_low_bitrate = (uint32_t)tmp;
1133  }
1134  }
1135  }
1136 }
switch_jb_type_t type
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_channel_t * channel
switch_bool_t elastic
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_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
_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.
const switch_codec_implementation_t * implementation
switch_core_session_t * session
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
uint32_t video_low_bitrate
switch_core_session_t * session
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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.
switch_codec_t * codec

◆ switch_jb_ts_mode()

void switch_jb_ts_mode ( switch_jb_t jb,
uint32_t  samples_per_frame,
uint32_t  samples_per_second 
)

Definition at line 1072 of file switch_jitterbuffer.c.

References switch_jb_s::node_hash_ts, switch_jb_s::samples_per_frame, switch_jb_s::samples_per_second, and switch_core_inthash_init().

Referenced by switch_rtp_activate_jitter_buffer().

1073 {
1074  jb->samples_per_frame = samples_per_frame;
1075  jb->samples_per_second = samples_per_second;
1077 }
switch_status_t switch_core_inthash_init(switch_inthash_t **hash)
switch_inthash_t * node_hash_ts
uint32_t samples_per_second
uint32_t samples_per_frame