RTS API Documentation  1.10.11
switch_jitterbuffer.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Dragos Oancea <dragos@freeswitch.org>
28  *
29  * switch_jitterbuffer.c -- Audio/Video Jitter Buffer
30  *
31  */
32 #include <switch.h>
33 #include <switch_jitterbuffer.h>
35 
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__)
41 
42 //const char *TOKEN_1 = "ONE";
43 //const char *TOKEN_2 = "TWO";
44 
45 struct switch_jb_s;
46 
47 static inline int check_jb_size(switch_jb_t *jb);
48 
49 typedef struct switch_jb_node_s {
52  uint32_t len;
53  uint8_t visible;
54  uint8_t bad_hits;
57  /* used for counting the number of partial or complete frames currently in the JB */
60 
61 typedef struct switch_jb_stats_s {
62  uint32_t reset_too_big;
64  uint32_t reset_ts_jump;
65  uint32_t reset_error;
66  uint32_t reset;
67  uint32_t size_max;
68  uint32_t size_est;
69  uint32_t acceleration;
70  uint32_t expand;
71  uint32_t jitter_max_ms;
75 
76 typedef struct switch_jb_jitter_s {
77  double *estimate;
80  uint32_t drop_gap;
83 
84 struct switch_jb_s {
86  uint32_t last_target_seq;
87  uint32_t highest_read_ts;
89  uint32_t highest_read_seq;
90  uint32_t highest_wrote_ts;
92  uint16_t target_seq;
93  uint32_t target_ts;
94  uint32_t last_target_ts;
95  uint16_t psuedo_seq;
96  uint16_t last_psuedo_seq;
97  uint32_t visible_nodes;
98  uint32_t allocated_nodes;
99  uint32_t complete_frames;
100  uint32_t frame_len;
101  uint32_t min_frame_len;
102  uint32_t max_frame_len;
106  uint32_t period_miss_inc;
110  uint32_t period_count;
111  uint32_t dropped;
114  uint32_t bitrate_control;
116  uint8_t write_init;
117  uint8_t read_init;
118  uint8_t debug_level;
119  uint16_t next_seq;
134  uint32_t buffer_lag;
135  uint32_t flush;
136  uint32_t packet_count;
137  uint32_t max_packet_len;
138  uint32_t period_len;
143 };
144 
145 
146 static int node_cmp(const void *l, const void *r)
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 }
156 
157 //http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c
158 switch_jb_node_t *sort_nodes(switch_jb_node_t *list, int (*cmp)(const void *, const void *)) {
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 }
235 
236 // static inline void thin_frames(switch_jb_t *jb, int freq, int max);
237 
238 
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 }
290 
291 static inline void push_to_top(switch_jb_t *jb, switch_jb_node_t *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 }
315 
316 static inline void hide_node(switch_jb_node_t *node, switch_bool_t pop)
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 }
345 
346 static inline void sort_free_nodes(switch_jb_t *jb)
347 {
351 }
352 
353 static inline void hide_nodes(switch_jb_t *jb)
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 }
363 
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 }
383 
384 static inline void drop_ts(switch_jb_t *jb, uint32_t ts)
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 }
405 
406 static inline switch_jb_node_t *jb_find_lowest_seq(switch_jb_t *jb, uint32_t ts)
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 }
424 
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 }
441 
442 static inline uint32_t jb_find_lowest_ts(switch_jb_t *jb)
443 {
445 
446  return lowest ? lowest->packet.header.ts : 0;
447 }
448 
449 #if 0
450 static inline void thin_frames(switch_jb_t *jb, int freq, int max)
451 {
452  switch_jb_node_t *node, *this_node;
453  int i = -1;
454  int dropped = 0;
455 
457  node = jb->node_list;
458 
459  while (node && dropped <= max) {
460  this_node = node;
461  node = node->next;
462 
463  if (this_node->visible) {
464  i++;
465  } else {
466  continue;
467  }
468 
469  if ((i % freq) == 0) {
470  drop_ts(jb, this_node->packet.header.ts);
471  dropped++;
472  }
473  }
474 
475  sort_free_nodes(jb);
477 }
478 
479 static inline switch_jb_node_t *jb_find_highest_node(switch_jb_t *jb)
480 {
481  switch_jb_node_t *np, *highest = NULL;
482 
484  for (np = jb->node_list; np; np = np->next) {
485  if (!np->visible) continue;
486 
487  if (!highest || ntohl(highest->packet.header.ts) < ntohl(np->packet.header.ts)) {
488  highest = np;
489  }
490  }
492 
493  return highest ? highest : NULL;
494 }
495 
496 
497 static inline uint32_t jb_find_highest_ts(switch_jb_t *jb)
498 {
499  switch_jb_node_t *highest = jb_find_highest_node(jb);
500 
501  return highest ? highest->packet.header.ts : 0;
502 }
503 
504 static inline void drop_newest_frame(switch_jb_t *jb)
505 {
506  uint32_t ts = jb_find_highest_ts(jb);
507 
508  drop_ts(jb, ts);
509  jb_debug(jb, 1, "Dropping highest frame ts:%u\n", ntohl(ts));
510 }
511 
512 
513 
514 
515 static inline switch_jb_node_t *jb_find_penultimate_node(switch_jb_t *jb)
516 {
517  switch_jb_node_t *np, *highest = NULL, *second_highest = NULL;
518 
520  for (np = jb->node_list; np; np = np->next) {
521  if (!np->visible) continue;
522 
523  if (!highest || ntohl(highest->packet.header.ts) < ntohl(np->packet.header.ts)) {
524  if (highest) second_highest = highest;
525  highest = np;
526  }
527  }
529 
530  return second_highest ? second_highest : highest;
531 }
532 #endif
533 
534 static inline void jb_hit(switch_jb_t *jb)
535 {
536  jb->period_good_count++;
537  jb->consec_good_count++;
538  jb->consec_miss_count = 0;
539 }
540 
541 static void jb_frame_inc_line(switch_jb_t *jb, int i, int line)
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 }
582 
583 #define jb_frame_inc(_jb, _i) jb_frame_inc_line(_jb, _i, __LINE__)
584 
585 
586 static inline void jb_miss(switch_jb_t *jb)
587 {
588  jb->period_miss_count++;
589  jb->consec_miss_count++;
590  jb->consec_good_count = 0;
591 }
592 
593 #if 0
594 static inline int verify_oldest_frame(switch_jb_t *jb)
595 {
596  switch_jb_node_t *lowest = NULL, *np = NULL;
597  int r = 0;
598 
599  lowest = jb_find_lowest_node(jb);
600 
601  if (!lowest || !(lowest = jb_find_lowest_seq(jb, lowest->packet.header.ts))) {
602  goto end;
603  }
604 
606 
608 
609  for (np = lowest->next; np; np = np->next) {
610 
611  if (!np->visible) continue;
612 
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);
615 
617  switch_core_inthash_insert(jb->missing_seq_hash, val, (void *)(intptr_t)1);
618  }
619  break;
620  }
621 
622  if (np->packet.header.ts != lowest->packet.header.ts || !np->next) {
623  r = 1;
624  }
625  }
626 
628 
629  end:
630 
631  return r;
632 }
633 #endif
634 
635 static inline void drop_oldest_frame(switch_jb_t *jb)
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 }
642 
643 
644 
645 #if 0
646 static inline void drop_second_newest_frame(switch_jb_t *jb)
647 {
648  switch_jb_node_t *second_newest = jb_find_penultimate_node(jb);
649 
650  if (second_newest) {
651  drop_ts(jb, second_newest->packet.header.ts);
652  jb_debug(jb, 1, "Dropping second highest frame ts:%u\n", ntohl(second_newest->packet.header.ts));
653  }
654 }
655 #endif
656 
657 static inline int check_seq(uint16_t a, uint16_t b)
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 }
668 
669 static inline int check_ts(uint32_t a, uint32_t b)
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 }
680 
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 }
757 
758 static inline void increment_ts(switch_jb_t *jb)
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 }
767 
768 static inline void set_read_ts(switch_jb_t *jb, uint32_t 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 }
777 
778 
779 static inline void increment_seq(switch_jb_t *jb)
780 {
781  jb->last_target_seq = jb->target_seq;
782  jb->target_seq = htons((ntohs(jb->target_seq) + 1));
783 }
784 
785 static inline void decrement_seq(switch_jb_t *jb)
786 {
787  jb->last_target_seq = jb->target_seq;
788  jb->target_seq = htons((ntohs(jb->target_seq) - 1));
789 }
790 
791 static inline void set_read_seq(switch_jb_t *jb, uint16_t seq)
792 {
793  jb->last_target_seq = seq;
794  jb->target_seq = htons((ntohs(jb->last_target_seq) + 1));
795 }
796 
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 }
879 
880 
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 }
912 
913 static inline int check_jb_size(switch_jb_t *jb)
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 }
995 
997 {
998  switch_status_t status = jb_next_packet_by_seq(jb, nodep);
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 }
1051 
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 }
1064 
1065 static inline void free_nodes(switch_jb_t *jb)
1066 {
1068  jb->node_list = NULL;
1070 }
1071 
1072 SWITCH_DECLARE(void) switch_jb_ts_mode(switch_jb_t *jb, uint32_t samples_per_frame, uint32_t samples_per_second)
1073 {
1074  jb->samples_per_frame = samples_per_frame;
1075  jb->samples_per_second = samples_per_second;
1077 }
1078 
1079 SWITCH_DECLARE(void) switch_jb_set_jitter_estimator(switch_jb_t *jb, double *jitter, uint32_t samples_per_frame, uint32_t samples_per_second)
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 }
1103 
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 }
1137 
1139 {
1140  switch_set_flag(jb, flag);
1141 }
1142 
1144 {
1145  switch_clear_flag(jb, flag);
1146 }
1147 
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 }
1163 
1165 {
1166  return jb->complete_frames;
1167 }
1168 
1170 {
1171  jb->debug_level = level;
1172 }
1173 
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 }
1223 
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 }
1232 
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 }
1241 
1242 SWITCH_DECLARE(switch_status_t) switch_jb_peek_frame(switch_jb_t *jb, uint32_t ts, uint16_t seq, int peek, switch_frame_t *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 }
1267 
1268 SWITCH_DECLARE(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)
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 }
1289 
1290 SWITCH_DECLARE(switch_status_t) switch_jb_set_frames(switch_jb_t *jb, uint32_t min_frame_len, uint32_t max_frame_len)
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 }
1321 
1323  uint32_t min_frame_len, uint32_t max_frame_len, switch_memory_pool_t *pool)
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 }
1356 
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 }
1384 
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 }
1466 
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 }
1546 
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 }
1566 
1568 {
1569  return jb->last_len;
1570 }
1571 
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 }
1763 
1764 /* For Emacs:
1765  * Local Variables:
1766  * mode:c
1767  * indent-tabs-mode:t
1768  * tab-width:4
1769  * c-basic-offset:4
1770  * End:
1771  * For VIM:
1772  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1773  */
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
switch_jb_type_t type
switch_bool_t m
Definition: switch_frame.h:83
#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
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.
Definition: switch_utils.h:700
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
Definition: switch_core.h:183
#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
uint32_t min_frame_len
uint32_t last_target_ts
switch_rtp_hdr_t header
Definition: switch_rtp.h:56
switch_inthash_t * missing_seq_hash
static void hide_nodes(switch_jb_t *jb)
switch_bool_t complete_frame_mark
uint32_t highest_read_ts
switch_bool_t elastic
switch_bool_t
Definition: switch_types.h:437
uint32_t timestamp
Definition: switch_frame.h:80
const cJSON *const b
Definition: switch_cJSON.h:243
uint32_t complete_frames
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.
Definition: switch_core.h:642
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)
switch_jb_type_t
#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.
uint32_t max_frame_len
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
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)
Definition: switch_apr.c:313
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.
Definition: switch_utils.h:724
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
static switch_jb_node_t * jb_find_lowest_node(switch_jb_t *jb)
uint32_t samples_per_second
uint16_t seq
Definition: switch_frame.h:81
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)
int64_t switch_time_t
Definition: switch_apr.h:188
const switch_codec_implementation_t * implementation
uint32_t max_packet_len
uint32_t buflen
Definition: switch_frame.h:70
uint32_t bitrate_control
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)
switch_mutex_t * mutex
uint32_t datalen
Definition: switch_frame.h:68
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)
Definition: switch_apr.c:308
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2881
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
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.
Definition: switch_utils.h:885
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
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)
switch_size_t last_len
#define RENACK_TIME
uint32_t visible_nodes
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.
Definition: switch_frame.h:54
uintptr_t switch_size_t
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)
Definition: switch_core.h:1247
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)
static void sort_free_nodes(switch_jb_t *jb)
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
#define SWITCH_RTP_HEADER_LEN
Definition: switch_rtp.h:44
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_miss_inc
uint32_t period_good_count
uint32_t period_miss_count
static int node_cmp(const void *l, const void *r)
uint16_t last_psuedo_seq
switch_status_t switch_jb_destroy(switch_jb_t **jbp)
#define SWITCH_SIZE_T_FMT
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
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)
#define FALSE
char body[SWITCH_RTP_MAX_BUF_LEN+4+sizeof(char *)]
Definition: switch_rtp.h:57
switch_mutex_t * list_mutex
switch_jb_flag_t flags
Main Library Header.
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)
#define SWITCH_DECLARE(type)
static void set_read_ts(switch_jb_t *jb, uint32_t ts)
uint32_t allocated_nodes
void switch_jb_set_flag(switch_jb_t *jb, switch_jb_flag_t flag)
switch_core_session_t * session
uint32_t last_target_seq
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)
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.
Definition: switch_utils.h:693
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)
switch_jb_stats_t stats
int count
Definition: switch_cJSON.h:204
struct fspr_pool_t switch_memory_pool_t
#define TRUE
#define SWITCH_RTP_MAX_PACKET_LEN
Definition: switch_rtp.h:48
switch_rtp_packet_t packet
switch_jb_flag_t
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)
#define switch_assert(expr)
switch_time_t switch_time_now(void)
Definition: switch_apr.c:325
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
memset(buf, 0, buflen)
switch_codec_t * codec
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.