remove a bunch of useless #include "options.h"
[asterisk/asterisk.git] / main / abstract_jb.c
1 /*
2  * abstract_jb: common implementation-independent jitterbuffer stuff
3  *
4  * Copyright (C) 2005, Attractel OOD
5  *
6  * Contributors:
7  * Slav Klenov <slav@securax.org>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  *
19  * A license has been granted to Digium (via disclaimer) for the use of
20  * this code.
21  */
22
23 /*! \file
24  *
25  * \brief Common implementation-independent jitterbuffer stuff.
26  * 
27  * \author Slav Klenov <slav@securax.org>
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/frame.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/term.h"
37 #include "asterisk/utils.h"
38
39 #include "asterisk/abstract_jb.h"
40 #include "fixedjitterbuf.h"
41 #include "jitterbuf.h"
42
43 /*! Internal jb flags */
44 enum {
45         JB_USE =                  (1 << 0),
46         JB_TIMEBASE_INITIALIZED = (1 << 1),
47         JB_CREATED =              (1 << 2)
48 };
49
50 /* Hooks for the abstract jb implementation */
51
52 /*! \brief Create */
53 typedef void * (*jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold);
54 /*! \brief Destroy */
55 typedef void (*jb_destroy_impl)(void *jb);
56 /*! \brief Put first frame */
57 typedef int (*jb_put_first_impl)(void *jb, struct ast_frame *fin, long now);
58 /*! \brief Put frame */
59 typedef int (*jb_put_impl)(void *jb, struct ast_frame *fin, long now);
60 /*! \brief Get frame for now */
61 typedef int (*jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl);
62 /*! \brief Get next */
63 typedef long (*jb_next_impl)(void *jb);
64 /*! \brief Remove first frame */
65 typedef int (*jb_remove_impl)(void *jb, struct ast_frame **fout);
66 /*! \brief Force resynch */
67 typedef void (*jb_force_resynch_impl)(void *jb);
68
69
70 /*!
71  * \brief Jitterbuffer implementation private struct.
72  */
73 struct ast_jb_impl
74 {
75         char name[AST_JB_IMPL_NAME_SIZE];
76         jb_create_impl create;
77         jb_destroy_impl destroy;
78         jb_put_first_impl put_first;
79         jb_put_impl put;
80         jb_get_impl get;
81         jb_next_impl next;
82         jb_remove_impl remove;
83         jb_force_resynch_impl force_resync;
84 };
85
86 /* Implementation functions */
87 /* fixed */
88 static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold);
89 static void jb_destroy_fixed(void *jb);
90 static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now);
91 static int jb_put_fixed(void *jb, struct ast_frame *fin, long now);
92 static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl);
93 static long jb_next_fixed(void *jb);
94 static int jb_remove_fixed(void *jb, struct ast_frame **fout);
95 static void jb_force_resynch_fixed(void *jb);
96 /* adaptive */
97 static void * jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold);
98 static void jb_destroy_adaptive(void *jb);
99 static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now);
100 static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now);
101 static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl);
102 static long jb_next_adaptive(void *jb);
103 static int jb_remove_adaptive(void *jb, struct ast_frame **fout);
104 static void jb_force_resynch_adaptive(void *jb);
105
106 /* Available jb implementations */
107 static struct ast_jb_impl avail_impl[] = 
108 {
109         {
110                 .name = "fixed",
111                 .create = jb_create_fixed,
112                 .destroy = jb_destroy_fixed,
113                 .put_first = jb_put_first_fixed,
114                 .put = jb_put_fixed,
115                 .get = jb_get_fixed,
116                 .next = jb_next_fixed,
117                 .remove = jb_remove_fixed,
118                 .force_resync = jb_force_resynch_fixed
119         },
120         {
121                 .name = "adaptive",
122                 .create = jb_create_adaptive,
123                 .destroy = jb_destroy_adaptive,
124                 .put_first = jb_put_first_adaptive,
125                 .put = jb_put_adaptive,
126                 .get = jb_get_adaptive,
127                 .next = jb_next_adaptive,
128                 .remove = jb_remove_adaptive,
129                 .force_resync = jb_force_resynch_adaptive
130         }
131 };
132
133 static int default_impl = 0;
134
135
136 /*! Abstract return codes */
137 enum {
138         JB_IMPL_OK,
139         JB_IMPL_DROP,
140         JB_IMPL_INTERP,
141         JB_IMPL_NOFRAME
142 };
143
144 /* Translations between impl and abstract return codes */
145 static int fixed_to_abstract_code[] =
146         {JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
147 static int adaptive_to_abstract_code[] =
148         {JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
149
150 /* JB_GET actions (used only for the frames log) */
151 static char *jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
152
153 /*! \brief Macros for the frame log files */
154 #define jb_framelog(...) do { \
155         if (jb->logfile) { \
156                 fprintf(jb->logfile, __VA_ARGS__); \
157                 fflush(jb->logfile); \
158         } \
159 } while (0)
160
161
162 /* Internal utility functions */
163 static void jb_choose_impl(struct ast_channel *chan);
164 static void jb_get_and_deliver(struct ast_channel *chan);
165 static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame);
166 static long get_now(struct ast_jb *jb, struct timeval *tv);
167
168
169 /* Interface ast jb functions impl */
170
171
172 static void jb_choose_impl(struct ast_channel *chan)
173 {
174         struct ast_jb *jb = &chan->jb;
175         struct ast_jb_conf *jbconf = &jb->conf;
176         struct ast_jb_impl *test_impl;
177         int i, avail_impl_count = sizeof(avail_impl) / sizeof(avail_impl[0]);
178         
179         jb->impl = &avail_impl[default_impl];
180         
181         if (ast_strlen_zero(jbconf->impl))
182                 return;
183                 
184         for (i = 0; i < avail_impl_count; i++) {
185                 test_impl = &avail_impl[i];
186                 if (!strcasecmp(jbconf->impl, test_impl->name)) {
187                         jb->impl = test_impl;
188                         return;
189                 }
190         }
191 }
192
193 int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
194 {
195         struct ast_jb *jb0 = &c0->jb;
196         struct ast_jb *jb1 = &c1->jb;
197         struct ast_jb_conf *conf0 = &jb0->conf;
198         struct ast_jb_conf *conf1 = &jb1->conf;
199         int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER;
200         int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER;
201         int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
202         int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
203         int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
204         int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
205         int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER;
206         int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER;
207         int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
208         int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
209         int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
210         int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
211         int inuse = 0;
212
213         /* Determine whether audio going to c0 needs a jitter buffer */
214         if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
215                 ast_set_flag(jb0, JB_USE);
216                 if (!c0_jb_timebase_initialized) {
217                         if (c1_jb_timebase_initialized) {
218                                 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
219                         } else {
220                                 gettimeofday(&jb0->timebase, NULL);
221                         }
222                         ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
223                 }
224                 
225                 if (!c0_jb_created) {
226                         jb_choose_impl(c0);
227                 }
228
229                 inuse = 1;
230         }
231         
232         /* Determine whether audio going to c1 needs a jitter buffer */
233         if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
234                 ast_set_flag(jb1, JB_USE);
235                 if (!c1_jb_timebase_initialized) {
236                         if (c0_jb_timebase_initialized) {
237                                 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
238                         } else {
239                                 gettimeofday(&jb1->timebase, NULL);
240                         }
241                         ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
242                 }
243                 
244                 if (!c1_jb_created) {
245                         jb_choose_impl(c1);
246                 }
247
248                 inuse = 1;
249         }
250
251         return inuse;
252 }
253
254 int ast_jb_get_when_to_wakeup(struct ast_channel *c0, struct ast_channel *c1, int time_left)
255 {
256         struct ast_jb *jb0 = &c0->jb;
257         struct ast_jb *jb1 = &c1->jb;
258         int c0_use_jb = ast_test_flag(jb0, JB_USE);
259         int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
260         int c1_use_jb = ast_test_flag(jb1, JB_USE);
261         int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
262         int wait, wait0, wait1;
263         struct timeval tv_now;
264         
265         if (time_left == 0) {
266                 /* No time left - the bridge will be retried */
267                 /* TODO: Test disable this */
268                 /*return 0;*/
269         }
270         
271         if (time_left < 0) {
272                 time_left = INT_MAX;
273         }
274         
275         gettimeofday(&tv_now, NULL);
276         
277         wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
278         wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
279         
280         wait = wait0 < wait1 ? wait0 : wait1;
281         wait = wait < time_left ? wait : time_left;
282         
283         if (wait == INT_MAX) {
284                 wait = -1;
285         } else if (wait < 1) {
286                 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
287                 wait = 1;
288         }
289         
290         return wait;
291 }
292
293
294 int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
295 {
296         struct ast_jb *jb = &chan->jb;
297         struct ast_jb_impl *jbimpl = jb->impl;
298         void *jbobj = jb->jbobj;
299         struct ast_frame *frr;
300         long now = 0;
301         
302         if (!ast_test_flag(jb, JB_USE))
303                 return -1;
304
305         if (f->frametype != AST_FRAME_VOICE) {
306                 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
307                         jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
308                         jbimpl->force_resync(jbobj);
309                 }
310                 
311                 return -1;
312         }
313
314         /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
315         if (!f->has_timing_info || f->len < 2 || f->ts < 0) {
316                 ast_log(LOG_WARNING, "%s recieved frame with invalid timing info: "
317                         "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
318                         chan->name, f->has_timing_info, f->len, f->ts, f->src);
319                 return -1;
320         }
321
322         frr = ast_frdup(f);
323
324         if (!frr) {
325                 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name);
326                 return -1;
327         }
328
329         if (!ast_test_flag(jb, JB_CREATED)) {
330                 if (create_jb(chan, frr)) {
331                         ast_frfree(frr);
332                         /* Disable the jitterbuffer */
333                         ast_clear_flag(jb, JB_USE);
334                         return -1;
335                 }
336
337                 ast_set_flag(jb, JB_CREATED);
338                 return 0;
339         } else {
340                 now = get_now(jb, NULL);
341                 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
342                         jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
343                         ast_frfree(frr);
344                         /*return -1;*/
345                         /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 
346                            be delivered at all */
347                         return 0;
348                 }
349
350                 jb->next = jbimpl->next(jbobj);
351
352                 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
353
354                 return 0;
355         }
356 }
357
358
359 void ast_jb_get_and_deliver(struct ast_channel *c0, struct ast_channel *c1)
360 {
361         struct ast_jb *jb0 = &c0->jb;
362         struct ast_jb *jb1 = &c1->jb;
363         int c0_use_jb = ast_test_flag(jb0, JB_USE);
364         int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
365         int c1_use_jb = ast_test_flag(jb1, JB_USE);
366         int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
367         
368         if (c0_use_jb && c0_jb_is_created)
369                 jb_get_and_deliver(c0);
370         
371         if (c1_use_jb && c1_jb_is_created)
372                 jb_get_and_deliver(c1);
373 }
374
375
376 static void jb_get_and_deliver(struct ast_channel *chan)
377 {
378         struct ast_jb *jb = &chan->jb;
379         struct ast_jb_impl *jbimpl = jb->impl;
380         void *jbobj = jb->jbobj;
381         struct ast_frame *f, finterp;
382         long now;
383         int interpolation_len, res;
384         
385         now = get_now(jb, NULL);
386         jb->next = jbimpl->next(jbobj);
387         if (now < jb->next) {
388                 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
389                 return;
390         }
391         
392         while (now >= jb->next) {
393                 interpolation_len = ast_codec_interp_len(jb->last_format);
394                 
395                 res = jbimpl->get(jbobj, &f, now, interpolation_len);
396                 
397                 switch (res) {
398                 case JB_IMPL_OK:
399                         /* deliver the frame */
400                         ast_write(chan, f);
401                 case JB_IMPL_DROP:
402                         jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
403                                 now, jb_get_actions[res], f->ts, f->len);
404                         jb->last_format = f->subclass;
405                         ast_frfree(f);
406                         break;
407                 case JB_IMPL_INTERP:
408                         /* interpolate a frame */
409                         f = &finterp;
410                         f->frametype = AST_FRAME_VOICE;
411                         f->subclass = jb->last_format;
412                         f->datalen  = 0;
413                         f->samples  = interpolation_len * 8;
414                         f->mallocd  = 0;
415                         f->src  = "JB interpolation";
416                         f->data  = NULL;
417                         f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
418                         f->offset = AST_FRIENDLY_OFFSET;
419                         /* deliver the interpolated frame */
420                         ast_write(chan, f);
421                         jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
422                         break;
423                 case JB_IMPL_NOFRAME:
424                         ast_log(LOG_WARNING,
425                                 "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
426                                 jbimpl->name, now, jb->next, jbimpl->next(jbobj));
427                         jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
428                         return;
429                 default:
430                         ast_log(LOG_ERROR, "This should never happen!\n");
431                         CRASH;
432                         break;
433                 }
434                 
435                 jb->next = jbimpl->next(jbobj);
436         }
437 }
438
439
440 static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
441 {
442         struct ast_jb *jb = &chan->jb;
443         struct ast_jb_conf *jbconf = &jb->conf;
444         struct ast_jb_impl *jbimpl = jb->impl;
445         void *jbobj;
446         struct ast_channel *bridged;
447         long now;
448         char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
449         char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
450         int res;
451
452         jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
453         if (!jbobj) {
454                 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
455                 return -1;
456         }
457         
458         now = get_now(jb, NULL);
459         res = jbimpl->put_first(jbobj, frr, now);
460         
461         /* The result of putting the first frame should not differ from OK. However, its possible
462            some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
463         if (res != JB_IMPL_OK) {
464                 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
465                 /*
466                 jbimpl->destroy(jbobj);
467                 return -1;
468                 */
469         }
470         
471         /* Init next */
472         jb->next = jbimpl->next(jbobj);
473         
474         /* Init last format for a first time. */
475         jb->last_format = frr->subclass;
476         
477         /* Create a frame log file */
478         if (ast_test_flag(jbconf, AST_JB_LOG)) {
479                 snprintf(name2, sizeof(name2), "%s", chan->name);
480                 tmp = strchr(name2, '/');
481                 if (tmp)
482                         *tmp = '#';
483                 
484                 bridged = ast_bridged_channel(chan);
485                 if (!bridged) {
486                         /* We should always have bridged chan if a jitterbuffer is in use */
487                         CRASH;
488                 }
489                 snprintf(name1, sizeof(name1), "%s", bridged->name);
490                 tmp = strchr(name1, '/');
491                 if (tmp)
492                         *tmp = '#';
493                 
494                 snprintf(logfile_pathname, sizeof(logfile_pathname),
495                         "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
496                 jb->logfile = fopen(logfile_pathname, "w+b");
497                 
498                 if (!jb->logfile)
499                         ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
500                 
501                 if (res == JB_IMPL_OK)
502                         jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
503                                 now, frr->ts, frr->len);
504                 else
505                         jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
506                                 now, frr->ts, frr->len);
507         }
508
509         ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
510         
511         /* Free the frame if it has not been queued in the jb */
512         if (res != JB_IMPL_OK)
513                 ast_frfree(frr);
514         
515         return 0;
516 }
517
518
519 void ast_jb_destroy(struct ast_channel *chan)
520 {
521         struct ast_jb *jb = &chan->jb;
522         struct ast_jb_impl *jbimpl = jb->impl;
523         void *jbobj = jb->jbobj;
524         struct ast_frame *f;
525
526         if (jb->logfile) {
527                 fclose(jb->logfile);
528                 jb->logfile = NULL;
529         }
530         
531         if (ast_test_flag(jb, JB_CREATED)) {
532                 /* Remove and free all frames still queued in jb */
533                 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
534                         ast_frfree(f);
535                 }
536                 
537                 jbimpl->destroy(jbobj);
538                 jb->jbobj = NULL;
539                 
540                 ast_clear_flag(jb, JB_CREATED);
541
542                 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name);
543         }
544 }
545
546
547 static long get_now(struct ast_jb *jb, struct timeval *tv)
548 {
549         struct timeval now;
550
551         if (!tv) {
552                 tv = &now;
553                 gettimeofday(tv, NULL);
554         }
555
556         return ast_tvdiff_ms(*tv, jb->timebase);
557 }
558
559
560 int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
561 {
562         int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
563         const char *name;
564         int tmp;
565         
566         if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen))
567                 return -1;
568         
569         name = varname + prefixlen;
570         
571         if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
572                 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
573         } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
574                 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
575         } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
576                 if ((tmp = atoi(value)) > 0)
577                         conf->max_size = tmp;
578         } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
579                 if ((tmp = atoi(value)) > 0)
580                         conf->resync_threshold = tmp;
581         } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
582                 if (!ast_strlen_zero(value))
583                         snprintf(conf->impl, sizeof(conf->impl), "%s", value);
584         } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
585                 ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
586         } else {
587                 return -1;
588         }
589         
590         return 0;
591 }
592
593
594 void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
595 {
596         memcpy(&chan->jb.conf, conf, sizeof(*conf));
597 }
598
599
600 void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
601 {
602         memcpy(conf, &chan->jb.conf, sizeof(*conf));
603 }
604
605
606 /* Implementation functions */
607
608 /* fixed */
609
610 static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold)
611 {
612         struct fixed_jb_conf conf;
613         
614         conf.jbsize = general_config->max_size;
615         conf.resync_threshold = resynch_threshold;
616         
617         return fixed_jb_new(&conf);
618 }
619
620
621 static void jb_destroy_fixed(void *jb)
622 {
623         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
624         
625         /* destroy the jb */
626         fixed_jb_destroy(fixedjb);
627 }
628
629
630 static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
631 {
632         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
633         int res;
634         
635         res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
636         
637         return fixed_to_abstract_code[res];
638 }
639
640
641 static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
642 {
643         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
644         int res;
645         
646         res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
647         
648         return fixed_to_abstract_code[res];
649 }
650
651
652 static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)
653 {
654         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
655         struct fixed_jb_frame frame;
656         int res;
657         
658         res = fixed_jb_get(fixedjb, &frame, now, interpl);
659         *fout = frame.data;
660         
661         return fixed_to_abstract_code[res];
662 }
663
664
665 static long jb_next_fixed(void *jb)
666 {
667         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
668         
669         return fixed_jb_next(fixedjb);
670 }
671
672
673 static int jb_remove_fixed(void *jb, struct ast_frame **fout)
674 {
675         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
676         struct fixed_jb_frame frame;
677         int res;
678         
679         res = fixed_jb_remove(fixedjb, &frame);
680         *fout = frame.data;
681         
682         return fixed_to_abstract_code[res];
683 }
684
685
686 static void jb_force_resynch_fixed(void *jb)
687 {
688         struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
689         
690         fixed_jb_set_force_resynch(fixedjb);
691 }
692
693
694 /* adaptive */
695
696 static void *jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold)
697 {
698         jb_conf jbconf;
699         jitterbuf *adaptivejb;
700
701         adaptivejb = jb_new();
702         if (adaptivejb) {
703                 jbconf.max_jitterbuf = general_config->max_size;
704                 jbconf.resync_threshold = general_config->resync_threshold;
705                 jbconf.max_contig_interp = 10;
706                 jb_setconf(adaptivejb, &jbconf);
707         }
708         
709         return adaptivejb;
710 }
711
712
713 static void jb_destroy_adaptive(void *jb)
714 {
715         jitterbuf *adaptivejb = (jitterbuf *) jb;
716         
717         jb_destroy(adaptivejb);
718 }
719
720
721 static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
722 {
723         return jb_put_adaptive(jb, fin, now);
724 }
725
726
727 static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
728 {
729         jitterbuf *adaptivejb = (jitterbuf *) jb;
730         int res;
731         
732         res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
733         
734         return adaptive_to_abstract_code[res];
735 }
736
737
738 static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
739 {
740         jitterbuf *adaptivejb = (jitterbuf *) jb;
741         jb_frame frame;
742         int res;
743         
744         res = jb_get(adaptivejb, &frame, now, interpl);
745         *fout = frame.data;
746         
747         return adaptive_to_abstract_code[res];
748 }
749
750
751 static long jb_next_adaptive(void *jb)
752 {
753         jitterbuf *adaptivejb = (jitterbuf *) jb;
754         
755         return jb_next(adaptivejb);
756 }
757
758
759 static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
760 {
761         jitterbuf *adaptivejb = (jitterbuf *) jb;
762         jb_frame frame;
763         int res;
764         
765         res = jb_getall(adaptivejb, &frame);
766         *fout = frame.data;
767         
768         return adaptive_to_abstract_code[res];
769 }
770
771
772 static void jb_force_resynch_adaptive(void *jb)
773 {
774 }