trying some ideas for soft-decision DTD based on residual-to-signal ratio
[speexdsp.git] / libspeex / jitter.c
1 /* 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
51 void 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 = 1000*jitter->frame_size / sampling_rate;
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
75 void speex_jitter_destroy(SpeexJitter *jitter)
76 {
77 }
78
79
80 void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp)
81 {
82    int i,j;
83    int arrival_margin;
84
85    if (jitter->reset_state)
86    {
87       jitter->reset_state=0;
88       jitter->pointer_timestamp = timestamp-jitter->frame_time * jitter->buffer_size;
89       for (i=0;i<MAX_MARGIN;i++)
90       {
91          jitter->shortterm_margin[i] = 0;
92          jitter->longterm_margin[i] = 0;
93       }
94       for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
95       {
96          jitter->len[i]=-1;
97          jitter->timestamp[i]=-1;
98       }
99       fprintf(stderr, "reset to %d\n", timestamp);
100    }
101    
102    /* Cleanup buffer (remove old packets that weren't played) */
103    for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
104    {
105       if (jitter->timestamp[i]<jitter->pointer_timestamp)
106       {
107          jitter->len[i]=-1;
108          /*if (jitter->timestamp[i] != -1)
109             fprintf (stderr, "discarding %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp);*/
110       }
111    }
112
113    /*Find an empty slot in the buffer*/
114    for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
115    {
116       if (jitter->len[i]==-1)
117          break;
118    }
119
120    /*fprintf(stderr, "%d %d %f\n", timestamp, jitter->pointer_timestamp, jitter->drift_average);*/
121    if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
122    {
123       int earliest=jitter->timestamp[0];
124       i=0;
125       for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
126       {
127          if (jitter->timestamp[j]<earliest)
128          {
129             earliest = jitter->timestamp[j];
130             i=j;
131          }
132       }
133       /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
134       /*No place left in the buffer*/
135       
136       /*skip some frame(s) */
137       /*return;*/
138    }
139    
140    /* Copy packet in buffer */
141    if (len>SPEEX_JITTER_MAX_PACKET_SIZE)
142       len=SPEEX_JITTER_MAX_PACKET_SIZE;
143    for (j=0;j<len/BYTES_PER_CHAR;j++)
144       jitter->buf[i][j]=packet[j];
145    jitter->timestamp[i]=timestamp;
146    jitter->len[i]=len;
147    
148    /* Don't count late packets when adjusting the synchro (we're taking care of them elsewhere) */
149    /*if (timestamp <= jitter->pointer_timestamp)
150    {
151       fprintf (stderr, "frame for timestamp %d arrived too late (at time %d)\n", timestamp, jitter->pointer_timestamp);
152    }*/
153
154    /* Adjust the buffer size depending on network conditions */
155    arrival_margin = (timestamp - jitter->pointer_timestamp - jitter->frame_time);
156    
157    if (arrival_margin >= -LATE_BINS*jitter->frame_time)
158    {
159       int int_margin;
160       for (i=0;i<MAX_MARGIN;i++)
161       {
162          jitter->shortterm_margin[i] *= .98;
163          jitter->longterm_margin[i] *= .995;
164       }
165       int_margin = (arrival_margin + LATE_BINS*jitter->frame_time)/jitter->frame_time;
166       if (int_margin>MAX_MARGIN-1)
167          int_margin = MAX_MARGIN-1;
168       if (int_margin>=0)
169       {
170          jitter->shortterm_margin[int_margin] += .02;
171          jitter->longterm_margin[int_margin] += .005;
172       }
173    }
174    
175    /*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);*/
176 }
177
178 void speex_jitter_get(SpeexJitter *jitter, short *out, int *current_timestamp)
179 {
180    int i;
181    int ret;
182    float late_ratio_short;
183    float late_ratio_long;
184    float ontime_ratio_short;
185    float ontime_ratio_long;
186    float early_ratio_short;
187    float early_ratio_long;
188    
189    late_ratio_short = 0;
190    late_ratio_long = 0;
191    for (i=0;i<LATE_BINS;i++)
192    {
193       late_ratio_short += jitter->shortterm_margin[i];
194       late_ratio_long += jitter->longterm_margin[i];
195    }
196    ontime_ratio_short = jitter->shortterm_margin[LATE_BINS];
197    ontime_ratio_long = jitter->longterm_margin[LATE_BINS];
198    early_ratio_short = early_ratio_long = 0;
199    for (i=LATE_BINS+1;i<MAX_MARGIN;i++)
200    {
201       early_ratio_short += jitter->shortterm_margin[i];
202       early_ratio_long += jitter->longterm_margin[i];
203    }
204    if (0&&jitter->pointer_timestamp%1000==0)
205    {
206       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);
207       /*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
208    }
209    
210    if (late_ratio_short > .1 || late_ratio_long > .03)
211    {
212       jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
213       jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2];
214       for (i=MAX_MARGIN-2;i>=0;i--)
215       {
216          jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i];
217          jitter->longterm_margin[i+1] = jitter->longterm_margin[i];         
218       }
219       jitter->shortterm_margin[0] = 0;
220       jitter->longterm_margin[0] = 0;            
221       /*fprintf (stderr, "interpolate frame\n");*/
222       speex_decode_int(jitter->dec, NULL, out);
223       if (current_timestamp)
224          *current_timestamp = jitter->pointer_timestamp;
225       return;
226    }
227    
228    /* Increment timestamp */
229    jitter->pointer_timestamp += jitter->frame_time;
230    
231    if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8)
232    {
233       jitter->shortterm_margin[0] += jitter->shortterm_margin[1];
234       jitter->longterm_margin[0] += jitter->longterm_margin[1];
235       for (i=1;i<MAX_MARGIN-1;i++)
236       {
237          jitter->shortterm_margin[i] = jitter->shortterm_margin[i+1];
238          jitter->longterm_margin[i] = jitter->longterm_margin[i+1];         
239       }
240       jitter->shortterm_margin[MAX_MARGIN-1] = 0;
241       jitter->longterm_margin[MAX_MARGIN-1] = 0;      
242       /*fprintf (stderr, "drop frame\n");*/
243       jitter->pointer_timestamp += jitter->frame_time;
244    }
245
246    if (current_timestamp)
247       *current_timestamp = jitter->pointer_timestamp;
248
249    /* Send zeros while we fill in the buffer */
250    if (jitter->pointer_timestamp<0)
251    {
252       for (i=0;i<jitter->frame_size;i++)
253          out[i]=0;
254       return;
255    }
256    
257    /* Search the buffer for a packet with the right timestamp */
258    for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
259    {
260       if (jitter->len[i]!=-1 && jitter->timestamp[i]==jitter->pointer_timestamp)
261          break;
262    }
263    
264    if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
265    {
266       /* No packet found */
267       if (jitter->valid_bits)
268       {
269          /* Try decoding last received packet */
270          ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
271          if (ret == 0)
272          {
273             jitter->lost_count = 0;
274             return;
275          } else {
276             jitter->valid_bits = 0;
277          }
278       }
279
280       /*fprintf (stderr, "lost/late frame %d\n", jitter->pointer_timestamp);*/
281       /*Packet is late or lost*/
282       speex_decode_int(jitter->dec, NULL, out);
283       jitter->lost_count++;
284       if (jitter->lost_count>=25)
285       {
286          jitter->lost_count = 0;
287          jitter->reset_state = 1;
288          speex_decoder_ctl(jitter->dec, SPEEX_RESET_STATE, NULL);
289       }
290       jitter->loss_rate = .999*jitter->loss_rate + .001;
291    } else {
292       jitter->lost_count = 0;
293       /* Found the right packet */
294       speex_bits_read_from(&jitter->current_packet, jitter->buf[i], jitter->len[i]);
295       jitter->len[i]=-1;
296       /* Decode packet */
297       ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
298       if (ret == 0)
299       {
300          jitter->valid_bits = 1;
301       } else {
302          /* Error while decoding */
303          for (i=0;i<jitter->frame_size;i++)
304             out[i]=0;
305       }
306       jitter->loss_rate = .999*jitter->loss_rate;
307    }
308
309
310 }
311
312 int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter)
313 {
314    return jitter->pointer_timestamp;
315 }