2017-01-06 07:10:15 +00:00
/*
2015-09-11 16:37:01 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 - 2014 , Anthony Minessale II < anthm @ freeswitch . org >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthm @ freeswitch . org >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
2017-01-06 07:10:15 +00:00
*
2015-09-11 16:37:01 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2019-03-05 19:09:25 +00:00
* Dragos Oancea < dragos @ freeswitch . org >
2015-09-11 16:37:01 +00:00
*
* switch_jitterbuffer . c - - Audio / Video Jitter Buffer
*
*/
# include <switch.h>
# include <switch_jitterbuffer.h>
# include "private/switch_hashtable_private.h"
2015-09-21 20:32:32 +00:00
# define NACK_TIME 80000
2015-09-19 05:23:56 +00:00
# define RENACK_TIME 100000
2015-09-11 16:37:01 +00:00
# define MAX_FRAME_PADDING 2
# define MAX_MISSING_SEQ 20
2017-03-03 20:18:16 +00:00
# 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__)
2015-09-11 16:37:01 +00:00
2015-09-19 04:36:11 +00:00
//const char *TOKEN_1 = "ONE";
//const char *TOKEN_2 = "TWO";
2015-09-11 16:37:01 +00:00
struct switch_jb_s ;
typedef struct switch_jb_node_s {
struct switch_jb_s * parent ;
switch_rtp_packet_t packet ;
uint32_t len ;
uint8_t visible ;
uint8_t bad_hits ;
struct switch_jb_node_s * prev ;
struct switch_jb_node_s * next ;
2019-03-05 19:09:25 +00:00
/* used for counting the number of partial or complete frames currently in the JB */
switch_bool_t complete_frame_mark ;
2015-09-11 16:37:01 +00:00
} switch_jb_node_t ;
struct switch_jb_s {
struct switch_jb_node_s * node_list ;
uint32_t last_target_seq ;
uint32_t highest_read_ts ;
2017-03-11 03:14:17 +00:00
uint32_t highest_dropped_ts ;
2015-09-11 16:37:01 +00:00
uint32_t highest_read_seq ;
uint32_t highest_wrote_ts ;
2017-03-11 03:14:17 +00:00
uint16_t highest_wrote_seq ;
2015-09-11 16:37:01 +00:00
uint16_t target_seq ;
2015-09-15 19:59:05 +00:00
uint32_t target_ts ;
uint32_t last_target_ts ;
uint16_t psuedo_seq ;
2015-10-02 00:11:51 +00:00
uint16_t last_psuedo_seq ;
2015-09-11 16:37:01 +00:00
uint32_t visible_nodes ;
2017-03-03 20:18:16 +00:00
uint32_t allocated_nodes ;
2015-09-11 16:37:01 +00:00
uint32_t complete_frames ;
uint32_t frame_len ;
uint32_t min_frame_len ;
uint32_t max_frame_len ;
uint32_t highest_frame_len ;
uint32_t period_miss_count ;
uint32_t consec_miss_count ;
2015-09-19 04:36:11 +00:00
uint32_t period_miss_inc ;
2015-09-11 16:37:01 +00:00
double period_miss_pct ;
uint32_t period_good_count ;
uint32_t consec_good_count ;
uint32_t period_count ;
uint32_t dropped ;
2015-09-15 19:59:05 +00:00
uint32_t samples_per_frame ;
uint32_t samples_per_second ;
2015-09-17 22:34:50 +00:00
uint32_t bitrate_control ;
2015-09-22 21:35:00 +00:00
uint32_t video_low_bitrate ;
2015-09-11 16:37:01 +00:00
uint8_t write_init ;
uint8_t read_init ;
uint8_t debug_level ;
uint16_t next_seq ;
switch_size_t last_len ;
switch_inthash_t * missing_seq_hash ;
switch_inthash_t * node_hash ;
2015-09-15 19:59:05 +00:00
switch_inthash_t * node_hash_ts ;
2015-09-11 16:37:01 +00:00
switch_mutex_t * mutex ;
switch_mutex_t * list_mutex ;
switch_memory_pool_t * pool ;
int free_pool ;
2015-10-22 18:26:47 +00:00
int drop_flag ;
2015-09-11 16:37:01 +00:00
switch_jb_flag_t flags ;
switch_jb_type_t type ;
switch_core_session_t * session ;
switch_channel_t * channel ;
2016-07-11 03:25:14 +00:00
uint32_t buffer_lag ;
uint32_t flush ;
2017-03-11 03:14:17 +00:00
uint32_t packet_count ;
uint32_t max_packet_len ;
2018-10-09 20:15:50 +00:00
uint32_t period_len ;
2019-07-25 14:21:39 +00:00
uint32_t nack_saved_the_day ;
uint32_t nack_didnt_save_the_day ;
2015-09-11 16:37:01 +00:00
} ;
static int node_cmp ( const void * l , const void * r )
{
switch_jb_node_t * a = ( switch_jb_node_t * ) l ;
switch_jb_node_t * b = ( switch_jb_node_t * ) r ;
2017-01-06 07:10:15 +00:00
2015-09-15 22:23:34 +00:00
if ( ! a - > visible ) return 0 ;
if ( ! b - > visible ) return 1 ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
return ntohs ( a - > packet . header . seq ) - ntohs ( b - > packet . header . seq ) ;
2015-09-11 16:37:01 +00:00
}
2015-09-15 22:23:34 +00:00
//http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c
switch_jb_node_t * sort_nodes ( switch_jb_node_t * list , int ( * cmp ) ( const void * , const void * ) ) {
switch_jb_node_t * p , * q , * e , * tail ;
int insize , nmerges , psize , qsize , i ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
if ( ! list ) {
return NULL ;
}
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
insize = 1 ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
while ( 1 ) {
p = list ;
list = NULL ;
tail = NULL ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
nmerges = 0 ; /* count number of merges we do in this pass */
while ( p ) {
nmerges + + ; /* there exists a merge to be done */
/* step `insize' places along from p */
q = p ;
psize = 0 ;
for ( i = 0 ; i < insize ; i + + ) {
psize + + ;
q = q - > next ;
if ( ! q ) break ;
2015-09-11 16:37:01 +00:00
}
2015-09-15 22:23:34 +00:00
/* if q hasn't fallen off end, we have two lists to merge */
qsize = insize ;
/* now we have two lists; merge them */
while ( psize > 0 | | ( qsize > 0 & & q ) ) {
/* decide whether next switch_jb_node_t of merge comes from p or q */
if ( psize = = 0 ) {
/* p is empty; e must come from q. */
e = q ; q = q - > next ; qsize - - ;
} else if ( qsize = = 0 | | ! q ) {
/* q is empty; e must come from p. */
e = p ; p = p - > next ; psize - - ;
} else if ( cmp ( p , q ) < = 0 ) {
/* First switch_jb_node_t of p is lower (or same);
* e must come from p . */
e = p ; p = p - > next ; psize - - ;
} else {
/* First switch_jb_node_t of q is lower; e must come from q. */
e = q ; q = q - > next ; qsize - - ;
}
/* add the next switch_jb_node_t to the merged list */
if ( tail ) {
tail - > next = e ;
2015-09-11 16:37:01 +00:00
} else {
2015-09-15 22:23:34 +00:00
list = e ;
2015-09-11 16:37:01 +00:00
}
2015-09-15 22:23:34 +00:00
/* Maintain reverse pointers in a doubly linked list. */
e - > prev = tail ;
2017-01-06 07:10:15 +00:00
2015-09-15 22:23:34 +00:00
tail = e ;
2015-09-11 16:37:01 +00:00
}
2015-09-15 22:23:34 +00:00
/* now p has stepped `insize' places along, and q has too */
p = q ;
2015-09-11 16:37:01 +00:00
}
2015-09-15 22:23:34 +00:00
tail - > next = NULL ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
/* If we have done only one merge, we're finished. */
if ( nmerges < = 1 ) /* allow for nmerges==0, the empty list case */
return list ;
2015-09-11 16:37:01 +00:00
2015-09-15 22:23:34 +00:00
/* Otherwise repeat, merging lists twice the size */
insize * = 2 ;
2015-09-11 16:37:01 +00:00
}
}
2018-08-23 23:56:40 +00:00
// static inline void thin_frames(switch_jb_t *jb, int freq, int max);
2018-05-15 22:09:55 +00:00
2015-09-15 22:23:34 +00:00
2015-09-11 16:37:01 +00:00
static inline switch_jb_node_t * new_node ( switch_jb_t * jb )
{
switch_jb_node_t * np ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) {
break ;
}
}
if ( ! np ) {
2018-05-15 22:09:55 +00:00
int mult = 2 ;
2017-03-11 03:14:17 +00:00
if ( jb - > type ! = SJB_VIDEO ) {
mult = 2 ;
} else {
if ( jb - > max_packet_len > mult ) {
mult = jb - > max_packet_len ;
}
}
2018-05-15 22:09:55 +00:00
2017-03-11 03:14:17 +00:00
if ( jb - > allocated_nodes > jb - > max_frame_len * mult ) {
jb_debug ( jb , 2 , " ALLOCATED FRAMES TOO HIGH! %d \n " , jb - > allocated_nodes ) ;
switch_jb_reset ( jb ) ;
switch_mutex_unlock ( jb - > list_mutex ) ;
return NULL ;
}
2018-05-15 22:09:55 +00:00
2015-09-11 16:37:01 +00:00
np = switch_core_alloc ( jb - > pool , sizeof ( * np ) ) ;
2017-03-03 20:18:16 +00:00
jb - > allocated_nodes + + ;
2015-09-11 16:37:01 +00:00
np - > next = jb - > node_list ;
if ( np - > next ) {
np - > next - > prev = np ;
}
jb - > node_list = np ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
}
switch_assert ( np ) ;
np - > bad_hits = 0 ;
np - > visible = 1 ;
jb - > visible_nodes + + ;
np - > parent = jb ;
switch_mutex_unlock ( jb - > list_mutex ) ;
return np ;
}
static inline void push_to_top ( switch_jb_t * jb , switch_jb_node_t * node )
{
if ( node = = jb - > node_list ) {
jb - > node_list = node - > next ;
} else if ( node - > prev ) {
node - > prev - > next = node - > next ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( node - > next ) {
node - > next - > prev = node - > prev ;
}
node - > next = jb - > node_list ;
node - > prev = NULL ;
if ( node - > next ) {
node - > next - > prev = node ;
}
jb - > node_list = node ;
switch_assert ( node - > next ! = node ) ;
switch_assert ( node - > prev ! = node ) ;
}
static inline void hide_node ( switch_jb_node_t * node , switch_bool_t pop )
{
switch_jb_t * jb = node - > parent ;
switch_mutex_lock ( jb - > list_mutex ) ;
if ( node - > visible ) {
node - > visible = 0 ;
node - > bad_hits = 0 ;
jb - > visible_nodes - - ;
if ( pop ) {
push_to_top ( jb , node ) ;
}
}
2015-09-15 19:59:05 +00:00
if ( jb - > node_hash_ts ) {
switch_core_inthash_delete ( jb - > node_hash_ts , node - > packet . header . ts ) ;
}
2017-03-03 20:18:16 +00:00
if ( switch_core_inthash_delete ( jb - > node_hash , node - > packet . header . seq ) ) {
2019-03-05 19:09:25 +00:00
if ( node - > complete_frame_mark & & jb - > type = = SJB_VIDEO ) {
2017-03-03 20:18:16 +00:00
jb - > complete_frames - - ;
2019-03-05 19:09:25 +00:00
node - > complete_frame_mark = FALSE ;
2017-03-03 20:18:16 +00:00
}
}
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > list_mutex ) ;
}
static inline void sort_free_nodes ( switch_jb_t * jb )
{
switch_mutex_lock ( jb - > list_mutex ) ;
2015-09-18 18:47:03 +00:00
jb - > node_list = sort_nodes ( jb - > node_list , node_cmp ) ;
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > list_mutex ) ;
}
static inline void hide_nodes ( switch_jb_t * jb )
{
switch_jb_node_t * np ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
hide_node ( np , SWITCH_FALSE ) ;
}
switch_mutex_unlock ( jb - > list_mutex ) ;
}
static inline void drop_ts ( switch_jb_t * jb , uint32_t ts )
{
switch_jb_node_t * np ;
int x = 0 ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) continue ;
if ( ts = = np - > packet . header . ts ) {
hide_node ( np , SWITCH_FALSE ) ;
x + + ;
}
}
if ( x ) {
sort_free_nodes ( jb ) ;
}
switch_mutex_unlock ( jb - > list_mutex ) ;
}
static inline switch_jb_node_t * jb_find_lowest_seq ( switch_jb_t * jb , uint32_t ts )
{
switch_jb_node_t * np , * lowest = NULL ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) continue ;
if ( ts & & ts ! = np - > packet . header . ts ) continue ;
if ( ! lowest | | ntohs ( lowest - > packet . header . seq ) > ntohs ( np - > packet . header . seq ) ) {
lowest = np ;
}
}
switch_mutex_unlock ( jb - > list_mutex ) ;
return lowest ;
}
static inline switch_jb_node_t * jb_find_lowest_node ( switch_jb_t * jb )
{
switch_jb_node_t * np , * lowest = NULL ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) continue ;
if ( ! lowest | | ntohl ( lowest - > packet . header . ts ) > ntohl ( np - > packet . header . ts ) ) {
lowest = np ;
}
}
switch_mutex_unlock ( jb - > list_mutex ) ;
return lowest ? lowest : NULL ;
}
static inline uint32_t jb_find_lowest_ts ( switch_jb_t * jb )
{
switch_jb_node_t * lowest = jb_find_lowest_node ( jb ) ;
return lowest ? lowest - > packet . header . ts : 0 ;
}
2018-08-23 23:56:40 +00:00
#if 0
2015-10-22 18:26:47 +00:00
static inline void thin_frames ( switch_jb_t * jb , int freq , int max )
{
2018-05-15 22:09:55 +00:00
switch_jb_node_t * node , * this_node ;
2015-10-22 18:26:47 +00:00
int i = - 1 ;
int dropped = 0 ;
switch_mutex_lock ( jb - > list_mutex ) ;
node = jb - > node_list ;
2018-05-15 22:09:55 +00:00
while ( node & & dropped < = max ) {
this_node = node ;
node = node - > next ;
if ( this_node - > visible ) {
2015-10-22 18:26:47 +00:00
i + + ;
} else {
continue ;
}
if ( ( i % freq ) = = 0 ) {
2018-05-15 22:09:55 +00:00
drop_ts ( jb , this_node - > packet . header . ts ) ;
2015-10-22 18:26:47 +00:00
dropped + + ;
}
}
sort_free_nodes ( jb ) ;
2017-01-06 07:10:15 +00:00
switch_mutex_unlock ( jb - > list_mutex ) ;
2015-10-22 18:26:47 +00:00
}
2015-09-17 22:34:50 +00:00
static inline switch_jb_node_t * jb_find_highest_node ( switch_jb_t * jb )
{
switch_jb_node_t * np , * highest = NULL ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) continue ;
if ( ! highest | | ntohl ( highest - > packet . header . ts ) < ntohl ( np - > packet . header . ts ) ) {
highest = np ;
}
}
switch_mutex_unlock ( jb - > list_mutex ) ;
return highest ? highest : NULL ;
}
2018-05-15 22:09:55 +00:00
2015-09-17 22:34:50 +00:00
static inline uint32_t jb_find_highest_ts ( switch_jb_t * jb )
{
switch_jb_node_t * highest = jb_find_highest_node ( jb ) ;
return highest ? highest - > packet . header . ts : 0 ;
}
2015-09-18 18:47:03 +00:00
2018-05-15 22:09:55 +00:00
static inline void drop_newest_frame ( switch_jb_t * jb )
{
uint32_t ts = jb_find_highest_ts ( jb ) ;
drop_ts ( jb , ts ) ;
jb_debug ( jb , 1 , " Dropping highest frame ts:%u \n " , ntohl ( ts ) ) ;
}
2015-09-18 03:31:22 +00:00
static inline switch_jb_node_t * jb_find_penultimate_node ( switch_jb_t * jb )
{
switch_jb_node_t * np , * highest = NULL , * second_highest = NULL ;
switch_mutex_lock ( jb - > list_mutex ) ;
for ( np = jb - > node_list ; np ; np = np - > next ) {
if ( ! np - > visible ) continue ;
if ( ! highest | | ntohl ( highest - > packet . header . ts ) < ntohl ( np - > packet . header . ts ) ) {
if ( highest ) second_highest = highest ;
highest = np ;
}
}
switch_mutex_unlock ( jb - > list_mutex ) ;
return second_highest ? second_highest : highest ;
}
2015-09-18 18:47:03 +00:00
# endif
2015-09-18 03:31:22 +00:00
2015-09-11 16:37:01 +00:00
static inline void jb_hit ( switch_jb_t * jb )
{
jb - > period_good_count + + ;
jb - > consec_good_count + + ;
jb - > consec_miss_count = 0 ;
}
2015-09-17 22:34:50 +00:00
static void jb_frame_inc_line ( switch_jb_t * jb , int i , int line )
2015-09-11 16:37:01 +00:00
{
uint32_t old_frame_len = jb - > frame_len ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( i = = 0 ) {
jb - > frame_len = jb - > min_frame_len ;
goto end ;
}
if ( i > 0 ) {
if ( ( jb - > frame_len + i ) < jb - > max_frame_len ) {
jb - > frame_len + = i ;
} else {
jb - > frame_len = jb - > max_frame_len ;
}
goto end ;
}
2019-07-12 16:43:02 +00:00
/* i < 0 */
if ( ( jb - > frame_len + i ) > jb - > min_frame_len ) {
jb - > frame_len + = i ;
} else {
jb - > frame_len = jb - > min_frame_len ;
2015-09-11 16:37:01 +00:00
}
end :
if ( jb - > frame_len > jb - > highest_frame_len ) {
jb - > highest_frame_len = jb - > frame_len ;
}
if ( old_frame_len ! = jb - > frame_len ) {
2018-10-09 20:15:50 +00:00
jb_debug ( jb , 1 , " %d Change framelen from %u to %u \n " , line , old_frame_len , jb - > frame_len ) ;
2017-06-22 00:26:14 +00:00
//if (jb->session) {
// switch_core_session_request_video_refresh(jb->session);
//}
2015-09-11 16:37:01 +00:00
}
}
2015-09-17 22:34:50 +00:00
# define jb_frame_inc(_jb, _i) jb_frame_inc_line(_jb, _i, __LINE__)
2015-09-15 19:59:05 +00:00
static inline void jb_miss ( switch_jb_t * jb )
{
jb - > period_miss_count + + ;
jb - > consec_miss_count + + ;
jb - > consec_good_count = 0 ;
}
2015-09-18 18:47:03 +00:00
#if 0
static inline int verify_oldest_frame ( switch_jb_t * jb )
2015-09-11 16:37:01 +00:00
{
2015-09-18 18:47:03 +00:00
switch_jb_node_t * lowest = NULL , * np = NULL ;
2015-09-11 16:37:01 +00:00
int r = 0 ;
2015-09-18 18:47:03 +00:00
lowest = jb_find_lowest_node ( jb ) ;
2015-09-11 16:37:01 +00:00
if ( ! lowest | | ! ( lowest = jb_find_lowest_seq ( jb , lowest - > packet . header . ts ) ) ) {
goto end ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_lock ( jb - > mutex ) ;
jb - > node_list = sort_nodes ( jb - > node_list , node_cmp ) ;
for ( np = lowest - > next ; np ; np = np - > next ) {
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( ! np - > visible ) continue ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( ntohs ( np - > packet . header . seq ) ! = ntohs ( np - > prev - > packet . header . seq ) + 1 ) {
2015-09-18 18:47:03 +00:00
uint32_t val = ( uint32_t ) htons ( ntohs ( np - > prev - > packet . header . seq ) + 1 ) ;
if ( ! switch_core_inthash_find ( jb - > missing_seq_hash , val ) ) {
2015-09-21 20:32:32 +00:00
switch_core_inthash_insert ( jb - > missing_seq_hash , val , ( void * ) ( intptr_t ) 1 ) ;
2015-09-18 18:47:03 +00:00
}
2015-09-11 16:37:01 +00:00
break ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( np - > packet . header . ts ! = lowest - > packet . header . ts | | ! np - > next ) {
2015-09-15 22:23:34 +00:00
r = 1 ;
2015-09-11 16:37:01 +00:00
}
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > mutex ) ;
end :
return r ;
}
2015-09-18 18:47:03 +00:00
# endif
2015-09-11 16:37:01 +00:00
static inline void drop_oldest_frame ( switch_jb_t * jb )
{
uint32_t ts = jb_find_lowest_ts ( jb ) ;
drop_ts ( jb , ts ) ;
jb_debug ( jb , 1 , " Dropping oldest frame ts:%u \n " , ntohl ( ts ) ) ;
}
2015-09-17 22:34:50 +00:00
2015-10-22 18:26:47 +00:00
2018-05-15 22:09:55 +00:00
#if 0
2015-10-22 18:26:47 +00:00
static inline void drop_second_newest_frame ( switch_jb_t * jb )
{
switch_jb_node_t * second_newest = jb_find_penultimate_node ( jb ) ;
2017-01-06 07:10:15 +00:00
2015-10-22 18:26:47 +00:00
if ( second_newest ) {
drop_ts ( jb , second_newest - > packet . header . ts ) ;
jb_debug ( jb , 1 , " Dropping second highest frame ts:%u \n " , ntohl ( second_newest - > packet . header . ts ) ) ;
}
}
2015-09-18 02:11:04 +00:00
# endif
2015-09-17 22:34:50 +00:00
2017-03-11 03:14:17 +00:00
static inline int check_seq ( uint16_t a , uint16_t b )
{
a = ntohs ( a ) ;
b = ntohs ( b ) ;
if ( a > = b | | ( b > a & & b > USHRT_MAX / 2 & & a < USHRT_MAX / 2 ) ) {
return 1 ;
}
return 0 ;
}
static inline int check_ts ( uint32_t a , uint32_t b )
{
a = ntohl ( a ) ;
b = ntohl ( b ) ;
if ( a > b | | ( b > a & & b > UINT_MAX / 2 & & a < UINT_MAX / 2 ) ) {
return 1 ;
}
return 0 ;
}
2015-09-11 16:37:01 +00:00
static inline void add_node ( switch_jb_t * jb , switch_rtp_packet_t * packet , switch_size_t len )
{
switch_jb_node_t * node = new_node ( jb ) ;
2017-03-11 03:14:17 +00:00
if ( ! node ) {
return ;
}
2015-09-11 16:37:01 +00:00
node - > packet = * packet ;
node - > len = len ;
switch_core_inthash_insert ( jb - > node_hash , node - > packet . header . seq , node ) ;
2015-09-15 19:59:05 +00:00
if ( jb - > node_hash_ts ) {
switch_core_inthash_insert ( jb - > node_hash_ts , node - > packet . header . ts , node ) ;
}
2018-10-09 20:15:50 +00:00
jb_debug ( jb , ( packet - > header . m ? 2 : 3 ) , " PUT packet last_ts:%u ts:%u seq:%u%s \n " ,
2015-09-11 16:37:01 +00:00
ntohl ( jb - > highest_wrote_ts ) , ntohl ( node - > packet . header . ts ) , ntohs ( node - > packet . header . seq ) , packet - > header . m ? " <MARK> " : " " ) ;
2016-01-14 23:38:03 +00:00
if ( jb - > write_init & & jb - > type = = SJB_VIDEO ) {
int seq_diff = 0 , ts_diff = 0 ;
if ( ntohs ( jb - > highest_wrote_seq ) > ( USHRT_MAX - 100 ) & & ntohs ( packet - > header . seq ) < 100 ) {
seq_diff = ( USHRT_MAX - ntohs ( jb - > highest_wrote_seq ) ) + ntohs ( packet - > header . seq ) ;
} else {
seq_diff = abs ( ( ( int ) ntohs ( packet - > header . seq ) - ntohs ( jb - > highest_wrote_seq ) ) ) ;
}
2017-01-06 07:10:15 +00:00
2016-01-14 23:38:03 +00:00
if ( ntohl ( jb - > highest_wrote_ts ) > ( UINT_MAX - 1000 ) & & ntohl ( node - > packet . header . ts ) < 1000 ) {
ts_diff = ( UINT_MAX - ntohl ( node - > packet . header . ts ) ) + ntohl ( node - > packet . header . ts ) ;
} else {
ts_diff = abs ( ( int ) ( ( int64_t ) ntohl ( node - > packet . header . ts ) - ( int64_t ) ntohl ( jb - > highest_wrote_ts ) ) ) ;
}
2017-01-06 07:10:15 +00:00
2017-03-03 00:18:18 +00:00
if ( ( ( seq_diff > = 100 ) | | ( ts_diff > ( 900000 * 5 ) ) ) ) {
2016-01-14 23:38:03 +00:00
jb_debug ( jb , 2 , " CHANGE DETECTED, PUNT %u \n " , abs ( ( ( int ) ntohs ( packet - > header . seq ) - ntohs ( jb - > highest_wrote_seq ) ) ) ) ;
switch_jb_reset ( jb ) ;
}
2015-09-19 01:54:42 +00:00
}
2017-01-06 07:10:15 +00:00
if ( ! jb - > write_init | | ntohs ( packet - > header . seq ) > ntohs ( jb - > highest_wrote_seq ) | |
2016-01-14 23:38:03 +00:00
( ntohs ( jb - > highest_wrote_seq ) > USHRT_MAX - 100 & & ntohs ( packet - > header . seq ) < 100 ) ) {
2015-09-11 16:37:01 +00:00
jb - > highest_wrote_seq = packet - > header . seq ;
}
if ( jb - > type = = SJB_VIDEO ) {
2019-07-25 23:56:16 +00:00
jb - > packet_count + + ;
2017-03-11 03:14:17 +00:00
if ( jb - > write_init & & check_seq ( packet - > header . seq , jb - > highest_wrote_seq ) & & check_ts ( node - > packet . header . ts , jb - > highest_wrote_ts ) ) {
2016-10-11 15:56:08 +00:00
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 ) ;
2015-09-11 16:37:01 +00:00
jb - > highest_wrote_ts = packet - > header . ts ;
2017-03-11 03:14:17 +00:00
jb - > complete_frames + + ;
2019-04-16 19:43:40 +00:00
jb - > packet_count - - ;
if ( jb - > packet_count > jb - > max_packet_len ) {
jb - > max_packet_len = jb - > packet_count ;
2017-03-11 03:14:17 +00:00
}
2019-04-16 19:43:40 +00:00
jb - > packet_count = 1 ;
2019-03-05 19:09:25 +00:00
node - > complete_frame_mark = TRUE ;
2015-09-11 16:37:01 +00:00
} else if ( ! jb - > write_init ) {
jb - > highest_wrote_ts = packet - > header . ts ;
}
} else {
2016-10-08 01:27:35 +00:00
if ( jb - > write_init | | jb - > type = = SJB_TEXT | | jb - > type = = SJB_AUDIO ) {
2016-07-21 08:22:37 +00:00
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 ) ;
2017-03-03 20:33:39 +00:00
jb - > complete_frames + + ;
2016-07-21 08:22:37 +00:00
} else {
2015-09-11 16:37:01 +00:00
jb - > highest_wrote_ts = packet - > header . ts ;
}
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( ! jb - > write_init ) jb - > write_init = 1 ;
}
2015-09-15 19:59:05 +00:00
static inline void increment_ts ( switch_jb_t * jb )
{
if ( ! jb - > target_ts ) return ;
2015-10-02 00:11:51 +00:00
jb - > last_psuedo_seq = jb - > psuedo_seq ;
jb - > last_target_ts = jb - > target_ts ;
2015-09-15 19:59:05 +00:00
jb - > target_ts = htonl ( ( ntohl ( jb - > target_ts ) + jb - > samples_per_frame ) ) ;
jb - > psuedo_seq + + ;
}
static inline void set_read_ts ( switch_jb_t * jb , uint32_t ts )
{
if ( ! ts ) return ;
2015-10-02 00:11:51 +00:00
jb - > last_psuedo_seq = jb - > psuedo_seq ;
2015-09-15 19:59:05 +00:00
jb - > last_target_ts = ts ;
jb - > target_ts = htonl ( ( ntohl ( jb - > last_target_ts ) + jb - > samples_per_frame ) ) ;
jb - > psuedo_seq + + ;
}
2015-09-11 16:37:01 +00:00
static inline void increment_seq ( switch_jb_t * jb )
{
2015-10-02 00:11:51 +00:00
jb - > last_target_seq = jb - > target_seq ;
2015-09-11 16:37:01 +00:00
jb - > target_seq = htons ( ( ntohs ( jb - > target_seq ) + 1 ) ) ;
}
static inline void set_read_seq ( switch_jb_t * jb , uint16_t seq )
{
jb - > last_target_seq = seq ;
jb - > target_seq = htons ( ( ntohs ( jb - > last_target_seq ) + 1 ) ) ;
}
2015-09-15 19:59:05 +00:00
static inline switch_status_t jb_next_packet_by_seq ( switch_jb_t * jb , switch_jb_node_t * * nodep )
2015-09-11 16:37:01 +00:00
{
switch_jb_node_t * node = NULL ;
top :
if ( jb - > type = = SJB_VIDEO ) {
if ( jb - > dropped ) {
jb - > dropped = 0 ;
jb_debug ( jb , 2 , " %s " , " DROPPED FRAME DETECTED RESYNCING \n " ) ;
jb - > target_seq = 0 ;
2017-01-06 07:10:15 +00:00
2017-06-26 17:56:42 +00:00
if ( jb - > session ) {
switch_core_session_request_video_refresh ( jb - > session ) ;
}
2015-09-11 16:37:01 +00:00
}
}
if ( ! jb - > target_seq ) {
2016-01-14 23:38:03 +00:00
if ( ( node = switch_core_inthash_find ( jb - > node_hash , jb - > target_seq ) ) ) {
jb_debug ( jb , 2 , " FOUND rollover seq: %u \n " , ntohs ( jb - > target_seq ) ) ;
} else if ( ( node = jb_find_lowest_seq ( jb , 0 ) ) ) {
2015-09-11 16:37:01 +00:00
jb_debug ( jb , 2 , " No target seq using seq: %u as a starting point \n " , ntohs ( node - > packet . header . seq ) ) ;
} else {
jb_debug ( jb , 1 , " %s " , " No nodes available.... \n " ) ;
}
jb_hit ( jb ) ;
} else if ( ( node = switch_core_inthash_find ( jb - > node_hash , jb - > target_seq ) ) ) {
jb_debug ( jb , 2 , " FOUND desired seq: %u \n " , ntohs ( jb - > target_seq ) ) ;
jb_hit ( jb ) ;
} else {
jb_debug ( jb , 2 , " MISSING desired seq: %u \n " , ntohs ( jb - > target_seq ) ) ;
jb_miss ( jb ) ;
if ( jb - > type = = SJB_VIDEO ) {
int x ;
2017-06-26 17:56:42 +00:00
if ( jb - > session ) {
switch_core_session_request_video_refresh ( jb - > session ) ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
for ( x = 0 ; x < 10 ; x + + ) {
increment_seq ( jb ) ;
if ( ( node = switch_core_inthash_find ( jb - > node_hash , jb - > target_seq ) ) ) {
jb_debug ( jb , 2 , " FOUND incremental seq: %u \n " , ntohs ( jb - > target_seq ) ) ;
if ( node - > packet . header . m | | node - > packet . header . ts = = jb - > highest_read_ts ) {
jb_debug ( jb , 2 , " %s " , " SAME FRAME DROPPING \n " ) ;
jb - > dropped + + ;
drop_ts ( jb , node - > packet . header . ts ) ;
2017-03-11 03:14:17 +00:00
jb - > highest_dropped_ts = ntohl ( node - > packet . header . ts ) ;
2018-10-09 20:15:50 +00:00
if ( jb - > period_miss_count > 2 & & jb - > period_miss_inc < 1 ) {
jb - > period_miss_inc + + ;
jb_frame_inc ( jb , 1 ) ;
}
2015-09-11 16:37:01 +00:00
node = NULL ;
goto top ;
}
break ;
} else {
jb_debug ( jb , 2 , " MISSING incremental seq: %u \n " , ntohs ( jb - > target_seq ) ) ;
}
}
2017-03-11 03:14:17 +00:00
2015-09-11 16:37:01 +00:00
} else {
increment_seq ( jb ) ;
}
}
* nodep = node ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( node ) {
set_read_seq ( jb , node - > packet . header . seq ) ;
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_NOTFOUND ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
}
2015-09-15 19:59:05 +00:00
static inline switch_status_t jb_next_packet_by_ts ( switch_jb_t * jb , switch_jb_node_t * * nodep )
{
switch_jb_node_t * node = NULL ;
if ( ! jb - > target_ts ) {
if ( ( node = jb_find_lowest_node ( jb ) ) ) {
jb_debug ( jb , 2 , " No target ts using ts: %u as a starting point \n " , ntohl ( node - > packet . header . ts ) ) ;
} else {
jb_debug ( jb , 1 , " %s " , " No nodes available.... \n " ) ;
}
jb_hit ( jb ) ;
} else if ( ( node = switch_core_inthash_find ( jb - > node_hash_ts , jb - > target_ts ) ) ) {
jb_debug ( jb , 2 , " FOUND desired ts: %u \n " , ntohl ( jb - > target_ts ) ) ;
jb_hit ( jb ) ;
} else {
jb_debug ( jb , 2 , " MISSING desired ts: %u \n " , ntohl ( jb - > target_ts ) ) ;
jb_miss ( jb ) ;
increment_ts ( jb ) ;
}
* nodep = node ;
2017-01-06 07:10:15 +00:00
2015-09-15 19:59:05 +00:00
if ( node ) {
set_read_ts ( jb , node - > packet . header . ts ) ;
node - > packet . header . seq = htons ( jb - > psuedo_seq ) ;
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_NOTFOUND ;
2017-01-06 07:10:15 +00:00
2015-09-15 19:59:05 +00:00
}
static inline switch_status_t jb_next_packet ( switch_jb_t * jb , switch_jb_node_t * * nodep )
{
if ( jb - > samples_per_frame ) {
return jb_next_packet_by_ts ( jb , nodep ) ;
} else {
return jb_next_packet_by_seq ( jb , nodep ) ;
}
}
2015-09-11 16:37:01 +00:00
static inline void free_nodes ( switch_jb_t * jb )
{
switch_mutex_lock ( jb - > list_mutex ) ;
jb - > node_list = NULL ;
switch_mutex_unlock ( jb - > list_mutex ) ;
}
2015-09-15 19:59:05 +00:00
SWITCH_DECLARE ( void ) switch_jb_ts_mode ( switch_jb_t * jb , uint32_t samples_per_frame , uint32_t samples_per_second )
{
jb - > samples_per_frame = samples_per_frame ;
jb - > samples_per_second = samples_per_second ;
switch_core_inthash_init ( & jb - > node_hash_ts ) ;
}
2015-09-11 16:37:01 +00:00
SWITCH_DECLARE ( void ) switch_jb_set_session ( switch_jb_t * jb , switch_core_session_t * session )
{
2015-09-22 21:35:00 +00:00
const char * var ;
2019-03-25 19:22:23 +00:00
if ( session ) {
jb - > session = session ;
jb - > channel = switch_core_session_get_channel ( session ) ;
if ( jb - > type = = SJB_VIDEO & & ! switch_test_flag ( jb , SJB_QUEUE_ONLY ) & &
( var = switch_channel_get_variable_dup ( jb - > channel , " jb_video_low_bitrate " , SWITCH_FALSE , - 1 ) ) ) {
int tmp = atoi ( var ) ;
if ( tmp > = 128 & & tmp < = 10240 ) {
jb - > video_low_bitrate = ( uint32_t ) tmp ;
}
2015-09-22 21:35:00 +00:00
}
}
2015-09-11 16:37:01 +00:00
}
SWITCH_DECLARE ( void ) switch_jb_set_flag ( switch_jb_t * jb , switch_jb_flag_t flag )
{
switch_set_flag ( jb , flag ) ;
}
SWITCH_DECLARE ( void ) switch_jb_clear_flag ( switch_jb_t * jb , switch_jb_flag_t flag )
{
switch_clear_flag ( jb , flag ) ;
}
SWITCH_DECLARE ( int ) switch_jb_poll ( switch_jb_t * jb )
{
2016-10-08 01:27:35 +00:00
if ( jb - > type = = SJB_TEXT ) {
if ( jb - > complete_frames < jb - > frame_len ) {
if ( jb - > complete_frames & & ! jb - > buffer_lag ) {
jb - > buffer_lag = 10 ;
}
if ( jb - > buffer_lag & & - - jb - > buffer_lag = = 0 ) {
jb - > flush = 1 ;
}
}
}
2017-01-06 07:10:15 +00:00
2016-10-08 01:27:35 +00:00
return ( jb - > complete_frames > = jb - > frame_len ) | | jb - > flush ;
2015-09-11 16:37:01 +00:00
}
SWITCH_DECLARE ( int ) switch_jb_frame_count ( switch_jb_t * jb )
{
return jb - > complete_frames ;
}
SWITCH_DECLARE ( void ) switch_jb_debug_level ( switch_jb_t * jb , uint8_t level )
{
jb - > debug_level = level ;
}
SWITCH_DECLARE ( void ) switch_jb_reset ( switch_jb_t * jb )
{
if ( jb - > type = = SJB_VIDEO ) {
switch_mutex_lock ( jb - > mutex ) ;
switch_core_inthash_destroy ( & jb - > missing_seq_hash ) ;
switch_core_inthash_init ( & jb - > missing_seq_hash ) ;
switch_mutex_unlock ( jb - > mutex ) ;
2015-09-18 03:31:22 +00:00
2017-06-26 17:56:42 +00:00
if ( jb - > session ) {
switch_core_session_request_video_refresh ( jb - > session ) ;
}
2015-09-11 16:37:01 +00:00
}
2018-04-20 18:33:57 +00:00
2015-09-11 16:37:01 +00:00
jb_debug ( jb , 2 , " %s " , " RESET BUFFER \n " ) ;
2018-04-20 18:33:57 +00:00
switch_mutex_lock ( jb - > mutex ) ;
hide_nodes ( jb ) ;
switch_mutex_unlock ( jb - > mutex ) ;
2015-10-22 18:26:47 +00:00
jb - > drop_flag = 0 ;
2015-09-11 16:37:01 +00:00
jb - > last_target_seq = 0 ;
jb - > target_seq = 0 ;
jb - > write_init = 0 ;
jb - > highest_wrote_seq = 0 ;
jb - > highest_wrote_ts = 0 ;
jb - > next_seq = 0 ;
jb - > highest_read_ts = 0 ;
jb - > highest_read_seq = 0 ;
jb - > read_init = 0 ;
jb - > complete_frames = 0 ;
jb - > period_miss_count = 0 ;
jb - > consec_miss_count = 0 ;
jb - > period_miss_pct = 0 ;
jb - > period_good_count = 0 ;
jb - > consec_good_count = 0 ;
jb - > period_count = 0 ;
2015-09-19 04:36:11 +00:00
jb - > period_miss_inc = 0 ;
2015-09-15 19:59:05 +00:00
jb - > target_ts = 0 ;
jb - > last_target_ts = 0 ;
2015-09-11 16:37:01 +00:00
}
2019-07-25 14:21:39 +00:00
SWITCH_DECLARE ( uint32_t ) switch_jb_get_nack_success ( switch_jb_t * jb )
{
uint32_t nack_recovered ; /*count*/
switch_mutex_lock ( jb - > mutex ) ;
nack_recovered = jb - > nack_saved_the_day + jb - > nack_didnt_save_the_day ;
switch_mutex_unlock ( jb - > mutex ) ;
return nack_recovered ;
}
2019-07-25 17:44:15 +00:00
SWITCH_DECLARE ( uint32_t ) switch_jb_get_packets_per_frame ( switch_jb_t * jb )
{
uint32_t ppf ;
switch_mutex_lock ( jb - > mutex ) ;
ppf = jb - > packet_count ; /* get current packets per frame */
switch_mutex_unlock ( jb - > mutex ) ;
return ppf ;
}
2015-09-15 19:59:05 +00:00
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 )
2015-09-11 16:37:01 +00:00
{
2015-09-15 19:59:05 +00:00
switch_jb_node_t * node = NULL ;
if ( seq ) {
uint16_t want_seq = seq + peek ;
2015-10-02 00:11:51 +00:00
node = switch_core_inthash_find ( jb - > node_hash , htons ( want_seq ) ) ;
2015-09-15 19:59:05 +00:00
} else if ( ts & & jb - > samples_per_frame ) {
2017-01-06 07:10:15 +00:00
uint32_t want_ts = ts + ( peek * jb - > samples_per_frame ) ;
2015-10-02 00:11:51 +00:00
node = switch_core_inthash_find ( jb - > node_hash_ts , htonl ( want_ts ) ) ;
2015-09-15 19:59:05 +00:00
}
2015-09-11 16:37:01 +00:00
2015-09-15 19:59:05 +00:00
if ( node ) {
2015-09-11 16:37:01 +00:00
frame - > seq = ntohs ( node - > packet . header . seq ) ;
frame - > timestamp = ntohl ( node - > packet . header . ts ) ;
frame - > m = node - > packet . header . m ;
2020-08-11 23:32:21 +00:00
frame - > datalen = node - > len - SWITCH_RTP_HEADER_LEN ;
2015-10-02 00:11:51 +00:00
2020-08-11 23:32:21 +00:00
if ( frame - > data & & frame - > buflen > node - > len - SWITCH_RTP_HEADER_LEN ) {
memcpy ( frame - > data , node - > packet . body , node - > len - SWITCH_RTP_HEADER_LEN ) ;
2015-09-11 16:37:01 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
}
2017-01-06 07:10:15 +00:00
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 )
2015-09-11 16:37:01 +00:00
{
switch_mutex_lock ( jb - > mutex ) ;
if ( min_frame_len ) {
* min_frame_len = jb - > min_frame_len ;
}
if ( max_frame_len ) {
* max_frame_len = jb - > max_frame_len ;
}
if ( cur_frame_len ) {
* cur_frame_len = jb - > frame_len ;
}
switch_mutex_unlock ( jb - > mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( switch_status_t ) switch_jb_set_frames ( switch_jb_t * jb , uint32_t min_frame_len , uint32_t max_frame_len )
{
2015-09-17 22:34:50 +00:00
int lowest = 0 ;
2015-09-11 16:37:01 +00:00
switch_mutex_lock ( jb - > mutex ) ;
2015-09-17 22:34:50 +00:00
if ( jb - > frame_len = = jb - > min_frame_len ) lowest = 1 ;
2015-09-11 16:37:01 +00:00
jb - > min_frame_len = min_frame_len ;
jb - > max_frame_len = max_frame_len ;
if ( jb - > frame_len > jb - > max_frame_len ) {
jb - > frame_len = jb - > max_frame_len ;
}
if ( jb - > frame_len < jb - > min_frame_len ) {
jb - > frame_len = jb - > min_frame_len ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( jb - > frame_len > jb - > highest_frame_len ) {
jb - > highest_frame_len = jb - > frame_len ;
}
2015-09-17 22:34:50 +00:00
if ( lowest ) {
jb - > frame_len = jb - > min_frame_len ;
}
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( 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_jb_t * jb ;
int free_pool = 0 ;
if ( ! pool ) {
switch_core_new_memory_pool ( & pool ) ;
free_pool = 1 ;
}
jb = switch_core_alloc ( pool , sizeof ( * jb ) ) ;
jb - > free_pool = free_pool ;
jb - > min_frame_len = jb - > frame_len = min_frame_len ;
jb - > max_frame_len = max_frame_len ;
jb - > pool = pool ;
jb - > type = type ;
jb - > highest_frame_len = jb - > frame_len ;
if ( jb - > type = = SJB_VIDEO ) {
switch_core_inthash_init ( & jb - > missing_seq_hash ) ;
2018-10-09 20:15:50 +00:00
jb - > period_len = 2500 ;
} else {
jb - > period_len = 250 ;
2015-09-11 16:37:01 +00:00
}
2018-10-09 20:15:50 +00:00
2015-09-11 16:37:01 +00:00
switch_core_inthash_init ( & jb - > node_hash ) ;
switch_mutex_init ( & jb - > mutex , SWITCH_MUTEX_NESTED , pool ) ;
switch_mutex_init ( & jb - > list_mutex , SWITCH_MUTEX_NESTED , pool ) ;
* jbp = jb ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( switch_status_t ) switch_jb_destroy ( switch_jb_t * * jbp )
{
switch_jb_t * jb = * jbp ;
* jbp = NULL ;
2017-01-06 07:10:15 +00:00
2019-07-25 14:21:39 +00:00
if ( jb - > type = = SJB_VIDEO & & ! switch_test_flag ( jb , SJB_QUEUE_ONLY ) ) {
jb_debug ( jb , 3 , " Stats: NACK saved the day: %u \n " , jb - > nack_saved_the_day ) ;
jb_debug ( jb , 3 , " Stats: NACK was late: %u \n " , jb - > nack_didnt_save_the_day ) ;
jb_debug ( jb , 3 , " Stats: Hash entrycount: missing_seq_hash %u \n " , switch_hashtable_count ( jb - > missing_seq_hash ) ) ;
}
2015-09-11 16:37:01 +00:00
if ( jb - > type = = SJB_VIDEO ) {
switch_core_inthash_destroy ( & jb - > missing_seq_hash ) ;
}
switch_core_inthash_destroy ( & jb - > node_hash ) ;
2015-09-15 19:59:05 +00:00
if ( jb - > node_hash_ts ) {
switch_core_inthash_destroy ( & jb - > node_hash_ts ) ;
}
2015-09-11 16:37:01 +00:00
free_nodes ( jb ) ;
if ( jb - > free_pool ) {
switch_core_destroy_memory_pool ( & jb - > pool ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( uint32_t ) switch_jb_pop_nack ( switch_jb_t * jb )
{
switch_hash_index_t * hi = NULL ;
uint32_t nack = 0 ;
uint16_t blp = 0 ;
2015-09-19 04:36:11 +00:00
uint16_t least = 0 ;
2015-09-11 16:37:01 +00:00
int i = 0 ;
void * val ;
const void * var ;
if ( jb - > type ! = SJB_VIDEO ) {
return 0 ;
}
switch_mutex_lock ( jb - > mutex ) ;
2015-09-19 04:36:11 +00:00
top :
2016-08-03 23:41:18 +00:00
for ( hi = switch_core_hash_first_iter ( jb - > missing_seq_hash , hi ) ; hi ; hi = switch_core_hash_next ( & hi ) ) {
2015-09-11 16:37:01 +00:00
uint16_t seq ;
2015-09-19 04:36:11 +00:00
//const char *token;
switch_time_t then = 0 ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_core_hash_this ( hi , & var , NULL , & val ) ;
2015-09-19 04:36:11 +00:00
//token = (const char *) val;
2015-09-11 16:37:01 +00:00
2015-09-19 04:36:11 +00:00
//if (token == TOKEN_2) {
2015-09-11 16:37:01 +00:00
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SKIP %u %s\n", ntohs(*((uint16_t *) var)), token);
2015-09-18 18:47:03 +00:00
//printf("WTf\n");
2015-09-19 04:36:11 +00:00
// continue;
//}
2017-01-06 07:10:15 +00:00
2015-09-19 04:36:11 +00:00
seq = ntohs ( * ( ( uint16_t * ) var ) ) ;
then = ( intptr_t ) val ;
2015-09-18 18:47:03 +00:00
2019-02-24 05:49:24 +00:00
if ( then ! = 1 & & ( ( uint32_t ) ( switch_time_now ( ) - then ) ) < RENACK_TIME ) {
jb_debug ( jb , 3 , " NACKABLE seq %u too soon to repeat \n " , seq ) ;
2015-09-18 18:47:03 +00:00
continue ;
}
2017-01-06 07:10:15 +00:00
2015-09-19 04:36:11 +00:00
//if (then != 1) {
// jb_debug(jb, 3, "NACKABLE seq %u not too soon to repeat %lu\n", seq, switch_time_now() - then);
//}
if ( seq < ntohs ( jb - > target_seq ) - jb - > frame_len ) {
jb_debug ( jb , 3 , " NACKABLE seq %u expired \n " , seq ) ;
switch_core_inthash_delete ( jb - > missing_seq_hash , ( uint32_t ) htons ( seq ) ) ;
goto top ;
}
2015-09-18 18:47:03 +00:00
2015-09-19 04:36:11 +00:00
if ( ! least | | seq < least ) {
least = seq ;
2015-09-11 16:37:01 +00:00
}
}
2016-08-03 23:41:18 +00:00
switch_safe_free ( hi ) ;
2015-09-19 04:36:11 +00:00
if ( least & & switch_core_inthash_delete ( jb - > missing_seq_hash , ( uint32_t ) htons ( least ) ) ) {
jb_debug ( jb , 3 , " Found NACKABLE seq %u \n " , least ) ;
nack = ( uint32_t ) htons ( least ) ;
switch_core_inthash_insert ( jb - > missing_seq_hash , nack , ( void * ) ( intptr_t ) switch_time_now ( ) ) ;
2015-09-11 16:37:01 +00:00
for ( i = 0 ; i < 16 ; i + + ) {
2015-09-19 04:36:11 +00:00
if ( switch_core_inthash_delete ( jb - > missing_seq_hash , ( uint32_t ) htons ( least + i + 1 ) ) ) {
switch_core_inthash_insert ( jb - > missing_seq_hash , ( uint32_t ) htons ( least + i + 1 ) , ( void * ) ( intptr_t ) switch_time_now ( ) ) ;
jb_debug ( jb , 3 , " Found addtl NACKABLE seq %u \n " , least + i + 1 ) ;
2015-09-11 16:37:01 +00:00
blp | = ( 1 < < i ) ;
}
}
blp = htons ( blp ) ;
nack | = ( uint32_t ) blp < < 16 ;
//jb_frame_inc(jb, 1);
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > mutex ) ;
return nack ;
}
SWITCH_DECLARE ( switch_status_t ) switch_jb_put_packet ( switch_jb_t * jb , switch_rtp_packet_t * packet , switch_size_t len )
{
uint32_t i ;
uint16_t want = ntohs ( jb - > next_seq ) , got = ntohs ( packet - > header . seq ) ;
2020-08-11 23:32:21 +00:00
if ( len > = SWITCH_RTP_MAX_PACKET_LEN ) {
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 ) ;
len = SWITCH_RTP_MAX_PACKET_LEN ;
2016-01-07 09:11:52 +00:00
}
2015-09-11 16:37:01 +00:00
switch_mutex_lock ( jb - > mutex ) ;
2017-03-11 03:14:17 +00:00
if ( jb - > highest_dropped_ts ) {
if ( ntohl ( packet - > header . ts ) < jb - > highest_dropped_ts ) {
jb_debug ( jb , 2 , " %s " , " TS ALREADY DROPPED, DROPPING PACKET \n " ) ;
switch_mutex_unlock ( jb - > mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
jb - > highest_dropped_ts = 0 ;
}
2015-09-11 16:37:01 +00:00
if ( ! want ) want = got ;
2016-07-11 03:25:14 +00:00
if ( switch_test_flag ( jb , SJB_QUEUE_ONLY ) | | jb - > type = = SJB_AUDIO | | jb - > type = = SJB_TEXT ) {
2015-09-11 16:37:01 +00:00
jb - > next_seq = htons ( got + 1 ) ;
} else {
2015-09-19 04:36:11 +00:00
if ( switch_core_inthash_delete ( jb - > missing_seq_hash , ( uint32_t ) htons ( got ) ) ) {
if ( got < ntohs ( jb - > target_seq ) ) {
jb_debug ( jb , 2 , " got nacked seq %u too late \n " , got ) ;
jb_frame_inc ( jb , 1 ) ;
2019-07-25 14:21:39 +00:00
jb - > nack_didnt_save_the_day + + ;
2015-09-19 04:36:11 +00:00
} else {
jb_debug ( jb , 2 , " got nacked %u saved the day! \n " , got ) ;
2019-07-25 14:21:39 +00:00
jb - > nack_saved_the_day + + ;
2015-09-19 04:36:11 +00:00
}
}
2015-09-11 16:37:01 +00:00
2015-09-18 18:47:03 +00:00
if ( got > want ) {
2015-09-19 01:54:42 +00:00
if ( got - want > jb - > max_frame_len & & got - want > 17 ) {
jb_debug ( jb , 2 , " Missing %u frames, Resetting \n " , got - want ) ;
switch_jb_reset ( jb ) ;
} else {
2015-09-19 04:36:11 +00:00
2018-10-09 20:15:50 +00:00
if ( jb - > type ! = SJB_VIDEO & & jb - > frame_len < got - want ) {
2015-09-21 20:32:32 +00:00
jb_frame_inc ( jb , 1 ) ;
2015-09-19 04:36:11 +00:00
}
2015-09-19 01:54:42 +00:00
jb_debug ( jb , 2 , " GOT %u WANTED %u; MARK SEQS MISSING %u - %u \n " , got , want , want , got - 1 ) ;
2017-01-06 07:10:15 +00:00
2015-09-19 01:54:42 +00:00
for ( i = want ; i < got ; i + + ) {
jb_debug ( jb , 2 , " MARK MISSING %u ts:%u \n " , i , ntohl ( packet - > header . ts ) ) ;
2015-09-21 20:32:32 +00:00
switch_core_inthash_insert ( jb - > missing_seq_hash , ( uint32_t ) htons ( i ) , ( void * ) ( intptr_t ) 1 ) ;
2015-09-19 01:54:42 +00:00
}
2015-09-11 16:37:01 +00:00
}
}
2015-09-18 18:47:03 +00:00
if ( got > = want | | ( want - got ) > 1000 ) {
jb - > next_seq = htons ( got + 1 ) ;
}
2015-09-11 16:37:01 +00:00
}
add_node ( jb , packet , len ) ;
2015-09-21 19:08:32 +00:00
2019-04-03 13:56:59 +00:00
if ( switch_test_flag ( jb , SJB_QUEUE_ONLY ) & & jb - > max_packet_len & & jb - > max_frame_len * 2 > jb - > max_packet_len & &
jb - > allocated_nodes > jb - > max_frame_len * 2 - 1 ) {
2019-04-02 16:59:45 +00:00
while ( ( jb - > max_frame_len * 2 - jb - > visible_nodes ) < jb - > max_packet_len ) {
drop_oldest_frame ( jb ) ;
}
2019-04-03 13:56:59 +00:00
} else if ( switch_test_flag ( jb , SJB_QUEUE_ONLY ) & & jb - > max_packet_len & & jb - > max_frame_len * 2 < jb - > max_packet_len ) {
/* rtp_nack_buffer_size less than initial max_packet_len */
drop_oldest_frame ( jb ) ;
2015-09-21 19:08:32 +00:00
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( 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_jb_node_t * node ;
switch_status_t status = SWITCH_STATUS_NOTFOUND ;
switch_mutex_lock ( jb - > mutex ) ;
if ( ( node = switch_core_inthash_find ( jb - > node_hash , seq ) ) ) {
jb_debug ( jb , 2 , " Found buffered seq: %u \n " , ntohs ( seq ) ) ;
* packet = node - > packet ;
* len = node - > len ;
2017-03-11 03:14:17 +00:00
packet - > header . version = 2 ;
2015-09-11 16:37:01 +00:00
status = SWITCH_STATUS_SUCCESS ;
} else {
jb_debug ( jb , 2 , " Missing buffered seq: %u \n " , ntohs ( seq ) ) ;
}
switch_mutex_unlock ( jb - > mutex ) ;
return status ;
}
SWITCH_DECLARE ( switch_size_t ) switch_jb_get_last_read_len ( switch_jb_t * jb )
{
return jb - > last_len ;
}
SWITCH_DECLARE ( switch_status_t ) switch_jb_get_packet ( switch_jb_t * jb , switch_rtp_packet_t * packet , switch_size_t * len )
{
switch_jb_node_t * node = NULL ;
switch_status_t status ;
2015-10-02 00:11:51 +00:00
int plc = 0 ;
2018-05-15 22:09:55 +00:00
2015-09-11 16:37:01 +00:00
switch_mutex_lock ( jb - > mutex ) ;
2015-10-07 16:21:51 +00:00
if ( jb - > complete_frames = = 0 ) {
2016-07-11 03:25:14 +00:00
jb - > flush = 0 ;
2015-10-07 16:21:51 +00:00
switch_goto_status ( SWITCH_STATUS_BREAK , end ) ;
}
2015-09-11 16:37:01 +00:00
if ( jb - > complete_frames < jb - > frame_len ) {
2016-10-11 15:56:08 +00:00
2016-10-08 01:27:35 +00:00
switch_jb_poll ( jb ) ;
2016-10-11 15:56:08 +00:00
2016-07-11 03:25:14 +00:00
if ( ! jb - > flush ) {
jb_debug ( jb , 2 , " BUFFERING %u/%u \n " , jb - > complete_frames , jb - > frame_len ) ;
switch_goto_status ( SWITCH_STATUS_MORE_DATA , end ) ;
}
2015-09-11 16:37:01 +00:00
}
2015-09-17 22:34:50 +00:00
jb_debug ( jb , 2 , " GET PACKET %u/%u n:%d \n " , jb - > complete_frames , jb - > frame_len , jb - > visible_nodes ) ;
2018-10-09 20:15:50 +00:00
if ( + + jb - > period_count > = jb - > period_len ) {
2015-09-11 16:37:01 +00:00
2018-10-09 20:15:50 +00:00
if ( jb - > consec_good_count > = ( jb - > period_len - 5 ) ) {
2015-09-11 16:37:01 +00:00
jb_frame_inc ( jb , - 1 ) ;
}
jb - > period_count = 1 ;
2015-09-19 04:36:11 +00:00
jb - > period_miss_inc = 0 ;
2015-09-11 16:37:01 +00:00
jb - > period_miss_count = 0 ;
jb - > period_good_count = 0 ;
jb - > consec_miss_count = 0 ;
jb - > consec_good_count = 0 ;
2015-09-21 20:32:32 +00:00
2015-09-22 21:35:00 +00:00
if ( jb - > type = = SJB_VIDEO & & jb - > channel & & jb - > video_low_bitrate ) {
2015-09-19 04:36:11 +00:00
//switch_time_t now = switch_time_now();
2015-09-18 18:47:03 +00:00
//int ok = (now - jb->last_bitrate_change) > 10000;
2017-01-06 07:10:15 +00:00
2015-09-18 18:47:03 +00:00
if ( switch_channel_test_flag ( jb - > channel , CF_VIDEO_BITRATE_UNMANAGABLE ) & & jb - > frame_len = = jb - > min_frame_len ) {
jb_debug ( jb , 2 , " %s " , " Allow BITRATE changes \n " ) ;
2017-04-21 21:15:53 +00:00
switch_channel_clear_flag_recursive ( jb - > channel , CF_VIDEO_BITRATE_UNMANAGABLE ) ;
2015-09-18 18:47:03 +00:00
jb - > bitrate_control = 0 ;
2015-09-21 20:32:32 +00:00
if ( jb - > session ) {
switch_core_session_request_video_refresh ( jb - > session ) ;
}
2017-03-11 03:14:17 +00:00
} else if ( ! switch_channel_test_flag ( jb - > channel , CF_VIDEO_BITRATE_UNMANAGABLE ) & & jb - > frame_len > jb - > max_frame_len / 2 ) {
2015-09-18 18:47:03 +00:00
switch_core_session_message_t msg = { 0 } ;
2015-09-22 21:35:00 +00:00
jb - > bitrate_control = jb - > video_low_bitrate ;
2017-03-11 03:14:17 +00:00
2015-09-18 18:47:03 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_BITRATE_REQ ;
msg . numeric_arg = jb - > bitrate_control * 1024 ;
msg . from = __FILE__ ;
2017-01-06 07:10:15 +00:00
2015-09-18 18:47:03 +00:00
jb_debug ( jb , 2 , " Force BITRATE to %d \n " , jb - > bitrate_control ) ;
2017-03-11 03:14:17 +00:00
2015-09-18 18:47:03 +00:00
switch_core_session_receive_message ( jb - > session , & msg ) ;
2017-04-21 21:15:53 +00:00
switch_channel_set_flag_recursive ( jb - > channel , CF_VIDEO_BITRATE_UNMANAGABLE ) ;
2015-09-21 20:32:32 +00:00
if ( jb - > session ) {
switch_core_session_request_video_refresh ( jb - > session ) ;
}
2015-09-18 18:47:03 +00:00
}
}
2015-09-11 16:37:01 +00:00
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
jb - > period_miss_pct = ( ( double ) jb - > period_miss_count / jb - > period_count ) * 100 ;
2018-05-15 22:09:55 +00:00
//if (jb->period_miss_pct > 60.0f) {
// jb_debug(jb, 2, "Miss percent %02f too high, resetting buffer.\n", jb->period_miss_pct);
// switch_jb_reset(jb);
//}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( ( status = jb_next_packet ( jb , & node ) ) = = SWITCH_STATUS_SUCCESS ) {
jb_debug ( jb , 2 , " Found next frame cur ts: %u seq: %u \n " , htonl ( node - > packet . header . ts ) , htons ( node - > packet . header . seq ) ) ;
2017-03-11 03:14:17 +00:00
if ( ! jb - > read_init | | check_seq ( node - > packet . header . seq , jb - > highest_read_seq ) ) {
2015-09-11 16:37:01 +00:00
jb - > highest_read_seq = node - > packet . header . seq ;
}
2017-01-06 07:10:15 +00:00
2017-03-11 03:14:17 +00:00
if ( jb - > type ! = SJB_VIDEO | |
( jb - > read_init & & check_seq ( node - > packet . header . seq , jb - > highest_read_seq ) & & check_ts ( node - > packet . header . ts , jb - > highest_read_ts ) ) ) {
2017-03-03 20:33:39 +00:00
2017-03-11 03:14:17 +00:00
if ( jb - > type ! = SJB_VIDEO ) {
2017-03-03 20:33:39 +00:00
jb - > complete_frames - - ;
}
2016-07-21 08:22:37 +00:00
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 ) ;
2015-09-11 16:37:01 +00:00
jb - > highest_read_ts = node - > packet . header . ts ;
} else if ( ! jb - > read_init ) {
jb - > highest_read_ts = node - > packet . header . ts ;
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( ! jb - > read_init ) jb - > read_init = 1 ;
} else {
if ( jb - > type = = SJB_VIDEO ) {
2018-04-20 18:33:57 +00:00
//switch_jb_reset(jb);
2015-09-11 16:37:01 +00:00
switch ( status ) {
case SWITCH_STATUS_RESTART :
jb_debug ( jb , 2 , " %s " , " Error encountered ask for new keyframe \n " ) ;
switch_goto_status ( SWITCH_STATUS_RESTART , end ) ;
case SWITCH_STATUS_NOTFOUND :
default :
jb_debug ( jb , 2 , " %s " , " No frames found wait for more \n " ) ;
switch_goto_status ( SWITCH_STATUS_MORE_DATA , end ) ;
}
} else {
switch ( status ) {
case SWITCH_STATUS_RESTART :
jb_debug ( jb , 2 , " %s " , " Error encountered \n " ) ;
switch_jb_reset ( jb ) ;
switch_goto_status ( SWITCH_STATUS_RESTART , end ) ;
case SWITCH_STATUS_NOTFOUND :
2017-01-06 07:10:15 +00:00
default :
2015-09-11 16:37:01 +00:00
if ( jb - > consec_miss_count > jb - > frame_len ) {
2018-05-15 22:09:55 +00:00
//switch_jb_reset(jb);
2015-09-11 16:37:01 +00:00
jb_frame_inc ( jb , 1 ) ;
2015-09-15 19:59:05 +00:00
jb_debug ( jb , 2 , " %s " , " Too many frames not found, RESIZE \n " ) ;
2015-09-11 16:37:01 +00:00
switch_goto_status ( SWITCH_STATUS_RESTART , end ) ;
} else {
jb_debug ( jb , 2 , " %s " , " Frame not found suggest PLC \n " ) ;
2015-10-02 00:11:51 +00:00
plc = 1 ;
2015-09-11 16:37:01 +00:00
switch_goto_status ( SWITCH_STATUS_NOTFOUND , end ) ;
}
}
}
}
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
if ( node ) {
status = SWITCH_STATUS_SUCCESS ;
2017-01-06 07:10:15 +00:00
2015-09-11 16:37:01 +00:00
* packet = node - > packet ;
* len = node - > len ;
jb - > last_len = * len ;
2017-03-11 03:14:17 +00:00
packet - > header . version = 2 ;
2015-09-11 16:37:01 +00:00
hide_node ( node , SWITCH_TRUE ) ;
2018-10-09 20:15:50 +00:00
jb_debug ( jb , 2 , " GET packet ts:%u seq:%u %s \n " , ntohl ( packet - > header . ts ) , ntohs ( packet - > header . seq ) , packet - > header . m ? " <MARK> " : " " ) ;
2015-09-11 16:37:01 +00:00
} else {
status = SWITCH_STATUS_MORE_DATA ;
}
end :
2015-10-02 00:11:51 +00:00
if ( plc ) {
uint16_t seq ;
2015-10-02 17:51:57 +00:00
uint32_t ts = 0 ;
2015-10-02 00:11:51 +00:00
if ( jb - > samples_per_frame ) {
seq = htons ( jb - > last_psuedo_seq ) ;
2015-10-02 17:51:57 +00:00
ts = jb - > last_target_ts ;
2015-10-02 00:11:51 +00:00
} else {
seq = jb - > last_target_seq ;
}
2017-01-06 07:10:15 +00:00
2015-10-02 00:11:51 +00:00
packet - > header . seq = seq ;
2015-10-02 00:29:45 +00:00
packet - > header . ts = ts ;
2015-10-02 00:11:51 +00:00
}
2015-09-11 16:37:01 +00:00
switch_mutex_unlock ( jb - > mutex ) ;
2018-05-25 16:07:24 +00:00
2018-05-15 22:09:55 +00:00
if ( jb - > type = = SJB_VIDEO ) {
2018-05-25 16:07:24 +00:00
if ( jb - > complete_frames > jb - > max_frame_len * 2 ) {
jb_debug ( jb , 2 , " JB TOO BIG (%d), RESET \n " , jb - > complete_frames ) ;
switch_jb_reset ( jb ) ;
}
2018-05-15 22:09:55 +00:00
} else {
2018-05-25 16:07:24 +00:00
int too_big = ( int ) ( jb - > max_frame_len * 1.5 ) ;
if ( jb - > visible_nodes > too_big & & status = = SWITCH_STATUS_SUCCESS ) {
status = SWITCH_STATUS_TIMEOUT ;
}
2018-05-15 22:09:55 +00:00
}
2015-09-11 16:37:01 +00:00
return status ;
}
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet :
*/