bridge_softmix: Add SDP "label" attribute to streams
authorGeorge Joseph <gjoseph@digium.com>
Tue, 16 Oct 2018 12:02:19 +0000 (06:02 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Wed, 24 Oct 2018 13:41:23 +0000 (08:41 -0500)
Adding the "label" attribute used for participant info correlation
was previously done in app_confbridge but it wasn't working
correctly because it didn't have knowledge about which video
streams belonged to which channel.  Only bridge_softmix has that
data so now it's set when the bridge topology is changed.

ASTERISK-28107

Change-Id: Ieddeca5799d710cad083af3fcc3e677fa2a2a499

apps/app_confbridge.c
apps/confbridge/confbridge_manager.c
bridges/bridge_softmix.c
include/asterisk/bridge.h
main/bridge.c

index edb7e03..5936400 100644 (file)
@@ -1568,6 +1568,10 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
                        }
                }
 
+               if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) {
+                       ast_bridge_set_send_sdp_label(conference->bridge, 1);
+               }
+
                /* Link it into the conference bridges container */
                if (!ao2_link(conference_bridges, conference)) {
                        ao2_ref(conference, -1);
index a7f2fce..e88bbc2 100644 (file)
@@ -355,56 +355,6 @@ static struct ast_json *pack_snapshots(    struct ast_bridge_snapshot *bridge_snaps
        return pack_bridge_and_channels(json_bridge, json_channel, msg);
 }
 
-enum label_direction {
-       LABEL_DIRECTION_SRC,
-       LABEL_DIRECTION_DEST,
-};
-
-static struct ast_stream *get_stream(struct ast_stream_topology *topology,
-       enum ast_media_type m_type)
-{
-       int count;
-       int i;
-
-       count = ast_stream_topology_get_count(topology);
-       if (count < 0) {
-               return NULL;
-       }
-
-       for (i = 0; i < count; i++) {
-               struct ast_stream *s;
-               enum ast_stream_state s_state;
-               enum ast_media_type s_type;
-
-               s = ast_stream_topology_get_stream(topology, i);
-               s_state = ast_stream_get_state(s);
-               s_type = ast_stream_get_type(s);
-               if (s_type == m_type
-                       && (s_state == AST_STREAM_STATE_SENDRECV || s_state == AST_STREAM_STATE_RECVONLY)) {
-                       return s;
-               }
-       }
-
-       return NULL;
-}
-
-static void set_media_labels(struct confbridge_conference *conference,
-       struct ast_channel *src_chan, struct ast_channel *dest_chan, enum label_direction dir)
-{
-       struct ast_stream_topology *topology;
-       struct ast_stream *stream;
-       struct ast_channel *chan = dir == LABEL_DIRECTION_SRC ? dest_chan : src_chan;
-
-       if (!chan) {
-               return;
-       }
-       topology = ast_channel_get_stream_topology(chan);
-       stream = get_stream(topology, AST_MEDIA_TYPE_VIDEO);
-       if (stream) {
-               ast_stream_set_metadata(stream, "SDP:LABEL", ast_channel_uniqueid(chan));
-       }
-}
-
 static void send_message(const char *msg_name, char *conf_name, struct ast_json *json_object,
        struct ast_channel *chan)
 {
@@ -508,7 +458,6 @@ void conf_send_event_to_participants(struct confbridge_conference *conference,
                                continue;
                        }
 
-                       set_media_labels(conference, chan, user->chan, LABEL_DIRECTION_SRC);
                        target_json_channel = channel_to_json(target_snapshot, extras, NULL);
                        ao2_ref(target_snapshot, -1);
 
@@ -538,8 +487,6 @@ void conf_send_event_to_participants(struct confbridge_conference *conference,
                        continue;
                }
 
-               set_media_labels(conference, chan, user->chan, LABEL_DIRECTION_DEST);
-
                json_object = pack_snapshots(obj->bridge, obj->channel, extras, NULL, msg);
 
                if (!json_object) {
index b11fccc..cf61340 100644 (file)
@@ -498,7 +498,7 @@ static int is_video_dest(const struct ast_stream *stream, const char *source_cha
 }
 
 static int append_source_streams(struct ast_stream_topology *dest,
-       const char *channel_name,
+       const char *channel_name, const char *sdp_label,
        const struct ast_stream_topology *source)
 {
        int i;
@@ -523,6 +523,12 @@ static int append_source_streams(struct ast_stream_topology *dest,
                if (!stream_clone) {
                        return -1;
                }
+
+               /* Sends an "a:label" attribute in the SDP for participant event correlation */
+               if (!ast_strlen_zero(sdp_label)) {
+                       ast_stream_set_metadata(stream_clone, "SDP:LABEL", sdp_label);
+               }
+
                if (ast_stream_topology_append_stream(dest, stream_clone) < 0) {
                        ast_stream_free(stream_clone);
                        return -1;
@@ -585,9 +591,11 @@ static int append_all_streams(struct ast_stream_topology *dest,
  * \param joiner The channel that is joining the softmix bridge
  * \param participants The current participants in the softmix bridge
  */
-static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast_bridge_channels_list *participants)
+static void sfu_topologies_on_join(struct ast_bridge *bridge,
+       struct ast_bridge_channel *joiner)
 {
        struct ast_stream_topology *joiner_video = NULL;
+       struct ast_bridge_channels_list *participants = &bridge->channels;
        struct ast_bridge_channel *participant;
        int res;
        struct softmix_channel *sc;
@@ -600,7 +608,9 @@ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast
        sc = joiner->tech_pvt;
 
        ast_channel_lock(joiner->chan);
-       res = append_source_streams(joiner_video, ast_channel_name(joiner->chan), ast_channel_get_stream_topology(joiner->chan));
+       res = append_source_streams(joiner_video, ast_channel_name(joiner->chan),
+               bridge->softmix.send_sdp_label ? ast_channel_uniqueid(joiner->chan) : NULL,
+               ast_channel_get_stream_topology(joiner->chan));
        sc->topology = ast_stream_topology_clone(ast_channel_get_stream_topology(joiner->chan));
        ast_channel_unlock(joiner->chan);
 
@@ -614,7 +624,8 @@ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast
                }
                ast_channel_lock(participant->chan);
                res = append_source_streams(sc->topology, ast_channel_name(participant->chan),
-                               ast_channel_get_stream_topology(participant->chan));
+                       bridge->softmix.send_sdp_label ? ast_channel_uniqueid(participant->chan) : NULL,
+                       ast_channel_get_stream_topology(participant->chan));
                ast_channel_unlock(participant->chan);
                if (res) {
                        goto cleanup;
@@ -704,7 +715,7 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan
                bridge_channel, 0, set_binaural, pos_id, is_announcement);
 
        if (bridge->softmix.video_mode.mode == AST_BRIDGE_VIDEO_MODE_SFU) {
-               sfu_topologies_on_join(bridge_channel, &bridge->channels);
+               sfu_topologies_on_join(bridge, bridge_channel);
        }
 
        softmix_poke_thread(softmix_data);
@@ -1063,9 +1074,11 @@ static int remove_all_original_streams(struct ast_stream_topology *dest,
        return 0;
 }
 
-static void sfu_topologies_on_source_change(struct ast_bridge_channel *source, struct ast_bridge_channels_list *participants)
+static void sfu_topologies_on_source_change(struct ast_bridge *bridge,
+       struct ast_bridge_channel *source)
 {
        struct ast_stream_topology *source_video = NULL;
+       struct ast_bridge_channels_list *participants = &bridge->channels;
        struct ast_bridge_channel *participant;
        int res;
 
@@ -1075,7 +1088,9 @@ static void sfu_topologies_on_source_change(struct ast_bridge_channel *source, s
        }
 
        ast_channel_lock(source->chan);
-       res = append_source_streams(source_video, ast_channel_name(source->chan), ast_channel_get_stream_topology(source->chan));
+       res = append_source_streams(source_video, ast_channel_name(source->chan),
+               bridge->softmix.send_sdp_label ? ast_channel_uniqueid(source->chan) : NULL,
+               ast_channel_get_stream_topology(source->chan));
        ast_channel_unlock(source->chan);
        if (res) {
                goto cleanup;
@@ -1198,7 +1213,7 @@ static int softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_br
                break;
        case AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED:
                if (bridge->softmix.video_mode.mode == AST_BRIDGE_VIDEO_MODE_SFU) {
-                       sfu_topologies_on_source_change(bridge_channel, &bridge->channels);
+                       sfu_topologies_on_source_change(bridge, bridge_channel);
                }
                break;
        default:
@@ -2383,7 +2398,7 @@ AST_TEST_DEFINE(sfu_append_source_streams)
                goto end;
        }
 
-       if (append_source_streams(topology_alice, "PJSIP/Bob-00000001", topology_bob)) {
+       if (append_source_streams(topology_alice, "PJSIP/Bob-00000001", NULL, topology_bob)) {
                ast_test_status_update(test, "Failed to append Bob's streams to Alice\n");
                goto end;
        }
@@ -2402,7 +2417,7 @@ AST_TEST_DEFINE(sfu_append_source_streams)
                goto end;
        }
 
-       if (append_source_streams(topology_bob, "PJSIP/Alice-00000000", topology_alice)) {
+       if (append_source_streams(topology_bob, "PJSIP/Alice-00000000", NULL, topology_alice)) {
                ast_test_status_update(test, "Failed to append Alice's streams to Bob\n");
                goto end;
        }
index 3584085..f4b1df8 100644 (file)
@@ -290,6 +290,11 @@ struct ast_bridge_softmix {
        unsigned int internal_mixing_interval;
        /*! TRUE if binaural convolve is activated in configuration. */
        unsigned int binaural_active;
+       /*!
+        * Add a "label" attribute to each stream in the SDP containing
+        * the channel uniqueid.  Used for participant info correlation.
+        */
+       unsigned int send_sdp_label;
 };
 
 AST_LIST_HEAD_NOLOCK(ast_bridge_channels_list, ast_bridge_channel);
@@ -986,6 +991,20 @@ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *
 const char *ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type video_mode);
 
 /*!
+ * \brief Controls whether to send a "label" attribute in each stream in an SDP
+ * \since 16.1.0
+ *
+ * \param bridge The bridge
+ * \param send_sdp_label Whether to send the labels or not
+ *
+ * \note The label will contain the uniqueid of the channel related to the stream.
+ * This is used to allow the recipient to correlate the stream to the participant
+ * information events sent by app_confbridge.
+ * The bridge will be locked in this function.
+ */
+void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label);
+
+/*!
  * \brief Acquire the channel's bridge for transfer purposes.
  * \since 13.21.0
  *
index db49180..d6e7a51 100644 (file)
@@ -4018,6 +4018,13 @@ const char *ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type vide
        }
 }
 
+void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label)
+{
+       ast_bridge_lock(bridge);
+       bridge->softmix.send_sdp_label = send_sdp_label;
+       ast_bridge_unlock(bridge);
+}
+
 static int channel_hash(const void *obj, int flags)
 {
        const struct ast_channel *chan = obj;