[xiph-commits] r14086 - in trunk/speex: include/speex libspeex
jm at svn.xiph.org
jm at svn.xiph.org
Fri Nov 2 00:01:26 PDT 2007
Author: jm
Date: 2007-11-02 00:01:25 -0700 (Fri, 02 Nov 2007)
New Revision: 14086
Modified:
trunk/speex/include/speex/speex_jitter.h
trunk/speex/libspeex/jitter.c
Log:
jitter buffer: First attempt at using the application's bufer status and
timing estimation on the get() side.
Modified: trunk/speex/include/speex/speex_jitter.h
===================================================================
--- trunk/speex/include/speex/speex_jitter.h 2007-11-01 21:27:27 UTC (rev 14085)
+++ trunk/speex/include/speex/speex_jitter.h 2007-11-02 07:01:25 UTC (rev 14086)
@@ -159,6 +159,12 @@
*/
void jitter_buffer_tick(JitterBuffer *jitter);
+/** Telling the jitter buffer about the remaining data in the application buffer
+ * @param jitter Jitter buffer state
+ * @param rem Amount of data buffered by the application (timestamp units)
+ */
+void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem);
+
/** Used like the ioctl function to control the jitter buffer parameters
*
* @param jitter Jitter buffer state
Modified: trunk/speex/libspeex/jitter.c
===================================================================
--- trunk/speex/libspeex/jitter.c 2007-11-01 21:27:27 UTC (rev 14085)
+++ trunk/speex/libspeex/jitter.c 2007-11-02 07:01:25 UTC (rev 14086)
@@ -53,8 +53,8 @@
#define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */
+#define TSUB(a,b) ((spx_int32_t)((a)-(b)))
-
#define GT32(a,b) (((spx_int32_t)((a)-(b)))>0)
#define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0)
#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
@@ -65,8 +65,10 @@
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) */
spx_uint32_t last_returned_timestamp;
+ spx_uint32_t next_stop;
JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
+ spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
void (*destroy) (void *); /**< Callback for destroying a packet */
@@ -121,6 +123,7 @@
/* Timestamp is actually undefined at this point */
jitter->pointer_timestamp = 0;
jitter->current_timestamp = 0;
+ jitter->next_stop = 0;
jitter->reset_state = 1;
jitter->lost_count = 0;
jitter->loss_rate = 0;
@@ -139,18 +142,56 @@
speex_free(jitter);
}
+void update_histogram(JitterBuffer *jitter, spx_int32_t arrival_margin)
+{
+ int i;
+ if (arrival_margin >= -jitter->late_cutoff)
+ {
+ /* Here we compute the histogram based on the time of arrival of the packet.
+ This is based on a (first-order) recursive average. We keep both a short-term
+ histogram and a long-term histogram */
+ spx_int32_t int_margin;
+ /* First, apply the "damping" of the recursive average to all bins */
+ for (i=0;i<MAX_MARGIN;i++)
+ {
+ jitter->shortterm_margin[i] *= .98;
+ jitter->longterm_margin[i] *= .995;
+ }
+ /* What histogram bin the packet should be counted in */
+ int_margin = LATE_BINS + arrival_margin;
+ if (int_margin>MAX_MARGIN-1)
+ int_margin = MAX_MARGIN-1;
+ if (int_margin<0)
+ int_margin = 0;
+ /* Add the packet to the right bin */
+ jitter->shortterm_margin[int_margin] += .02;
+ jitter->longterm_margin[int_margin] += .005;
+ } else {
+ /* Packet has arrived *way* too late, we pretty much consider it lost and not take it into account in the histogram */
+ /*fprintf (stderr, "way too late = %d\n", arrival_margin);*/
+ if (jitter->lost_count>20)
+ {
+ jitter_buffer_reset(jitter);
+ }
+ }
+}
+
/** Put one packet into the jitter buffer */
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
{
int i,j;
+ int late;
spx_int32_t arrival_margin;
spx_int32_t arrival_time;
/*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
+
+ /* Syncing on the first packet to arrive */
if (jitter->reset_state)
{
jitter->reset_state=0;
jitter->pointer_timestamp = packet->timestamp;
jitter->current_timestamp = packet->timestamp;
+ jitter->next_stop = packet->timestamp;
/*fprintf(stderr, "reset to %d\n", timestamp);*/
}
@@ -169,107 +210,79 @@
}
}
- /*Find an empty slot in the buffer*/
- for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
+ 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 (LT32(packet->timestamp, jitter->next_stop))
{
- if (jitter->packets[i].data==NULL)
- break;
+ fprintf(stderr, "late by %d\n", jitter->next_stop - packet->timestamp);
+
+ /* The arrival margin is how much in advance (or in this case late) the packet it (in resolution units) */
+ arrival_margin = (((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop))/jitter->resolution - jitter->buffer_margin;
+
+ fprintf(stderr, "put arrival_margin = %d\n", arrival_margin);
+
+ update_histogram(jitter, arrival_margin);
+ late = 1;
+ } else {
+ late = 0;
}
+
+ /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
+ if (GE32(packet->timestamp+packet->span, jitter->pointer_timestamp))
+ {
- /*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->packets[0].timestamp;
- i=0;
- for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
+ /*Find an empty slot in the buffer*/
+ for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
- if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp,earliest))
+ 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++)
{
- earliest = jitter->packets[j].timestamp;
- i=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;
+ 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 */
if (jitter->destroy)
- jitter->destroy(jitter->packets[i].data);
- else
- speex_free(jitter->packets[i].data);
- jitter->packets[i].data=NULL;
- if (jitter->lost_count>20)
{
- jitter_buffer_reset(jitter);
+ jitter->packets[i].data = packet->data;
+ } else {
+ jitter->packets[i].data=(char*)speex_alloc(packet->len);
+ for (j=0;j<packet->len;j++)
+ jitter->packets[i].data[j]=packet->data[j];
}
- /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
+ jitter->packets[i].timestamp=packet->timestamp;
+ jitter->packets[i].span=packet->span;
+ jitter->packets[i].len=packet->len;
+ jitter->packets[i].user_data=packet->user_data;
+ if (late)
+ jitter->arrival[i] = 0;
+ else
+ jitter->arrival[i] = jitter->next_stop;
}
- /* 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<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].user_data=packet->user_data;
- if (jitter->sub_clock == -1)
- arrival_time = jitter->pointer_timestamp;
- else
- arrival_time = jitter->current_timestamp + jitter->sub_clock;
-
- if (jitter->current_timestamp + jitter->sub_clock > jitter->pointer_timestamp)
- speex_warning("something's wrong with the time");
-
- /* Adjust the buffer size depending on network conditions.
- The arrival margin is how much in advance (or late) the packet it */
- /* FIXME: We might be one tick off in considering what's late */
- arrival_margin = (((spx_int32_t)packet->timestamp) - ((spx_int32_t)arrival_time))/jitter->resolution - jitter->buffer_margin;
-
- if (arrival_margin >= -jitter->late_cutoff)
- {
- /* Here we compute the histogram based on the time of arrival of the packet.
- This is based on a (first-order) recursive average. We keep both a short-term
- histogram and a long-term histogram */
- spx_int32_t int_margin;
- /* First, apply the "damping" of the recursive average to all bins */
- for (i=0;i<MAX_MARGIN;i++)
- {
- jitter->shortterm_margin[i] *= .98;
- jitter->longterm_margin[i] *= .995;
- }
- /* What histogram bin the packet should be counted in */
- int_margin = LATE_BINS + arrival_margin;
- if (int_margin>MAX_MARGIN-1)
- int_margin = MAX_MARGIN-1;
- if (int_margin<0)
- int_margin = 0;
- /* Add the packet to the right bin */
- jitter->shortterm_margin[int_margin] += .02;
- jitter->longterm_margin[int_margin] += .005;
- } else {
- /* Packet has arrived *way* too late, we pretty much consider it lost and not take it into account in the histogram */
- /*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
}
/** Get one packet from the jitter buffer */
@@ -301,6 +314,8 @@
packet->span = jitter->delay_step;
jitter->pointer_timestamp += jitter->delay_step;
packet->len = 0;
+ fprintf (stderr, "Deferred interpolate\n");
+
return JITTER_BUFFER_MISSING;
}
/*fprintf (stderr, "get packet %d %d\n", jitter->pointer_timestamp, jitter->current_timestamp);*/
@@ -393,10 +408,29 @@
/* 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 */
+
+ /* In this case, 0 isn't as a valid timestamp */
+ if (jitter->arrival[i] != 0)
+ {
+ spx_int32_t arrival_margin;
+ fprintf(stderr, "early by %d\n", jitter->packets[i].timestamp - jitter->arrival[i]);
+
+ /* The arrival margin is how much in advance (or in this case late) the packet it (in resolution units) */
+ arrival_margin = (((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]))/jitter->resolution - jitter->buffer_margin;
+
+ fprintf(stderr, "get arrival_margin = %d\n", arrival_margin);
+
+ update_histogram(jitter, arrival_margin);
+
+ }
+
+
+ /* FIXME: Check for potential overflow */
packet->len = jitter->packets[i].len;
/* Copy packet */
if (jitter->destroy)
@@ -420,6 +454,7 @@
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;
+
if (incomplete)
return JITTER_BUFFER_INCOMPLETE;
else
@@ -456,6 +491,8 @@
jitter->longterm_margin[0] = 0;
jitter->pointer_timestamp -= jitter->delay_step;
jitter->current_timestamp -= jitter->delay_step;
+ fprintf (stderr, "Forced to interpolate\n");
+
/*fprintf (stderr, "i");*/
/*fprintf (stderr, "interpolate (getting some slack)\n");*/
}
@@ -509,8 +546,14 @@
if (jitter->sub_clock == -1)
jitter->sub_clock = 0;
jitter->sub_clock += jitter->resolution;
+ jitter->next_stop = jitter->pointer_timestamp;
}
+void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
+{
+ jitter->next_stop = jitter->pointer_timestamp - rem;
+}
+
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
{
@@ -560,6 +603,7 @@
jitter->pointer_timestamp -= jitter->delay_step;
jitter->current_timestamp -= jitter->delay_step;
jitter->interp_requested = 1;
+ fprintf (stderr, "Decision to interpolate\n");
return JITTER_BUFFER_ADJUST_INTERPOLATE;
} else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8)
@@ -578,6 +622,7 @@
/*fprintf (stderr, "d");*/
jitter->pointer_timestamp += jitter->delay_step;
jitter->current_timestamp += jitter->delay_step;
+ fprintf (stderr, "Decision to drop\n");
return JITTER_BUFFER_ADJUST_DROP;
}
More information about the commits
mailing list