| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2004-2005, Horizon Wimba, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributors: | 
					
						
							|  |  |  |  * Steve Kann <stevek@stevek.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-06-14 14:12:56 +00:00
										 |  |  |  * A license has been granted to Digium (via disclaimer) for the use of | 
					
						
							|  |  |  |  * this code. | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief jitterbuf: an application-independent jitterbuffer | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  |  * \author Steve Kann <stevek@stevek.com> | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | #include "jitterbuf.h"
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | /*! define these here, just for ancient compiler systems */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | #define JB_LONGMAX 2147483647L
 | 
					
						
							|  |  |  | #define JB_LONGMIN (-JB_LONGMAX - 1L)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
 | 
					
						
							|  |  |  | #define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
 | 
					
						
							|  |  |  | #define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEEP_DEBUG
 | 
					
						
							|  |  |  | #define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define jb_dbg2(...) ((void)0)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static jb_output_function_t warnf, errf, dbgf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	errf = err; | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	warnf = warn; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	dbgf = dbg; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void increment_losspct(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;     | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void decrement_losspct(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->info.losspct = (499 * jb->info.losspct)/500;     | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void jb_reset(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	/* only save settings */ | 
					
						
							|  |  |  | 	jb_conf s = jb->info.conf; | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 	memset(jb, 0, sizeof(*jb)); | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	jb->info.conf = s; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  | 	/* initialize length, using the default value */ | 
					
						
							|  |  |  | 	jb->info.current = jb->info.target = jb->info.conf.target_extra = JB_TARGET_EXTRA; | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 	jb->info.silence_begin_ts = -1;  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | jitterbuf * jb_new()  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jitterbuf *jb; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 	if (!(jb = ast_malloc(sizeof(*jb))))  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_reset(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg2("jb_new() = %x\n", jb); | 
					
						
							|  |  |  | 	return jb; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void jb_destroy(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_frame *frame;  | 
					
						
							|  |  |  | 	jb_dbg2("jb_destroy(%x)\n", jb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free all the frames on the "free list" */ | 
					
						
							|  |  |  | 	frame = jb->free; | 
					
						
							|  |  |  | 	while (frame != NULL) { | 
					
						
							|  |  |  | 		jb_frame *next = frame->next; | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(frame); | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		frame = next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free ourselves! */  | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:30:23 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | static int longcmp(const void *a, const void *b)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return *(long *)a - *(long *)b; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-21 06:30:23 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | /*!	\brief simple history manipulation 
 | 
					
						
							|  |  |  |  	\note maybe later we can make the history buckets variable size, or something? */ | 
					
						
							|  |  |  | /* drop parameter determines whether we will drop outliers to minimize
 | 
					
						
							|  |  |  |  * delay */ | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | static int history_put(jitterbuf *jb, long ts, long now, long ms)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	long delay = now - (ts - jb->info.resync_offset); | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	long kicked; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* don't add special/negative times to history */ | 
					
						
							|  |  |  | 	if (ts <= 0)  | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* check for drastic change in delay */ | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	if (jb->info.conf.resync_threshold != -1) { | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 		if (abs(delay - jb->info.last_delay) > threshold) { | 
					
						
							|  |  |  | 			jb->info.cnt_delay_discont++; | 
					
						
							|  |  |  | 			if (jb->info.cnt_delay_discont > 3) { | 
					
						
							|  |  |  | 				/* resync the jitterbuffer */ | 
					
						
							|  |  |  | 				jb->info.cnt_delay_discont = 0; | 
					
						
							|  |  |  | 				jb->hist_ptr = 0; | 
					
						
							|  |  |  | 				jb->hist_maxbuf_valid = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, delay, threshold, ts - now); | 
					
						
							|  |  |  | 				jb->info.resync_offset = ts - now; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:30:10 +00:00
										 |  |  | 				jb->info.last_delay = delay = 0; /* after resync, frame is right on time */ | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			jb->info.last_delay = delay; | 
					
						
							|  |  |  | 			jb->info.cnt_delay_discont = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-17 01:59:59 +00:00
										 |  |  | 	kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ]; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* optimization; the max/min buffers don't need to be recalculated, if this packet's
 | 
					
						
							|  |  |  | 	 * entry doesn't change them.  This happens if this packet is not involved, _and_ any packet | 
					
						
							|  |  |  | 	 * that got kicked out of the history is also not involved  | 
					
						
							|  |  |  | 	 * We do a number of comparisons, but it's probably still worthwhile, because it will usually | 
					
						
							|  |  |  | 	 * succeed, and should be a lot faster than going through all 500 packets in history */ | 
					
						
							|  |  |  | 	if (!jb->hist_maxbuf_valid) | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* don't do this until we've filled history 
 | 
					
						
							|  |  |  | 	 * (reduces some edge cases below) */ | 
					
						
							|  |  |  | 	if (jb->hist_ptr < JB_HISTORY_SZ) | 
					
						
							|  |  |  | 		goto invalidate; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* if the new delay would go into min */ | 
					
						
							|  |  |  | 	if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) | 
					
						
							|  |  |  | 		goto invalidate; | 
					
						
							| 
									
										
										
										
											2008-03-04 23:04:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* or max.. */ | 
					
						
							|  |  |  | 	if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) | 
					
						
							|  |  |  | 		goto invalidate; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* or the kicked delay would be in min */ | 
					
						
							|  |  |  | 	if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])  | 
					
						
							|  |  |  | 		goto invalidate; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])  | 
					
						
							|  |  |  | 		goto invalidate; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* if we got here, we don't need to invalidate, 'cause this delay didn't 
 | 
					
						
							|  |  |  | 	 * affect things */ | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* end optimization */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | invalidate: | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->hist_maxbuf_valid = 0; | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void history_calc_maxbuf(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	int i,j; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (jb->hist_ptr == 0)  | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* initialize maxbuf/minbuf to the latest value */ | 
					
						
							|  |  |  | 	for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) { | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; | 
					
						
							|  |  |  |  * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->hist_maxbuf[i] = JB_LONGMIN; | 
					
						
							|  |  |  | 		jb->hist_minbuf[i] = JB_LONGMAX; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* use insertion sort to populate maxbuf */ | 
					
						
							|  |  |  | 	/* we want it to be the top "n" values, in order */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* start at the beginning, or JB_HISTORY_SZ frames ago */ | 
					
						
							|  |  |  | 	i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	for (;i<jb->hist_ptr;i++) { | 
					
						
							|  |  |  | 		long toins = jb->history[i % JB_HISTORY_SZ]; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* if the maxbuf should get this */ | 
					
						
							|  |  |  | 		if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])  { | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			/* insertion-sort it into the maxbuf */ | 
					
						
							|  |  |  | 			for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) { | 
					
						
							|  |  |  | 				/* found where it fits */ | 
					
						
							|  |  |  | 				if (toins > jb->hist_maxbuf[j]) { | 
					
						
							|  |  |  | 					/* move over */ | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 					memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0])); | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 					/* insert */ | 
					
						
							|  |  |  | 					jb->hist_maxbuf[j] = toins; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* if the minbuf should get this */ | 
					
						
							|  |  |  | 		if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])  { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* insertion-sort it into the maxbuf */ | 
					
						
							|  |  |  | 			for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) { | 
					
						
							|  |  |  | 				/* found where it fits */ | 
					
						
							|  |  |  | 				if (toins < jb->hist_minbuf[j]) { | 
					
						
							|  |  |  | 					/* move over */ | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 					memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0])); | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 					/* insert */ | 
					
						
							|  |  |  | 					jb->hist_minbuf[j] = toins; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		if (0) {  | 
					
						
							|  |  |  | 			int k; | 
					
						
							|  |  |  | 			fprintf(stderr, "toins = %ld\n", toins); | 
					
						
							|  |  |  | 			fprintf(stderr, "maxbuf ="); | 
					
						
							|  |  |  | 			for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)  | 
					
						
							|  |  |  | 				fprintf(stderr, "%ld ", jb->hist_maxbuf[k]); | 
					
						
							|  |  |  | 			fprintf(stderr, "\nminbuf ="); | 
					
						
							|  |  |  | 			for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)  | 
					
						
							|  |  |  | 				fprintf(stderr, "%ld ", jb->hist_minbuf[k]); | 
					
						
							|  |  |  | 			fprintf(stderr, "\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->hist_maxbuf_valid = 1; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void history_get(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	long max, min, jitter; | 
					
						
							| 
									
										
										
										
											2008-08-10 19:35:50 +00:00
										 |  |  | 	int idx; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	int count; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!jb->hist_maxbuf_valid)  | 
					
						
							|  |  |  | 		history_calc_maxbuf(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* count is how many items in history we're examining */ | 
					
						
							|  |  |  | 	count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 19:35:50 +00:00
										 |  |  | 	/* idx is the "n"ths highest/lowest that we'll look for */ | 
					
						
							|  |  |  | 	idx = count * JB_HISTORY_DROPPCT / 100; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 19:35:50 +00:00
										 |  |  | 	/* sanity checks for idx */ | 
					
						
							|  |  |  | 	if (idx > (JB_HISTORY_MAXBUF_SZ - 1))  | 
					
						
							|  |  |  | 		idx = JB_HISTORY_MAXBUF_SZ - 1; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 19:35:50 +00:00
										 |  |  | 	if (idx < 0) { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->info.min = 0; | 
					
						
							|  |  |  | 		jb->info.jitter = 0; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 19:35:50 +00:00
										 |  |  | 	max = jb->hist_maxbuf[idx]; | 
					
						
							|  |  |  | 	min = jb->hist_minbuf[idx]; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jitter = max - min; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* these debug stmts compare the difference between looking at the absolute jitter, and the
 | 
					
						
							|  |  |  | 	 * values we get by throwing away the outliers */ | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter); | 
					
						
							|  |  |  | 	fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]); | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->info.min = min; | 
					
						
							|  |  |  | 	jb->info.jitter = jitter; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | /* returns 1 if frame was inserted into head of queue, 0 otherwise */ | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_frame *frame; | 
					
						
							|  |  |  | 	jb_frame *p; | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 	int head = 0; | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	long resync_ts = ts - jb->info.resync_offset; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 	if ((frame = jb->free)) { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->free = frame->next; | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 	} else if (!(frame = ast_malloc(sizeof(*frame)))) { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb_err("cannot allocate frame\n"); | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb->info.frames_cur++; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	frame->data = data; | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	frame->ts = resync_ts; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	frame->ms = ms; | 
					
						
							|  |  |  | 	frame->type = type; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * frames are a circular list, jb-frames points to to the lowest ts,  | 
					
						
							|  |  |  | 	 * jb->frames->prev points to the highest ts | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!jb->frames) {  /* queue is empty */ | 
					
						
							|  |  |  | 		jb->frames = frame; | 
					
						
							|  |  |  | 		frame->next = frame; | 
					
						
							|  |  |  | 		frame->prev = frame; | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 		head = 1; | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 	} else if (resync_ts < jb->frames->ts) { | 
					
						
							| 
									
										
										
										
											2005-05-12 19:21:41 +00:00
										 |  |  | 		frame->next = jb->frames; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		frame->prev = jb->frames->prev; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		frame->next->prev = frame; | 
					
						
							|  |  |  | 		frame->prev->next = frame; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-12 19:21:41 +00:00
										 |  |  | 		/* frame is out of order */ | 
					
						
							|  |  |  | 		jb->info.frames_ooo++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->frames = frame; | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 		head = 1; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	} else {  | 
					
						
							|  |  |  | 		p = jb->frames; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* frame is out of order */ | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 		if (resync_ts < p->prev->ts) jb->info.frames_ooo++; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 		while (resync_ts < p->prev->ts && p->prev != jb->frames)  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			p = p->prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		frame->next = p; | 
					
						
							|  |  |  | 		frame->prev = p->prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		frame->next->prev = frame; | 
					
						
							|  |  |  | 		frame->prev->next = frame; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 	return head; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long queue_next(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (jb->frames)  | 
					
						
							|  |  |  | 		return jb->frames->ts; | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long queue_last(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (jb->frames)  | 
					
						
							|  |  |  | 		return jb->frames->prev->ts; | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_frame *frame; | 
					
						
							|  |  |  | 	frame = jb->frames; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!frame) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 	if (all || ts >= frame->ts) { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* remove this frame */ | 
					
						
							|  |  |  | 		frame->prev->next = frame->next; | 
					
						
							|  |  |  | 		frame->next->prev = frame->prev; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		if (frame->next == frame) | 
					
						
							|  |  |  | 			jb->frames = NULL; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			jb->frames = frame->next; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* insert onto "free" single-linked list */ | 
					
						
							|  |  |  | 		frame->next = jb->free; | 
					
						
							|  |  |  | 		jb->free = frame; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->info.frames_cur--; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* we return the frame pointer, even though it's on free list, 
 | 
					
						
							|  |  |  | 		 * but caller must copy data */ | 
					
						
							|  |  |  | 		return frame; | 
					
						
							|  |  |  | 	}  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static jb_frame *queue_get(jitterbuf *jb, long ts)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return _queue_get(jb,ts,0); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static jb_frame *queue_getall(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return _queue_get(jb,0,1); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-03 21:16:01 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | /* some diagnostics */ | 
					
						
							|  |  |  | static void jb_dbginfo(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (dbgf == NULL)  | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n", | 
					
						
							|  |  |  | 		jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n", | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 		jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8); | 
					
						
							|  |  |  | 	if (jb->info.frames_in > 0)  | 
					
						
							|  |  |  | 		jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n", | 
					
						
							|  |  |  | 			jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),  | 
					
						
							|  |  |  | 			jb->info.frames_late * 100/jb->info.frames_in); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 	jb_dbg("jb info: queue %d -> %d.  last_ts %d (queue len: %d) last_ms %d\n", | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		queue_next(jb),  | 
					
						
							|  |  |  | 		queue_last(jb), | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		jb->info.next_voice_ts,  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		queue_last(jb) - queue_next(jb), | 
					
						
							|  |  |  | 		jb->info.last_voice_ms); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-03 21:16:01 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEEP_DEBUG
 | 
					
						
							|  |  |  | static void jb_chkqueue(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	int i=0; | 
					
						
							|  |  |  | 	jb_frame *p = jb->frames; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!p) { | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		if (p->next == NULL)  { | 
					
						
							|  |  |  | 			jb_err("Queue is BROKEN at item [%d]", i);	 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 		p=p->next; | 
					
						
							|  |  |  | 	} while (p->next != jb->frames); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void jb_dbgqueue(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	int i=0; | 
					
						
							|  |  |  | 	jb_frame *p = jb->frames; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg("queue: "); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!p) { | 
					
						
							|  |  |  | 		jb_dbg("EMPTY\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	do { | 
					
						
							|  |  |  | 		jb_dbg("[%d]=%ld ", i++, p->ts); | 
					
						
							|  |  |  | 		p=p->next; | 
					
						
							|  |  |  | 	} while (p->next != jb->frames); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg("\n"); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-01-29 17:03:31 +00:00
										 |  |  | 	long numts; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 	numts = 0; | 
					
						
							|  |  |  | 	if (jb->frames) | 
					
						
							|  |  |  | 		numts = jb->frames->prev->ts - jb->frames->ts; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 	if (numts >= jb->info.conf.max_jitterbuf) { | 
					
						
							|  |  |  | 		if (!jb->dropem) { | 
					
						
							|  |  |  | 			ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n", | 
					
						
							|  |  |  | 				jb->info.conf.max_jitterbuf); | 
					
						
							|  |  |  | 			jb->dropem = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		jb->info.frames_dropped++; | 
					
						
							| 
									
										
										
										
											2007-01-29 17:03:31 +00:00
										 |  |  | 		return JB_DROP; | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		jb->dropem = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-01-29 17:03:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (type == JB_TYPE_VOICE) { | 
					
						
							|  |  |  | 		/* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
 | 
					
						
							|  |  |  | 		 * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */ | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 		if (history_put(jb,ts,now,ms)) { | 
					
						
							|  |  |  | 			jb->info.frames_dropped++; | 
					
						
							| 
									
										
										
										
											2005-05-19 00:34:28 +00:00
										 |  |  | 			return JB_DROP; | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-10 18:16:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	jb->info.frames_in++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-19 01:24:09 +00:00
										 |  |  | 	/* if put into head of queue, caller needs to reschedule */ | 
					
						
							|  |  |  | 	if (queue_put(jb,data,type,ms,ts)) { | 
					
						
							|  |  |  | 		return JB_SCHED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return JB_OK; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_frame *frame; | 
					
						
							|  |  |  | 	long diff; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:02:07 +00:00
										 |  |  | 	static int dbg_cnt = 0; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */ | 
					
						
							|  |  |  | 	/* get jitter info */ | 
					
						
							|  |  |  | 	history_get(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-21 01:02:07 +00:00
										 |  |  | 	if (dbg_cnt && dbg_cnt % 50 == 0) { | 
					
						
							|  |  |  | 		jb_dbg("\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dbg_cnt++; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* target */ | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  | 	jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra;  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* if a hard clamp was requested, use it */ | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) { | 
					
						
							| 
									
										
										
										
											2008-03-18 15:43:34 +00:00
										 |  |  | 		jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf); | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 		jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	diff = jb->info.target - jb->info.current; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff,  */ | 
					
						
							|  |  |  | 	/*	jb->info.last_voice_ms, jb->info.last_adjustment, now); */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* let's work on non-silent case first */ | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 	if (!jb->info.silence_begin_ts) {  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* we want to grow */ | 
					
						
							|  |  |  | 		if ((diff > 0) &&  | 
					
						
							| 
									
										
										
										
											2005-05-09 13:56:43 +00:00
										 |  |  | 			/* we haven't grown in the delay length */ | 
					
						
							|  |  |  | 			(((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			/* we need to grow more than the "length" we have left */ | 
					
						
							|  |  |  | 			(diff > queue_last(jb)  - queue_next(jb)) ) ) { | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			/* grow by interp frame length */ | 
					
						
							|  |  |  | 			jb->info.current += interpl; | 
					
						
							|  |  |  | 			jb->info.next_voice_ts += interpl; | 
					
						
							|  |  |  | 			jb->info.last_voice_ms = interpl; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			jb->info.last_adjustment = now; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 			jb->info.cnt_contig_interp++; | 
					
						
							|  |  |  | 			if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { | 
					
						
							|  |  |  | 				jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			jb_dbg("G"); | 
					
						
							|  |  |  | 			return JB_INTERP; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* not a voice frame; just return it. */ | 
					
						
							|  |  |  | 		if (frame && frame->type != JB_TYPE_VOICE) { | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 			if (frame->type == JB_TYPE_SILENCE) { | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 				jb->info.silence_begin_ts = frame->ts; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 				jb->info.cnt_contig_interp = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			*frameout = *frame; | 
					
						
							|  |  |  | 			jb->info.frames_out++; | 
					
						
							|  |  |  | 			jb_dbg("o"); | 
					
						
							|  |  |  | 			return JB_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		/* voice frame is later than expected */ | 
					
						
							|  |  |  | 		if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) { | 
					
						
							|  |  |  | 			if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) { | 
					
						
							|  |  |  | 				/* either we interpolated past this frame in the last jb_get */ | 
					
						
							|  |  |  | 				/* or the frame is still in order, but came a little too quick */  | 
					
						
							|  |  |  | 				*frameout = *frame; | 
					
						
							|  |  |  | 				/* reset expectation for next frame */ | 
					
						
							|  |  |  | 				jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; | 
					
						
							|  |  |  | 				jb->info.frames_out++; | 
					
						
							|  |  |  | 				decrement_losspct(jb); | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 				jb->info.cnt_contig_interp = 0; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 				jb_dbg("v"); | 
					
						
							|  |  |  | 				return JB_OK; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				/* voice frame is late */ | 
					
						
							|  |  |  | 				*frameout = *frame; | 
					
						
							|  |  |  | 				jb->info.frames_out++; | 
					
						
							|  |  |  | 				decrement_losspct(jb); | 
					
						
							|  |  |  | 				jb->info.frames_late++; | 
					
						
							|  |  |  | 				jb->info.frames_lost--; | 
					
						
							|  |  |  | 				jb_dbg("l"); | 
					
						
							|  |  |  | 				/*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
 | 
					
						
							|  |  |  | 				jb_warninfo(jb); */ | 
					
						
							|  |  |  | 				return JB_DROP; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* keep track of frame sizes, to allow for variable sized-frames */ | 
					
						
							|  |  |  | 		if (frame && frame->ms > 0) { | 
					
						
							|  |  |  | 			jb->info.last_voice_ms = frame->ms; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* we want to shrink; shrink at 1 frame / 500ms */ | 
					
						
							| 
									
										
										
										
											2005-05-09 13:56:43 +00:00
										 |  |  | 		/* unless we don't have a frame, then shrink 1 frame */ | 
					
						
							|  |  |  | 		/* every 80ms (though perhaps we can shrink even faster */ | 
					
						
							|  |  |  | 		/* in this case) */ | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  | 		if (diff < -jb->info.conf.target_extra &&  | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			((!frame && jb->info.last_adjustment + 80 < now) ||  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			(jb->info.last_adjustment + 500 < now))) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			jb->info.last_adjustment = now; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 			jb->info.cnt_contig_interp = 0; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (frame) { | 
					
						
							|  |  |  | 				*frameout = *frame; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 				/* shrink by frame size we're throwing out */ | 
					
						
							|  |  |  | 				jb->info.current -= frame->ms; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 				jb->info.frames_out++; | 
					
						
							|  |  |  | 				decrement_losspct(jb); | 
					
						
							|  |  |  | 				jb->info.frames_dropped++; | 
					
						
							|  |  |  | 				jb_dbg("s"); | 
					
						
							|  |  |  | 				return JB_DROP; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 				/* shrink by last_voice_ms */ | 
					
						
							|  |  |  | 				jb->info.current -= jb->info.last_voice_ms; | 
					
						
							|  |  |  | 				jb->info.frames_lost++; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 				increment_losspct(jb); | 
					
						
							|  |  |  | 				jb_dbg("S"); | 
					
						
							|  |  |  | 				return JB_NOFRAME; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* lost frame */ | 
					
						
							|  |  |  | 		if (!frame) { | 
					
						
							|  |  |  | 			/* this is a bit of a hack for now, but if we're close to
 | 
					
						
							|  |  |  | 			 * target, and we find a missing frame, it makes sense to | 
					
						
							|  |  |  | 			 * grow, because the frame might just be a bit late; | 
					
						
							|  |  |  | 			 * otherwise, we presently get into a pattern where we return | 
					
						
							|  |  |  | 			 * INTERP for the lost frame, then it shows up next, and we | 
					
						
							|  |  |  | 			 * throw it away because it's late */ | 
					
						
							|  |  |  | 	  		/* I've recently only been able to replicate this using
 | 
					
						
							|  |  |  | 			 * iaxclient talking to app_echo on asterisk.  In this case, | 
					
						
							|  |  |  | 			 * my outgoing packets go through asterisk's (old) | 
					
						
							|  |  |  | 			 * jitterbuffer, and then might get an unusual increasing delay  | 
					
						
							|  |  |  | 			 * there if it decides to grow?? */ | 
					
						
							|  |  |  | 			/* Update: that might have been a different bug, that has been fixed..
 | 
					
						
							|  |  |  | 			 * But, this still seemed like a good idea, except that it ended up making a single actual | 
					
						
							|  |  |  | 			 * lost frame get interpolated two or more times, when there was "room" to grow, so it might | 
					
						
							|  |  |  | 			 * be a bit of a bad idea overall */ | 
					
						
							|  |  |  | 			/*if (diff > -1 * jb->info.last_voice_ms) { 
 | 
					
						
							|  |  |  | 				jb->info.current += jb->info.last_voice_ms; | 
					
						
							|  |  |  | 				jb->info.last_adjustment = now; | 
					
						
							|  |  |  | 				jb_warn("g"); | 
					
						
							|  |  |  | 				return JB_INTERP; | 
					
						
							|  |  |  | 			} */ | 
					
						
							|  |  |  | 			jb->info.frames_lost++; | 
					
						
							|  |  |  | 			increment_losspct(jb); | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			jb->info.next_voice_ts += interpl; | 
					
						
							|  |  |  | 			jb->info.last_voice_ms = interpl; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 			jb->info.cnt_contig_interp++; | 
					
						
							|  |  |  | 			if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { | 
					
						
							|  |  |  | 				jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			jb_dbg("L"); | 
					
						
							|  |  |  | 			return JB_INTERP; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* normal case; return the frame, increment stuff */ | 
					
						
							|  |  |  | 		*frameout = *frame; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		jb->info.next_voice_ts += frame->ms; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		jb->info.frames_out++; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 		jb->info.cnt_contig_interp = 0; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		decrement_losspct(jb); | 
					
						
							|  |  |  | 		jb_dbg("v"); | 
					
						
							|  |  |  | 		return JB_OK; | 
					
						
							|  |  |  | 	} else {      | 
					
						
							|  |  |  | 		/* TODO: after we get the non-silent case down, we'll make the
 | 
					
						
							|  |  |  | 		 * silent case -- basically, we'll just grow and shrink faster | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		 * here, plus handle next_voice_ts a bit differently */ | 
					
						
							| 
									
										
										
										
											2008-03-04 23:04:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		/* to disable silent special case altogether, just uncomment this: */ | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 		/* jb->info.silence_begin_ts = 0; */ | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  |  		/* shrink interpl len every 10ms during silence */ | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  |  		if (diff < -jb->info.conf.target_extra && | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  |  			jb->info.last_adjustment + 10 <= now) { | 
					
						
							|  |  |  |  			jb->info.current -= interpl; | 
					
						
							|  |  |  |  			jb->info.last_adjustment = now; | 
					
						
							|  |  |  |  		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		frame = queue_get(jb, now - jb->info.current); | 
					
						
							|  |  |  | 		if (!frame) { | 
					
						
							|  |  |  | 			return JB_NOFRAME; | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 		} else if (frame->type != JB_TYPE_VOICE) { | 
					
						
							|  |  |  | 			/* normal case; in silent mode, got a non-voice frame */ | 
					
						
							|  |  |  | 			*frameout = *frame; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			jb->info.frames_out++; | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 			return JB_OK; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 		if (frame->ts < jb->info.silence_begin_ts) { | 
					
						
							|  |  |  | 			/* voice frame is late */ | 
					
						
							|  |  |  | 			*frameout = *frame; | 
					
						
							|  |  |  | 			jb->info.frames_out++; | 
					
						
							|  |  |  | 			decrement_losspct(jb); | 
					
						
							|  |  |  | 			jb->info.frames_late++; | 
					
						
							|  |  |  | 			jb->info.frames_lost--; | 
					
						
							|  |  |  | 			jb_dbg("l"); | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			/*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
 | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 			jb_warninfo(jb); */ | 
					
						
							|  |  |  | 			return JB_DROP; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			/* voice frame */ | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			/* try setting current to target right away here */ | 
					
						
							|  |  |  | 			jb->info.current = jb->info.target; | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 			jb->info.silence_begin_ts = 0; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			jb->info.last_voice_ms = frame->ms; | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			jb->info.frames_out++; | 
					
						
							|  |  |  | 			decrement_losspct(jb); | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			*frameout = *frame; | 
					
						
							|  |  |  | 			jb_dbg("V"); | 
					
						
							|  |  |  | 			return JB_OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | long jb_next(jitterbuf *jb)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-05-09 14:24:58 +00:00
										 |  |  | 	if (jb->info.silence_begin_ts) { | 
					
						
							| 
									
										
										
										
											2007-01-25 19:20:51 +00:00
										 |  |  | 		if (jb->frames) { | 
					
						
							|  |  |  | 			long next = queue_next(jb); | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			history_get(jb); | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 			/* shrink during silence */ | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  | 			if (jb->info.target - jb->info.current < -jb->info.conf.target_extra) | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 				return jb->info.last_adjustment + 10; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 			return next + jb->info.target; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 			return JB_LONGMAX; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2005-05-12 19:01:03 +00:00
										 |  |  | 		return jb->info.next_voice_ts; | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | 	enum jb_return_code ret = _jb_get(jb, frameout, now, interpl); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	static int lastts=0; | 
					
						
							|  |  |  | 	int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0; | 
					
						
							|  |  |  | 	jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists); | 
					
						
							|  |  |  | 	if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n"); | 
					
						
							|  |  |  | 	lastts = thists; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-01-23 00:11:32 +00:00
										 |  |  | 	if (ret == JB_INTERP)  | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 		frameout->ms = jb->info.last_voice_ms; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	jb_frame *frame; | 
					
						
							|  |  |  | 	frame = queue_getall(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	if (!frame) { | 
					
						
							|  |  |  | 		return JB_NOFRAME; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	*frameout = *frame; | 
					
						
							|  |  |  | 	return JB_OK; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	history_get(jb); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	*stats = jb->info; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return JB_OK; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 01:37:56 +00:00
										 |  |  | enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)  | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	/* take selected settings from the struct */ | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-02 17:45:38 +00:00
										 |  |  | 	jb->info.conf.max_jitterbuf = conf->max_jitterbuf; | 
					
						
							|  |  |  |  	jb->info.conf.resync_threshold = conf->resync_threshold; | 
					
						
							| 
									
										
										
										
											2005-06-21 01:20:14 +00:00
										 |  |  | 	jb->info.conf.max_contig_interp = conf->max_contig_interp; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-21 00:24:08 +00:00
										 |  |  | 	/* -1 indicates use of the default JB_TARGET_EXTRA value */ | 
					
						
							|  |  |  | 	jb->info.conf.target_extra = ( conf->target_extra == -1 ) | 
					
						
							|  |  |  | 		? JB_TARGET_EXTRA | 
					
						
							|  |  |  | 		: conf->target_extra | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	/* update these to match new target_extra setting */ | 
					
						
							|  |  |  | 	jb->info.current = jb->info.conf.target_extra; | 
					
						
							|  |  |  | 	jb->info.target = jb->info.conf.target_extra; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-02 23:31:29 +00:00
										 |  |  | 	return JB_OK; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |