<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12735">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; 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 9f14776..ecb0830 100644</span><br><span>--- a/apps/app_mixmonitor.c</span><br><span>+++ b/apps/app_mixmonitor.c</span><br><span>@@ -117,6 +117,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>@@ -349,7 +354,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>@@ -361,6 +367,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>@@ -377,6 +384,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>@@ -967,6 +975,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 cb3c4bc..3feb114 100644</span><br><span>--- a/main/audiohook.c</span><br><span>+++ b/main/audiohook.c</span><br><span>@@ -335,6 +335,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/+/12735">change 12735</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/+/12735"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: Ibf5ed73a811087727bd561a89a59f4447b4ee20e </div>
<div style="display:none"> Gerrit-Change-Number: 12735 </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-Reviewer: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>