| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (C) 2005, Attractel OOD | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributors: | 
					
						
							|  |  |  |  * Slav Klenov <slav@securax.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							| 
									
										
										
										
											2006-06-14 14:12:56 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * A license has been granted to Digium (via disclaimer) for the use of | 
					
						
							|  |  |  |  * this code. | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | /*! \file
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  |  * \brief Jitterbuffering algorithm. | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  |  * \author Slav Klenov <slav@securax.org> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 16:20:16 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-08 16:36:34 +00:00
										 |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | #include "fixedjitterbuf.h"
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | #undef FIXED_JB_DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | #ifdef FIXED_JB_DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | #define ASSERT(a)
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define ASSERT(a) assert(a)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | /*! \brief private fixed_jb structure */ | 
					
						
							|  |  |  | struct fixed_jb | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	struct fixed_jb_frame *frames; | 
					
						
							|  |  |  | 	struct fixed_jb_frame *tail; | 
					
						
							|  |  |  | 	struct fixed_jb_conf conf; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	long rxcore; | 
					
						
							|  |  |  | 	long delay; | 
					
						
							|  |  |  | 	long next_delivery; | 
					
						
							|  |  |  | 	int force_resynch; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | static struct fixed_jb_frame *alloc_jb_frame(struct fixed_jb *jb); | 
					
						
							|  |  |  | static void release_jb_frame(struct fixed_jb *jb, struct fixed_jb_frame *frame); | 
					
						
							|  |  |  | static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame); | 
					
						
							|  |  |  | static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long now); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | static inline struct fixed_jb_frame *alloc_jb_frame(struct fixed_jb *jb) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	return ast_calloc(1, sizeof(*jb)); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | static inline void release_jb_frame(struct fixed_jb *jb, struct fixed_jb_frame *frame) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(frame); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	struct fixed_jb_frame *fr; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* unlink the frame */ | 
					
						
							|  |  |  | 	fr = jb->frames; | 
					
						
							|  |  |  | 	jb->frames = fr->next; | 
					
						
							|  |  |  | 	if (jb->frames) { | 
					
						
							|  |  |  | 		jb->frames->prev = NULL; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* the jb is empty - update tail */ | 
					
						
							|  |  |  | 		jb->tail = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* update next */ | 
					
						
							|  |  |  | 	jb->next_delivery = fr->delivery + fr->ms; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* copy the destination */ | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	memcpy(frame, fr, sizeof(struct fixed_jb_frame)); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* and release the frame */ | 
					
						
							|  |  |  | 	release_jb_frame(jb, fr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | struct fixed_jb *fixed_jb_new(struct fixed_jb_conf *conf) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	struct fixed_jb *jb; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	if (!(jb = ast_calloc(1, sizeof(*jb)))) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* First copy our config */ | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	memcpy(&jb->conf, conf, sizeof(struct fixed_jb_conf)); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-02 15:57:02 +00:00
										 |  |  | 	/* we don't need the passed config anymore - continue working with the saved one */ | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	conf = &jb->conf; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* validate the configuration */ | 
					
						
							|  |  |  | 	if (conf->jbsize < 1) | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		conf->jbsize = FIXED_JB_SIZE_DEFAULT; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (conf->resync_threshold < 1) | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		conf->resync_threshold = FIXED_JB_RESYNCH_THRESHOLD_DEFAULT; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Set the constant delay to the jitterbuf */ | 
					
						
							|  |  |  | 	jb->delay = conf->jbsize; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	return jb; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | void fixed_jb_destroy(struct fixed_jb *jb) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* jitterbuf MUST be empty before it can be destroyed */ | 
					
						
							|  |  |  | 	ASSERT(jb->frames == NULL); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(jb); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long now) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	long diff, offset; | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	struct fixed_jb_frame *frame; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* If jb is empty, just reinitialize the jb */ | 
					
						
							|  |  |  | 	if (!jb->frames) { | 
					
						
							|  |  |  | 		/* debug check: tail should also be NULL */ | 
					
						
							|  |  |  | 		ASSERT(jb->tail == NULL); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return fixed_jb_put_first(jb, data, ms, ts, now); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Adjust all jb state just as the new frame is with delivery = the delivery of the last
 | 
					
						
							|  |  |  | 	   frame (e.g. this one with max delivery) + the length of the last frame. */ | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Get the diff in timestamps */ | 
					
						
							|  |  |  | 	diff = ts - jb->tail->ts; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Ideally this should be just the length of the last frame. The deviation is the desired
 | 
					
						
							|  |  |  | 	   offset */ | 
					
						
							|  |  |  | 	offset = diff - jb->tail->ms; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Do we really need to resynch, or this is just a frame for dropping? */ | 
					
						
							|  |  |  | 	if (!jb->force_resynch && (offset < jb->conf.resync_threshold && offset > -jb->conf.resync_threshold)) | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_DROP; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Reset the force resynch flag */ | 
					
						
							|  |  |  | 	jb->force_resynch = 0; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* apply the offset to the jb state */ | 
					
						
							|  |  |  | 	jb->rxcore -= offset; | 
					
						
							|  |  |  | 	frame = jb->frames; | 
					
						
							|  |  |  | 	while (frame) { | 
					
						
							|  |  |  | 		frame->ts += offset; | 
					
						
							|  |  |  | 		frame = frame->next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* now jb_put() should add the frame at a last position */ | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	return fixed_jb_put(jb, data, ms, ts, now); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | void fixed_jb_set_force_resynch(struct fixed_jb *jb) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	jb->force_resynch = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* this is our first frame - set the base of the receivers time */ | 
					
						
							|  |  |  | 	jb->rxcore = now - ts; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* init next for a first time - it should be the time the first frame should be played */ | 
					
						
							|  |  |  | 	jb->next_delivery = now + jb->delay; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* put the frame */ | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	return fixed_jb_put(jb, data, ms, ts, now); | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	struct fixed_jb_frame *frame, *next, *newframe; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	long delivery; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* debug check the validity of the input params */ | 
					
						
							|  |  |  | 	ASSERT(data != NULL); | 
					
						
							|  |  |  | 	/* do not allow frames shorter than 2 ms */ | 
					
						
							|  |  |  | 	ASSERT(ms >= 2); | 
					
						
							|  |  |  | 	ASSERT(ts >= 0); | 
					
						
							|  |  |  | 	ASSERT(now >= 0); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	delivery = jb->rxcore + jb->delay + ts; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* check if the new frame is not too late */ | 
					
						
							|  |  |  | 	if (delivery < jb->next_delivery) { | 
					
						
							|  |  |  | 		/* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
 | 
					
						
							|  |  |  | 		   the force resynch flag was not set. */ | 
					
						
							|  |  |  | 		return resynch_jb(jb, data, ms, ts, now); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* what if the delivery time is bigger than next + delay? Seems like a frame for the future.
 | 
					
						
							|  |  |  | 	   However, allow more resync_threshold ms in advance */ | 
					
						
							|  |  |  | 	if (delivery > jb->next_delivery + jb->delay + jb->conf.resync_threshold) { | 
					
						
							|  |  |  | 		/* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
 | 
					
						
							|  |  |  | 		   the force resynch flag was not set. */ | 
					
						
							|  |  |  | 		return resynch_jb(jb, data, ms, ts, now); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* find the right place in the frames list, sorted by delivery time */ | 
					
						
							|  |  |  | 	frame = jb->tail; | 
					
						
							|  |  |  | 	while (frame && frame->delivery > delivery) { | 
					
						
							|  |  |  | 		frame = frame->prev; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Check if the new delivery time is not covered already by the chosen frame */ | 
					
						
							|  |  |  | 	if (frame && (frame->delivery == delivery || | 
					
						
							|  |  |  | 		         delivery < frame->delivery + frame->ms || | 
					
						
							|  |  |  | 		         (frame->next && delivery + ms > frame->next->delivery))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* TODO: Should we check for resynch here? Be careful to do not allow threshold smaller than
 | 
					
						
							|  |  |  | 		   the size of the jb */ | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 		/* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
 | 
					
						
							|  |  |  | 		   the force resynch flag was not set. */ | 
					
						
							|  |  |  | 		return resynch_jb(jb, data, ms, ts, now); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Reset the force resynch flag */ | 
					
						
							|  |  |  | 	jb->force_resynch = 0; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Get a new frame */ | 
					
						
							|  |  |  | 	newframe = alloc_jb_frame(jb); | 
					
						
							|  |  |  | 	newframe->data = data; | 
					
						
							|  |  |  | 	newframe->ts = ts; | 
					
						
							|  |  |  | 	newframe->ms = ms; | 
					
						
							|  |  |  | 	newframe->delivery = delivery; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* and insert it right on place */ | 
					
						
							|  |  |  | 	if (frame) { | 
					
						
							|  |  |  | 		next = frame->next; | 
					
						
							|  |  |  | 		frame->next = newframe; | 
					
						
							|  |  |  | 		if (next) { | 
					
						
							|  |  |  | 			newframe->next = next; | 
					
						
							|  |  |  | 			next->prev = newframe; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			/* insert after the last frame - should update tail */ | 
					
						
							|  |  |  | 			jb->tail = newframe; | 
					
						
							|  |  |  | 			newframe->next = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		newframe->prev = frame; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_OK; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} else if (!jb->frames) { | 
					
						
							|  |  |  | 		/* the frame list is empty or thats just the first frame ever */ | 
					
						
							|  |  |  | 		/* tail should also be NULL is that case */ | 
					
						
							|  |  |  | 		ASSERT(jb->tail == NULL); | 
					
						
							|  |  |  | 		jb->frames = jb->tail = newframe; | 
					
						
							|  |  |  | 		newframe->next = NULL; | 
					
						
							|  |  |  | 		newframe->prev = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_OK; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		/* insert on a first position - should update frames head */ | 
					
						
							|  |  |  | 		newframe->next = jb->frames; | 
					
						
							|  |  |  | 		newframe->prev = NULL; | 
					
						
							|  |  |  | 		jb->frames->prev = newframe; | 
					
						
							|  |  |  | 		jb->frames = newframe; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_OK; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ASSERT(now >= 0); | 
					
						
							|  |  |  | 	ASSERT(interpl >= 2); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	if (now < jb->next_delivery) { | 
					
						
							|  |  |  | 		/* too early for the next frame */ | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_NOFRAME; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Is the jb empty? */ | 
					
						
							|  |  |  | 	if (!jb->frames) { | 
					
						
							|  |  |  | 		/* should interpolate a frame */ | 
					
						
							|  |  |  | 		/* update next */ | 
					
						
							|  |  |  | 		jb->next_delivery += interpl; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_INTERP; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* Isn't it too late for the first frame available in the jb? */ | 
					
						
							|  |  |  | 	if (now > jb->frames->delivery + jb->frames->ms) { | 
					
						
							|  |  |  | 		/* yes - should drop this frame and update next to point the next frame (get_jb_head() does it) */ | 
					
						
							|  |  |  | 		get_jb_head(jb, frame); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_DROP; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* isn't it too early to play the first frame available? */ | 
					
						
							|  |  |  | 	if (now < jb->frames->delivery) { | 
					
						
							|  |  |  | 		/* yes - should interpolate one frame */ | 
					
						
							|  |  |  | 		/* update next */ | 
					
						
							|  |  |  | 		jb->next_delivery += interpl; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_INTERP; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	/* we have a frame for playing now (get_jb_head() updates next) */ | 
					
						
							|  |  |  | 	get_jb_head(jb, frame); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	return FIXED_JB_OK; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | long fixed_jb_next(struct fixed_jb *jb) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return jb->next_delivery; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout) | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!jb->frames) | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 		return FIXED_JB_NOFRAME; | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | 	get_jb_head(jb, frameout); | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 14:07:03 +00:00
										 |  |  | 	return FIXED_JB_OK; | 
					
						
							| 
									
										
										
										
											2006-05-31 16:56:50 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-12 15:58:43 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | int fixed_jb_is_late(struct fixed_jb *jb, long ts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return jb->rxcore + jb->delay + ts < jb->next_delivery; | 
					
						
							|  |  |  | } |