summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-04-04 19:19:55 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-04-04 19:19:55 +0000
commit03beadb6e9d88d4c99d097a45e87267a6b2f36b4 (patch)
tree15296cb9e2f13ea6397dd6e163a2397e5f9f7965 /main/channel.c
parent9be438299d47e71a36d252ea55d5432ac751504f (diff)
internal_timing: Remove the option and always make it enabled if a timing module is loaded.
The masquerade supertest frequently fails because either the local channel chain doesn't completely optimize out or the DTMF handshake doesn't completely get accross. Local channel optimization requires frames flowing to trigger when optimization can happen. When optimization happens the media frame that triggered the optimization is dropped. Sending DTMF requires frames to flow in the other direction for timing purposes while sending nothing. If internal timing is not enabled when MOH is playing, Asterisk switches to received timing when an audio frame is received. With optimization dropping media frames and MOH not sending frames unless it receives frames, occasionaly there are no more frames being passed and the test fails. * The asterisk command line -I option and the asterisk.conf internal_timing option are removed. Asterisk now always uses internal timing when needed if any timing module is loaded. The issue ASTERISK-14861 did this quite awhile ago in v1.4 but effectively is broken if other internal timing modules besides DAHDI are used. The ast_read_generator_actions() now only does received timing if it has no choice for frame generators like MOH, silence, and playback streaming. * Cleaned up some code dealing with frame generators in ast_deactivate_generator(), generator_write_format_change(), ast_activate_generator(), and ast_channel_stop_silence_generator(). * Removed ast_internal_timing_enabled(), AST_OPT_FLAG_INTERNAL_TIMING, and ast_opt_internal_timing. ASTERISK-22846 #close Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/3414/ ........ Merged revisions 411715 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 411716 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 411717 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@411724 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c138
1 files changed, 74 insertions, 64 deletions
diff --git a/main/channel.c b/main/channel.c
index 23ea4b7c0..94b0e8b1c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2943,12 +2943,13 @@ int ast_channel_get_up_time(struct ast_channel *chan)
return (ast_tvdiff_ms(ast_tvnow(), ast_channel_answertime(chan)) / 1000);
}
-void ast_deactivate_generator(struct ast_channel *chan)
+static void deactivate_generator_nolock(struct ast_channel *chan)
{
- ast_channel_lock(chan);
if (ast_channel_generatordata(chan)) {
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
+ struct ast_generator *generator = ast_channel_generator(chan);
+
+ if (generator && generator->release) {
+ generator->release(chan, ast_channel_generatordata(chan));
}
ast_channel_generatordata_set(chan, NULL);
ast_channel_generator_set(chan, NULL);
@@ -2956,14 +2957,23 @@ void ast_deactivate_generator(struct ast_channel *chan)
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
ast_settimeout(chan, 0, NULL, NULL);
}
+}
+
+void ast_deactivate_generator(struct ast_channel *chan)
+{
+ ast_channel_lock(chan);
+ deactivate_generator_nolock(chan);
ast_channel_unlock(chan);
}
static void generator_write_format_change(struct ast_channel *chan)
{
+ struct ast_generator *generator;
+
ast_channel_lock(chan);
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->write_format_change) {
- ast_channel_generator(chan)->write_format_change(chan, ast_channel_generatordata(chan));
+ generator = ast_channel_generator(chan);
+ if (generator && generator->write_format_change) {
+ generator->write_format_change(chan, ast_channel_generatordata(chan));
}
ast_channel_unlock(chan);
}
@@ -3009,8 +3019,10 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
ast_channel_lock(chan);
if (ast_channel_generatordata(chan)) {
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
+ struct ast_generator *generator_old = ast_channel_generator(chan);
+
+ if (generator_old && generator_old->release) {
+ generator_old->release(chan, ast_channel_generatordata(chan));
}
}
if (gen->alloc && !(generatordata = gen->alloc(chan, params))) {
@@ -3642,49 +3654,57 @@ static void send_dtmf_end_event(struct ast_channel *chan,
static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f)
{
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->generate && ast_channel_generatordata(chan) && !ast_internal_timing_enabled(chan)) {
- void *tmp = ast_channel_generatordata(chan);
- int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = ast_channel_generator(chan)->generate;
- int res;
- int samples;
+ struct ast_generator *generator;
+ void *gendata;
+ int res;
+ int samples;
+
+ generator = ast_channel_generator(chan);
+ if (!generator
+ || !generator->generate
+ || f->frametype != AST_FRAME_VOICE
+ || !ast_channel_generatordata(chan)
+ || ast_channel_timingfunc(chan)) {
+ return;
+ }
- if (ast_channel_timingfunc(chan)) {
- ast_debug(1, "Generator got voice, switching to phase locked mode\n");
- ast_settimeout(chan, 0, NULL, NULL);
- }
+ /*
+ * We must generate frames in phase locked mode since
+ * we have no internal timer available.
+ */
- ast_channel_generatordata_set(chan, NULL); /* reset, to let writes go through */
+ if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ float factor;
- if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
- float factor;
- factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
- samples = (int) ( ((float) f->samples) * factor );
- } else {
- samples = f->samples;
- }
+ factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
+ samples = (int) (((float) f->samples) * factor);
+ } else {
+ samples = f->samples;
+ }
- /* This unlock is here based on two assumptions that hold true at this point in the
- * code. 1) this function is only called from within __ast_read() and 2) all generators
- * call ast_write() in their generate callback.
- *
- * The reason this is added is so that when ast_write is called, the lock that occurs
- * there will not recursively lock the channel. Doing this will cause intended deadlock
- * avoidance not to work in deeper functions
- */
- ast_channel_unlock(chan);
- res = generate(chan, tmp, f->datalen, samples);
- ast_channel_lock(chan);
- ast_channel_generatordata_set(chan, tmp);
+ gendata = ast_channel_generatordata(chan);
+ ast_channel_generatordata_set(chan, NULL); /* reset, to let writes go through */
+
+ /*
+ * This unlock is here based on two assumptions that hold true at
+ * this point in the code. 1) this function is only called from
+ * within __ast_read() and 2) all generators call ast_write() in
+ * their generate callback.
+ *
+ * The reason this is added is so that when ast_write is called,
+ * the lock that occurs there will not recursively lock the
+ * channel. Doing this will allow deadlock avoidance to work in
+ * deeper functions.
+ */
+ ast_channel_unlock(chan);
+ res = generator->generate(chan, gendata, f->datalen, samples);
+ ast_channel_lock(chan);
+ if (generator == ast_channel_generator(chan)) {
+ ast_channel_generatordata_set(chan, gendata);
if (res) {
ast_debug(1, "Auto-deactivating generator\n");
ast_deactivate_generator(chan);
}
-
- } else if (f->frametype == AST_FRAME_CNG) {
- if (ast_channel_generator(chan) && !ast_channel_timingfunc(chan) && (ast_channel_timingfd(chan) > -1)) {
- ast_debug(1, "Generator got CNG, switching to timed mode\n");
- ast_settimeout(chan, 50, generator_force, chan);
- }
}
}
@@ -4265,11 +4285,6 @@ done:
return f;
}
-int ast_internal_timing_enabled(struct ast_channel *chan)
-{
- return (ast_opt_internal_timing && ast_channel_timingfd(chan) > -1);
-}
-
struct ast_frame *ast_read(struct ast_channel *chan)
{
return __ast_read(chan, 0);
@@ -7693,30 +7708,24 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha
return state;
}
-static int internal_deactivate_generator(struct ast_channel *chan, void* generator)
+static int deactivate_silence_generator(struct ast_channel *chan)
{
ast_channel_lock(chan);
if (!ast_channel_generatordata(chan)) {
- ast_debug(1, "Trying to stop silence generator when there is no "
- "generator on '%s'\n", ast_channel_name(chan));
+ ast_debug(1, "Trying to stop silence generator when there is no generator on '%s'\n",
+ ast_channel_name(chan));
ast_channel_unlock(chan);
return 0;
}
- if (ast_channel_generator(chan) != generator) {
- ast_debug(1, "Trying to stop silence generator when it is not the current "
- "generator on '%s'\n", ast_channel_name(chan));
+ if (ast_channel_generator(chan) != &silence_generator) {
+ ast_debug(1, "Trying to stop silence generator when it is not the current generator on '%s'\n",
+ ast_channel_name(chan));
ast_channel_unlock(chan);
return 0;
}
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
- }
- ast_channel_generatordata_set(chan, NULL);
- ast_channel_generator_set(chan, NULL);
- ast_channel_set_fd(chan, AST_GENERATOR_FD, -1);
- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
- ast_settimeout(chan, 0, NULL, NULL);
+ deactivate_generator_nolock(chan);
+
ast_channel_unlock(chan);
return 1;
@@ -7724,10 +7733,11 @@ static int internal_deactivate_generator(struct ast_channel *chan, void* generat
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
{
- if (!state)
+ if (!state) {
return;
+ }
- if (internal_deactivate_generator(chan, &silence_generator)) {
+ if (deactivate_silence_generator(chan)) {
ast_debug(1, "Stopped silence generator on '%s'\n", ast_channel_name(chan));
if (ast_set_write_format(chan, &state->old_write_format) < 0)
ast_log(LOG_ERROR, "Could not return write format to its original state\n");