]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Updates follow_talker video_mode in confbridge application.
authorDavid Vossel <dvossel@digium.com>
Mon, 11 Jul 2011 18:44:06 +0000 (18:44 +0000)
committerDavid Vossel <dvossel@digium.com>
Mon, 11 Jul 2011 18:44:06 +0000 (18:44 +0000)
follow_talker mode originally echoed the same video stream
to all participants. As the primary talker switched around, the
video stream would result in the talker seeing themselves.  Now
the primary talker sees the last person who was talking rather than
themselves.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@327640 65c4cc65-6c06-0410-ace0-fbb531ad65f3

bridges/bridge_softmix.c
include/asterisk/bridging.h
main/bridging.c

index 8828d640a71cce851857885d89f1bb4efeb36d60..00b0556d05fc80c1377ac2c4e825881e2e29548f 100644 (file)
@@ -435,13 +435,30 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann
        }
 }
 
-static void softmix_pass_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
 {
        struct ast_bridge_channel *tmp;
        AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
                if (tmp->suspended) {
                        continue;
                }
+               if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) {
+                       ast_write(tmp->chan, frame);
+                       break;
+               }
+       }
+}
+
+static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame, int echo)
+{
+       struct ast_bridge_channel *tmp;
+       AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
+               if (tmp->suspended) {
+                       continue;
+               }
+               if ((tmp->chan == bridge_channel->chan) && !echo) {
+                       continue;
+               }
                ast_write(tmp->chan, frame);
        }
 }
@@ -472,20 +489,26 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
 
        /* Determine if this video frame should be distributed or not */
        if (frame->frametype == AST_FRAME_VIDEO) {
+               int num_src = ast_bridge_number_video_src(bridge);
+               int video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
+
                switch (bridge->video_mode.mode) {
                case AST_BRIDGE_VIDEO_MODE_NONE:
                        break;
                case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
-                       if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) {
-                               softmix_pass_video(bridge, bridge_channel, frame);
+                       if (video_src_priority == 1) {
+                               softmix_pass_video_all(bridge, bridge_channel, frame, 1);
                        }
                        break;
                case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
                        ast_mutex_lock(&sc->lock);
                        ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan, sc->video_talker.energy_average, ast_format_get_video_mark(&frame->subclass.format));
                        ast_mutex_unlock(&sc->lock);
-                       if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) {
-                               softmix_pass_video(bridge, bridge_channel, frame);
+                       if (video_src_priority == 1) {
+                               int echo = num_src > 1 ? 0 : 1;
+                               softmix_pass_video_all(bridge, bridge_channel, frame, echo);
+                       } else if (video_src_priority == 2) {
+                               softmix_pass_video_top_priority(bridge, frame);
                        }
                        break;
                }
index 849f88741630158b2a3450d940ef32c49df8e073..54137b0283097388eea27b15009f2be3764b3ee4 100644 (file)
@@ -190,6 +190,9 @@ struct ast_bridge_video_talker_src_data {
        /*! Only accept video coming from this channel */
        struct ast_channel *chan_vsrc;
        int average_talking_energy;
+
+       /*! Current talker see's this person */
+       struct ast_channel *chan_old_vsrc;
 };
 
 struct ast_bridge_video_mode {
@@ -527,8 +530,18 @@ void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge);
  */
 void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyfame);
 
+/*!
+ * \brief Returns the number of video sources currently active in the bridge
+ */
+int ast_bridge_number_video_src(struct ast_bridge *bridge);
+
 /*!
  * \brief Determine if a channel is a video src for the bridge
+ *
+ * \retval 0 Not a current video source of the bridge.
+ * \retval None 0, is a video source of the bridge, The number
+ *         returned represents the priority this video stream has
+ *         on the bridge where 1 is the highest priority.
  */
 int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan);
 
index 1563e478927653b45d30820cbdd3438383d187ab..835a849fbab74576a2cfd0e666cec09396ff5b29 100644 (file)
@@ -1489,6 +1489,9 @@ static void cleanup_video_mode(struct ast_bridge *bridge)
                if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
                        ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc);
                }
+               if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+                       ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc);
+               }
        }
        memset(&bridge->video_mode, 0, sizeof(bridge->video_mode));
 }
@@ -1525,20 +1528,51 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a
        if (data->chan_vsrc == chan) {
                data->average_talking_energy = talker_energy;
        } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
+               if (data->chan_old_vsrc) {
+                       ast_channel_unref(data->chan_old_vsrc);
+               }
                if (data->chan_vsrc) {
-                       ast_channel_unref(data->chan_vsrc);
+                       data->chan_old_vsrc = data->chan_vsrc;
+                       ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE);
                }
                data->chan_vsrc = ast_channel_ref(chan);
                data->average_talking_energy = talker_energy;
-               ast_indicate(chan, AST_CONTROL_VIDUPDATE);
        } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
                ast_indicate(chan, AST_CONTROL_VIDUPDATE);
        } else if (!data->chan_vsrc && is_keyframe) {
                data->chan_vsrc = ast_channel_ref(chan);
                data->average_talking_energy = talker_energy;
                ast_indicate(chan, AST_CONTROL_VIDUPDATE);
+       } else if (!data->chan_old_vsrc && is_keyframe) {
+               data->chan_old_vsrc = ast_channel_ref(chan);
+               ast_indicate(chan, AST_CONTROL_VIDUPDATE);
+       }
+       ao2_unlock(bridge);
+}
+
+int ast_bridge_number_video_src(struct ast_bridge *bridge)
+{
+       int res = 0;
+
+       ao2_lock(bridge);
+       switch (bridge->video_mode.mode) {
+       case AST_BRIDGE_VIDEO_MODE_NONE:
+               break;
+       case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
+               if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) {
+                       res = 1;
+               }
+               break;
+       case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
+               if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
+                       res++;
+               }
+               if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+                       res++;
+               }
        }
        ao2_unlock(bridge);
+       return res;
 }
 
 int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
@@ -1557,7 +1591,10 @@ int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
        case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
                if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) {
                        res = 1;
+               } else if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
+                       res = 2;
                }
+
        }
        ao2_unlock(bridge);
        return res;
@@ -1583,6 +1620,13 @@ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *
                                ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc);
                        }
                        bridge->video_mode.mode_data.talker_src_data.chan_vsrc = NULL;
+                       bridge->video_mode.mode_data.talker_src_data.average_talking_energy = 0;
+               }
+               if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
+                       if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+                               ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc);
+                       }
+                       bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc = NULL;
                }
        }
        ao2_unlock(bridge);