diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index af2949209056d91034ca12b886501bc5029a3def..6746c473cf733e4b88cd42e46dfee71349f6e576 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -115,6 +115,11 @@ Like with the basic filename argument, if an absolute path isn't given, it will create the file in the configured monitoring directory.</para> </option> + <option name="S"> + <para>When combined with the <replaceable>r</replaceable> or <replaceable>t</replaceable> + option, inserts silence when necessary to maintain synchronization between the receive + and transmit audio streams.</para> + </option> <option name="i"> <argument name="chanvar" required="true" /> <para>Stores the MixMonitor's ID on this channel variable.</para> @@ -347,7 +352,8 @@ enum mixmonitor_flags { MUXFLAG_VMRECIPIENTS = (1 << 10), MUXFLAG_BEEP = (1 << 11), MUXFLAG_BEEP_START = (1 << 12), - MUXFLAG_BEEP_STOP = (1 << 13) + MUXFLAG_BEEP_STOP = (1 << 13), + MUXFLAG_RWSYNC = (1 << 14), }; enum mixmonitor_args { @@ -359,6 +365,7 @@ enum mixmonitor_args { OPT_ARG_UID, OPT_ARG_VMRECIPIENTS, OPT_ARG_BEEP_INTERVAL, + OPT_ARG_RWSYNC, OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */ }; @@ -375,6 +382,7 @@ AST_APP_OPTIONS(mixmonitor_opts, { AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME), AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID), AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS), + AST_APP_OPTION_ARG('S', MUXFLAG_RWSYNC, OPT_ARG_RWSYNC), }); struct mixmonitor_ds { @@ -962,6 +970,9 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename, } ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC); + if ((ast_test_flag(mixmonitor, MUXFLAG_RWSYNC))) { + ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE); + } if (readvol) mixmonitor->audiohook.options.read_volume = readvol; diff --git a/doc/CHANGES-staging/mixmonitor-s-option.txt b/doc/CHANGES-staging/mixmonitor-s-option.txt new file mode 100644 index 0000000000000000000000000000000000000000..d08b86d3fc3acfb7e3a12647c3a11aa10699abe4 --- /dev/null +++ b/doc/CHANGES-staging/mixmonitor-s-option.txt @@ -0,0 +1,7 @@ +Subject: app_mixmonitor + +An option 'S' has been added to MixMonitor. If used in combination with +the r() and/or t() options, if a frame is available to write to one of +those files but not the other, a frame of silence if written to the file +that does not have an audio frame. This should prevent the two files +from "drifting" when mixed after the fact. diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h index cae8cc0711902699b9163f5fc416d7b56f3c4088..1252e3655b63ab1143260ada36d3b3e026809cab 100644 --- a/include/asterisk/audiohook.h +++ b/include/asterisk/audiohook.h @@ -64,6 +64,8 @@ enum ast_audiohook_flags { AST_AUDIOHOOK_MUTE_READ = (1 << 5), /*!< audiohook should be mute frames read */ AST_AUDIOHOOK_MUTE_WRITE = (1 << 6), /*!< audiohook should be mute frames written */ AST_AUDIOHOOK_COMPATIBLE = (1 << 7), /*!< is the audiohook native slin compatible */ + + AST_AUDIOHOOK_SUBSTITUTE_SILENCE = (1 << 8), /*!< Substitute silence for missing audio */ }; enum ast_audiohook_init_flags { diff --git a/main/audiohook.c b/main/audiohook.c index 04a379fefe190042c5fd52ca00e42e76d4e341cb..4db32ea7c0de0222150306e4d46a4f9e80bece3f 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -338,6 +338,17 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate); + /* Should we substitute silence if one side lacks audio? */ + if ((ast_test_flag(audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE))) { + if (read_reference && !read_buf && write_buf) { + read_buf = buf1; + memset(buf1, 0, sizeof(buf1)); + } else if (write_reference && read_buf && !write_buf) { + write_buf = buf2; + memset(buf2, 0, sizeof(buf2)); + } + } + /* Basically we figure out which buffer to use... and if mixing can be done here */ if (read_buf && read_reference) { frame.data.ptr = read_buf;