]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merging the issue11259 branch.
authorMark Michelson <mmichelson@digium.com>
Wed, 6 Aug 2008 00:25:10 +0000 (00:25 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 6 Aug 2008 00:25:10 +0000 (00:25 +0000)
The purpose of this branch was to take into account
"burps" which could cause jitterbuffers to misbehave.
One such example is if the L option to Dial() were used
to inject audio into a bridged conversation at regular
intervals. Since the audio here was not passed through
the jitterbuffer, it would cause a gap in the jitterbuffer's
timestamps which would cause a frames to be dropped for a
brief period.

Now ast_generic_bridge will empty and reset the jitterbuffer
each time it is called. This causes injected audio to be handled
properly.

ast_generic_bridge also will empty and reset the jitterbuffer
if it receives an AST_CONTROL_SRCUPDATE frame since the change
in audio source could negatively affect the jitterbuffer.

All of this was made possible by adding a new public API call
to the abstract_jb called ast_jb_empty_and_reset.

(closes issue #11259)
Reported by: plack
Tested by: putnopvut

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@135841 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_skel.c
include/asterisk/abstract_jb.h
main/abstract_jb.c
main/channel.c
main/fixedjitterbuf.h

index 55830ebee86fdf0f239c971946f35c793edddf2f..5fdd98a44d29b97e6acdaf06a44bcfa2809e5c90 100644 (file)
@@ -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] : "<unspecified>");
-
+*/
        ast_module_user_remove(u);
 
-       return res;
+       return 0;
 }
 
 static int unload_module(void)
index fc2bf5c90a3b4e23ef0e701d4b588bb6529326a2..820e87cea7ccf713662a004a6301813df17b7563 100644 (file)
@@ -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)
 }
index 1fd4dcdcd6a7adfa7bfadd4f0bda0de1b5a2ffec..226df462bac2532a4d0c2b1bc25db689eee4460b 100644 (file)
@@ -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);
+}
index fb51c20fa8b07b72b176b8392c5de068a2a96a1e..ecf84ac213ee8cd945d10dd554b62c1b0b464bc1 100644 (file)
@@ -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;
index 541e99d2d597834d0a6dab46ab44daf07840bb2c..868e24b663d6779b11edb7a659a56631b789add7 100644 (file)
@@ -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