summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorJenkins2 <jenkins2@gerrit.asterisk.org>2017-08-23 14:45:52 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-08-23 14:45:52 -0500
commita1e9ec40df89ea97b2612cc81eab28a6a8f61fca (patch)
tree997873bbc86b4d6d138ee155b0ea128ada8b6aeb /bridges
parent9e79976212271b49808aa533a08f00b9c59c6dda (diff)
parent17976d1b4e302b3aa7cc510109a78010d7893fe1 (diff)
Merge changes from topic 'ASTERISK-27212'
* changes: bridge_channel.c: Fix FRACK when mapping frames to the bridge. bridge: Fix softmix bridge deadlock.
Diffstat (limited to 'bridges')
-rw-r--r--bridges/bridge_softmix.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 2d71fc37c..59b16b78e 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -1686,7 +1686,8 @@ static void map_source_to_destinations(const char *source_stream_name, const cha
}
}
-/*\brief stream_topology_changed callback
+/*!
+ * \brief stream_topology_changed callback
*
* For most video modes, nothing beyond the ordinary is required.
* For the SFU case, though, we need to completely remap the streams
@@ -1724,34 +1725,52 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
/* Second traversal: Map specific video channels from their source to their destinations.
*
- * This is similar to what is done in ast_stream_topology_map(), except that
- * video channels are handled differently. Each video source has it's own
- * unique index on the bridge. this way, a particular channel's source video
- * can be distributed to the appropriate destination streams on the other
- * channels
+ * This is similar to what is done in ast_stream_topology_map(),
+ * except that video channels are handled differently. Each video
+ * source has it's own unique index on the bridge. This way, a
+ * particular channel's source video can be distributed to the
+ * appropriate destination streams on the other channels.
*/
AST_LIST_TRAVERSE(&bridge->channels, participant, entry) {
int i;
struct ast_stream_topology *topology;
+ ast_bridge_channel_lock(participant);
ast_channel_lock(participant->chan);
topology = ast_channel_get_stream_topology(participant->chan);
+ if (topology) {
+ /*
+ * Sigh. We have to clone to avoid deadlock in
+ * map_source_to_destinations() because topology
+ * is not an ao2 object.
+ */
+ topology = ast_stream_topology_clone(topology);
+ }
+ if (!topology) {
+ /* Oh, my, we are in trouble. */
+ ast_channel_unlock(participant->chan);
+ ast_bridge_channel_unlock(participant);
+ continue;
+ }
for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
- ast_bridge_channel_lock(participant);
+
if (is_video_source(stream)) {
AST_VECTOR_APPEND(&media_types, AST_MEDIA_TYPE_VIDEO);
AST_VECTOR_REPLACE(&participant->stream_map.to_bridge, i, AST_VECTOR_SIZE(&media_types) - 1);
AST_VECTOR_REPLACE(&participant->stream_map.to_channel, AST_VECTOR_SIZE(&media_types) - 1, -1);
- /* Unlock the participant to prevent potential deadlock
- * in map_source_to_destinations
+ /*
+ * Unlock the channel and participant to prevent
+ * potential deadlock in map_source_to_destinations().
*/
+ ast_channel_unlock(participant->chan);
ast_bridge_channel_unlock(participant);
map_source_to_destinations(ast_stream_get_name(stream), ast_channel_name(participant->chan),
AST_VECTOR_SIZE(&media_types) - 1, &bridge->channels);
ast_bridge_channel_lock(participant);
+ ast_channel_lock(participant->chan);
} else if (is_video_dest(stream, NULL, NULL)) {
/* We expect to never read media from video destination channels, but just
* in case, we should set their to_bridge value to -1.
@@ -1773,10 +1792,12 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
AST_VECTOR_REPLACE(&participant->stream_map.to_bridge, i, index);
AST_VECTOR_REPLACE(&participant->stream_map.to_channel, index, i);
}
- ast_bridge_channel_unlock(participant);
}
+ ast_stream_topology_free(topology);
+
ast_channel_unlock(participant->chan);
+ ast_bridge_channel_unlock(participant);
}
}