mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-18 18:46:16 +00:00
Introduction of the JITTERBUFFER dialplan function.
Review: https://reviewboard.asterisk.org/r/1157/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@314509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -49,43 +49,6 @@ enum {
|
||||
JB_CREATED = (1 << 2)
|
||||
};
|
||||
|
||||
/* Hooks for the abstract jb implementation */
|
||||
|
||||
/*! \brief Create */
|
||||
typedef void * (*jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold);
|
||||
/*! \brief Destroy */
|
||||
typedef void (*jb_destroy_impl)(void *jb);
|
||||
/*! \brief Put first frame */
|
||||
typedef int (*jb_put_first_impl)(void *jb, struct ast_frame *fin, long now);
|
||||
/*! \brief Put frame */
|
||||
typedef int (*jb_put_impl)(void *jb, struct ast_frame *fin, long now);
|
||||
/*! \brief Get frame for now */
|
||||
typedef int (*jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl);
|
||||
/*! \brief Get next */
|
||||
typedef long (*jb_next_impl)(void *jb);
|
||||
/*! \brief Remove first frame */
|
||||
typedef int (*jb_remove_impl)(void *jb, struct ast_frame **fout);
|
||||
/*! \brief Force resynch */
|
||||
typedef void (*jb_force_resynch_impl)(void *jb);
|
||||
/*! \brief Empty and reset jb */
|
||||
typedef void (*jb_empty_and_reset_impl)(void *jb);
|
||||
|
||||
/*!
|
||||
* \brief Jitterbuffer implementation private struct.
|
||||
*/
|
||||
struct ast_jb_impl
|
||||
{
|
||||
char name[AST_JB_IMPL_NAME_SIZE];
|
||||
jb_create_impl create;
|
||||
jb_destroy_impl destroy;
|
||||
jb_put_first_impl put_first;
|
||||
jb_put_impl put;
|
||||
jb_get_impl get;
|
||||
jb_next_impl next;
|
||||
jb_remove_impl remove;
|
||||
jb_force_resynch_impl force_resync;
|
||||
jb_empty_and_reset_impl empty_and_reset;
|
||||
};
|
||||
|
||||
/* Implementation functions */
|
||||
/* fixed */
|
||||
@@ -113,6 +76,7 @@ static void jb_empty_and_reset_adaptive(void *jb);
|
||||
static const struct ast_jb_impl avail_impl[] = {
|
||||
{
|
||||
.name = "fixed",
|
||||
.type = AST_JB_FIXED,
|
||||
.create = jb_create_fixed,
|
||||
.destroy = jb_destroy_fixed,
|
||||
.put_first = jb_put_first_fixed,
|
||||
@@ -125,6 +89,7 @@ static const struct ast_jb_impl avail_impl[] = {
|
||||
},
|
||||
{
|
||||
.name = "adaptive",
|
||||
.type = AST_JB_ADAPTIVE,
|
||||
.create = jb_create_adaptive,
|
||||
.destroy = jb_destroy_adaptive,
|
||||
.put_first = jb_put_first_adaptive,
|
||||
@@ -139,20 +104,11 @@ static const struct ast_jb_impl avail_impl[] = {
|
||||
|
||||
static int default_impl = 0;
|
||||
|
||||
|
||||
/*! Abstract return codes */
|
||||
enum {
|
||||
JB_IMPL_OK,
|
||||
JB_IMPL_DROP,
|
||||
JB_IMPL_INTERP,
|
||||
JB_IMPL_NOFRAME
|
||||
};
|
||||
|
||||
/* Translations between impl and abstract return codes */
|
||||
static const int fixed_to_abstract_code[] =
|
||||
{JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
|
||||
{AST_JB_IMPL_OK, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME};
|
||||
static const int adaptive_to_abstract_code[] =
|
||||
{JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
|
||||
{AST_JB_IMPL_OK, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_INTERP, AST_JB_IMPL_DROP, AST_JB_IMPL_OK};
|
||||
|
||||
/* JB_GET actions (used only for the frames log) */
|
||||
static const char * const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
|
||||
@@ -346,7 +302,7 @@ int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
|
||||
return 0;
|
||||
} else {
|
||||
now = get_now(jb, NULL);
|
||||
if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
|
||||
if (jbimpl->put(jbobj, frr, now) != AST_JB_IMPL_OK) {
|
||||
jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
|
||||
ast_frfree(frr);
|
||||
/*return -1;*/
|
||||
@@ -403,16 +359,16 @@ static void jb_get_and_deliver(struct ast_channel *chan)
|
||||
res = jbimpl->get(jbobj, &f, now, interpolation_len);
|
||||
|
||||
switch (res) {
|
||||
case JB_IMPL_OK:
|
||||
case AST_JB_IMPL_OK:
|
||||
/* deliver the frame */
|
||||
ast_write(chan, f);
|
||||
case JB_IMPL_DROP:
|
||||
case AST_JB_IMPL_DROP:
|
||||
jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
|
||||
now, jb_get_actions[res], f->ts, f->len);
|
||||
ast_format_copy(&jb->last_format, &f->subclass.format);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
case JB_IMPL_INTERP:
|
||||
case AST_JB_IMPL_INTERP:
|
||||
/* interpolate a frame */
|
||||
f = &finterp;
|
||||
ast_format_copy(&f->subclass.format, &jb->last_format);
|
||||
@@ -424,9 +380,9 @@ static void jb_get_and_deliver(struct ast_channel *chan)
|
||||
ast_write(chan, f);
|
||||
jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
|
||||
break;
|
||||
case JB_IMPL_NOFRAME:
|
||||
case AST_JB_IMPL_NOFRAME:
|
||||
ast_log(LOG_WARNING,
|
||||
"JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
|
||||
"AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
|
||||
jbimpl->name, now, jb->next, jbimpl->next(jbobj));
|
||||
jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
|
||||
return;
|
||||
@@ -464,7 +420,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
|
||||
|
||||
/* The result of putting the first frame should not differ from OK. However, its possible
|
||||
some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
|
||||
if (res != JB_IMPL_OK) {
|
||||
if (res != AST_JB_IMPL_OK) {
|
||||
ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
|
||||
/*
|
||||
jbimpl->destroy(jbobj);
|
||||
@@ -508,7 +464,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
|
||||
}
|
||||
}
|
||||
|
||||
if (res == JB_IMPL_OK) {
|
||||
if (res == AST_JB_IMPL_OK) {
|
||||
jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
|
||||
now, frr->ts, frr->len);
|
||||
} else {
|
||||
@@ -520,7 +476,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
|
||||
ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
|
||||
|
||||
/* Free the frame if it has not been queued in the jb */
|
||||
if (res != JB_IMPL_OK) {
|
||||
if (res != AST_JB_IMPL_OK) {
|
||||
ast_frfree(frr);
|
||||
}
|
||||
|
||||
@@ -542,7 +498,7 @@ void ast_jb_destroy(struct ast_channel *chan)
|
||||
|
||||
if (ast_test_flag(jb, JB_CREATED)) {
|
||||
/* Remove and free all frames still queued in jb */
|
||||
while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
|
||||
while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
|
||||
ast_frfree(f);
|
||||
}
|
||||
|
||||
@@ -831,3 +787,14 @@ static void jb_empty_and_reset_adaptive(void *jb)
|
||||
|
||||
jb_reset(adaptivejb);
|
||||
}
|
||||
|
||||
const struct ast_jb_impl *ast_jb_get_impl(enum ast_jb_type type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_LEN(avail_impl); i++) {
|
||||
if (avail_impl[i].type == type) {
|
||||
return &avail_impl[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user