doubango/tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h
c732d49e
 /* File from: http://cms.speakup.nl/tech/opensource/jitterbuffer/verslag-20051209.pdf/ */
 
 /*******************************************************
  * jitterbuffer: 
  * an application-independent jitterbuffer, which tries 
  * to achieve the maximum user perception during a call.
  * For more information look at:
  * http://www.speakup.nl/opensource/jitterbuffer/
  *
  * Copyright on this file is held by:
  * - Jesse Kaijen <jesse@speakup.nl>  
  * - SpeakUp <info@speakup.nl>
  *
  * Contributors:
  * Jesse Kaijen <jesse@speakup.nl>
  *
  * Version: 1.1
  * 
  * Changelog:
 * 1.0 => 1.1 (2006-03-24) (thanks to Micheal Jerris, freeswitch.org)
  * - added MSVC 2005 project files
  * - added JB_NOJB as return value
  *
  *
  * This program is free software, distributed under the terms of:
  * - the GNU Lesser (Library) General Public License
  * - the Mozilla Public License
  * 
  * if you are interested in an different licence type, please contact us.
  *
  * How to use the jitterbuffer, please look at the comments 
  * in the headerfile.
  *
  * Further details on specific implementations, 
  * please look at the comments in the code file.
  */
 
 #ifndef TINYDAV_JITTERBUFFER_H_
 #define TINYDAV_JITTERBUFFER_H_
 
 #include "tinydav_config.h"
 
 #if !(HAVE_SPEEX_DSP && HAVE_SPEEX_JB)
 
 TDAV_BEGIN_DECLS
 
 /***********
  * The header file consists of four parts.
  * - configuration constants, structs and parameter definitions
  * - functions
  * - How to use the jitterbuffer and 
  *   which responsibilities do YOU have
  * - debug messages explained
  */
 
 
 // configuration constants
 /* Number of historical timestamps to use in calculating jitter and jitterbuffer size */ 
 #ifndef JB_HISTORY_SIZE
 #	define JB_HISTORY_SIZE 500
 #endif
 
 /* minimum jitterbuffer size, disabled if 0 */
 #define JB_MIN_SIZE 0
 /* maximum jitterbuffer size, disabled if 0 */ 
 #define JB_MAX_SIZE 0
  /* maximum successive interpolating frames, disabled if 0 */
 #define JB_MAX_SUCCESSIVE_INTERP 0
 /* amount of extra delay allowed before shrinking */
 #define JB_ALLOW_EXTRA_DELAY 30																														
 /* ms between growing */
 #define JB_WAIT_GROW 60
 /* ms between shrinking */
 #define JB_WAIT_SHRINK 250
 /* ms that the JB max may be off */
 #define JB_MAX_DIFF 6000 //in a RTP stream the max_diff may be 3000 packets (most packets are 20ms)
 
 //structs
 typedef struct jb_info {
 	long frames_received;       /* Number of frames received by the jitterbuffer */
   long frames_late;           /* Number of frames that were late */
   long frames_lost;           /* Number of frames that were lost */
   long frames_ooo;            /* Number of frames that were Out Of Order */
   long frames_dropped;        /* Number of frames that were dropped due shrinkage of the jitterbuffer */
   long frames_dropped_twice;  /* Number of frames that were dropped because this timestamp was already in the jitterbuffer */
                               
   long delay;     /* Current delay due the jitterbuffer */
 	long jitter; 		/* jitter measured within current history interval*/
 	long losspct; 	/* recent lost frame percentage (network and jitterbuffer loss) */
 	                            
 	long delay_target;   /* The delay where we want to grow to */
 	long losspct_jb;     /* recent lost percentage due the jitterbuffer */
 	long last_voice_ms;	 /* the duration of the last voice frame */
   short silence;       /* If we are in silence 1-yes 0-no */
   long iqr;            /* Inter Quartile Range of current history, if the squareroot is taken it is a good estimate of jitter */
 } jb_info;
 
 typedef struct jb_frame {
 	void *data;		                /* the frame data */
 	long ts;	                    /* the senders timestamp */
 	long ms;	                    /* length of this frame in ms */
 	int  type;	                  /* the type of frame */
 	int codec;                    /* codec of this frame, undefined if nonvoice */
 	struct jb_frame *next, *prev; /* pointers to the next and previous frames in the queue */ 
 } jb_frame;
 
 typedef struct jb_hist_element {
 	long delay; /* difference between time of arrival and senders timestamp */
 	long ts;    /* senders timestamp */
 	long ms;    /* length of this frame in ms */
 	int codec;  /* wich codec this frame has */
 } jb_hist_element;								
 
 typedef struct jb_settings {
   /* settings */
 	long min_jb;	              /* defines a hard clamp to use in setting the jitterbuffer delay */
   long max_jb;	              /* defines a hard clamp to use in setting the jitterbuffer delay */
   long max_successive_interp; /* the maximum count of successive interpolations before assuming silence */
   long extra_delay;           /* amount of extra delay allowed before shrinking */
   long wait_grow;             /* ms between growing */
   long wait_shrink;           /* ms between shrinking */
   long max_diff;              /* maximum number of milliseconds the jitterbuffer may be off */
 } jb_settings;
 
 typedef struct jitterbuffer {
 	struct jb_hist_element hist[JB_HISTORY_SIZE]; /* the history of the last received frames */
 	long hist_sorted_delay[JB_HISTORY_SIZE];      /* a sorted buffer of the delays (lowest first) */
 	long hist_sorted_timestamp[JB_HISTORY_SIZE];  /* a sorted buffer of the timestamps (lowest first) */
 	
 	int  hist_pointer;          /* points to index in history for next entry */
 	long last_adjustment;       /* the time of the last adjustment (growing or shrinking) */
   long next_voice_time;	      /* the next ts is to be read from the jb (senders timestamp) */
 	long cnt_successive_interp; /* the count of consecutive interpolation frames */	
 	long silence_begin_ts;      /* the time of the last CNG frame, when in silence */
 	long min;		                /* the clock difference within current history interval */
 	long current; 		          /* the present jitterbuffer adjustment */
 	long target; 		            /* the target jitterbuffer adjustment */
 	long last_delay;            /* the delay of the last packet, used for calc. jitter */
 	                            
 	jb_frame *voiceframes; 	 /* queued voiceframes */
 	jb_frame *controlframes; /* queued controlframes */
 	jb_settings settings;    /* the settings of the jitterbuffer */
 	jb_info info;            /* the statistics of the jitterbuffer */
 } jitterbuffer;
 
 //parameter definitions
 /* return codes */
 #define JB_OK		0
 #define JB_EMPTY	1
 #define JB_NOFRAME	2
 #define JB_INTERP	3
 #define JB_NOJB		4
 
 
 /* frame types */
 #define JB_TYPE_CONTROL	1
 #define JB_TYPE_VOICE	2
 #define JB_TYPE_SILENCE	3
 
 /* the jitterbuffer behaives different for each codec. */
 /* Look in the code if a codec has his function defined */
 /* default is g711x behaiviour */
 #define JB_CODEC_SPEEX 10       //NOT defined
 #define JB_CODEC_ILBC 9         //NOT defined
 #define JB_CODEC_GSM_EFR 8
 #define JB_CODEC_GSM_FR 7       //NOT defined
 #define JB_CODEC_G723_1 6
 #define JB_CODEC_G729A 5
 #define JB_CODEC_G729 4
 #define JB_CODEC_G711x_PLC 3
 #define JB_CODEC_G711x 2
 #define JB_CODEC_OTHER 1        //NOT defined
 
 
 /*
  * Creates a new jitterbuffer and sets the default settings.
  * Always use this function for creating a new jitterbuffer. 
  */
 jitterbuffer *jb_new();
 
 /*
  * The control frames and possible personal settings are kept. 
  * History and voice/silence frames are destroyed. 
  */
 void jb_reset(jitterbuffer *jb);
 
 /*
  * Resets the jitterbuffer totally, all the control/voice/silence frames are destroyed
  * default settings are put as well. 
  */
 void jb_reset_all(jitterbuffer *jb);
 
 /*
  * Destroy the jitterbuffer and any frame within. 
  * Always use this function for destroying a jitterbuffer,
  * otherwise there is a chance of memory leaking.
  */
 void jb_destroy(jitterbuffer *jb);
 
 /*
  * Define your own settings for the jitterbuffer. Only settings !=0
  * are put in the jitterbuffer.
  */
 void jb_set_settings(jitterbuffer *jb, jb_settings *settings);
 
 /*
  * Get the statistics for the jitterbuffer. 
  * Copying the statistics directly for the jitterbuffer won't work because
  * The statistics are only calculated when calling this function.
  */
 void jb_get_info(jitterbuffer *jb, jb_info *stats);
 
 /*
  * Get the current settings of the jitterbuffer.
  */
 void jb_get_settings(jitterbuffer *jb, jb_settings *settings);
 
 /*
  * Gives an estimation of the MOS of a call given the
  * packetloss p, delay d, and wich codec is used.
  * The assumption is made that the echo cancelation is around 37dB.
  */
 float jb_guess_mos(float p, long d, int codec);
 
 /*
  * returns JB_OK if there are still frames left in the jitterbuffer
  * otherwise JB_EMPTY is returned.
  */
 int jb_has_frames(jitterbuffer *jb);
 
 /*
  * put a packet(frame) into the jitterbuffer.
  * *data - points to the packet
  * type - type of packet, JB_CONTROL|JB_VOICE|JB_SILENCE
  * ms - duration of frame (only voice)
  * ts - timestamp sender
  * now - current timestamp (timestamp of arrival)
  * codec - which codec the frame holds (only voice), if not defined, g711x will be used
  *
  * if type==control @REQUIRE: *data, type, ts, now
  * if type==voice   @REQUIRE: *data, type, ms, ts, now @OPTIONAL: codec
  * if type==silence @REQUIRE: *data, type, ts, now
  * on return *data is undefined
  */
 void jb_put(jitterbuffer *jb, void *data, int type, long ms, long ts, long now, int codec);
 
 /*
  * Get a packet from the jitterbuffer if it's available.
  * control packets have a higher priority above voice and silence packets
  * they are always delivered as fast as possible. The delay of the jitterbuffer
  * doesn't work for these packets. 
  * @REQUIRE 1<interpl <= jb->settings->extra_delay (=default JB_ALLOW_EXTRA_DELAY)
  *
  * return will be:
  * JB_OK, *data points to the packet
  * JB_INTERP, please interpolate for interpl milliseconds
  * JB_NOFRAME, no frame scheduled
  * JB_EMPTY, the jitterbuffer is empty
  */
 int jb_get(jitterbuffer *jb, void **data, long now, long interpl);
 
 /* debug functions */
 typedef 		void (*jb_output_function_t)(const char *fmt, ...);
 void 			jb_setoutput(jb_output_function_t warn, jb_output_function_t err, jb_output_function_t dbg);
 
 
 /*******************************
  * The use of the jitterbuffer *
  *******************************
  * Always create a new jitterbuffer with jb_new().
  * Always destroy a jitterbuffer with jb_destroy().
  *
  * There is no lock(mutex) mechanism, that your responsibility.
  * The reason for this is that different environments require
  * different ways of implementing a lock.
  *
  * The following functions require a lock on the jitterbuffer:
  * jb_reset(), jb_reset_all(), jb_destroy(), jb_set_settings(),
  * jb_get_info(), jb_get_settings(), jb_has_frames(), jb_put(),
  * jb_get()
  *
  * The following functions do NOT require a lock on the jitterbuffer:
  * jb_new(), jb_guess_mos()
  *
  * Since control packets have a higher priority above any other packet
  * a call may already be ended while there is audio left to play. We
  * advice that you poll the jitterbuffer if there are frames left.
  *
  * If the audiopath is oneway (eg. voicemailbox) and the latency doesn't
  * matter, we advice to set a minimum jitterbuffer size. Then there is
  * less loss and the quality is better.
  */
 
 
 /****************************
  * debug messages explained *
  ****************************
  * N  - jb_new()
  * R  - jb_reset()
  * r  - jb_reset_all()
  * D  - jb_destroy()
  * S  - jb_set_settings()
  * H  - jb_has_frames()
  * I  - jb_get_info()
  * S  - jb_get_settings()
  * pC - jb_put() put Control packet
  * pT - jb_put() Timestamp was already in the queue
  * pV - jb_put() put Voice packet
  * pS - jb_put() put Silence packet
  *
  * A  - jb_get()
  * // below are all the possible debug info when trying to get a packet
  * gC - get_control() - there is a control message
  * gs - get_voice() - there is a silence frame
  * gS - get_voice() - we are in silence
  * gL - get_voice() - are in silence, frame is late
  * gP - get_voice() - are in silence, play frame (end of silence)
  * ag - get_voicecase() - grow little bit (diff < interpl/2)
  * aG - get_voicecase() - grow interpl
  * as - get_voicecase() - shrink by voiceframe we throw out
  * aS - get_voicecase() - shrink by interpl
  * aN - get_voicecase() - no time yet
  * aL - get_voicecase() - frame is late
  * aP - get_voicecase() - play frame
  * aI - get_voicecase() - interpolate
  */
 
 TDAV_END_DECLS
 
 #endif /* !(HAVE_SPEEX_DSP && HAVE_SPEEX_JB) */
 
 #endif /* TINYDAV_JITTERBUFFER_H_ */