예제 #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;

}
예제 #2
0
파일: jitter.c 프로젝트: CEPBEP/onion-phone
/** 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;
	}

}
예제 #3
0
파일: jitter.c 프로젝트: CEPBEP/onion-phone
/** 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"); */
	}

}
예제 #4
0
int
obsd41_ioctl_file(nix_env_t        *env,
				  xec_endian_t      endian,
				  int               fd,
				  obsd41_ulong_t    request,
				  obsd41_uintptr_t  arg)
{
	xec_mem_if_t *mem = nix_env_get_memory(env);

	switch (request) {
		case OBSD41_FIONREAD:
		{
			size_t         bytes;
			uint32_t      *obytes;
			xec_mem_flg_t  mf = 0;

			/* arg is a pointer in the guest addres space. */
			obytes = (uint32_t *)xec_mem_gtoh(mem, arg, &mf);
			if (mf != 0) {
				nix_env_set_errno(env, EFAULT);
				return (-1);
			}

			if (nix_ioctl(fd, NIX_FIONREAD, &bytes, env) < 0)
				return (-1);

			__nix_try
			{
				*obytes = GE32(bytes);
			}
			__nix_catch_any
			{
				nix_env_set_errno(env, EFAULT);
				return (-1);
			}
			__nix_end_try

			return (0);
		}

		case OBSD41_TIOCSETA:
		case OBSD41_TIOCSETAW:
		case OBSD41_TIOCSETAF:
		{
			struct nix_termios     ios;
			struct obsd41_termios *oios;
			int                    req = 0;
			xec_mem_flg_t          mf  = 0;

			switch (request) {
				case OBSD41_TIOCSETA:  req = NIX_TIOCSETA;  break;
				case OBSD41_TIOCSETAW: req = NIX_TIOCSETAW; break;
				case OBSD41_TIOCSETAF: req = NIX_TIOCSETAF; break;
			}

			/* arg is a pointer in the guest addres space. */
			oios = (struct obsd41_termios *)xec_mem_gtoh(mem, arg, &mf);
			if (mf != 0) {
				nix_env_set_errno(env, EFAULT);
				return (-1);
			}

			__nix_try
			{
				obsd41_termios_to_nix_termios(endian, oios, &ios);
			}
			__nix_catch_any
			{
				nix_env_set_errno(env, EFAULT);
				return (-1);
			}
			__nix_end_try

			return (nix_ioctl(fd, req, &ios, env)); 
		}

		default:
			break;
	}

	nix_env_set_errno (env, EINVAL);
	return (-1);
}