[xiph-commits] r11093 - trunk/speex/libspeex
jm at svn.xiph.org
jm at svn.xiph.org
Tue Apr 4 01:30:28 PDT 2006
Author: jm
Date: 2006-04-04 01:30:25 -0700 (Tue, 04 Apr 2006)
New Revision: 11093
Modified:
trunk/speex/libspeex/jitter.c
Log:
Got fine timing adjustments to work (tick size instead of frame size
granularity). This fixed a periodic drop/interpolate problem. Bit
more comments too.
Modified: trunk/speex/libspeex/jitter.c
===================================================================
--- trunk/speex/libspeex/jitter.c 2006-04-04 02:27:39 UTC (rev 11092)
+++ trunk/speex/libspeex/jitter.c 2006-04-04 08:30:25 UTC (rev 11093)
@@ -55,23 +55,24 @@
#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
+/** Jitter buffer structure */
struct JitterBuffer_ {
- int buffer_size; /**< Buffer size */
- spx_uint32_t pointer_timestamp; /**< Pointer timestamp */
+ spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
+ spx_uint32_t current_timestamp; /**< Timestamp of the local clock (what we will *play* next) */
- char *buf[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Buffer of packets */
- spx_uint32_t timestamp[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Timestamp of packet */
+ char *buf[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Buffer of packets (NULL if slot is free) */
+ spx_uint32_t timestamp[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Timestamp of packet */
int span[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Timestamp of packet */
int len[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Number of bytes in packet */
int tick_size; /**< Output granularity */
- int reset_state; /**< True if Speex state was reset */
- int buffer_margin;
+ int reset_state; /**< True if state was just reset */
+ int buffer_margin; /**< How many frames we want to keep in the buffer (lower bound) */
- int lost_count; /**< Number of lost packets */
- float shortterm_margin[MAX_MARGIN]; /**< Short term margins */
- float longterm_margin[MAX_MARGIN]; /**< Long term margins */
- float loss_rate; /**< Loss rate */
+ int lost_count; /**< Number of consecutive lost packets */
+ float shortterm_margin[MAX_MARGIN]; /**< Short term margin histogram */
+ float longterm_margin[MAX_MARGIN]; /**< Long term margin histogram */
+ float loss_rate; /**< Average loss rate */
};
/** Initialise jitter buffer */
@@ -104,6 +105,7 @@
}
/* Timestamp is actually undefined at this point */
jitter->pointer_timestamp = 0;
+ jitter->current_timestamp = 0;
jitter->reset_state = 1;
jitter->lost_count = 0;
jitter->loss_rate = 0;
@@ -132,13 +134,14 @@
{
jitter->reset_state=0;
jitter->pointer_timestamp = timestamp;
+ jitter->current_timestamp = 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] && jitter->timestamp[i] + jitter->span[i] <= jitter->pointer_timestamp)
+ 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]);
@@ -161,7 +164,7 @@
i=0;
for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
{
- if (!jitter->buf[i] || jitter->timestamp[j]<earliest)
+ if (!jitter->buf[i] || LT32(jitter->timestamp[j],earliest))
{
earliest = jitter->timestamp[j];
i=j;
@@ -183,7 +186,7 @@
jitter->len[i]=len;
/* Adjust the buffer size depending on network conditions */
- arrival_margin = (timestamp - jitter->pointer_timestamp) - jitter->buffer_margin*jitter->tick_size;
+ arrival_margin = (timestamp - jitter->current_timestamp) - jitter->buffer_margin*jitter->tick_size;
if (arrival_margin >= -LATE_BINS*jitter->tick_size)
{
@@ -238,13 +241,20 @@
int chunk_size;
int incomplete = 0;
- /*fprintf (stderr, "get packet %d\n", jitter->pointer_timestamp);*/
+ if (LT32(jitter->current_timestamp, jitter->pointer_timestamp-jitter->tick_size))
+ {
+ 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);*/
if (span && *span)
chunk_size = *span;
else
chunk_size = jitter->tick_size;
-
+
+ /* Compiling arrival statistics */
+
late_ratio_short = 0;
late_ratio_long = 0;
for (i=0;i<LATE_BINS;i++)
@@ -266,9 +276,11 @@
/*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
}
- /* If too many packets are arriving late */
+ /* 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--)
@@ -279,6 +291,8 @@
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)
{
@@ -293,14 +307,18 @@
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 && jitter->timestamp[i]+jitter->span[i]>=jitter->pointer_timestamp+chunk_size)
+ if (jitter->buf[i] && jitter->timestamp[i]==jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
break;
}
@@ -309,7 +327,7 @@
{
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
- if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && jitter->timestamp[i]+jitter->span[i]>=jitter->pointer_timestamp+chunk_size)
+ if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
break;
}
}
@@ -319,7 +337,7 @@
{
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
- if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && jitter->timestamp[i]+jitter->span[i]>jitter->pointer_timestamp)
+ if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp))
break;
}
}
@@ -334,9 +352,9 @@
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
/* check if packet starts within current chunk */
- if (jitter->buf[i] && jitter->timestamp[i]<jitter->pointer_timestamp+chunk_size && jitter->timestamp[i]>=jitter->pointer_timestamp)
+ if (jitter->buf[i] && LT32(jitter->timestamp[i],jitter->pointer_timestamp+chunk_size) && GE32(jitter->timestamp[i],jitter->pointer_timestamp))
{
- if (!found || jitter->timestamp[i]<best_time || (jitter->timestamp[i]==best_time && jitter->span[i]>best_span))
+ 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];
@@ -385,7 +403,7 @@
}
- /* If nothing */
+ /* If we haven't found anything worth returning */
/*fprintf (stderr, "not found\n");*/
jitter->lost_count++;
/*fprintf (stderr, "m");*/
@@ -411,7 +429,7 @@
void jitter_buffer_tick(JitterBuffer *jitter)
{
- jitter->pointer_timestamp += jitter->tick_size;
+ jitter->current_timestamp += jitter->tick_size;
}
More information about the commits
mailing list