Jitterbuffering algorithm. More...
Go to the source code of this file.
Data Structures | |
struct | fixed_jb_conf |
struct | fixed_jb_frame |
Defines | |
#define | FIXED_JB_RESYNCH_THRESHOLD_DEFAULT 1000 |
#define | FIXED_JB_SIZE_DEFAULT 200 |
Enumerations | |
enum | { FIXED_JB_OK, FIXED_JB_DROP, FIXED_JB_INTERP, FIXED_JB_NOFRAME } |
Functions | |
void | fixed_jb_destroy (struct fixed_jb *jb) |
int | fixed_jb_get (struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl) |
struct fixed_jb * | fixed_jb_new (struct fixed_jb_conf *conf) |
long | fixed_jb_next (struct fixed_jb *jb) |
int | fixed_jb_put (struct fixed_jb *jb, void *data, long ms, long ts, long now) |
int | fixed_jb_put_first (struct fixed_jb *jb, void *data, long ms, long ts, long now) |
int | fixed_jb_remove (struct fixed_jb *jb, struct fixed_jb_frame *frameout) |
void | fixed_jb_set_force_resynch (struct fixed_jb *jb) |
Jitterbuffering algorithm.
Definition in file fixedjitterbuf.h.
#define FIXED_JB_RESYNCH_THRESHOLD_DEFAULT 1000 |
Definition at line 45 of file fixedjitterbuf.h.
Referenced by fixed_jb_new().
#define FIXED_JB_SIZE_DEFAULT 200 |
Definition at line 44 of file fixedjitterbuf.h.
Referenced by fixed_jb_new().
anonymous enum |
Definition at line 35 of file fixedjitterbuf.h.
void fixed_jb_destroy | ( | struct fixed_jb * | jb | ) |
Definition at line 125 of file fixedjitterbuf.c.
References ASSERT, ast_free, and fixed_jb::frames.
Referenced by jb_destroy_fixed().
int fixed_jb_get | ( | struct fixed_jb * | jb, |
struct fixed_jb_frame * | frame, | ||
long | now, | ||
long | interpl | ||
) |
Definition at line 290 of file fixedjitterbuf.c.
References ASSERT, fixed_jb_frame::delivery, FIXED_JB_DROP, FIXED_JB_INTERP, FIXED_JB_NOFRAME, FIXED_JB_OK, frames, fixed_jb::frames, get_jb_head(), fixed_jb_frame::ms, and fixed_jb::next_delivery.
Referenced by jb_get_fixed().
{ ASSERT(now >= 0); ASSERT(interpl >= 2); if (now < jb->next_delivery) { /* too early for the next frame */ return FIXED_JB_NOFRAME; } /* Is the jb empty? */ if (!jb->frames) { /* should interpolate a frame */ /* update next */ jb->next_delivery += interpl; return FIXED_JB_INTERP; } /* 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); return FIXED_JB_DROP; } /* 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; return FIXED_JB_INTERP; } /* we have a frame for playing now (get_jb_head() updates next) */ get_jb_head(jb, frame); return FIXED_JB_OK; }
struct fixed_jb* fixed_jb_new | ( | struct fixed_jb_conf * | conf | ) | [read] |
Definition at line 98 of file fixedjitterbuf.c.
References ast_calloc, fixed_jb::conf, fixed_jb::delay, FIXED_JB_RESYNCH_THRESHOLD_DEFAULT, FIXED_JB_SIZE_DEFAULT, fixed_jb_conf::jbsize, and fixed_jb_conf::resync_threshold.
Referenced by jb_create_fixed().
{ struct fixed_jb *jb; if (!(jb = ast_calloc(1, sizeof(*jb)))) return NULL; /* First copy our config */ memcpy(&jb->conf, conf, sizeof(struct fixed_jb_conf)); /* we dont need the passed config anymore - continue working with the saved one */ conf = &jb->conf; /* validate the configuration */ if (conf->jbsize < 1) conf->jbsize = FIXED_JB_SIZE_DEFAULT; if (conf->resync_threshold < 1) conf->resync_threshold = FIXED_JB_RESYNCH_THRESHOLD_DEFAULT; /* Set the constant delay to the jitterbuf */ jb->delay = conf->jbsize; return jb; }
long fixed_jb_next | ( | struct fixed_jb * | jb | ) |
Definition at line 333 of file fixedjitterbuf.c.
References fixed_jb::next_delivery.
Referenced by jb_next_fixed().
{ return jb->next_delivery; }
int fixed_jb_put | ( | struct fixed_jb * | jb, |
void * | data, | ||
long | ms, | ||
long | ts, | ||
long | now | ||
) |
Definition at line 196 of file fixedjitterbuf.c.
References alloc_jb_frame(), ASSERT, fixed_jb::conf, fixed_jb_frame::data, fixed_jb::delay, fixed_jb_frame::delivery, FIXED_JB_OK, fixed_jb::force_resynch, fixed_jb::frames, fixed_jb_frame::ms, fixed_jb_frame::next, fixed_jb::next_delivery, fixed_jb_frame::prev, fixed_jb_conf::resync_threshold, resynch_jb(), fixed_jb::rxcore, fixed_jb::tail, and fixed_jb_frame::ts.
Referenced by fixed_jb_put_first(), jb_put_fixed(), and resynch_jb().
{ struct fixed_jb_frame *frame, *next, *newframe; long delivery; /* 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); delivery = jb->rxcore + jb->delay + ts; /* 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); } /* 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; } /* 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 */ /* 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); } /* Reset the force resynch flag */ jb->force_resynch = 0; /* Get a new frame */ newframe = alloc_jb_frame(jb); newframe->data = data; newframe->ts = ts; newframe->ms = ms; newframe->delivery = delivery; /* 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; return FIXED_JB_OK; } 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; return FIXED_JB_OK; } else { /* insert on a first position - should update frames head */ newframe->next = jb->frames; newframe->prev = NULL; jb->frames->prev = newframe; jb->frames = newframe; return FIXED_JB_OK; } }
int fixed_jb_put_first | ( | struct fixed_jb * | jb, |
void * | data, | ||
long | ms, | ||
long | ts, | ||
long | now | ||
) |
Definition at line 183 of file fixedjitterbuf.c.
References fixed_jb::delay, fixed_jb_put(), fixed_jb::next_delivery, fixed_jb::rxcore, and fixed_jb_frame::ts.
Referenced by jb_put_first_fixed(), and resynch_jb().
{ /* this is our first frame - set the base of the receivers time */ jb->rxcore = now - ts; /* init next for a first time - it should be the time the first frame should be played */ jb->next_delivery = now + jb->delay; /* put the frame */ return fixed_jb_put(jb, data, ms, ts, now); }
int fixed_jb_remove | ( | struct fixed_jb * | jb, |
struct fixed_jb_frame * | frameout | ||
) |
Definition at line 339 of file fixedjitterbuf.c.
References FIXED_JB_NOFRAME, FIXED_JB_OK, fixed_jb::frames, and get_jb_head().
Referenced by jb_empty_and_reset_fixed(), and jb_remove_fixed().
{ if (!jb->frames) return FIXED_JB_NOFRAME; get_jb_head(jb, frameout); return FIXED_JB_OK; }
void fixed_jb_set_force_resynch | ( | struct fixed_jb * | jb | ) |
Definition at line 177 of file fixedjitterbuf.c.
References fixed_jb::force_resynch.
Referenced by jb_force_resynch_fixed().
{ jb->force_resynch = 1; }