Ejemplo n.º 1
0
/***********
 * put a nonvoice frame into the nonvoice queue
 */
static void put_control(jitterbuffer *jb, void *data, int type, long ts) 
{
  jb_frame *frame, *p;
    
  frame = malloc(sizeof(jb_frame));
  if(!frame) {
    jb_err("cannot allocate frame\n");
    return;
  }
  frame->data = data;
  frame->ts = ts;
  frame->type = type;
  frame->next = NULL;
  data = NULL;//to avoid stealing memory
  
  p = jb->controlframes;
  if (p) { //there are already control messages
    if (ts < p->ts) {
      jb->controlframes = frame;
      frame->next = p;
    } else {
      while (p->next && (ts >=p->next->ts)) {//sort on timestamps! so find place to put...
        p = p->next; 
      }
      if (p->next) {
        frame->next = p->next;
      }
      p->next = frame;
    }
  } else {
    jb->controlframes = frame;
  }
}
Ejemplo n.º 2
0
/***********
 * Set settings for the jitterbuffer. 
 * Only if a setting is defined it will be written
 * in the jb->settings.
 * This means that no setting can be set to zero
 */
void jb_set_settings(jitterbuffer *jb, jb_settings *settings) 
{
  jb_dbg("S");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_set_settings()\n");
    return;
  }
  
  if (settings->min_jb) {
    jb->settings.min_jb = settings->min_jb;
  }
  if (settings->max_jb) {
    jb->settings.max_jb = settings->max_jb;
  }
  if (settings->max_successive_interp) {
    jb->settings.max_successive_interp = settings->max_successive_interp;
  }
  if (settings->extra_delay) {
    jb->settings.extra_delay = settings->extra_delay;
  }
  if (settings->wait_grow) {
    jb->settings.wait_grow = settings->wait_grow;
  }
  if (settings->wait_shrink) {
    jb->settings.wait_shrink = settings->wait_shrink;
  }
  if (settings->max_diff) {
    jb->settings.max_diff = settings->max_diff;
  }
}
Ejemplo n.º 3
0
/***********
 * validates the statistics
 * the losspct due the jitterbuffer will be calculated.
 * delay and delay_target will be calculated
 * *stats = info
 */
void jb_get_info(jitterbuffer *jb, jb_info *stats) 
{
  long max_index, pointer;
  
  jb_dbg("I");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_get_info()\n");
    return;
  }
  
  jb->info.delay = jb->current - jb->min;
  jb->info.delay_target = jb->target - jb->min;
  
  //calculate the losspct...
  max_index = (jb->hist_pointer < JB_HISTORY_SIZE) ? 
jb->hist_pointer : JB_HISTORY_SIZE-1;
  if (max_index>1) {
    pointer = find_pointer(&jb->hist_sorted_delay[0], max_index, 
jb->current);
    jb->info.losspct = ((max_index - pointer)*100/max_index);
    if (jb->info.losspct < 0) {
      jb->info.losspct = 0;
    }
  } else {
    jb->info.losspct = 0;
  }
  
  *stats = jb->info;
}
Ejemplo n.º 4
0
/* returns 1 if frame was inserted into head of queue, 0 otherwise */
static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts) 
{
	jb_frame *frame;
	jb_frame *p;
	int head = 0;
	long resync_ts = ts - jb->info.resync_offset;

	if ((frame = jb->free)) {
		jb->free = frame->next;
	} else if (!(frame = ast_malloc(sizeof(*frame)))) {
		jb_err("cannot allocate frame\n");
		return 0;
	}

	jb->info.frames_cur++;

	frame->data = data;
	frame->ts = resync_ts;
	frame->ms = ms;
	frame->type = type;

	/* 
	 * frames are a circular list, jb-frames points to to the lowest ts, 
	 * jb->frames->prev points to the highest ts
	 */

	if (!jb->frames) {  /* queue is empty */
		jb->frames = frame;
		frame->next = frame;
		frame->prev = frame;
		head = 1;
	} else if (resync_ts < jb->frames->ts) {
		frame->next = jb->frames;
		frame->prev = jb->frames->prev;

		frame->next->prev = frame;
		frame->prev->next = frame;

		/* frame is out of order */
		jb->info.frames_ooo++;

		jb->frames = frame;
		head = 1;
	} else { 
		p = jb->frames;

		/* frame is out of order */
		if (resync_ts < p->prev->ts) jb->info.frames_ooo++;

		while (resync_ts < p->prev->ts && p->prev != jb->frames) 
			p = p->prev;

		frame->next = p;
		frame->prev = p->prev;

		frame->next->prev = frame;
		frame->prev->next = frame;
	}
	return head;
}
Ejemplo n.º 5
0
/***********
 * Put a packet into the jitterbuffers 
 * Only the timestamps of voicepackets are put in the history
 * this because the jitterbuffer only works for voicepackets
 * don't put packets twice in history and queue (e.g. transmitting every frame twice)
 * keep track of statistics
 */
