diff --git a/apps/app_skel.c b/apps/app_skel.c index 55830ebee8..5fdd98a44d 100644 --- a/apps/app_skel.c +++ b/apps/app_skel.c @@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/module.h" #include "asterisk/lock.h" #include "asterisk/app.h" +#include "asterisk/utils.h" static char *app = "Skel"; static char *synopsis = @@ -72,28 +73,26 @@ AST_APP_OPTIONS(app_opts,{ AST_APP_OPTION_ARG('c', OPTION_C, OPTION_ARG_C), }); +static void *dogballs(void *shit) +{ + ast_log(LOG_NOTICE, "Oh GOD!! I am a thread magician!!\n"); + return NULL; +} static int app_exec(struct ast_channel *chan, void *data) { - int res = 0; - struct ast_flags flags; + int i; struct ast_module_user *u; - char *parse, *opts[OPTION_ARG_ARRAY_SIZE]; - AST_DECLARE_APP_ARGS(args, - AST_APP_ARG(dummy); - AST_APP_ARG(options); - ); - - if (ast_strlen_zero(data)) { - ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n", app); - return -1; - } + pthread_t thread; u = ast_module_user_add(chan); /* Do our thing here */ - /* We need to make a copy of the input string if we are going to modify it! */ + for (i = 0; i < 100; ++i) { + ast_pthread_create(&thread, NULL, dogballs, NULL); + } +/* parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); @@ -112,10 +111,10 @@ static int app_exec(struct ast_channel *chan, void *data) if (ast_test_flag(&flags, OPTION_C)) ast_log(LOG_NOTICE, "Option C is set with : %s\n", opts[OPTION_ARG_C] ? opts[OPTION_ARG_C] : ""); - +*/ ast_module_user_remove(u); - return res; + return 0; } static int unload_module(void) diff --git a/include/asterisk/abstract_jb.h b/include/asterisk/abstract_jb.h index fc2bf5c90a..820e87cea7 100644 --- a/include/asterisk/abstract_jb.h +++ b/include/asterisk/abstract_jb.h @@ -212,6 +212,12 @@ void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf); */ void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf); +/*! + * \brief drops all frames from a jitterbuffer and resets it + * \param c0 one channel of a bridge + * \param c1 the other channel of the bridge + */ +void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/main/abstract_jb.c b/main/abstract_jb.c index 1fd4dcdcd6..226df462ba 100644 --- a/main/abstract_jb.c +++ b/main/abstract_jb.c @@ -70,7 +70,8 @@ typedef long (*jb_next_impl)(void *jb); 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. @@ -86,6 +87,7 @@ struct ast_jb_impl jb_next_impl next; jb_remove_impl remove; jb_force_resynch_impl force_resync; + jb_empty_and_reset_impl empty_and_reset; }; /* Implementation functions */ @@ -98,6 +100,7 @@ static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interp static long jb_next_fixed(void *jb); static int jb_remove_fixed(void *jb, struct ast_frame **fout); static void jb_force_resynch_fixed(void *jb); +static void jb_empty_and_reset_fixed(void *jb); /* adaptive */ static void * jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold); static void jb_destroy_adaptive(void *jb); @@ -107,6 +110,7 @@ static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long int static long jb_next_adaptive(void *jb); static int jb_remove_adaptive(void *jb, struct ast_frame **fout); static void jb_force_resynch_adaptive(void *jb); +static void jb_empty_and_reset_adaptive(void *jb); /* Available jb implementations */ static struct ast_jb_impl avail_impl[] = @@ -120,7 +124,8 @@ static struct ast_jb_impl avail_impl[] = .get = jb_get_fixed, .next = jb_next_fixed, .remove = jb_remove_fixed, - .force_resync = jb_force_resynch_fixed + .force_resync = jb_force_resynch_fixed, + .empty_and_reset = jb_empty_and_reset_fixed, }, { .name = "adaptive", @@ -131,7 +136,8 @@ static struct ast_jb_impl avail_impl[] = .get = jb_get_adaptive, .next = jb_next_adaptive, .remove = jb_remove_adaptive, - .force_resync = jb_force_resynch_adaptive + .force_resync = jb_force_resynch_adaptive, + .empty_and_reset = jb_empty_and_reset_adaptive, } }; @@ -226,7 +232,7 @@ int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1) } ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); } - + if (!c0_jb_created) { jb_choose_impl(c0); } @@ -608,22 +614,37 @@ void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf) memcpy(conf, &chan->jb.conf, sizeof(*conf)); } +void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1) +{ + struct ast_jb *jb0 = &c0->jb; + struct ast_jb *jb1 = &c1->jb; + int c0_use_jb = ast_test_flag(jb0, JB_USE); + int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); + int c1_use_jb = ast_test_flag(jb1, JB_USE); + int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); + + if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { + jb0->impl->empty_and_reset(jb0->jbobj); + } + + if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { + jb1->impl->empty_and_reset(jb1->jbobj); + } +} /* Implementation functions */ /* fixed */ - static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold) { struct fixed_jb_conf conf; - + conf.jbsize = general_config->max_size; conf.resync_threshold = resynch_threshold; - + return fixed_jb_new(&conf); } - static void jb_destroy_fixed(void *jb) { struct fixed_jb *fixedjb = (struct fixed_jb *) jb; @@ -696,6 +717,15 @@ static void jb_force_resynch_fixed(void *jb) fixed_jb_set_force_resynch(fixedjb); } +static void jb_empty_and_reset_fixed(void *jb) +{ + struct fixed_jb *fixedjb = jb; + struct fixed_jb_frame f; + + while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { + ast_frfree(f.data); + } +} /* adaptive */ @@ -778,3 +808,15 @@ static int jb_remove_adaptive(void *jb, struct ast_frame **fout) static void jb_force_resynch_adaptive(void *jb) { } + +static void jb_empty_and_reset_adaptive(void *jb) +{ + jitterbuf *adaptivejb = jb; + jb_frame f; + + while (jb_getall(adaptivejb, &f) == JB_OK) { + ast_frfree(f.data); + } + + jb_reset(adaptivejb); +} diff --git a/main/channel.c b/main/channel.c index fb51c20fa8..ecf84ac213 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3779,6 +3779,8 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct /* Check the need of a jitterbuffer for each channel */ jb_in_use = ast_jb_do_usecheck(c0, c1); + if (jb_in_use) + ast_jb_empty_and_reset(c0, c1); for (;;) { struct ast_channel *who, *other; @@ -3843,6 +3845,9 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct case AST_CONTROL_VIDUPDATE: case AST_CONTROL_SRCUPDATE: ast_indicate_data(other, f->subclass, f->data, f->datalen); + if (jb_in_use) { + ast_jb_empty_and_reset(c0, c1); + } break; default: *fo = f; diff --git a/main/fixedjitterbuf.h b/main/fixedjitterbuf.h index 541e99d2d5..868e24b663 100644 --- a/main/fixedjitterbuf.h +++ b/main/fixedjitterbuf.h @@ -85,7 +85,6 @@ int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout); void fixed_jb_set_force_resynch(struct fixed_jb *jb); - #if defined(__cplusplus) || defined(c_plusplus) } #endif