<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12737">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Benjamin Keith Ford: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">audiohook.c: Substitute silence for unavailable audio frames<br><br>There are 4 scenarios to consider when capturing audio from a channel<br>with an audiohook:<br><br> 1. There is no rx and no tx audio, so return nothing.<br> 2. There is rx but no tx audio, so return rx.<br> 3. There is tx but no rx audio, so return tx.<br> 4. There is rx and tx audio, so mix them and return.<br><br>The file passed as the primary argument to MixMonitor will be written to<br>in scenarios 2, 3, and 4. However, if you pass the r() and t() options<br>to MixMonitor, a frame will only be written to the r() file if there was<br>rx audio and a frame will only be written to the t() file if there was<br>tx audio.<br><br>If you subsequently take the r() and t() files and try to mix them, the<br>sides of the conversation will 'drift' and be non-representative of the<br>user experience.<br><br>This patch adds a new 'S' option to MixMonitor that injects a frame of<br>silence on either the r() side or the t() side of the channel so that<br>when later mixed, there is no such drift.<br><br>Change-Id: Ibf5ed73a811087727bd561a89a59f4447b4ee20e<br>---<br>M apps/app_mixmonitor.c<br>A doc/CHANGES-staging/mixmonitor-s-option.txt<br>M include/asterisk/audiohook.h<br>M main/audiohook.c<br>4 files changed, 32 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c</span><br><span>index af29492..6746c47 100644</span><br><span>--- a/apps/app_mixmonitor.c</span><br><span>+++ b/apps/app_mixmonitor.c</span><br><span>@@ -115,6 +115,11 @@</span><br><span> Like with the basic filename argument, if an absolute path isn't given, it will create</span><br><span> the file in the configured monitoring directory.</para></span><br><span> </option></span><br><span style="color: hsl(120, 100%, 40%);">+ <option name="S"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>When combined with the <replaceable>r</replaceable> or <replaceable>t</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+ option, inserts silence when necessary to maintain synchronization between the receive</span><br><span style="color: hsl(120, 100%, 40%);">+ and transmit audio streams.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </option></span><br><span> <option name="i"></span><br><span> <argument name="chanvar" required="true" /></span><br><span> <para>Stores the MixMonitor's ID on this channel variable.</para></span><br><span>@@ -347,7 +352,8 @@</span><br><span> MUXFLAG_VMRECIPIENTS = (1 << 10),</span><br><span> MUXFLAG_BEEP = (1 << 11),</span><br><span> MUXFLAG_BEEP_START = (1 << 12),</span><br><span style="color: hsl(0, 100%, 40%);">- MUXFLAG_BEEP_STOP = (1 << 13)</span><br><span style="color: hsl(120, 100%, 40%);">+ MUXFLAG_BEEP_STOP = (1 << 13),</span><br><span style="color: hsl(120, 100%, 40%);">+ MUXFLAG_RWSYNC = (1 << 14),</span><br><span> };</span><br><span> </span><br><span> enum mixmonitor_args {</span><br><span>@@ -359,6 +365,7 @@</span><br><span> OPT_ARG_UID,</span><br><span> OPT_ARG_VMRECIPIENTS,</span><br><span> OPT_ARG_BEEP_INTERVAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ OPT_ARG_RWSYNC,</span><br><span> OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */</span><br><span> };</span><br><span> </span><br><span>@@ -375,6 +382,7 @@</span><br><span> AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),</span><br><span> AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID),</span><br><span> AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_OPTION_ARG('S', MUXFLAG_RWSYNC, OPT_ARG_RWSYNC),</span><br><span> });</span><br><span> </span><br><span> struct mixmonitor_ds {</span><br><span>@@ -962,6 +970,9 @@</span><br><span> }</span><br><span> </span><br><span> ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((ast_test_flag(mixmonitor, MUXFLAG_RWSYNC))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (readvol)</span><br><span> mixmonitor->audiohook.options.read_volume = readvol;</span><br><span>diff --git a/doc/CHANGES-staging/mixmonitor-s-option.txt b/doc/CHANGES-staging/mixmonitor-s-option.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..d08b86d</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/mixmonitor-s-option.txt</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: app_mixmonitor</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+An option 'S' has been added to MixMonitor. If used in combination with</span><br><span style="color: hsl(120, 100%, 40%);">+the r() and/or t() options, if a frame is available to write to one of</span><br><span style="color: hsl(120, 100%, 40%);">+those files but not the other, a frame of silence if written to the file</span><br><span style="color: hsl(120, 100%, 40%);">+that does not have an audio frame. This should prevent the two files</span><br><span style="color: hsl(120, 100%, 40%);">+from "drifting" when mixed after the fact.</span><br><span>diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h</span><br><span>index cae8cc0..1252e36 100644</span><br><span>--- a/include/asterisk/audiohook.h</span><br><span>+++ b/include/asterisk/audiohook.h</span><br><span>@@ -64,6 +64,8 @@</span><br><span> AST_AUDIOHOOK_MUTE_READ = (1 << 5), /*!< audiohook should be mute frames read */</span><br><span> AST_AUDIOHOOK_MUTE_WRITE = (1 << 6), /*!< audiohook should be mute frames written */</span><br><span> AST_AUDIOHOOK_COMPATIBLE = (1 << 7), /*!< is the audiohook native slin compatible */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_AUDIOHOOK_SUBSTITUTE_SILENCE = (1 << 8), /*!< Substitute silence for missing audio */</span><br><span> };</span><br><span> </span><br><span> enum ast_audiohook_init_flags {</span><br><span>diff --git a/main/audiohook.c b/main/audiohook.c</span><br><span>index 04a379f..4db32ea 100644</span><br><span>--- a/main/audiohook.c</span><br><span>+++ b/main/audiohook.c</span><br><span>@@ -338,6 +338,17 @@</span><br><span> </span><br><span> frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Should we substitute silence if one side lacks audio? */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((ast_test_flag(audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (read_reference && !read_buf && write_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ read_buf = buf1;</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf1, 0, sizeof(buf1));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (write_reference && read_buf && !write_buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ write_buf = buf2;</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf2, 0, sizeof(buf2));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Basically we figure out which buffer to use... and if mixing can be done here */</span><br><span> if (read_buf && read_reference) {</span><br><span> frame.data.ptr = read_buf;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12737">change 12737</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/12737"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 17 </div>
<div style="display:none"> Gerrit-Change-Id: Ibf5ed73a811087727bd561a89a59f4447b4ee20e </div>
<div style="display:none"> Gerrit-Change-Number: 12737 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>