ast_json_pack(): Use safer json ref mechanism.
[asterisk/asterisk.git] / main / fixedjitterbuf.c
index 93c4cd2..3c350b4 100644 (file)
  * this code.
  */
 
-/*! \file 
- * 
+/*! \file
+ *
  * \brief Jitterbuffering algorithm.
- * 
+ *
  * \author Slav Klenov <slav@securax.org>
  */
 
-#include "asterisk.h"
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk.h"
 
 #include <assert.h>
 
@@ -73,7 +75,7 @@ static inline void release_jb_frame(struct fixed_jb *jb, struct fixed_jb_frame *
 static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame)
 {
        struct fixed_jb_frame *fr;
-       
+
        /* unlink the frame */
        fr = jb->frames;
        jb->frames = fr->next;
@@ -83,13 +85,13 @@ static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame)
                /* the jb is empty - update tail */
                jb->tail = NULL;
        }
-       
+
        /* update next */
        jb->next_delivery = fr->delivery + fr->ms;
-       
+
        /* copy the destination */
        memcpy(frame, fr, sizeof(struct fixed_jb_frame));
-       
+
        /* and release the frame */
        release_jb_frame(jb, fr);
 }
@@ -98,26 +100,26 @@ static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame)
 struct fixed_jb *fixed_jb_new(struct fixed_jb_conf *conf)
 {
        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 don't 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;
 }
 
@@ -126,7 +128,7 @@ void fixed_jb_destroy(struct fixed_jb *jb)
 {
        /* jitterbuf MUST be empty before it can be destroyed */
        ASSERT(jb->frames == NULL);
-       
+
        ast_free(jb);
 }
 
@@ -135,32 +137,32 @@ static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long no
 {
        long diff, offset;
        struct fixed_jb_frame *frame;
-       
+
        /* If jb is empty, just reinitialize the jb */
        if (!jb->frames) {
                /* debug check: tail should also be NULL */
                ASSERT(jb->tail == NULL);
-               
+
                return fixed_jb_put_first(jb, data, ms, ts, now);
        }
-       
+
        /* 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. */
-       
+
        /* Get the diff in timestamps */
        diff = ts - jb->tail->ts;
-       
+
        /* Ideally this should be just the length of the last frame. The deviation is the desired
           offset */
        offset = diff - jb->tail->ms;
-       
+
        /* 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))
                return FIXED_JB_DROP;
-       
+
        /* Reset the force resynch flag */
        jb->force_resynch = 0;
-       
+
        /* apply the offset to the jb state */
        jb->rxcore -= offset;
        frame = jb->frames;
@@ -168,7 +170,7 @@ static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long no
                frame->ts += offset;
                frame = frame->next;
        }
-       
+
        /* now jb_put() should add the frame at a last position */
        return fixed_jb_put(jb, data, ms, ts, now);
 }
@@ -184,36 +186,35 @@ int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long n
 {
        /* 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_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
 {
        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) {
@@ -227,7 +228,7 @@ int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
        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 ||
@@ -235,22 +236,22 @@ int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
        {
                /* 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;
@@ -264,7 +265,7 @@ int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
                        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 */
@@ -273,7 +274,7 @@ int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
                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 */
@@ -281,7 +282,7 @@ int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
                newframe->prev = NULL;
                jb->frames->prev = newframe;
                jb->frames = newframe;
-               
+
                return FIXED_JB_OK;
        }
 }
@@ -291,41 +292,41 @@ int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, lo
 {
        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;
 }
 
@@ -340,8 +341,13 @@ int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
 {
        if (!jb->frames)
                return FIXED_JB_NOFRAME;
-       
+
        get_jb_head(jb, frameout);
-       
+
        return FIXED_JB_OK;
 }
+
+int fixed_jb_is_late(struct fixed_jb *jb, long ts)
+{
+       return jb->rxcore + jb->delay + ts < jb->next_delivery;
+}