123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976 |
- #include "jbuf.h"
- #include "jerrno.h"
- #include <memory.h>
- #include <assert.h>
- #ifdef _WIN32
- #else
- #define max(a,b) (((a) > (b)) ? (a) : (b))
- #define min(a,b) (((a) < (b)) ? (a) : (b))
- #endif // _WIN32
- /* Minimal difference between JB size and 2*burst-level to perform
- * JB shrinking.
- */
- #define SAFE_SHRINKING_DIFF 1
- /* Minimal gap (in ms) between JB shrinking */
- #define MIN_SHRINK_GAP_MSEC 200
- /* Invalid sequence number, used as the initial value. */
- #define INVALID_OFFSET -9999
- /* Maximum burst length, whenever an operation is bursting longer than
- * this value, JB will assume that the opposite operation was idle.
- */
- #define MAX_BURST_MSEC 1000
- /* Number of OP switches to be performed in JB_STATUS_INITIALIZING, before
- * JB can switch its states to JB_STATUS_PROCESSING.
- */
- #define INIT_CYCLE 10
- /**
- * Calculate integer square root of an integer.
- *
- * @param i Integer to be calculated.
- *
- * @return Square root result.
- */
- static __inline unsigned isqrt(unsigned i)
- {
- unsigned res = 1, prev;
-
- /* Rough guess, calculate half bit of input */
- prev = i >> 2;
- while (prev) {
- prev >>= 2;
- res <<= 1;
- }
- /* Babilonian method */
- do {
- prev = res;
- res = (prev + i/prev) >> 1;
- } while ((prev+res)>>1 != res);
- return res;
- }
- typedef struct math_stat
- {
- int n; /* number of samples */
- int max; /* maximum value */
- int min; /* minimum value */
- int last; /* last value */
- int mean; /* mean */
- /* Private members */
- float fmean_; /* mean(floating point) */
- double m2_; /* variance * n */
- } math_stat;
- /**
- * Initialize statistics state.
- *
- * @param stat Statistic state.
- */
- static __inline void math_stat_init(math_stat *stat)
- {
- memset(stat, 0,sizeof(math_stat));
- }
- /**
- * Update statistics state as a new sample comes.
- *
- * @param stat Statistic state.
- * @param val The new sample data.
- */
- static __inline void math_stat_update(math_stat *stat, int val)
- {
- float delta;
- stat->last = val;
-
- if (stat->n++) {
- if (stat->min > val)
- stat->min = val;
- if (stat->max < val)
- stat->max = val;
- } else {
- stat->min = stat->max = val;
- }
- delta = val - stat->fmean_;
- stat->fmean_ += delta/stat->n;
-
- /* Return mean value with 'rounding' */
- stat->mean = (int) (stat->fmean_ + 0.5);
- stat->m2_ += (int)(delta * (val-stat->fmean_));
- }
- /**
- * Get the standard deviation of specified statistics state.
- *
- * @param stat Statistic state.
- *
- * @return The standard deviation.
- */
- static __inline unsigned math_stat_get_stddev(const math_stat *stat)
- {
- if (stat->n == 0) return 0;
- return (isqrt((unsigned)(stat->m2_/stat->n)));
- }
- /**
- * Set the standard deviation of statistics state. This is useful when
- * the statistic state is operated in 'read-only' mode as a storage of
- * statistical data.
- *
- * @param stat Statistic state.
- *
- * @param dev The standard deviation.
- */
- static __inline void math_stat_set_stddev(math_stat *stat, unsigned dev)
- {
- if (stat->n == 0)
- stat->n = 1;
- stat->m2_ = dev*dev*stat->n;
- }
- /* Struct of JB internal buffer, represented in a circular buffer containing
- * frame content, frame type, frame length, and frame bit info.
- */
- typedef struct jb_framelist_t
- {
- /* Settings */
- unsigned frame_size; /**< maximum size of frame */
- unsigned max_count; /**< maximum number of frames */
- /* Buffers */
- char *content; /**< frame content array */
- int *frame_type; /**< frame type array */
- size_t *content_len; /**< frame length array */
- unsigned *bit_info; /**< frame bit info array */
- /* States */
- unsigned head; /**< index of head, pointed frame
- will be returned by next GET */
- unsigned size; /**< current size of framelist,
- including discarded frames. */
- unsigned discarded_num; /**< current number of discarded
- frames. */
- int origin; /**< original index of flist_head */
- } jb_framelist_t;
- struct jitterbuf
- {
- /* Settings (consts) */
- size_t jb_frame_size; /**< frame size */
- unsigned jb_frame_ptime; /**< frame duration. */
- size_t jb_max_count; /**< capacity of jitter buffer,
- in frames */
- int jb_init_prefetch; /**< Initial prefetch */
- int jb_min_prefetch; /**< Minimum allowable prefetch */
- int jb_max_prefetch; /**< Maximum allowable prefetch */
- int jb_max_burst; /**< maximum possible burst, whenever
- burst exceeds this value, it
- won't be included in level
- calculation */
- int jb_min_shrink_gap; /**< How often can we shrink */
- /* Buffer */
- jb_framelist_t jb_framelist; /**< the buffer */
- /* States */
- int jb_level; /**< delay between source &
- destination (calculated according
- of the number of burst get/put
- operations) */
- int jb_max_hist_level; /**< max level during the last level
- calculations */
- int jb_stable_hist; /**< num of times the delay has been
- lower then the prefetch num */
- int jb_last_op; /**< last operation executed
- (put/get) */
- int jb_eff_level; /**< effective burst level */
- int jb_prefetch; /**< no. of frame to insert before
- removing some (at the beginning
- of the framelist->content
- operation), the value may be
- continuously updated based on
- current frame burst level. */
- int jb_status; /**< status is 'init' until the first
- 'put' operation */
- int jb_init_cycle_cnt; /**< status is 'init' until the first
- 'put' operation */
- int jb_last_del_seq; /**< Seq # of last frame deleted */
- int jb_last_discard_seq;/**< Seq # of last frame discarded */
- /* Statistics */
- math_stat jb_delay; /**< Delay statistics of jitter buffer
- (in ms) */
- math_stat jb_burst; /**< Burst statistics (in frames) */
- unsigned jb_lost; /**< Number of lost frames. */
- unsigned jb_discard; /**< Number of discarded frames. */
- unsigned jb_empty; /**< Number of empty/prefetching frame
- returned by GET. */
- int jb_seq;
- };
- #define JB_STATUS_INITIALIZING 0
- #define JB_STATUS_PROCESSING 1
- #define JB_STATUS_PREFETCHING 2
- /* Progressive discard algorithm introduced to reduce JB latency
- * by discarding incoming frames with adaptive aggressiveness based on
- * actual burst level.
- */
- #define PROGRESSIVE_DISCARD 0
- /* Internal JB frame flag, discarded frame will not be returned by JB to
- * application, it's just simply discarded.
- */
- #define JB_DISCARDED_FRAME 1024
- static int jb_framelist_reset(jb_framelist_t *framelist);
- static unsigned jb_framelist_remove_head(jb_framelist_t *framelist,
- unsigned count);
- static int jb_framelist_init(jb_framelist_t *framelist,
- unsigned frame_size,
- unsigned max_count)
- {
- memset(framelist, 0, sizeof(jb_framelist_t));
- framelist->frame_size = frame_size;
- framelist->max_count = max_count;
- framelist->content = (char*) malloc(framelist->frame_size*framelist->max_count);
- framelist->frame_type = (int*)malloc(sizeof(framelist->frame_type[0])*framelist->max_count);
- framelist->content_len = (size_t*)malloc(sizeof(framelist->content_len[0])*framelist->max_count);
- framelist->bit_info = (unsigned*)malloc(sizeof(framelist->bit_info[0])*framelist->max_count);
- return jb_framelist_reset(framelist);
- }
- static int jb_framelist_destroy(jb_framelist_t *framelist)
- {
- free(framelist->content);
- free(framelist->frame_type);
- free(framelist->content_len);
- free(framelist->bit_info);
- return 0;
- }
- static int jb_framelist_reset(jb_framelist_t *framelist)
- {
- framelist->head = 0;
- framelist->origin = INVALID_OFFSET;
- framelist->size = 0;
- framelist->discarded_num = 0;
- memset(framelist->frame_type,
- JB_MISSING_FRAME,
- sizeof(framelist->frame_type[0]) *
- framelist->max_count);
- memset(framelist->content_len, 0,
- sizeof(framelist->content_len[0]) *
- framelist->max_count);
- return 0;
- }
- static unsigned jb_framelist_size(const jb_framelist_t *framelist)
- {
- return framelist->size;
- }
- static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist)
- {
- return (framelist->size - framelist->discarded_num);
- }
- static int jb_framelist_origin(const jb_framelist_t *framelist)
- {
- return framelist->origin;
- }
- static int jb_framelist_get(jb_framelist_t *framelist,
- void *frame, size_t *size,
- jb_frame_type *p_type,
- unsigned *bit_info)
- {
- if (framelist->size) {
- /* Skip discarded frames */
- while (framelist->frame_type[framelist->head] == JB_DISCARDED_FRAME)
- {
- jb_framelist_remove_head(framelist, 1);
- }
- /* Return the head frame if any */
- if (framelist->size) {
- memcpy(frame,
- framelist->content +
- framelist->head * framelist->frame_size,
- framelist->frame_size);
- *p_type = (jb_frame_type)
- framelist->frame_type[framelist->head];
- if (size)
- *size = framelist->content_len[framelist->head];
- if (bit_info)
- *bit_info = framelist->bit_info[framelist->head];
- framelist->frame_type[framelist->head] = JB_MISSING_FRAME;
- framelist->content_len[framelist->head] = 0;
- framelist->bit_info[framelist->head] = 0;
- framelist->origin++;
- framelist->head = (framelist->head + 1) % framelist->max_count;
- framelist->size--;
- return 1;
- }
- }
- /* No frame available */
- memset(frame, 0, framelist->frame_size);
- return 0;
- }
- /* Remove oldest frames as many as param 'count' */
- static unsigned jb_framelist_remove_head(jb_framelist_t *framelist,
- unsigned count)
- {
- if (count > framelist->size)
- count = framelist->size;
- if (count) {
- /* may be done in two steps if overlapping */
- unsigned step1,step2;
- unsigned tmp = framelist->head+count;
- unsigned i;
- if (tmp > framelist->max_count) {
- step1 = framelist->max_count - framelist->head;
- step2 = count-step1;
- } else {
- step1 = count;
- step2 = 0;
- }
- for (i = framelist->head; i < (framelist->head + step1); ++i) {
- if (framelist->frame_type[i] == JB_DISCARDED_FRAME) {
- assert(framelist->discarded_num > 0);
- framelist->discarded_num--;
- }
- }
- memset(framelist->frame_type+framelist->head,
- JB_MISSING_FRAME,
- step1*sizeof(framelist->frame_type[0]));
- memset(framelist->content_len+framelist->head,0,
- step1*sizeof(framelist->content_len[0]));
- if (step2) {
- for (i = 0; i < step2; ++i) {
- if (framelist->frame_type[i] == JB_DISCARDED_FRAME) {
- assert(framelist->discarded_num > 0);
- framelist->discarded_num--;
- }
- }
- memset(framelist->frame_type,JB_MISSING_FRAME,step2*sizeof(framelist->frame_type[0]));
- memset(framelist->content_len,0,step2*sizeof(framelist->content_len[0]));
- }
- /* update states */
- framelist->origin += count;
- framelist->head = (framelist->head + count) % framelist->max_count;
- framelist->size -= count;
- }
- return count;
- }
- static int jb_framelist_put_at(jb_framelist_t *framelist,
- int index,
- const void *frame,
- unsigned frame_size,
- unsigned bit_info,
- unsigned frame_type)
- {
- int distance;
- unsigned pos;
- enum { MAX_MISORDER = 100 };
- enum { MAX_DROPOUT = 3000 };
- assert(frame_size <= framelist->frame_size);
- /* too late or sequence restart */
- if (index < framelist->origin) {
- if (framelist->origin - index < MAX_MISORDER) {
- /* too late */
- return PJ_ETOOSMALL;
- } else {
- /* sequence restart */
- framelist->origin = index - framelist->size;
- }
- }
- /* if jbuf is empty, just reset the origin */
- if (framelist->size == 0) {
- assert(framelist->discarded_num == 0);
- framelist->origin = index;
- }
- /* get distance of this frame to the first frame in the buffer */
- distance = index - framelist->origin;
- /* far jump, the distance is greater than buffer capacity */
- if (distance >= (int)framelist->max_count) {
- if (distance > MAX_DROPOUT) {
- /* jump too far, reset the buffer */
- jb_framelist_reset(framelist);
- framelist->origin = index;
- distance = 0;
- } else {
- /* otherwise, reject the frame */
- return PJ_ETOOMANY;
- }
- }
- /* get the slot position */
- pos = (framelist->head + distance) % framelist->max_count;
- /* if the slot is occupied, it must be duplicated frame, ignore it. */
- if (framelist->frame_type[pos] != JB_MISSING_FRAME)
- return PJ_EEXISTS;
- /* put the frame into the slot */
- framelist->frame_type[pos] = frame_type;
- framelist->content_len[pos] = frame_size;
- framelist->bit_info[pos] = bit_info;
- /* update framelist size */
- if (framelist->origin + (int)framelist->size <= index)
- framelist->size = distance + 1;
- if(JB_NORMAL_FRAME == frame_type) {
- /* copy frame content */
- memcpy(framelist->content + pos * framelist->frame_size,
- frame, frame_size);
- return PJ_SUCCESS;
- } else {
- /* frame is being discarded */
- framelist->discarded_num++;
- return PJ_EIGNORED;
- }
- }
- enum media_jb_op
- {
- JB_OP_INIT = -1,
- JB_OP_PUT = 1,
- JB_OP_GET = 2
- };
- int jbuf_create(unsigned frame_size, unsigned ptime,unsigned max_count,jitterbuf **p_jb)
- {
- jitterbuf *jb;
- int status;
- jb = malloc(sizeof(struct jitterbuf));
- status = jb_framelist_init(&jb->jb_framelist, frame_size, max_count);
- if (status != 0)
- return status;
- jb->jb_frame_size = frame_size;
- jb->jb_frame_ptime = ptime;
- jb->jb_prefetch = min(JB_DEFAULT_INIT_DELAY,max_count*4/5);
- jb->jb_min_prefetch = 0;
- jb->jb_max_prefetch = max_count*4/5;
- jb->jb_max_count = max_count;
- jb->jb_min_shrink_gap= MIN_SHRINK_GAP_MSEC / ptime;
- jb->jb_max_burst = MAX_BURST_MSEC / ptime;
- jb->jb_last_discard_seq = 0;
- jb->jb_seq = 0;
- math_stat_init(&jb->jb_delay);
- math_stat_init(&jb->jb_burst);
- jbuf_reset(jb);
- *p_jb = jb;
- return 0;
- }
- /*
- * Set the jitter buffer to fixed delay mode. The default behavior
- * is to adapt the delay with actual packet delay.
- *
- */
- int jbuf_set_fixed( jitterbuf *jb, unsigned prefetch)
- {
- assert(prefetch <= jb->jb_max_count);
- jb->jb_min_prefetch = jb->jb_max_prefetch =
- jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
- return 0;
- }
- /*
- * Set the jitter buffer to adaptive mode.
- */
- int jbuf_set_adaptive( jitterbuf *jb,
- unsigned prefetch,
- unsigned min_prefetch,
- unsigned max_prefetch)
- {
- assert(jb);
- assert(min_prefetch < max_prefetch && prefetch <= max_prefetch && max_prefetch <= jb->jb_max_count);
- jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
- jb->jb_min_prefetch = min_prefetch;
- jb->jb_max_prefetch = max_prefetch;
- return 0;
- }
- int jbuf_reset(jitterbuf *jb)
- {
- jb->jb_level = 0;
- jb->jb_last_op = JB_OP_INIT;
- jb->jb_stable_hist = 0;
- jb->jb_status = JB_STATUS_INITIALIZING;
- jb->jb_init_cycle_cnt= 0;
- jb->jb_max_hist_level= 0;
- jb_framelist_reset(&jb->jb_framelist);
- return 0;
- }
- int jbuf_destroy(jitterbuf *jb)
- {
- if (!jb)
- return -1;
- jb_framelist_destroy(&jb->jb_framelist);
- free(jb);
- return 0;
- }
- static void jbuf_calculate_jitter(jitterbuf *jb)
- {
- int diff, cur_size;
- cur_size = jb_framelist_eff_size(&jb->jb_framelist);
- math_stat_update(&jb->jb_burst, jb->jb_level);
- jb->jb_max_hist_level = max(jb->jb_max_hist_level, jb->jb_level);
- /* Burst level is decreasing */
- if (jb->jb_level < jb->jb_eff_level) {
- enum { STABLE_HISTORY_LIMIT = 20 };
- jb->jb_stable_hist++;
- /* Only update the effective level (and prefetch) if 'stable'
- * condition is reached (not just short time impulse)
- */
- if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) {
- diff = (jb->jb_eff_level - jb->jb_max_hist_level) / 3;
- if (diff < 1)
- diff = 1;
- /* Update effective burst level */
- jb->jb_eff_level -= diff;
- /* Update prefetch based on level */
- if (jb->jb_init_prefetch) {
- jb->jb_prefetch = jb->jb_eff_level;
- if (jb->jb_prefetch < jb->jb_min_prefetch)
- jb->jb_prefetch = jb->jb_min_prefetch;
- }
- /* Reset history */
- jb->jb_max_hist_level = 0;
- jb->jb_stable_hist = 0;
- }
- }
- /* Burst level is increasing */
- else if (jb->jb_level > jb->jb_eff_level) {
- /* Instaneous set effective burst level to recent maximum level */
- jb->jb_eff_level = min(jb->jb_max_hist_level,
- (int)(jb->jb_max_count*4/5));
- /* Update prefetch based on level */
- if (jb->jb_init_prefetch) {
- jb->jb_prefetch = jb->jb_eff_level;
- if (jb->jb_prefetch > jb->jb_max_prefetch)
- jb->jb_prefetch = jb->jb_max_prefetch;
- }
- jb->jb_stable_hist = 0;
- /* Do not reset max_hist_level. */
- //jb->jb_max_hist_level = 0;
- }
- /* Level is unchanged */
- else {
- jb->jb_stable_hist = 0;
- }
- }
- void jbuf_update(jitterbuf *jb, int oper)
- {
- if(jb->jb_last_op != oper) {
- jb->jb_last_op = oper;
- if (jb->jb_status == JB_STATUS_INITIALIZING) {
- /* Switch status 'initializing' -> 'processing' after some OP
- * switch cycles and current OP is GET (burst level is calculated
- * based on PUT burst), so burst calculation is guaranted to be
- * performed right after the status switching.
- */
- if (++jb->jb_init_cycle_cnt >= INIT_CYCLE && oper == JB_OP_GET) {
- jb->jb_status = JB_STATUS_PROCESSING;
- } else {
- jb->jb_level = 0;
- return;
- }
- }
- /* Perform jitter calculation based on PUT burst-level only, since
- * GET burst-level may not be accurate, e.g: when VAD is active.
- * Note that when burst-level is too big, i.e: exceeds jb_max_burst,
- * the GET op may be idle, in this case, we better skip the jitter
- * calculation.
- */
- if (oper == JB_OP_GET && jb->jb_level < jb->jb_max_burst)
- jbuf_calculate_jitter(jb);
- jb->jb_level = 0;
- }
- /* These code is used for shortening the delay in the jitter buffer.
- * It needs shrink only when there is possibility of drift. Drift
- * detection is performed by inspecting the jitter buffer size, if
- * its size is twice of current burst level, there can be drift.
- *
- * Moreover, normally drift level is quite low, so JB shouldn't need
- * to shrink aggresively, it will shrink maximum one frame per
- * MIN_SHRINK_GAP_MSEC ms. Theoritically, JB may handle drift level
- * as much as = FRAME_PTIME/MIN_SHRINK_GAP_MSEC * 100%
- *
- * Whenever there is drift, where PUT > GET, this method will keep
- * the latency (JB size) as much as twice of burst level.
- */
- /* Shrinking due of drift will be implicitly done by progressive discard,
- * so just disable it when progressive discard is active.
- */
- #if !PROGRESSIVE_DISCARD
- if (jb->jb_status != JB_STATUS_PROCESSING)
- return;
- {
- int diff, burst_level;
- burst_level = max(jb->jb_eff_level, jb->jb_level);
- diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2;
- if (diff >= SAFE_SHRINKING_DIFF) {
- int seq_origin;
- /* Check and adjust jb_last_del_seq, in case there was
- * seq restart
- */
- seq_origin = jb_framelist_origin(&jb->jb_framelist);
- if (seq_origin < jb->jb_last_del_seq)
- jb->jb_last_del_seq = seq_origin;
- if (seq_origin - jb->jb_last_del_seq >= jb->jb_min_shrink_gap)
- {
- /* Shrink slowly, one frame per cycle */
- diff = 1;
- /* Drop frame(s)! */
- diff = jb_framelist_remove_head(&jb->jb_framelist, diff);
- jb->jb_last_del_seq = jb_framelist_origin(&jb->jb_framelist);
- jb->jb_discard += diff;
- }
- }
- }
- #endif /* !PROGRESSIVE_DISCARD */
- }
- void jbuf_put_frame( jitterbuf *jb, const void *frame, size_t frame_size)
- {
- int frame_seq = jb->jb_seq ++;
- jbuf_put_frame2(jb, frame, frame_size, 0, frame_seq, NULL);
- }
- void jbuf_put_frame2(jitterbuf *jb,
- const void *frame,
- size_t frame_size,
- unsigned bit_info,
- int frame_seq,
- int *discarded)
- {
- size_t min_frame_size;
- int new_size, cur_size, frame_type = JB_NORMAL_FRAME;
- int status;
- cur_size = jb_framelist_eff_size(&jb->jb_framelist);
- #if PROGRESSIVE_DISCARD
- {
- unsigned interval, seq_delta;
- unsigned burst_level, burst_factor;
- /* Calculating discard interval (aggressiveness) based on
- * (current size / burst level).
- */
- if (jb->jb_status == JB_STATUS_PROCESSING) {
- burst_level = max(jb->jb_eff_level, jb->jb_level);
- burst_factor = cur_size / burst_level;
- /* Tolerate small spikes */
- if ((burst_level <= 5) && (burst_factor < 3))
- burst_factor = 0;
- } else {
- burst_factor = 0;
- }
- switch (burst_factor) {
- case 0:
- interval = 0;
- break;
- case 1:
- interval = 7;
- break;
- case 2:
- interval = 5;
- break;
- default:
- interval = 4;
- break;
- }
- /* Do the math now to see if we should discard this packet.
- * Calculate the distance from the last sequence
- * discarded. If negative, then this is an out of
- * order frame so just proceed with discard. Else
- * see if the delta is at least the intervals worth away
- * from the last frame discarded.
- */
- seq_delta = (unsigned short)(frame_seq - jb->jb_last_discard_seq);
- if ((0 != interval) && (seq_delta >= interval)) {
- frame_type = JB_DISCARDED_FRAME;
- jb->jb_last_discard_seq = frame_seq;
- }
- }
- #endif /* PROGRESSIVE_DISCARD */
- /* Attempt to store the frame */
- min_frame_size = min(frame_size, jb->jb_frame_size);
- status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
- min_frame_size, bit_info, frame_type);
- /* Jitter buffer is full, remove some older frames */
- while (status == PJ_ETOOMANY) {
- int distance;
- unsigned removed;
- /* When progressive discard activated, just remove as few as possible
- * just to make this frame in.
- */
- #if PROGRESSIVE_DISCARD
- /* The cases of seq-jump, out-of-order, and seq restart should have
- * been handled/normalized by previous call of jb_framelist_put_at().
- * So we're confident about 'distance' value here.
- */
- distance = (frame_seq - jb_framelist_origin(&jb->jb_framelist)) -
- jb->jb_max_count + 1;
- assert(distance > 0);
- #else
- distance = max(jb->jb_max_count/4, 1);
- #endif
- removed = jb_framelist_remove_head(&jb->jb_framelist, distance);
- status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
- min_frame_size, bit_info, frame_type);
- jb->jb_discard += removed;
- }
- /* Get new JB size after PUT */
- new_size = jb_framelist_eff_size(&jb->jb_framelist);
- /* Return the flag if this frame is discarded */
- if (discarded)
- *discarded = (status != PJ_SUCCESS);
- if (status == PJ_SUCCESS) {
- if (jb->jb_status == JB_STATUS_PREFETCHING) {
- if (new_size >= jb->jb_prefetch)
- jb->jb_status = JB_STATUS_PROCESSING;
- }
- jb->jb_level += (new_size > cur_size ? new_size-cur_size : 1);
- jbuf_update(jb, JB_OP_PUT);
- } else
- jb->jb_discard++;
- }
- /*
- * Get frame from jitter buffer.
- */
- void jbuf_get_frame( jitterbuf *jb, void *frame, char *p_frame_type)
- {
- jbuf_get_frame2(jb, frame, NULL, p_frame_type, NULL);
- }
- /*
- * Get frame from jitter buffer.
- */
- void jbuf_get_frame2(jitterbuf *jb,
- void *frame,
- size_t *size,
- char *p_frame_type,
- unsigned *bit_info)
- {
- if (jb->jb_status == JB_STATUS_PREFETCHING) {
- /* Can't return frame because jitter buffer is filling up
- * minimum prefetch.
- */
- *p_frame_type = JB_ZERO_PREFETCH_FRAME;
- if (size)
- *size = 0;
- jb->jb_empty++;
- } else {
- jb_frame_type ftype = JB_NORMAL_FRAME;
- int res;
- /* Try to retrieve a frame from frame list */
- res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype,
- bit_info);
- if (res) {
- /* We've successfully retrieved a frame from the frame list, but
- * the frame could be a blank frame!
- */
- if (ftype == JB_NORMAL_FRAME) {
- *p_frame_type = JB_NORMAL_FRAME;
- } else {
- *p_frame_type = JB_MISSING_FRAME;
- jb->jb_lost++;
- }
- /* Store delay history at the first GET */
- if (jb->jb_last_op == JB_OP_PUT) {
- unsigned cur_size;
- /* We've just retrieved one frame, so add one to cur_size */
- cur_size = jb_framelist_eff_size(&jb->jb_framelist) + 1;
- math_stat_update(&jb->jb_delay,
- cur_size*jb->jb_frame_ptime);
- }
- } else {
- /* Jitter buffer is empty */
- if (jb->jb_prefetch)
- jb->jb_status = JB_STATUS_PREFETCHING;
- *p_frame_type = JB_ZERO_EMPTY_FRAME;
- if (size)
- *size = 0;
- jb->jb_empty++;
- }
- }
- jb->jb_level++;
- jbuf_update(jb, JB_OP_GET);
- }
- int jbuf_get_state(const jitterbuf *jb, jb_state *state )
- {
- assert(jb && state);
- state->frame_size = jb->jb_frame_size;
- state->min_prefetch = jb->jb_min_prefetch;
- state->max_prefetch = jb->jb_max_prefetch;
- state->burst = jb->jb_eff_level;
- state->prefetch = jb->jb_prefetch;
- state->size = jb_framelist_eff_size(&jb->jb_framelist);
- state->avg_delay = jb->jb_delay.mean;
- state->min_delay = jb->jb_delay.min;
- state->max_delay = jb->jb_delay.max;
- state->dev_delay = math_stat_get_stddev(&jb->jb_delay);
- state->avg_burst = jb->jb_burst.mean;
- state->empty = jb->jb_empty;
- state->discard = jb->jb_discard;
- state->lost = jb->jb_lost;
- return 0;
- }
|