Esempio n. 1
0
/** Get one packet from the jitter buffer */
int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint32_t *start_offset)
{
   int i, j;
   float late_ratio_short;
   float late_ratio_long;
   float ontime_ratio_short;
   float ontime_ratio_long;
   float early_ratio_short;
   float early_ratio_long;
   int chunk_size;
   int incomplete = 0;
   
   if (LT32(jitter->current_timestamp+jitter->tick_size, jitter->pointer_timestamp))
   {
      jitter->current_timestamp = jitter->pointer_timestamp;
      speex_warning("did you forget to call jitter_buffer_tick() by any chance?");
   }
   /*fprintf (stderr, "get packet %d %d\n", jitter->pointer_timestamp, jitter->current_timestamp);*/

   /* FIXME: This should be only what remaining of the current tick */
   chunk_size = jitter->tick_size;
   
   /* Compiling arrival statistics */
   
   late_ratio_short = 0;
   late_ratio_long = 0;
   for (i=0;i<LATE_BINS;i++)
   {
      late_ratio_short += jitter->shortterm_margin[i];
      late_ratio_long += jitter->longterm_margin[i];
   }
   ontime_ratio_short = jitter->shortterm_margin[LATE_BINS];
   ontime_ratio_long = jitter->longterm_margin[LATE_BINS];
   early_ratio_short = early_ratio_long = 0;
   for (i=LATE_BINS+1;i<MAX_MARGIN;i++)
   {
      early_ratio_short += jitter->shortterm_margin[i];
      early_ratio_long += jitter->longterm_margin[i];
   }
   if (0&&jitter->pointer_timestamp%1000==0)
   {
      /*fprintf (stderr, "%f %f %f %f %f %f\n", early_ratio_short, early_ratio_long, ontime_ratio_short, ontime_ratio_long, late_ratio_short, late_ratio_long);*/
      /*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
   }
   
   /* Adjusting the buffering */
   
   if (late_ratio_short > .1 || late_ratio_long > .03)
   {
      /* If too many packets are arriving late */
      jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
      jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2];
      for (i=MAX_MARGIN-3;i>=0;i--)
      {
         jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i];
         jitter->longterm_margin[i+1] = jitter->longterm_margin[i];         
      }
      jitter->shortterm_margin[0] = 0;
      jitter->longterm_margin[0] = 0;            
      jitter->pointer_timestamp -= jitter->tick_size;
      jitter->current_timestamp -= jitter->tick_size;
      /*fprintf (stderr, "i");*/
      /*fprintf (stderr, "interpolate (getting some slack)\n");*/
   } else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8)
   {
      /* Many frames arriving early */
      jitter->shortterm_margin[0] += jitter->shortterm_margin[1];
      jitter->longterm_margin[0] += jitter->longterm_margin[1];
      for (i=1;i<MAX_MARGIN-1;i++)
      {
         jitter->shortterm_margin[i] = jitter->shortterm_margin[i+1];
         jitter->longterm_margin[i] = jitter->longterm_margin[i+1];         
      }
      jitter->shortterm_margin[MAX_MARGIN-1] = 0;
      jitter->longterm_margin[MAX_MARGIN-1] = 0;      
      /*fprintf (stderr, "drop frame\n");*/
      /*fprintf (stderr, "d");*/
      jitter->pointer_timestamp += jitter->tick_size;
      jitter->current_timestamp += jitter->tick_size;
      /*fprintf (stderr, "dropping packet (getting more aggressive)\n");*/
   }
   
   /* Searching for the packet that fits best */
   
   /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
   for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
   {
      if (jitter->buf[i] && jitter->timestamp[i]==jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
         break;
   }
   
   /* If no match, try for an "older" packet that still spans (fully) the current chunk */
   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
   {
      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
      {
         if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
            break;
      }
   }
   
   /* If still no match, try for an "older" packet that spans part of the current chunk */
   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
   {
      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
      {
         if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp))
            break;
      }
   }
   
   /* If still no match, try for earliest packet possible */
   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
   {
      int found = 0;
      spx_uint32_t best_time=0;
      int best_span=0;
      int besti=0;
      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
      {
         /* check if packet starts within current chunk */
         if (jitter->buf[i] && LT32(jitter->timestamp[i],jitter->pointer_timestamp+chunk_size) && GE32(jitter->timestamp[i],jitter->pointer_timestamp))
         {
            if (!found || LT32(jitter->timestamp[i],best_time) || (jitter->timestamp[i]==best_time && GT32(jitter->span[i],best_span)))
            {
               best_time = jitter->timestamp[i];
               best_span = jitter->span[i];
               besti = i;
               found = 1;
            }
         }
      }
      if (found)
      {
         i=besti;
         incomplete = 1;
         /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp, chunk_size, jitter->span[i]);*/
      }
   }

   /* If we find something */
   if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
   {
      /* We (obviously) haven't lost this packet */
      jitter->lost_count = 0;
      jitter->loss_rate = .999*jitter->loss_rate;
      /* Check for potential overflow */
      packet->len = jitter->len[i];
      /* Copy packet */
      for (j=0;j<(int)packet->len;j++)
         packet->data[j] = jitter->buf[i][j];
      /* Remove packet */
      speex_free(jitter->buf[i]);
      jitter->buf[i] = NULL;
      /* Set timestamp and span (if requested) */
      if (start_offset)
         *start_offset = jitter->timestamp[i]-jitter->pointer_timestamp;
      packet->timestamp = jitter->timestamp[i];
      packet->span = jitter->span[i];
      /* Point at the end of the current packet */
      jitter->pointer_timestamp = jitter->timestamp[i]+jitter->span[i];
      if (incomplete)
         return JITTER_BUFFER_INCOMPLETE;
      else
         return JITTER_BUFFER_OK;
   }
   
   
   /* If we haven't found anything worth returning */
   /*fprintf (stderr, "not found\n");*/
   jitter->lost_count++;
   /*fprintf (stderr, "m");*/
   /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
   jitter->loss_rate = .999*jitter->loss_rate + .001;
   if (start_offset)
      *start_offset = 0;
   packet->timestamp = jitter->pointer_timestamp;
   packet->span = jitter->tick_size;
   jitter->pointer_timestamp += chunk_size;
   packet->len = 0;
   return JITTER_BUFFER_MISSING;

}
Esempio n. 2
0
/** Get one packet from the jitter buffer */
EXPORT int jitter_buffer_get(JitterBuffer * jitter, JitterBufferPacket * packet,
			     spx_int32_t desired_span,
			     spx_int32_t * start_offset)
{
	int i;
	unsigned int j;
	spx_int16_t opt;

	if (start_offset != NULL)
		*start_offset = 0;

	/* Syncing on the first call */
	if (jitter->reset_state) {
		int found = 0;
		/* Find the oldest packet */
		spx_uint32_t oldest = 0;
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			if (jitter->packets[i].data
			    && (!found
				|| LT32(jitter->packets[i].timestamp,
					oldest))) {
				oldest = jitter->packets[i].timestamp;
				found = 1;
			}
		}
		if (found) {
			jitter->reset_state = 0;
			jitter->pointer_timestamp = oldest;
			jitter->next_stop = oldest;
		} else {
			packet->timestamp = 0;
			packet->span = jitter->interp_requested;
			return JITTER_BUFFER_MISSING;
		}
	}

	jitter->last_returned_timestamp = jitter->pointer_timestamp;

	if (jitter->interp_requested != 0) {
		packet->timestamp = jitter->pointer_timestamp;
		packet->span = jitter->interp_requested;

		/* Increment the pointer because it got decremented in the delay update */
		jitter->pointer_timestamp += jitter->interp_requested;
		packet->len = 0;
		/*fprintf (stderr, "Deferred interpolate\n"); */

		jitter->interp_requested = 0;

		jitter->buffered = packet->span - desired_span;

		return JITTER_BUFFER_INSERTION;
	}

	/* Searching for the packet that fits best */

	/* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
	for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
		if (jitter->packets[i].data
		    && jitter->packets[i].timestamp == jitter->pointer_timestamp
		    && GE32(jitter->packets[i].timestamp +
			    jitter->packets[i].span,
			    jitter->pointer_timestamp + desired_span))
			break;
	}

	/* If no match, try for an "older" packet that still spans (fully) the current chunk */
	if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) {
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			if (jitter->packets[i].data
			    && LE32(jitter->packets[i].timestamp,
				    jitter->pointer_timestamp)
			    && GE32(jitter->packets[i].timestamp +
				    jitter->packets[i].span,
				    jitter->pointer_timestamp + desired_span))
				break;
		}
	}

	/* If still no match, try for an "older" packet that spans part of the current chunk */
	if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) {
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			if (jitter->packets[i].data
			    && LE32(jitter->packets[i].timestamp,
				    jitter->pointer_timestamp)
			    && GT32(jitter->packets[i].timestamp +
				    jitter->packets[i].span,
				    jitter->pointer_timestamp))
				break;
		}
	}

	/* If still no match, try for earliest packet possible */
	if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) {
		int found = 0;
		spx_uint32_t best_time = 0;
		int best_span = 0;
		int besti = 0;
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			/* check if packet starts within current chunk */
			if (jitter->packets[i].data
			    && LT32(jitter->packets[i].timestamp,
				    jitter->pointer_timestamp + desired_span)
			    && GE32(jitter->packets[i].timestamp,
				    jitter->pointer_timestamp)) {
				if (!found
				    || LT32(jitter->packets[i].timestamp,
					    best_time)
				    || (jitter->packets[i].timestamp ==
					best_time
					&& GT32(jitter->packets[i].span,
						best_span))) {
					best_time =
					    jitter->packets[i].timestamp;
					best_span = jitter->packets[i].span;
					besti = i;
					found = 1;
				}
			}
		}
		if (found) {
			i = besti;
			/*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span); */
		}
	}

	/* If we find something */
	if (i != SPEEX_JITTER_MAX_BUFFER_SIZE) {
		spx_int32_t offset;

		/* We (obviously) haven't lost this packet */
		jitter->lost_count = 0;

		/* In this case, 0 isn't as a valid timestamp */
		if (jitter->arrival[i] != 0) {
			update_timings(jitter,
				       ((spx_int32_t) jitter->packets[i].
					timestamp) -
				       ((spx_int32_t) jitter->arrival[i]) -
				       jitter->buffer_margin);
		}

		/* Copy packet */
		if (jitter->destroy) {
			packet->data = jitter->packets[i].data;
			packet->len = jitter->packets[i].len;
		} else {
			if (jitter->packets[i].len > packet->len) {
				speex_warning_int
				    ("jitter_buffer_get(): packet too large to fit. Size is",
				     jitter->packets[i].len);
			} else {
				packet->len = jitter->packets[i].len;
			}
			for (j = 0; j < packet->len; j++)
				packet->data[j] = jitter->packets[i].data[j];
			/* Remove packet */
			speex_free(jitter->packets[i].data);
		}
		jitter->packets[i].data = NULL;
		/* Set timestamp and span (if requested) */
		offset =
		    (spx_int32_t) jitter->packets[i].timestamp -
		    (spx_int32_t) jitter->pointer_timestamp;
		if (start_offset != NULL)
			*start_offset = offset;
		else if (offset != 0)
			speex_warning_int
			    ("jitter_buffer_get() discarding non-zero start_offset",
			     offset);

		packet->timestamp = jitter->packets[i].timestamp;
		jitter->last_returned_timestamp = packet->timestamp;

		packet->span = jitter->packets[i].span;
		packet->sequence = jitter->packets[i].sequence;
		packet->user_data = jitter->packets[i].user_data;
		/* Point to the end of the current packet */
		jitter->pointer_timestamp =
		    jitter->packets[i].timestamp + jitter->packets[i].span;

		jitter->buffered = packet->span - desired_span;

		if (start_offset != NULL)
			jitter->buffered += *start_offset;

		return JITTER_BUFFER_OK;
	}

	/* If we haven't found anything worth returning */

	/*fprintf (stderr, "not found\n"); */
	jitter->lost_count++;
	/*fprintf (stderr, "m"); */
	/*fprintf (stderr, "lost_count = %d\n", jitter->lost_count); */

	opt = compute_opt_delay(jitter);

	/* Should we force an increase in the buffer or just do normal interpolation? */
	if (opt < 0) {
		/* Need to increase buffering */

		/* Shift histogram to compensate */
		shift_timings(jitter, -opt);

		packet->timestamp = jitter->pointer_timestamp;
		packet->span = -opt;
		/* Don't move the pointer_timestamp forward */
		packet->len = 0;

		jitter->buffered = packet->span - desired_span;
		return JITTER_BUFFER_INSERTION;
		/*jitter->pointer_timestamp -= jitter->delay_step; */
		/*fprintf (stderr, "Forced to interpolate\n"); */
	} else {
		/* Normal packet loss */
		packet->timestamp = jitter->pointer_timestamp;

		desired_span =
		    ROUND_DOWN(desired_span, jitter->concealment_size);
		packet->span = desired_span;
		jitter->pointer_timestamp += desired_span;
		packet->len = 0;

		jitter->buffered = packet->span - desired_span;
		return JITTER_BUFFER_MISSING;
		/*fprintf (stderr, "Normal loss\n"); */
	}

}
Esempio n. 3
0
/** Put one packet into the jitter buffer */
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
{
   int i,j;
   spx_int32_t arrival_margin;
   /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
   if (jitter->reset_state)
   {
      jitter->reset_state=0;
      jitter->pointer_timestamp = packet->timestamp;
      jitter->current_timestamp = packet->timestamp;
      /*fprintf(stderr, "reset to %d\n", timestamp);*/
   }
   
   /* Cleanup buffer (remove old packets that weren't played) */
   for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
   {
      if (jitter->buf[i] && LE32(jitter->timestamp[i] + jitter->span[i], jitter->pointer_timestamp))
      {
         /*fprintf (stderr, "cleaned (not played)\n");*/
         speex_free(jitter->buf[i]);
         jitter->buf[i] = NULL;
      }
   }

   /*Find an empty slot in the buffer*/
   for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
   {
      if (jitter->buf[i]==NULL)
         break;
   }

   /*fprintf(stderr, "%d %d %f\n", timestamp, jitter->pointer_timestamp, jitter->drift_average);*/
   /*No place left in the buffer*/
   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
   {
      int earliest=jitter->timestamp[0];
      i=0;
      for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
      {
         if (!jitter->buf[i] || LT32(jitter->timestamp[j],earliest))
         {
            earliest = jitter->timestamp[j];
            i=j;
         }
      }
      speex_free(jitter->buf[i]);
      jitter->buf[i]=NULL;
      if (jitter->lost_count>20)
      {
         jitter_buffer_reset(jitter);
      }
      /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/      
   }
   
   /* Copy packet in buffer */
   jitter->buf[i]=(char*)speex_alloc(packet->len);
   for (j=0;j<(int)packet->len;j++)
      jitter->buf[i][j]=packet->data[j];
   jitter->timestamp[i]=packet->timestamp;
   jitter->span[i]=packet->span;
   jitter->len[i]=packet->len;
   
   /* Adjust the buffer size depending on network conditions */
   arrival_margin = (packet->timestamp - jitter->current_timestamp) - jitter->buffer_margin*jitter->tick_size;
   
   if (arrival_margin >= -LATE_BINS*jitter->tick_size)
   {
      spx_int32_t int_margin;
      for (i=0;i<MAX_MARGIN;i++)
      {
         jitter->shortterm_margin[i] *= .98;
         jitter->longterm_margin[i] *= .995;
      }
      int_margin = LATE_BINS + arrival_margin/jitter->tick_size;
      if (int_margin>MAX_MARGIN-1)
         int_margin = MAX_MARGIN-1;
      if (int_margin>=0)
      {
         jitter->shortterm_margin[int_margin] += .02;
         jitter->longterm_margin[int_margin] += .005;
      }
   } else {
      
      /*fprintf (stderr, "way too late = %d\n", arrival_margin);*/
      if (jitter->lost_count>20)
      {
         jitter_buffer_reset(jitter);
      }
   }
#if 0 /* Enable to check how much is being buffered */
   if (rand()%1000==0)
   {
      int count = 0;
      for (j=0;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
      {
         if (jitter->buf[j])
            count++;
      }
      fprintf (stderr, "buffer_size = %d\n", count);
   }
#endif
}
Esempio n. 4
0
/** Put one packet into the jitter buffer */
EXPORT void jitter_buffer_put(JitterBuffer * jitter,
			      const JitterBufferPacket * packet)
{
	int i, j;
	int late;
	/*fprintf (stderr, "put packet %d %d\n", timestamp, span); */

	/* Cleanup buffer (remove old packets that weren't played) */
	if (!jitter->reset_state) {
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			/* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */
			if (jitter->packets[i].data
			    && LE32(jitter->packets[i].timestamp +
				    jitter->packets[i].span,
				    jitter->pointer_timestamp)) {
				/*fprintf (stderr, "cleaned (not played)\n"); */
				if (jitter->destroy)
					jitter->destroy(jitter->packets[i].
							data);
				else
					speex_free(jitter->packets[i].data);
				jitter->packets[i].data = NULL;
			}
		}
	}

	/*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp); */
	/* Check if packet is late (could still be useful though) */
	if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) {
		update_timings(jitter,
			       ((spx_int32_t) packet->timestamp) -
			       ((spx_int32_t) jitter->next_stop) -
			       jitter->buffer_margin);
		late = 1;
	} else {
		late = 0;
	}

	/* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is
	 * used to resync. */
	if (jitter->lost_count > 20) {
		jitter_buffer_reset(jitter);
	}

	/* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
	if (jitter->reset_state
	    || GE32(packet->timestamp + packet->span + jitter->delay_step,
		    jitter->pointer_timestamp)) {

		/*Find an empty slot in the buffer */
		for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) {
			if (jitter->packets[i].data == NULL)
				break;
		}

		/*No place left in the buffer, need to make room for it by discarding the oldest packet */
		if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) {
			int earliest = jitter->packets[0].timestamp;
			i = 0;
			for (j = 1; j < SPEEX_JITTER_MAX_BUFFER_SIZE; j++) {
				if (!jitter->packets[i].data
				    || LT32(jitter->packets[j].timestamp,
					    earliest)) {
					earliest = jitter->packets[j].timestamp;
					i = j;
				}
			}
			if (jitter->destroy)
				jitter->destroy(jitter->packets[i].data);
			else
				speex_free(jitter->packets[i].data);
			jitter->packets[i].data = NULL;
			/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp); */
		}

		/* Copy packet in buffer */
		if (jitter->destroy) {
			jitter->packets[i].data = packet->data;
		} else {
			jitter->packets[i].data =
			    (char *)speex_alloc(packet->len);
			for (j = 0; j < (int)packet->len; j++)
				jitter->packets[i].data[j] = packet->data[j];
		}
		jitter->packets[i].timestamp = packet->timestamp;
		jitter->packets[i].span = packet->span;
		jitter->packets[i].len = packet->len;
		jitter->packets[i].sequence = packet->sequence;
		jitter->packets[i].user_data = packet->user_data;
		if (jitter->reset_state || late)
			jitter->arrival[i] = 0;
		else
			jitter->arrival[i] = jitter->next_stop;
	}

}