bridge_softmix.c: Report not talking immediately when muted.
authorRichard Mudgett <rmudgett@digium.com>
Wed, 31 Jan 2018 01:22:51 +0000 (19:22 -0600)
committerRichard Mudgett <rmudgett@digium.com>
Wed, 31 Jan 2018 19:14:40 +0000 (13:14 -0600)
Currently in app_confbridge if someone mutes a channel while that channel
is talking, the talk detection code is suspended while the channel is
muted.  As far an an external observer is concerned, the muted channel's
talk status is still "talking" even though the channel is not contributing
audio to the conference bridge.  When the channel is later unmuted, it
takes the usual 'dsp_silence_threshold' option time to clear the talking
status even though the channel may have stopped talking while the channel
was muted.

* In bridge_softmix.c, clear the talking status and report talking stopped
if the channel was talking when the channel is muted.  When the channel is
unmuted and the channel is still talking then report the channel as
talking since it is contributing audio to the bridge again.

ASTERISK-27647

Change-Id: Ie4fdbc05a0bc7343c2972bab012e2567917b3d4e

bridges/bridge_softmix.c

index 1ff92ad..461b6e5 100644 (file)
@@ -860,12 +860,17 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
 {
        struct softmix_channel *sc = bridge_channel->tech_pvt;
        struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
+       int silent = 0;
        int totalsilence = 0;
        int cur_energy = 0;
        int silence_threshold = bridge_channel->tech_args.silence_threshold ?
                bridge_channel->tech_args.silence_threshold :
                DEFAULT_SOFTMIX_SILENCE_THRESHOLD;
-       char update_talking = -1;  /* if this is set to 0 or 1, tell the bridge that the channel has started or stopped talking. */
+       /*
+        * If update_talking is set to 0 or 1, tell the bridge that the channel
+        * has started or stopped talking.
+        */
+       char update_talking = -1;
 
        /* Write the frame into the conference */
        ast_mutex_lock(&sc->lock);
@@ -893,7 +898,7 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
 
        /* The channel will be leaving soon if there is no dsp. */
        if (sc->dsp) {
-               ast_dsp_silence_with_energy(sc->dsp, frame, &totalsilence, &cur_energy);
+               silent = ast_dsp_silence_with_energy(sc->dsp, frame, &totalsilence, &cur_energy);
        }
 
        if (bridge->softmix.video_mode.mode == AST_BRIDGE_VIDEO_MODE_TALKER_SRC) {
@@ -910,15 +915,16 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
        }
 
        if (totalsilence < silence_threshold) {
-               if (!sc->talking) {
+               if (!sc->talking && !silent) {
+                       /* Tell the write process we have audio to be mixed out */
+                       sc->talking = 1;
                        update_talking = 1;
                }
-               sc->talking = 1; /* tell the write process we have audio to be mixed out */
        } else {
                if (sc->talking) {
+                       sc->talking = 0;
                        update_talking = 0;
                }
-               sc->talking = 0;
        }
 
        /* Before adding audio in, make sure we haven't fallen behind. If audio has fallen
@@ -928,9 +934,8 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
                ast_slinfactory_flush(&sc->factory);
        }
 
-       /* If a frame was provided add it to the smoother, unless drop silence is enabled and this frame
-        * is not determined to be talking. */
-       if (!(bridge_channel->tech_args.drop_silence && !sc->talking)) {
+       if (sc->talking || !bridge_channel->tech_args.drop_silence) {
+               /* Add frame to the smoother for mixing with other channels. */
                ast_slinfactory_feed(&sc->factory, frame);
        }
 
@@ -942,6 +947,38 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
        }
 }
 
+/*!
+ * \internal
+ * \brief Check for voice status updates.
+ * \since 13.20.0
+ *
+ * \param bridge Which bridge we are in
+ * \param bridge_channel Which channel we are checking
+ *
+ * \return Nothing
+ */
+static void softmix_bridge_check_voice(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+       struct softmix_channel *sc = bridge_channel->tech_pvt;
+
+       if (sc->talking
+               && bridge_channel->features->mute) {
+               /*
+                * We were muted while we were talking.
+                *
+                * Immediately stop contributing to mixing
+                * and report no longer talking.
+                */
+               ast_mutex_lock(&sc->lock);
+               ast_slinfactory_flush(&sc->factory);
+               sc->talking = 0;
+               ast_mutex_unlock(&sc->lock);
+
+               /* Notify that we are no longer talking. */
+               ast_bridge_channel_notify_talking(bridge_channel, 0);
+       }
+}
+
 static int remove_all_original_streams(struct ast_stream_topology *dest,
        const struct ast_stream_topology *source,
        const struct ast_stream_topology *original)
@@ -1119,6 +1156,7 @@ static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha
        switch (frame->frametype) {
        case AST_FRAME_NULL:
                /* "Accept" the frame and discard it. */
+               softmix_bridge_check_voice(bridge, bridge_channel);
                break;
        case AST_FRAME_DTMF_BEGIN:
        case AST_FRAME_DTMF_END: