1
/* Copyright (C) 2002 Jean-Marc Valin
4
Adaptive jitter buffer for Speex
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
10
- Redistributions of source code must retain the above copyright
11
notice, this list of conditions and the following disclaimer.
13
- Redistributions in binary form must reproduce the above copyright
14
notice, this list of conditions and the following disclaimer in the
15
documentation and/or other materials provided with the distribution.
17
- Neither the name of the Xiph.org Foundation nor the names of its
18
contributors may be used to endorse or promote products derived from
19
this software without specific prior written permission.
21
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
- Add short-term estimate
38
- Defensive programming
39
+ warn when last returned < last desired (begative buffering)
40
+ warn if update_delay not called between get() and tick() or is called twice in a row
41
- Linked list structure for holding the packets instead of the current fixed-size array
42
+ return memory to a pool
43
+ allow pre-allocation of the pool
44
+ optional max number of elements
58
#include <speex/speex.h>
59
#include <speex/speex_bits.h>
60
#include <speex/speex_jitter.h>
61
#include "os_support.h"
67
#define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */
69
#define TSUB(a,b) ((spx_int32_t)((a)-(b)))
71
#define GT32(a,b) (((spx_int32_t)((a)-(b)))>0)
72
#define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0)
73
#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
74
#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
76
#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
78
#define MAX_TIMINGS 40
82
/** Buffer that keeps the time of arrival of the latest packets */
84
int filled; /**< Number of entries occupied in "timing" and "counts"*/
85
int curr_count; /**< Number of packet timings we got (including those we discarded) */
86
spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */
87
spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */
90
static void tb_init(struct TimingBuffer *tb)
96
/* Add the timing of a new packet to the TimingBuffer */
97
static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
100
/* Discard packet that won't make it into the list because they're too early */
101
if (tb->filled >= MAX_TIMINGS && timing >= tb->timing[tb->filled-1])
107
/* Find where the timing info goes in the sorted list */
109
/* FIXME: Do bisection instead of linear search */
110
while (pos<tb->filled && timing >= tb->timing[pos])
115
speex_assert(pos <= tb->filled && pos < MAX_TIMINGS);
117
/* Shift everything so we can perform the insertion */
118
if (pos < tb->filled)
120
int move_size = tb->filled-pos;
121
if (tb->filled == MAX_TIMINGS)
123
SPEEX_MOVE(&tb->timing[pos+1], &tb->timing[pos], move_size);
124
SPEEX_MOVE(&tb->counts[pos+1], &tb->counts[pos], move_size);
127
tb->timing[pos] = timing;
128
tb->counts[pos] = tb->curr_count;
131
if (tb->filled<MAX_TIMINGS)
137
/** Jitter buffer structure */
138
struct JitterBuffer_ {
139
spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
140
spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */
141
spx_uint32_t next_stop; /**< Estimated time the next get() will be called */
143
spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/
145
JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
146
spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
148
void (*destroy) (void *); /**< Callback for destroying a packet */
150
spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */
151
spx_int32_t concealment_size; /**< Size of the packet loss concealment "units" */
152
int reset_state; /**< True if state was just reset */
153
int buffer_margin; /**< How many frames we want to keep in the buffer (lower bound) */
154
int late_cutoff; /**< How late must a packet be for it not to be considered at all */
155
int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */
156
int auto_adjust; /**< Whether to automatically adjust the delay at any time */
158
struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */
159
struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */
160
int window_size; /**< Total window over which the late frames are counted */
161
int subwindow_size; /**< Sub-window size for faster computation */
162
int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */
163
int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */
164
int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */
166
int lost_count; /**< Number of consecutive lost packets */
169
/** Based on available data, this computes the optimal delay for the jitter buffer.
170
The optimised function is in timestamp units and is:
171
cost = delay + late_factor*[number of frames that would be late if we used that delay]
172
@param tb Array of buffers
173
@param late_factor Equivalent cost of a late frame (in timestamp units)
175
static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
179
spx_int32_t best_cost=0x7fffffff;
181
int pos[MAX_BUFFERS];
184
int penalty_taken = 0;
188
struct TimingBuffer *tb;
192
/* Number of packet timings we have received (including those we didn't keep) */
194
for (i=0;i<MAX_BUFFERS;i++)
195
tot_count += tb[i].curr_count;
199
/* Compute cost for one lost packet */
200
if (jitter->latency_tradeoff != 0)
201
late_factor = jitter->latency_tradeoff * 100.0f / tot_count;
203
late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count;
205
/*fprintf(stderr, "late_factor = %f\n", late_factor);*/
206
for (i=0;i<MAX_BUFFERS;i++)
209
/* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late
210
for the current settings) */
211
for (i=0;i<TOP_DELAY;i++)
216
/* Pick latest amoung all sub-windows */
217
for (j=0;j<MAX_BUFFERS;j++)
219
if (pos[j] < tb[j].filled && tb[j].timing[pos[j]] < latest)
222
latest = tb[j].timing[pos[j]];
232
latest = ROUND_DOWN(latest, jitter->delay_step);
235
/* Actual cost function that tells us how bad using this delay would be */
236
cost = -latest + late_factor*late;
237
/*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/
238
if (cost < best_cost)
247
/* For the next timing we will consider, there will be one more late packet to count */
249
/* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */
250
if (latest >= 0 && !penalty_taken)
258
/* This is a default "automatic latency tradeoff" when none is provided */
259
jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY;
260
/*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/
262
/* FIXME: Compute a short-term estimate too and combine with the long-term one */
264
/* Prevents reducing the buffer size when we haven't really had much data */
265
if (tot_count < TOP_DELAY && opt > 0)
271
/** Initialise jitter buffer */
272
EXPORT JitterBuffer *jitter_buffer_init(int step_size)
274
JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
279
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
280
jitter->packets[i].data=NULL;
281
jitter->delay_step = step_size;
282
jitter->concealment_size = step_size;
283
/*FIXME: Should this be 0 or 1?*/
284
jitter->buffer_margin = 0;
285
jitter->late_cutoff = 50;
286
jitter->destroy = NULL;
287
jitter->latency_tradeoff = 0;
288
jitter->auto_adjust = 1;
290
jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp);
291
jitter_buffer_reset(jitter);
296
/** Reset jitter buffer */
297
EXPORT void jitter_buffer_reset(JitterBuffer *jitter)
300
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
302
if (jitter->packets[i].data)
305
jitter->destroy(jitter->packets[i].data);
307
speex_free(jitter->packets[i].data);
308
jitter->packets[i].data = NULL;
311
/* Timestamp is actually undefined at this point */
312
jitter->pointer_timestamp = 0;
313
jitter->next_stop = 0;
314
jitter->reset_state = 1;
315
jitter->lost_count = 0;
316
jitter->buffered = 0;
317
jitter->auto_tradeoff = 32000;
319
for (i=0;i<MAX_BUFFERS;i++)
321
tb_init(&jitter->_tb[i]);
322
jitter->timeBuffers[i] = &jitter->_tb[i];
324
/*fprintf (stderr, "reset\n");*/
327
/** Destroy jitter buffer */
328
EXPORT void jitter_buffer_destroy(JitterBuffer *jitter)
330
jitter_buffer_reset(jitter);
334
/** Take the following timing into consideration for future calculations */
335
static void update_timings(JitterBuffer *jitter, spx_int32_t timing)
341
/* If the current sub-window is full, perform a rotation and discard oldest sub-widow */
342
if (jitter->timeBuffers[0]->curr_count >= jitter->subwindow_size)
345
/*fprintf(stderr, "Rotate buffer\n");*/
346
struct TimingBuffer *tmp = jitter->timeBuffers[MAX_BUFFERS-1];
347
for (i=MAX_BUFFERS-1;i>=1;i--)
348
jitter->timeBuffers[i] = jitter->timeBuffers[i-1];
349
jitter->timeBuffers[0] = tmp;
350
tb_init(jitter->timeBuffers[0]);
352
tb_add(jitter->timeBuffers[0], timing);
355
/** Compensate all timings when we do an adjustment of the buffering */
356
static void shift_timings(JitterBuffer *jitter, spx_int16_t amount)
359
for (i=0;i<MAX_BUFFERS;i++)
361
for (j=0;j<jitter->timeBuffers[i]->filled;j++)
362
jitter->timeBuffers[i]->timing[j] += amount;
367
/** Put one packet into the jitter buffer */
368
EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
372
/*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
374
/* Cleanup buffer (remove old packets that weren't played) */
375
if (!jitter->reset_state)
377
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
379
/* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */
380
if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp))
382
/*fprintf (stderr, "cleaned (not played)\n");*/
384
jitter->destroy(jitter->packets[i].data);
386
speex_free(jitter->packets[i].data);
387
jitter->packets[i].data = NULL;
392
/*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/
393
/* Check if packet is late (could still be useful though) */
394
if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop))
396
update_timings(jitter, ((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop) - jitter->buffer_margin);
402
/* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is
404
if (jitter->lost_count>20)
406
jitter_buffer_reset(jitter);
409
/* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
410
if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
413
/*Find an empty slot in the buffer*/
414
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
416
if (jitter->packets[i].data==NULL)
420
/*No place left in the buffer, need to make room for it by discarding the oldest packet */
421
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
423
int earliest=jitter->packets[0].timestamp;
425
for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
427
if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp,earliest))
429
earliest = jitter->packets[j].timestamp;
434
jitter->destroy(jitter->packets[i].data);
436
speex_free(jitter->packets[i].data);
437
jitter->packets[i].data=NULL;
438
/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
441
/* Copy packet in buffer */
444
jitter->packets[i].data = packet->data;
446
jitter->packets[i].data=(char*)speex_alloc(packet->len);
447
for (j=0;j<packet->len;j++)
448
jitter->packets[i].data[j]=packet->data[j];
450
jitter->packets[i].timestamp=packet->timestamp;
451
jitter->packets[i].span=packet->span;
452
jitter->packets[i].len=packet->len;
453
jitter->packets[i].sequence=packet->sequence;
454
jitter->packets[i].user_data=packet->user_data;
455
if (jitter->reset_state || late)
456
jitter->arrival[i] = 0;
458
jitter->arrival[i] = jitter->next_stop;
464
/** Get one packet from the jitter buffer */
465
EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset)
472
if (start_offset != NULL)
475
/* Syncing on the first call */
476
if (jitter->reset_state)
479
/* Find the oldest packet */
480
spx_uint32_t oldest=0;
481
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
483
if (jitter->packets[i].data && (!found || LT32(jitter->packets[i].timestamp,oldest)))
485
oldest = jitter->packets[i].timestamp;
491
jitter->reset_state=0;
492
jitter->pointer_timestamp = oldest;
493
jitter->next_stop = oldest;
495
packet->timestamp = 0;
496
packet->span = jitter->interp_requested;
497
return JITTER_BUFFER_MISSING;
502
jitter->last_returned_timestamp = jitter->pointer_timestamp;
504
if (jitter->interp_requested != 0)
506
packet->timestamp = jitter->pointer_timestamp;
507
packet->span = jitter->interp_requested;
509
/* Increment the pointer because it got decremented in the delay update */
510
jitter->pointer_timestamp += jitter->interp_requested;
512
/*fprintf (stderr, "Deferred interpolate\n");*/
514
jitter->interp_requested = 0;
516
jitter->buffered = packet->span - desired_span;
518
return JITTER_BUFFER_INSERTION;
521
/* Searching for the packet that fits best */
523
/* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
524
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
526
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))
530
/* If no match, try for an "older" packet that still spans (fully) the current chunk */
531
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
533
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
535
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))
540
/* If still no match, try for an "older" packet that spans part of the current chunk */
541
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
543
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
545
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))
550
/* If still no match, try for earliest packet possible */
551
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
554
spx_uint32_t best_time=0;
557
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
559
/* check if packet starts within current chunk */
560
if (jitter->packets[i].data && LT32(jitter->packets[i].timestamp,jitter->pointer_timestamp+desired_span) && GE32(jitter->packets[i].timestamp,jitter->pointer_timestamp))
562
if (!found || LT32(jitter->packets[i].timestamp,best_time) || (jitter->packets[i].timestamp==best_time && GT32(jitter->packets[i].span,best_span)))
564
best_time = jitter->packets[i].timestamp;
565
best_span = jitter->packets[i].span;
575
/*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/
579
/* If we find something */
580
if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
584
/* We (obviously) haven't lost this packet */
585
jitter->lost_count = 0;
587
/* In this case, 0 isn't as a valid timestamp */
588
if (jitter->arrival[i] != 0)
590
update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin);
597
packet->data = jitter->packets[i].data;
598
packet->len = jitter->packets[i].len;
600
if (jitter->packets[i].len > packet->len)
602
speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len);
604
packet->len = jitter->packets[i].len;
606
for (j=0;j<packet->len;j++)
607
packet->data[j] = jitter->packets[i].data[j];
609
speex_free(jitter->packets[i].data);
611
jitter->packets[i].data = NULL;
612
/* Set timestamp and span (if requested) */
613
offset = (spx_int32_t)jitter->packets[i].timestamp-(spx_int32_t)jitter->pointer_timestamp;
614
if (start_offset != NULL)
615
*start_offset = offset;
616
else if (offset != 0)
617
speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset);
619
packet->timestamp = jitter->packets[i].timestamp;
620
jitter->last_returned_timestamp = packet->timestamp;
622
packet->span = jitter->packets[i].span;
623
packet->sequence = jitter->packets[i].sequence;
624
packet->user_data = jitter->packets[i].user_data;
625
/* Point to the end of the current packet */
626
jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;
628
jitter->buffered = packet->span - desired_span;
630
if (start_offset != NULL)
631
jitter->buffered += *start_offset;
633
return JITTER_BUFFER_OK;
637
/* If we haven't found anything worth returning */
639
/*fprintf (stderr, "not found\n");*/
640
jitter->lost_count++;
641
/*fprintf (stderr, "m");*/
642
/*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
644
opt = compute_opt_delay(jitter);
646
/* Should we force an increase in the buffer or just do normal interpolation? */
649
/* Need to increase buffering */
651
/* Shift histogram to compensate */
652
shift_timings(jitter, -opt);
654
packet->timestamp = jitter->pointer_timestamp;
656
/* Don't move the pointer_timestamp forward */
659
jitter->buffered = packet->span - desired_span;
660
return JITTER_BUFFER_INSERTION;
661
/*jitter->pointer_timestamp -= jitter->delay_step;*/
662
/*fprintf (stderr, "Forced to interpolate\n");*/
664
/* Normal packet loss */
665
packet->timestamp = jitter->pointer_timestamp;
667
desired_span = ROUND_DOWN(desired_span, jitter->concealment_size);
668
packet->span = desired_span;
669
jitter->pointer_timestamp += desired_span;
672
jitter->buffered = packet->span - desired_span;
673
return JITTER_BUFFER_MISSING;
674
/*fprintf (stderr, "Normal loss\n");*/
680
EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet)
683
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
685
if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->last_returned_timestamp)
688
if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
691
packet->len = jitter->packets[i].len;
694
packet->data = jitter->packets[i].data;
696
for (j=0;j<packet->len;j++)
697
packet->data[j] = jitter->packets[i].data[j];
699
speex_free(jitter->packets[i].data);
701
jitter->packets[i].data = NULL;
702
packet->timestamp = jitter->packets[i].timestamp;
703
packet->span = jitter->packets[i].span;
704
packet->sequence = jitter->packets[i].sequence;
705
packet->user_data = jitter->packets[i].user_data;
706
return JITTER_BUFFER_OK;
711
return JITTER_BUFFER_MISSING;
715
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
716
static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
718
spx_int16_t opt = compute_opt_delay(jitter);
719
/*fprintf(stderr, "opt adjustment is %d ", opt);*/
723
shift_timings(jitter, -opt);
725
jitter->pointer_timestamp += opt;
726
jitter->interp_requested = -opt;
727
/*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/
730
shift_timings(jitter, -opt);
731
jitter->pointer_timestamp += opt;
732
/*fprintf (stderr, "Decision to drop %d samples\n", opt);*/
738
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
739
EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
741
/* If the programmer calls jitter_buffer_update_delay() directly,
742
automatically disable auto-adjustment */
743
jitter->auto_adjust = 0;
745
return _jitter_buffer_update_delay(jitter, packet, start_offset);
748
/** Get pointer timestamp of jitter buffer */
749
EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
751
return jitter->pointer_timestamp;
754
EXPORT void jitter_buffer_tick(JitterBuffer *jitter)
756
/* Automatically-adjust the buffering delay if requested */
757
if (jitter->auto_adjust)
758
_jitter_buffer_update_delay(jitter, NULL, NULL);
760
if (jitter->buffered >= 0)
762
jitter->next_stop = jitter->pointer_timestamp - jitter->buffered;
764
jitter->next_stop = jitter->pointer_timestamp;
765
speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);
767
jitter->buffered = 0;
770
EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
772
/* Automatically-adjust the buffering delay if requested */
773
if (jitter->auto_adjust)
774
_jitter_buffer_update_delay(jitter, NULL, NULL);
776
if (jitter->buffered < 0)
777
speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);
778
jitter->next_stop = jitter->pointer_timestamp - rem;
782
/* Used like the ioctl function to control the jitter buffer parameters */
783
EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
788
case JITTER_BUFFER_SET_MARGIN:
789
jitter->buffer_margin = *(spx_int32_t*)ptr;
791
case JITTER_BUFFER_GET_MARGIN:
792
*(spx_int32_t*)ptr = jitter->buffer_margin;
794
case JITTER_BUFFER_GET_AVALIABLE_COUNT:
796
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
798
if (jitter->packets[i].data && LE32(jitter->pointer_timestamp, jitter->packets[i].timestamp))
803
*(spx_int32_t*)ptr = count;
805
case JITTER_BUFFER_SET_DESTROY_CALLBACK:
806
jitter->destroy = (void (*) (void *))ptr;
808
case JITTER_BUFFER_GET_DESTROY_CALLBACK:
809
*(void (**) (void *))ptr = jitter->destroy;
811
case JITTER_BUFFER_SET_DELAY_STEP:
812
jitter->delay_step = *(spx_int32_t*)ptr;
814
case JITTER_BUFFER_GET_DELAY_STEP:
815
*(spx_int32_t*)ptr = jitter->delay_step;
817
case JITTER_BUFFER_SET_CONCEALMENT_SIZE:
818
jitter->concealment_size = *(spx_int32_t*)ptr;
820
case JITTER_BUFFER_GET_CONCEALMENT_SIZE:
821
*(spx_int32_t*)ptr = jitter->concealment_size;
823
case JITTER_BUFFER_SET_MAX_LATE_RATE:
824
jitter->max_late_rate = *(spx_int32_t*)ptr;
825
jitter->window_size = 100*TOP_DELAY/jitter->max_late_rate;
826
jitter->subwindow_size = jitter->window_size/MAX_BUFFERS;
828
case JITTER_BUFFER_GET_MAX_LATE_RATE:
829
*(spx_int32_t*)ptr = jitter->max_late_rate;
831
case JITTER_BUFFER_SET_LATE_COST:
832
jitter->latency_tradeoff = *(spx_int32_t*)ptr;
834
case JITTER_BUFFER_GET_LATE_COST:
835
*(spx_int32_t*)ptr = jitter->latency_tradeoff;
838
speex_warning_int("Unknown jitter_buffer_ctl request: ", request);