void jb_put(jitterbuffer *jb, void *data, int type, long ms, long ts, long now, int codec) 
{ 
  long pointer, max_index;
  
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_put()\n");
    return;
  }
  
  jb->info.frames_received++;

  if (type == JB_TYPE_CONTROL) {
    //put the packet into the contol-queue of the jitterbuffer
    jb_dbg("pC");
    put_control(jb,data,type,ts);

  } else if (type == JB_TYPE_VOICE) {
    // only add voice that aren't already in the buffer
    max_index = (jb->hist_pointer < JB_HISTORY_SIZE) ? jb->hist_pointer : JB_HISTORY_SIZE-1;
    pointer = find_pointer(&jb->hist_sorted_timestamp[0], max_index, ts);
    if (jb->hist_sorted_timestamp[pointer]==ts) { //timestamp already in queue
      jb_dbg("pT");
      free(data); 
      jb->info.frames_dropped_twice++;
    } else { //add
      jb_dbg("pV");
      /* add voicepacket to history */
      put_history(jb,ts,now,ms,codec);
      /*calculate jitterbuffer size*/
      calculate_info(jb, ts, now, codec);
      /*put the packet into the queue of the jitterbuffer*/
      put_voice(jb,data,type,ms,ts,codec);
    } 

  } else if (type == JB_TYPE_SILENCE){ //silence
    jb_dbg("pS");
    put_voice(jb,data,type,ms,ts,codec);

  } else {//should NEVER happen
    jb_err("jb_put(): type not known\n");
    free(data);
  }
}
Ejemplo n.º 6
0
/***********
 * gives the settings for this jitterbuffer
 * *settings = settings
 */
void jb_get_settings(jitterbuffer *jb, jb_settings *settings) 
{
  jb_dbg("S");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_get_settings()\n");
    return;
  }
  
  *settings = jb->settings;
}
Ejemplo n.º 7
0
/***********
 * destroy the jitterbuffer
 * free all the [non]voice frames with reset_all
 * free the jitterbuffer
 */
void jb_destroy(jitterbuffer *jb) 
{
  jb_dbg("D");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_destroy()\n");
    return;
  }
  
  jb_reset_all(jb);
  free(jb);
}
Ejemplo n.º 8
0
/***********
 * create a new jitterbuffer
 * return NULL if malloc doesn't work
 * else return jb with default_settings.
 */
jitterbuffer *jb_new() 
{
  jitterbuffer *jb;
  
  jb_dbg("N");
  jb = tsk_calloc(1, sizeof(jitterbuffer));
  if (!jb) {
    jb_err("cannot allocate jitterbuffer\n");
    return NULL;
  }
  set_default_settings(jb);
  reset(jb);
  return jb;
}
Ejemplo n.º 9
0
/***********
 * if there are any frames left in JB returns JB_OK, otherwise returns JB_EMPTY
 */
int jb_has_frames(jitterbuffer *jb)
{
  jb_dbg("H");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_has_frames()\n");
    return JB_NOJB;
  }
  
  if(jb->controlframes || jb->voiceframes) {
    return JB_OK;
  } else {
    return JB_EMPTY;
  }
}
Ejemplo n.º 10
0
/***********
 * control frames have a higher priority then voice frames
 * returns JB_OK if a frame is available and *data points to the packet
 * returns JB_NOFRAME if it's no time to play voice and no control available
 * returns JB_INTERP if interpolating is required
 * returns JB_EMPTY if no voice frame is in the jitterbuffer (only during silence)
 */
int jb_get(jitterbuffer *jb, void **data, long now, long interpl) 
{
  int result;
  
  jb_dbg("A");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_get()\n");
    return JB_NOJB;
  }
  
  result = get_control(jb, data);
  if (result != JB_OK ) { //no control message available maybe there is voice...
    result = get_voice(jb, data, now, interpl);
  }
  return result;
}
Ejemplo n.º 11
0
static void jb_chkqueue(jitterbuf *jb) 
{
	int i=0;
	jb_frame *p = jb->frames;

	if (!p) {
		return;
	}

	do {
		if (p->next == NULL)  {
			jb_err("Queue is BROKEN at item [%d]", i);	
		}
		i++;
		p=p->next;
	} while (p->next != jb->frames);
}
Ejemplo n.º 12
0
/***********
 * put a voice or silence frame into the jitterbuffer 
 */
static void put_voice(jitterbuffer *jb, void *data, int type, long ms, long ts, int codec) 
{
  jb_frame *frame, *p;
  frame = malloc(sizeof(jb_frame));
  if(!frame) {
    jb_err("cannot allocate frame\n");
    return;
  }
  
  frame->data = data;
  frame->ts = ts;
  frame->ms = ms;
  frame->type = type;
  frame->codec = codec;
  
  data = NULL; //to avoid stealing the memory location
  /* 
   * frames are a circular list, jb->voiceframes points to to the lowest ts, 
   * jb->voiceframes->prev points to the highest ts
   */
  if(!jb->voiceframes) {  /* queue is empty */
    jb->voiceframes = frame;
    frame->next = frame;
    frame->prev = frame;
  } else { 
    p = jb->voiceframes;
    if(ts < p->prev->ts) { //frame is out of order
      jb->info.frames_ooo++;
    }
    if (ts < p->ts) { //frame is lowest, let voiceframes point to it!
      jb->voiceframes = frame;
    } else {
      while(ts < p->prev->ts ) {
        p = p->prev;
      }
    }
    frame->next = p;
    frame->prev = p->prev;
    frame->next->prev = frame;
    frame->prev->next = frame;
  }
}
Ejemplo n.º 13
0
/***********
 * empty nonvoice messages
 * empty voice messages
 * reset statistics 
 * reset settings to default
 */
