blob: 55a0833fa78f483b56c7eefbfebc9600c66ba192 [file] [log] [blame]
Benny Prijonoeb30bf52006-03-04 20:43:52 +00001/* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_jitter.h
3
4 Adaptive jitter buffer for Speex
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
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.
16
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.
20
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.
32
33*/
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#ifndef NULL
40#define NULL 0
41#endif
42
43#include "misc.h"
44#include <speex/speex.h>
45#include <speex/speex_bits.h>
46#include <speex/speex_jitter.h>
47#include <stdio.h>
48
49#define LATE_BINS 4
50
51void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate)
52{
53 int i;
54 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
55 {
56 jitter->len[i]=-1;
57 jitter->timestamp[i]=-1;
58 }
59
60 jitter->dec = decoder;
61 speex_decoder_ctl(decoder, SPEEX_GET_FRAME_SIZE, &jitter->frame_size);
62 jitter->frame_time = jitter->frame_size;
63
64 speex_bits_init(&jitter->current_packet);
65 jitter->valid_bits = 0;
66
67 jitter->buffer_size = 4;
68
69 jitter->pointer_timestamp = -jitter->frame_time * jitter->buffer_size;
70 jitter->reset_state = 1;
71 jitter->lost_count = 0;
72 jitter->loss_rate = 0;
73}
74
75void speex_jitter_destroy(SpeexJitter *jitter)
76{
77 speex_bits_destroy(&jitter->current_packet);
78}
79
80
81void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp)
82{
83 int i,j;
84 int arrival_margin;
85
86 if (jitter->reset_state)
87 {
88 jitter->reset_state=0;
89 jitter->pointer_timestamp = timestamp-jitter->frame_time * jitter->buffer_size;
90 for (i=0;i<MAX_MARGIN;i++)
91 {
92 jitter->shortterm_margin[i] = 0;
93 jitter->longterm_margin[i] = 0;
94 }
95 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
96 {
97 jitter->len[i]=-1;
98 jitter->timestamp[i]=-1;
99 }
100 fprintf(stderr, "reset to %d\n", timestamp);
101 }
102
103 /* Cleanup buffer (remove old packets that weren't played) */
104 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
105 {
106 if (jitter->timestamp[i]<jitter->pointer_timestamp)
107 {
108 jitter->len[i]=-1;
109 /*if (jitter->timestamp[i] != -1)
110 fprintf (stderr, "discarding %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp);*/
111 }
112 }
113
114 /*Find an empty slot in the buffer*/
115 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
116 {
117 if (jitter->len[i]==-1)
118 break;
119 }
120
121 /*fprintf(stderr, "%d %d %f\n", timestamp, jitter->pointer_timestamp, jitter->drift_average);*/
122 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
123 {
124 int earliest=jitter->timestamp[0];
125 i=0;
126 for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
127 {
128 if (jitter->timestamp[j]<earliest)
129 {
130 earliest = jitter->timestamp[j];
131 i=j;
132 }
133 }
134 /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
135 /*No place left in the buffer*/
136
137 /*skip some frame(s) */
138 /*return;*/
139 }
140
141 /* Copy packet in buffer */
142 if (len>SPEEX_JITTER_MAX_PACKET_SIZE)
143 len=SPEEX_JITTER_MAX_PACKET_SIZE;
144 for (j=0;j<len/BYTES_PER_CHAR;j++)
145 jitter->buf[i][j]=packet[j];
146 jitter->timestamp[i]=timestamp;
147 jitter->len[i]=len;
148
149 /* Don't count late packets when adjusting the synchro (we're taking care of them elsewhere) */
150 /*if (timestamp <= jitter->pointer_timestamp)
151 {
152 fprintf (stderr, "frame for timestamp %d arrived too late (at time %d)\n", timestamp, jitter->pointer_timestamp);
153 }*/
154
155 /* Adjust the buffer size depending on network conditions */
156 arrival_margin = (timestamp - jitter->pointer_timestamp - jitter->frame_time);
157
158 if (arrival_margin >= -LATE_BINS*jitter->frame_time)
159 {
160 int int_margin;
161 for (i=0;i<MAX_MARGIN;i++)
162 {
163 jitter->shortterm_margin[i] *= .98;
164 jitter->longterm_margin[i] *= .995;
165 }
166 int_margin = (arrival_margin + LATE_BINS*jitter->frame_time)/jitter->frame_time;
167 if (int_margin>MAX_MARGIN-1)
168 int_margin = MAX_MARGIN-1;
169 if (int_margin>=0)
170 {
171 jitter->shortterm_margin[int_margin] += .02;
172 jitter->longterm_margin[int_margin] += .005;
173 }
174 }
175
176 /*fprintf (stderr, "margin : %d %d %f %f %f %f\n", arrival_margin, jitter->buffer_size, 100*jitter->loss_rate, 100*jitter->late_ratio, 100*jitter->ontime_ratio, 100*jitter->early_ratio);*/
177}
178
179void speex_jitter_get(SpeexJitter *jitter, short *out, int *current_timestamp)
180{
181 int i;
182 int ret;
183 float late_ratio_short;
184 float late_ratio_long;
185 float ontime_ratio_short;
186 float ontime_ratio_long;
187 float early_ratio_short;
188 float early_ratio_long;
189
190 late_ratio_short = 0;
191 late_ratio_long = 0;
192 for (i=0;i<LATE_BINS;i++)
193 {
194 late_ratio_short += jitter->shortterm_margin[i];
195 late_ratio_long += jitter->longterm_margin[i];
196 }
197 ontime_ratio_short = jitter->shortterm_margin[LATE_BINS];
198 ontime_ratio_long = jitter->longterm_margin[LATE_BINS];
199 early_ratio_short = early_ratio_long = 0;
200 for (i=LATE_BINS+1;i<MAX_MARGIN;i++)
201 {
202 early_ratio_short += jitter->shortterm_margin[i];
203 early_ratio_long += jitter->longterm_margin[i];
204 }
205 if (0&&jitter->pointer_timestamp%1000==0)
206 {
207 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);
208 /*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
209 }
210
211 if (late_ratio_short > .1 || late_ratio_long > .03)
212 {
213 jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
214 jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2];
215 for (i=MAX_MARGIN-3;i>=0;i--)
216 {
217 jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i];
218 jitter->longterm_margin[i+1] = jitter->longterm_margin[i];
219 }
220 jitter->shortterm_margin[0] = 0;
221 jitter->longterm_margin[0] = 0;
222 /*fprintf (stderr, "interpolate frame\n");*/
223 speex_decode_int(jitter->dec, NULL, out);
224 if (current_timestamp)
225 *current_timestamp = jitter->pointer_timestamp;
226 return;
227 }
228
229 /* Increment timestamp */
230 jitter->pointer_timestamp += jitter->frame_time;
231
232 if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8)
233 {
234 jitter->shortterm_margin[0] += jitter->shortterm_margin[1];
235 jitter->longterm_margin[0] += jitter->longterm_margin[1];
236 for (i=1;i<MAX_MARGIN-1;i++)
237 {
238 jitter->shortterm_margin[i] = jitter->shortterm_margin[i+1];
239 jitter->longterm_margin[i] = jitter->longterm_margin[i+1];
240 }
241 jitter->shortterm_margin[MAX_MARGIN-1] = 0;
242 jitter->longterm_margin[MAX_MARGIN-1] = 0;
243 /*fprintf (stderr, "drop frame\n");*/
244 jitter->pointer_timestamp += jitter->frame_time;
245 }
246
247 if (current_timestamp)
248 *current_timestamp = jitter->pointer_timestamp;
249
250 /* Send zeros while we fill in the buffer */
251 if (jitter->pointer_timestamp<0)
252 {
253 for (i=0;i<jitter->frame_size;i++)
254 out[i]=0;
255 return;
256 }
257
258 /* Search the buffer for a packet with the right timestamp */
259 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
260 {
261 if (jitter->len[i]!=-1 && jitter->timestamp[i]==jitter->pointer_timestamp)
262 break;
263 }
264
265 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
266 {
267 /* No packet found */
268 if (jitter->valid_bits)
269 {
270 /* Try decoding last received packet */
271 ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
272 if (ret == 0)
273 {
274 jitter->lost_count = 0;
275 return;
276 } else {
277 jitter->valid_bits = 0;
278 }
279 }
280
281 /*fprintf (stderr, "lost/late frame %d\n", jitter->pointer_timestamp);*/
282 /*Packet is late or lost*/
283 speex_decode_int(jitter->dec, NULL, out);
284 jitter->lost_count++;
285 if (jitter->lost_count>=25)
286 {
287 jitter->lost_count = 0;
288 jitter->reset_state = 1;
289 speex_decoder_ctl(jitter->dec, SPEEX_RESET_STATE, NULL);
290 }
291 jitter->loss_rate = .999*jitter->loss_rate + .001;
292 } else {
293 jitter->lost_count = 0;
294 /* Found the right packet */
295 speex_bits_read_from(&jitter->current_packet, jitter->buf[i], jitter->len[i]);
296 jitter->len[i]=-1;
297 /* Decode packet */
298 ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
299 if (ret == 0)
300 {
301 jitter->valid_bits = 1;
302 } else {
303 /* Error while decoding */
304 for (i=0;i<jitter->frame_size;i++)
305 out[i]=0;
306 }
307 jitter->loss_rate = .999*jitter->loss_rate;
308 }
309
310
311}
312
313int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter)
314{
315 return jitter->pointer_timestamp;
316}