summaryrefslogtreecommitdiffstats
path: root/tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h')
-rw-r--r--tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h333
1 files changed, 333 insertions, 0 deletions
diff --git a/tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h b/tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h
new file mode 100644
index 0000000..c6d2449
--- /dev/null
+++ b/tinyDAV/include/tinydav/audio/tdav_jitterbuffer.h
@@ -0,0 +1,333 @@
+/* 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_ */
+
OpenPOWER on IntegriCloud