2 * abstract_jb: common implementation-independent jitterbuffer stuff
4 * Copyright (C) 2005, Attractel OOD
7 * Slav Klenov <slav@securax.org>
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.
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.
19 * A license has been granted to Digium (via disclaimer) for the use of
25 * \brief Common implementation-independent jitterbuffer stuff.
27 * \author Slav Klenov <slav@securax.org>
32 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
37 #include "asterisk/frame.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/term.h"
41 #include "asterisk/options.h"
42 #include "asterisk/utils.h"
44 #include "asterisk/abstract_jb.h"
45 #include "fixedjitterbuf.h"
46 #include "jitterbuf.h"
48 /*! Internal jb flags */
51 JB_TIMEBASE_INITIALIZED
= (1 << 1),
55 /* Hooks for the abstract jb implementation */
58 typedef void * (*jb_create_impl
)(struct ast_jb_conf
*general_config
, long resynch_threshold
);
60 typedef void (*jb_destroy_impl
)(void *jb
);
61 /*! \brief Put first frame */
62 typedef int (*jb_put_first_impl
)(void *jb
, struct ast_frame
*fin
, long now
);
63 /*! \brief Put frame */
64 typedef int (*jb_put_impl
)(void *jb
, struct ast_frame
*fin
, long now
);
65 /*! \brief Get frame for now */
66 typedef int (*jb_get_impl
)(void *jb
, struct ast_frame
**fout
, long now
, long interpl
);
67 /*! \brief Get next */
68 typedef long (*jb_next_impl
)(void *jb
);
69 /*! \brief Remove first frame */
70 typedef int (*jb_remove_impl
)(void *jb
, struct ast_frame
**fout
);
71 /*! \brief Force resynch */
72 typedef void (*jb_force_resynch_impl
)(void *jb
);
73 /*! \brief Empty and reset jb */
74 typedef void (*jb_empty_and_reset_impl
)(void *jb
);
77 * \brief Jitterbuffer implementation private struct.
81 char name
[AST_JB_IMPL_NAME_SIZE
];
82 jb_create_impl create
;
83 jb_destroy_impl destroy
;
84 jb_put_first_impl put_first
;
88 jb_remove_impl remove
;
89 jb_force_resynch_impl force_resync
;
90 jb_empty_and_reset_impl empty_and_reset
;
93 /* Implementation functions */
95 static void * jb_create_fixed(struct ast_jb_conf
*general_config
, long resynch_threshold
);
96 static void jb_destroy_fixed(void *jb
);
97 static int jb_put_first_fixed(void *jb
, struct ast_frame
*fin
, long now
);
98 static int jb_put_fixed(void *jb
, struct ast_frame
*fin
, long now
);
99 static int jb_get_fixed(void *jb
, struct ast_frame
**fout
, long now
, long interpl
);
100 static long jb_next_fixed(void *jb
);
101 static int jb_remove_fixed(void *jb
, struct ast_frame
**fout
);
102 static void jb_force_resynch_fixed(void *jb
);
103 static void jb_empty_and_reset_fixed(void *jb
);
105 static void * jb_create_adaptive(struct ast_jb_conf
*general_config
, long resynch_threshold
);
106 static void jb_destroy_adaptive(void *jb
);
107 static int jb_put_first_adaptive(void *jb
, struct ast_frame
*fin
, long now
);
108 static int jb_put_adaptive(void *jb
, struct ast_frame
*fin
, long now
);
109 static int jb_get_adaptive(void *jb
, struct ast_frame
**fout
, long now
, long interpl
);
110 static long jb_next_adaptive(void *jb
);
111 static int jb_remove_adaptive(void *jb
, struct ast_frame
**fout
);
112 static void jb_force_resynch_adaptive(void *jb
);
113 static void jb_empty_and_reset_adaptive(void *jb
);
115 /* Available jb implementations */
116 static struct ast_jb_impl avail_impl
[] =
120 .create
= jb_create_fixed
,
121 .destroy
= jb_destroy_fixed
,
122 .put_first
= jb_put_first_fixed
,
125 .next
= jb_next_fixed
,
126 .remove
= jb_remove_fixed
,
127 .force_resync
= jb_force_resynch_fixed
,
128 .empty_and_reset
= jb_empty_and_reset_fixed
,
132 .create
= jb_create_adaptive
,
133 .destroy
= jb_destroy_adaptive
,
134 .put_first
= jb_put_first_adaptive
,
135 .put
= jb_put_adaptive
,
136 .get
= jb_get_adaptive
,
137 .next
= jb_next_adaptive
,
138 .remove
= jb_remove_adaptive
,
139 .force_resync
= jb_force_resynch_adaptive
,
140 .empty_and_reset
= jb_empty_and_reset_adaptive
,
144 static int default_impl
= 0;
147 /*! Abstract return codes */
155 /* Translations between impl and abstract return codes */
156 static int fixed_to_abstract_code
[] =
157 {JB_IMPL_OK
, JB_IMPL_DROP
, JB_IMPL_INTERP
, JB_IMPL_NOFRAME
};
158 static int adaptive_to_abstract_code
[] =
159 {JB_IMPL_OK
, JB_IMPL_NOFRAME
, JB_IMPL_NOFRAME
, JB_IMPL_INTERP
, JB_IMPL_DROP
, JB_IMPL_OK
};
161 /* JB_GET actions (used only for the frames log) */
162 static char *jb_get_actions
[] = {"Delivered", "Dropped", "Interpolated", "No"};
164 /*! \brief Macros for the frame log files */
165 #define jb_framelog(...) do { \
167 fprintf(jb->logfile, __VA_ARGS__); \
168 fflush(jb->logfile); \
173 /* Internal utility functions */
174 static void jb_choose_impl(struct ast_channel
*chan
);
175 static void jb_get_and_deliver(struct ast_channel
*chan
);
176 static int create_jb(struct ast_channel
*chan
, struct ast_frame
*first_frame
);
177 static long get_now(struct ast_jb
*jb
, struct timeval
*tv
);
180 /* Interface ast jb functions impl */
183 static void jb_choose_impl(struct ast_channel
*chan
)
185 struct ast_jb
*jb
= &chan
->jb
;
186 struct ast_jb_conf
*jbconf
= &jb
->conf
;
187 struct ast_jb_impl
*test_impl
;
188 int i
, avail_impl_count
= sizeof(avail_impl
) / sizeof(avail_impl
[0]);
190 jb
->impl
= &avail_impl
[default_impl
];
192 if (ast_strlen_zero(jbconf
->impl
))
195 for (i
= 0; i
< avail_impl_count
; i
++) {
196 test_impl
= &avail_impl
[i
];
197 if (!strcasecmp(jbconf
->impl
, test_impl
->name
)) {
198 jb
->impl
= test_impl
;
204 int ast_jb_do_usecheck(struct ast_channel
*c0
, struct ast_channel
*c1
)
206 struct ast_jb
*jb0
= &c0
->jb
;
207 struct ast_jb
*jb1
= &c1
->jb
;
208 struct ast_jb_conf
*conf0
= &jb0
->conf
;
209 struct ast_jb_conf
*conf1
= &jb1
->conf
;
210 int c0_wants_jitter
= c0
->tech
->properties
& AST_CHAN_TP_WANTSJITTER
;
211 int c0_creates_jitter
= c0
->tech
->properties
& AST_CHAN_TP_CREATESJITTER
;
212 int c0_jb_enabled
= ast_test_flag(conf0
, AST_JB_ENABLED
);
213 int c0_force_jb
= ast_test_flag(conf0
, AST_JB_FORCED
);
214 int c0_jb_timebase_initialized
= ast_test_flag(jb0
, JB_TIMEBASE_INITIALIZED
);
215 int c0_jb_created
= ast_test_flag(jb0
, JB_CREATED
);
216 int c1_wants_jitter
= c1
->tech
->properties
& AST_CHAN_TP_WANTSJITTER
;
217 int c1_creates_jitter
= c1
->tech
->properties
& AST_CHAN_TP_CREATESJITTER
;
218 int c1_jb_enabled
= ast_test_flag(conf1
, AST_JB_ENABLED
);
219 int c1_force_jb
= ast_test_flag(conf1
, AST_JB_FORCED
);
220 int c1_jb_timebase_initialized
= ast_test_flag(jb1
, JB_TIMEBASE_INITIALIZED
);
221 int c1_jb_created
= ast_test_flag(jb1
, JB_CREATED
);
224 /* Determine whether audio going to c0 needs a jitter buffer */
225 if (((!c0_wants_jitter
&& c1_creates_jitter
) || (c0_force_jb
&& c1_creates_jitter
)) && c0_jb_enabled
) {
226 ast_set_flag(jb0
, JB_USE
);
227 if (!c0_jb_timebase_initialized
) {
228 if (c1_jb_timebase_initialized
) {
229 memcpy(&jb0
->timebase
, &jb1
->timebase
, sizeof(struct timeval
));
231 gettimeofday(&jb0
->timebase
, NULL
);
233 ast_set_flag(jb0
, JB_TIMEBASE_INITIALIZED
);
236 if (!c0_jb_created
) {
243 /* Determine whether audio going to c1 needs a jitter buffer */
244 if (((!c1_wants_jitter
&& c0_creates_jitter
) || (c1_force_jb
&& c0_creates_jitter
)) && c1_jb_enabled
) {
245 ast_set_flag(jb1
, JB_USE
);
246 if (!c1_jb_timebase_initialized
) {
247 if (c0_jb_timebase_initialized
) {
248 memcpy(&jb1
->timebase
, &jb0
->timebase
, sizeof(struct timeval
));
250 gettimeofday(&jb1
->timebase
, NULL
);
252 ast_set_flag(jb1
, JB_TIMEBASE_INITIALIZED
);
255 if (!c1_jb_created
) {
265 int ast_jb_get_when_to_wakeup(struct ast_channel
*c0
, struct ast_channel
*c1
, int time_left
)
267 struct ast_jb
*jb0
= &c0
->jb
;
268 struct ast_jb
*jb1
= &c1
->jb
;
269 int c0_use_jb
= ast_test_flag(jb0
, JB_USE
);
270 int c0_jb_is_created
= ast_test_flag(jb0
, JB_CREATED
);
271 int c1_use_jb
= ast_test_flag(jb1
, JB_USE
);
272 int c1_jb_is_created
= ast_test_flag(jb1
, JB_CREATED
);
273 int wait
, wait0
, wait1
;
274 struct timeval tv_now
;
276 if (time_left
== 0) {
277 /* No time left - the bridge will be retried */
278 /* TODO: Test disable this */
286 gettimeofday(&tv_now
, NULL
);
288 wait0
= (c0_use_jb
&& c0_jb_is_created
) ? jb0
->next
- get_now(jb0
, &tv_now
) : time_left
;
289 wait1
= (c1_use_jb
&& c1_jb_is_created
) ? jb1
->next
- get_now(jb1
, &tv_now
) : time_left
;
291 wait
= wait0
< wait1
? wait0
: wait1
;
292 wait
= wait
< time_left
? wait
: time_left
;
294 if (wait
== INT_MAX
) {
296 } else if (wait
< 1) {
297 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
305 int ast_jb_put(struct ast_channel
*chan
, struct ast_frame
*f
)
307 struct ast_jb
*jb
= &chan
->jb
;
308 struct ast_jb_impl
*jbimpl
= jb
->impl
;
309 void *jbobj
= jb
->jbobj
;
310 struct ast_frame
*frr
;
313 if (!ast_test_flag(jb
, JB_USE
))
316 if (f
->frametype
!= AST_FRAME_VOICE
) {
317 if (f
->frametype
== AST_FRAME_DTMF
&& ast_test_flag(jb
, JB_CREATED
)) {
318 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now
);
319 jbimpl
->force_resync(jbobj
);
325 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
326 if (!ast_test_flag(f
, AST_FRFLAG_HAS_TIMING_INFO
) || f
->len
< 2 || f
->ts
< 0) {
327 ast_log(LOG_WARNING
, "%s recieved frame with invalid timing info: "
328 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
329 chan
->name
, ast_test_flag(f
, AST_FRFLAG_HAS_TIMING_INFO
), f
->len
, f
->ts
, f
->src
);
336 ast_log(LOG_ERROR
, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan
->name
);
340 if (!ast_test_flag(jb
, JB_CREATED
)) {
341 if (create_jb(chan
, frr
)) {
343 /* Disable the jitterbuffer */
344 ast_clear_flag(jb
, JB_USE
);
348 ast_set_flag(jb
, JB_CREATED
);
351 now
= get_now(jb
, NULL
);
352 if (jbimpl
->put(jbobj
, frr
, now
) != JB_IMPL_OK
) {
353 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now
, frr
->ts
, frr
->len
);
356 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
357 be delivered at all */
361 jb
->next
= jbimpl
->next(jbobj
);
363 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now
, frr
->ts
, frr
->len
);
370 void ast_jb_get_and_deliver(struct ast_channel
*c0
, struct ast_channel
*c1
)
372 struct ast_jb
*jb0
= &c0
->jb
;
373 struct ast_jb
*jb1
= &c1
->jb
;
374 int c0_use_jb
= ast_test_flag(jb0
, JB_USE
);
375 int c0_jb_is_created
= ast_test_flag(jb0
, JB_CREATED
);
376 int c1_use_jb
= ast_test_flag(jb1
, JB_USE
);
377 int c1_jb_is_created
= ast_test_flag(jb1
, JB_CREATED
);
379 if (c0_use_jb
&& c0_jb_is_created
)
380 jb_get_and_deliver(c0
);
382 if (c1_use_jb
&& c1_jb_is_created
)
383 jb_get_and_deliver(c1
);
387 static void jb_get_and_deliver(struct ast_channel
*chan
)
389 struct ast_jb
*jb
= &chan
->jb
;
390 struct ast_jb_impl
*jbimpl
= jb
->impl
;
391 void *jbobj
= jb
->jbobj
;
392 struct ast_frame
*f
, finterp
;
394 int interpolation_len
, res
;
396 now
= get_now(jb
, NULL
);
397 jb
->next
= jbimpl
->next(jbobj
);
398 if (now
< jb
->next
) {
399 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now
, jb
->next
);
403 while (now
>= jb
->next
) {
404 interpolation_len
= ast_codec_interp_len(jb
->last_format
);
406 res
= jbimpl
->get(jbobj
, &f
, now
, interpolation_len
);
410 /* deliver the frame */
413 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
414 now
, jb_get_actions
[res
], f
->ts
, f
->len
);
415 jb
->last_format
= f
->subclass
;
419 /* interpolate a frame */
421 f
->frametype
= AST_FRAME_VOICE
;
422 f
->subclass
= jb
->last_format
;
424 f
->samples
= interpolation_len
* 8;
426 f
->src
= "JB interpolation";
428 f
->delivery
= ast_tvadd(jb
->timebase
, ast_samp2tv(jb
->next
, 1000));
429 f
->offset
= AST_FRIENDLY_OFFSET
;
430 /* deliver the interpolated frame */
432 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now
, interpolation_len
);
434 case JB_IMPL_NOFRAME
:
436 "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
437 jbimpl
->name
, now
, jb
->next
, jbimpl
->next(jbobj
));
438 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now
);
441 ast_log(LOG_ERROR
, "This should never happen!\n");
442 ast_assert("JB type unknown" == NULL
);
446 jb
->next
= jbimpl
->next(jbobj
);
451 static int create_jb(struct ast_channel
*chan
, struct ast_frame
*frr
)
453 struct ast_jb
*jb
= &chan
->jb
;
454 struct ast_jb_conf
*jbconf
= &jb
->conf
;
455 struct ast_jb_impl
*jbimpl
= jb
->impl
;
457 struct ast_channel
*bridged
;
459 char logfile_pathname
[20 + AST_JB_IMPL_NAME_SIZE
+ 2*AST_CHANNEL_NAME
+ 1];
460 char name1
[AST_CHANNEL_NAME
], name2
[AST_CHANNEL_NAME
], *tmp
;
463 jbobj
= jb
->jbobj
= jbimpl
->create(jbconf
, jbconf
->resync_threshold
);
465 ast_log(LOG_WARNING
, "Failed to create jitterbuffer on channel '%s'\n", chan
->name
);
469 now
= get_now(jb
, NULL
);
470 res
= jbimpl
->put_first(jbobj
, frr
, now
);
472 /* The result of putting the first frame should not differ from OK. However, its possible
473 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
474 if (res
!= JB_IMPL_OK
) {
475 ast_log(LOG_WARNING
, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan
->name
);
477 jbimpl->destroy(jbobj);
483 jb
->next
= jbimpl
->next(jbobj
);
485 /* Init last format for a first time. */
486 jb
->last_format
= frr
->subclass
;
488 /* Create a frame log file */
489 if (ast_test_flag(jbconf
, AST_JB_LOG
)) {
490 snprintf(name2
, sizeof(name2
), "%s", chan
->name
);
491 tmp
= strchr(name2
, '/');
495 bridged
= ast_bridged_channel(chan
);
496 /* We should always have bridged chan if a jitterbuffer is in use */
497 ast_assert(bridged
!= NULL
);
499 snprintf(name1
, sizeof(name1
), "%s", bridged
->name
);
500 tmp
= strchr(name1
, '/');
504 snprintf(logfile_pathname
, sizeof(logfile_pathname
),
505 "/tmp/ast_%s_jb_%s--%s.log", jbimpl
->name
, name1
, name2
);
506 jb
->logfile
= fopen(logfile_pathname
, "w+b");
509 ast_log(LOG_WARNING
, "Failed to create frame log file with pathname '%s'\n", logfile_pathname
);
511 if (res
== JB_IMPL_OK
)
512 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
513 now
, frr
->ts
, frr
->len
);
515 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
516 now
, frr
->ts
, frr
->len
);
519 if (option_verbose
> 2)
520 ast_verbose(VERBOSE_PREFIX_3
"%s jitterbuffer created on channel %s\n", jbimpl
->name
, chan
->name
);
522 /* Free the frame if it has not been queued in the jb */
523 if (res
!= JB_IMPL_OK
)
530 void ast_jb_destroy(struct ast_channel
*chan
)
532 struct ast_jb
*jb
= &chan
->jb
;
533 struct ast_jb_impl
*jbimpl
= jb
->impl
;
534 void *jbobj
= jb
->jbobj
;
542 if (ast_test_flag(jb
, JB_CREATED
)) {
543 /* Remove and free all frames still queued in jb */
544 while (jbimpl
->remove(jbobj
, &f
) == JB_IMPL_OK
) {
548 jbimpl
->destroy(jbobj
);
551 ast_clear_flag(jb
, JB_CREATED
);
553 if (option_verbose
> 2)
554 ast_verbose(VERBOSE_PREFIX_3
"%s jitterbuffer destroyed on channel %s\n", jbimpl
->name
, chan
->name
);
559 static long get_now(struct ast_jb
*jb
, struct timeval
*tv
)
565 gettimeofday(tv
, NULL
);
568 return ast_tvdiff_ms(*tv
, jb
->timebase
);
572 int ast_jb_read_conf(struct ast_jb_conf
*conf
, char *varname
, char *value
)
574 int prefixlen
= sizeof(AST_JB_CONF_PREFIX
) - 1;
578 if (strncasecmp(AST_JB_CONF_PREFIX
, varname
, prefixlen
))
581 name
= varname
+ prefixlen
;
583 if (!strcasecmp(name
, AST_JB_CONF_ENABLE
)) {
584 ast_set2_flag(conf
, ast_true(value
), AST_JB_ENABLED
);
585 } else if (!strcasecmp(name
, AST_JB_CONF_FORCE
)) {
586 ast_set2_flag(conf
, ast_true(value
), AST_JB_FORCED
);
587 } else if (!strcasecmp(name
, AST_JB_CONF_MAX_SIZE
)) {
588 if ((tmp
= atoi(value
)) > 0)
589 conf
->max_size
= tmp
;
590 } else if (!strcasecmp(name
, AST_JB_CONF_RESYNCH_THRESHOLD
)) {
591 if ((tmp
= atoi(value
)) > 0)
592 conf
->resync_threshold
= tmp
;
593 } else if (!strcasecmp(name
, AST_JB_CONF_IMPL
)) {
594 if (!ast_strlen_zero(value
))
595 snprintf(conf
->impl
, sizeof(conf
->impl
), "%s", value
);
596 } else if (!strcasecmp(name
, AST_JB_CONF_LOG
)) {
597 ast_set2_flag(conf
, ast_true(value
), AST_JB_LOG
);
606 void ast_jb_configure(struct ast_channel
*chan
, const struct ast_jb_conf
*conf
)
608 memcpy(&chan
->jb
.conf
, conf
, sizeof(*conf
));
612 void ast_jb_get_config(const struct ast_channel
*chan
, struct ast_jb_conf
*conf
)
614 memcpy(conf
, &chan
->jb
.conf
, sizeof(*conf
));
617 void ast_jb_empty_and_reset(struct ast_channel
*c0
, struct ast_channel
*c1
)
619 struct ast_jb
*jb0
= &c0
->jb
;
620 struct ast_jb
*jb1
= &c1
->jb
;
621 int c0_use_jb
= ast_test_flag(jb0
, JB_USE
);
622 int c0_jb_is_created
= ast_test_flag(jb0
, JB_CREATED
);
623 int c1_use_jb
= ast_test_flag(jb1
, JB_USE
);
624 int c1_jb_is_created
= ast_test_flag(jb1
, JB_CREATED
);
626 if (c0_use_jb
&& c0_jb_is_created
&& jb0
->impl
->empty_and_reset
) {
627 jb0
->impl
->empty_and_reset(jb0
->jbobj
);
630 if (c1_use_jb
&& c1_jb_is_created
&& jb1
->impl
->empty_and_reset
) {
631 jb1
->impl
->empty_and_reset(jb1
->jbobj
);
635 /* Implementation functions */
638 static void * jb_create_fixed(struct ast_jb_conf
*general_config
, long resynch_threshold
)
640 struct fixed_jb_conf conf
;
642 conf
.jbsize
= general_config
->max_size
;
643 conf
.resync_threshold
= resynch_threshold
;
645 return fixed_jb_new(&conf
);
648 static void jb_destroy_fixed(void *jb
)
650 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
653 fixed_jb_destroy(fixedjb
);
657 static int jb_put_first_fixed(void *jb
, struct ast_frame
*fin
, long now
)
659 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
662 res
= fixed_jb_put_first(fixedjb
, fin
, fin
->len
, fin
->ts
, now
);
664 return fixed_to_abstract_code
[res
];
668 static int jb_put_fixed(void *jb
, struct ast_frame
*fin
, long now
)
670 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
673 res
= fixed_jb_put(fixedjb
, fin
, fin
->len
, fin
->ts
, now
);
675 return fixed_to_abstract_code
[res
];
679 static int jb_get_fixed(void *jb
, struct ast_frame
**fout
, long now
, long interpl
)
681 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
682 struct fixed_jb_frame frame
;
685 res
= fixed_jb_get(fixedjb
, &frame
, now
, interpl
);
688 return fixed_to_abstract_code
[res
];
692 static long jb_next_fixed(void *jb
)
694 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
696 return fixed_jb_next(fixedjb
);
700 static int jb_remove_fixed(void *jb
, struct ast_frame
**fout
)
702 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
703 struct fixed_jb_frame frame
;
706 res
= fixed_jb_remove(fixedjb
, &frame
);
709 return fixed_to_abstract_code
[res
];
713 static void jb_force_resynch_fixed(void *jb
)
715 struct fixed_jb
*fixedjb
= (struct fixed_jb
*) jb
;
717 fixed_jb_set_force_resynch(fixedjb
);
720 static void jb_empty_and_reset_fixed(void *jb
)
722 struct fixed_jb
*fixedjb
= jb
;
723 struct fixed_jb_frame f
;
725 while (fixed_jb_remove(fixedjb
, &f
) == FIXED_JB_OK
) {
732 static void *jb_create_adaptive(struct ast_jb_conf
*general_config
, long resynch_threshold
)
735 jitterbuf
*adaptivejb
;
737 adaptivejb
= jb_new();
739 jbconf
.max_jitterbuf
= general_config
->max_size
;
740 jbconf
.resync_threshold
= general_config
->resync_threshold
;
741 jbconf
.max_contig_interp
= 10;
742 jb_setconf(adaptivejb
, &jbconf
);
749 static void jb_destroy_adaptive(void *jb
)
751 jitterbuf
*adaptivejb
= (jitterbuf
*) jb
;
753 jb_destroy(adaptivejb
);
757 static int jb_put_first_adaptive(void *jb
, struct ast_frame
*fin
, long now
)
759 return jb_put_adaptive(jb
, fin
, now
);
763 static int jb_put_adaptive(void *jb
, struct ast_frame
*fin
, long now
)
765 jitterbuf
*adaptivejb
= (jitterbuf
*) jb
;
768 res
= jb_put(adaptivejb
, fin
, JB_TYPE_VOICE
, fin
->len
, fin
->ts
, now
);
770 return adaptive_to_abstract_code
[res
];
774 static int jb_get_adaptive(void *jb
, struct ast_frame
**fout
, long now
, long interpl
)
776 jitterbuf
*adaptivejb
= (jitterbuf
*) jb
;
780 res
= jb_get(adaptivejb
, &frame
, now
, interpl
);
783 return adaptive_to_abstract_code
[res
];
787 static long jb_next_adaptive(void *jb
)
789 jitterbuf
*adaptivejb
= (jitterbuf
*) jb
;
791 return jb_next(adaptivejb
);
795 static int jb_remove_adaptive(void *jb
, struct ast_frame
**fout
)
797 jitterbuf
*adaptivejb
= (jitterbuf
*) jb
;
801 res
= jb_getall(adaptivejb
, &frame
);
804 return adaptive_to_abstract_code
[res
];
808 static void jb_force_resynch_adaptive(void *jb
)
812 static void jb_empty_and_reset_adaptive(void *jb
)
814 jitterbuf
*adaptivejb
= jb
;
817 while (jb_getall(adaptivejb
, &f
) == JB_OK
) {
821 jb_reset(adaptivejb
);