void jb_reset_all(jitterbuffer *jb) 
{
  jb_frame *frame;
  
  jb_dbg("r");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_reset_all()\n");
    return;
  }
  
  // free nonvoice
  while(jb->controlframes) {
    frame = jb->controlframes;
    jb->controlframes = frame->next;
    frame_free(frame);
  }
  // free voice and reset statistics is done by jb_reset
  jb_reset(jb);
  set_default_settings(jb);
}
Ejemplo n.º 14
0
/***********
 * empty voice messages 
 * reset statistics 
 * keep the settings
 */
void jb_reset(jitterbuffer *jb) 
{
  jb_frame *frame;
  
  jb_dbg("R");
  if (jb == NULL) {
    jb_err("no jitterbuffer in jb_reset()\n");
    return;
  }
  
  //free voice
  while(jb->voiceframes) {
    frame = get_all_frames(jb);
    frame_free(frame);
  }
  //reset stats
  memset(&(jb->info),0,sizeof(jb_info) );
  // set default settings
  reset(jb);
}
Ejemplo n.º 15
0
/***********
 * The voicecase has four 'options'
 * - difference is way off, reset
 * - diff > 0, we may need to grow
 * - diff < 0, we may need to shrink
 * - everything else
 */
static int get_voicecase(jitterbuffer *jb, void **data, long now, long interpl, long diff) 
{
  jb_frame *frame;
  int result;
  
   // * - difference is way off, reset
  if (diff > jb->settings.max_diff || -diff > jb->settings.max_diff) {
    jb_err("wakko diff in get_voicecase\n");
    reset(jb); //reset hist because the timestamps are wakko. 
    result = JB_NOFRAME;
  //- diff > 0, we may need to grow
  } else if ((diff > 0) && 
                   (now > (jb->last_adjustment + jb->settings.wait_grow) 
                    || (now + jb->current + interpl) < get_next_framets(jb) ) ) { //grow
    /* first try to grow */
    if (diff<interpl/2) {
      jb_dbg("ag");
      jb->current +=diff;
    } else {
      jb_dbg("aG");
      /* grow by interp frame len */
      jb->current += interpl;
    }
    jb->last_adjustment = now;
    result = get_voice(jb, data, now, interpl);
  //- diff < 0, we may need to shrink
  } else if ( (diff < 0) 
                && (now > (jb->last_adjustment + jb->settings.wait_shrink)) 
                && ((-diff) > jb->settings.extra_delay) ) {
    /* now try to shrink
     * if there is a frame shrink by frame length
     * otherwise shrink by interpl
     */
    jb->last_adjustment = now;
    
    frame = get_frame(jb, now - jb->current);
    if(frame) {
      jb_dbg("as");
      /* shrink by frame size we're throwing out */
      jb->info.frames_dropped++;
      jb->current -= frame->ms;
      frame_free(frame);
    } else {
      jb_dbg("aS");
      /* shrink by interpl */
      jb->current -= interpl;
    }
    result = get_voice(jb, data, now, interpl);
  } else  { 
    /* if it is not the time to play a result = JB_NOFRAME
     * else We try to play a frame if a frame is available
     * and not late it is played otherwise 
     * if available it is dropped and the next is tried
     * last option is interpolating
     */
    if (now - jb->current < jb->next_voice_time) {
      jb_dbg("aN");
      result = JB_NOFRAME;
    } else {
      frame = get_frame(jb, now - jb->current);
      if (frame) { //there is a frame
        /* voice frame is late */
        if(frame->ts < jb->next_voice_time) {   //late
          jb_dbg("aL");
          jb->info.frames_late++;
          frame_free(frame);
          result = get_voice(jb, data, now, interpl);
        } else {
          jb_dbg("aP");
          /* normal case; return the frame, increment stuff */
          *data = frame->data;
          frame->data = NULL;
          jb->next_voice_time = frame->ts + frame->ms;
          jb->cnt_successive_interp = 0;
          frame_free(frame);
          result = JB_OK;
        }
      } else { // no frame, thus interpolate
        jb->cnt_successive_interp++;
        /* assume silence instead of continuing to interpolate */
        if (jb->settings.max_successive_interp && jb->cnt_successive_interp >= jb->settings.max_successive_interp) {
          jb->info.silence = 1;
          jb->silence_begin_ts = jb->next_voice_time;
        }
        jb_dbg("aI");
        jb->next_voice_time += interpl;
        result = JB_INTERP;
      }
    }
  }
  return result;

}