diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 5e0a4856ff589d5ad78a399054f7a134915acc73..9197df6fb5f1a226e1748d2905048810bb234717 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -573,27 +573,24 @@ static int append_all_streams(struct ast_stream_topology *dest, */ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast_bridge_channels_list *participants) { - struct ast_stream_topology *joiner_topology = NULL; struct ast_stream_topology *joiner_video = NULL; - struct ast_stream_topology *existing_video = NULL; struct ast_bridge_channel *participant; int res; + struct softmix_channel *sc; joiner_video = ast_stream_topology_alloc(); if (!joiner_video) { return; } + 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)); + sc->topology = ast_stream_topology_clone(ast_channel_get_stream_topology(joiner->chan)); ast_channel_unlock(joiner->chan); - if (res) { - goto cleanup; - } - - existing_video = ast_stream_topology_alloc(); - if (!existing_video) { + if (res || !sc->topology) { goto cleanup; } @@ -602,7 +599,7 @@ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast continue; } ast_channel_lock(participant->chan); - res = append_source_streams(existing_video, ast_channel_name(participant->chan), + res = append_source_streams(sc->topology, ast_channel_name(participant->chan), ast_channel_get_stream_topology(participant->chan)); ast_channel_unlock(participant->chan); if (res) { @@ -610,41 +607,22 @@ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast } } - ast_channel_lock(joiner->chan); - joiner_topology = ast_stream_topology_clone(ast_channel_get_stream_topology(joiner->chan)); - ast_channel_unlock(joiner->chan); - if (!joiner_topology) { - goto cleanup; - } - if (append_all_streams(joiner_topology, existing_video)) { - goto cleanup; - } - ast_channel_request_stream_topology_change(joiner->chan, joiner_topology, NULL); + ast_channel_request_stream_topology_change(joiner->chan, sc->topology, NULL); AST_LIST_TRAVERSE(participants, participant, entry) { - struct ast_stream_topology *participant_topology; - if (participant == joiner) { continue; } - ast_channel_lock(participant->chan); - participant_topology = ast_stream_topology_clone(ast_channel_get_stream_topology(participant->chan)); - ast_channel_unlock(participant->chan); - if (!participant_topology) { - goto cleanup; - } - if (append_all_streams(participant_topology, joiner_video)) { - ast_stream_topology_free(participant_topology); + + sc = participant->tech_pvt; + if (append_all_streams(sc->topology, joiner_video)) { goto cleanup; } - ast_channel_request_stream_topology_change(participant->chan, participant_topology, NULL); - ast_stream_topology_free(participant_topology); + ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL); } cleanup: ast_stream_topology_free(joiner_video); - ast_stream_topology_free(existing_video); - ast_stream_topology_free(joiner_topology); } /*! \brief Function called when a channel is joined into the bridge */ @@ -718,65 +696,36 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan return 0; } -static int remove_destination_streams(struct ast_stream_topology *dest, - const char *channel_name, - const struct ast_stream_topology *source) +static void remove_destination_streams(struct ast_stream_topology *topology, + const char *channel_name) { int i; - for (i = 0; i < ast_stream_topology_get_count(source); ++i) { + for (i = 0; i < ast_stream_topology_get_count(topology); ++i) { struct ast_stream *stream; - struct ast_stream *stream_clone; - stream = ast_stream_topology_get_stream(source, i); - - stream_clone = ast_stream_clone(stream, NULL); - if (!stream_clone) { - continue; - } + stream = ast_stream_topology_get_stream(topology, i); if (is_video_dest(stream, channel_name, NULL)) { - ast_stream_set_state(stream_clone, AST_STREAM_STATE_REMOVED); - } - - if (ast_stream_topology_append_stream(dest, stream_clone) < 0) { - ast_stream_free(stream_clone); + ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED); } } - - return 0; } static int sfu_topologies_on_leave(struct ast_bridge_channel *leaver, struct ast_bridge_channels_list *participants) { - struct ast_stream_topology *leaver_topology; struct ast_bridge_channel *participant; - - leaver_topology = ast_stream_topology_alloc(); - if (!leaver_topology) { - return -1; - } + struct softmix_channel *sc; AST_LIST_TRAVERSE(participants, participant, entry) { - struct ast_stream_topology *participant_topology; - - participant_topology = ast_stream_topology_alloc(); - if (!participant_topology) { - continue; - } - - ast_channel_lock(participant->chan); - remove_destination_streams(participant_topology, ast_channel_name(leaver->chan), ast_channel_get_stream_topology(participant->chan)); - ast_channel_unlock(participant->chan); - ast_channel_request_stream_topology_change(participant->chan, participant_topology, NULL); - ast_stream_topology_free(participant_topology); + sc = participant->tech_pvt; + remove_destination_streams(sc->topology, ast_channel_name(leaver->chan)); + ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL); } - ast_channel_lock(leaver->chan); - remove_destination_streams(leaver_topology, "", ast_channel_get_stream_topology(leaver->chan)); - ast_channel_unlock(leaver->chan); - ast_channel_request_stream_topology_change(leaver->chan, leaver_topology, NULL); - ast_stream_topology_free(leaver_topology); + sc = leaver->tech_pvt; + remove_destination_streams(sc->topology, ""); + ast_channel_request_stream_topology_change(leaver->chan, sc->topology, NULL); return 0; } @@ -806,6 +755,8 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch bridge_channel->tech_pvt = NULL; + ast_stream_topology_free(sc->topology); + /* Drop mutex lock */ ast_mutex_destroy(&sc->lock); @@ -1055,30 +1006,23 @@ static void sfu_topologies_on_source_change(struct ast_bridge_channel *source, s AST_LIST_TRAVERSE(participants, participant, entry) { struct ast_stream_topology *original_topology; - struct ast_stream_topology *participant_topology; + struct softmix_channel *sc; if (participant == source) { continue; } - ast_channel_lock(participant->chan); - original_topology = ast_stream_topology_clone(ast_channel_get_stream_topology(participant->chan)); - ast_channel_unlock(participant->chan); - if (!original_topology) { - goto cleanup; - } + sc = participant->tech_pvt; - participant_topology = ast_stream_topology_clone(original_topology); - if (!participant_topology) { - ast_stream_topology_free(original_topology); + original_topology = ast_stream_topology_clone(sc->topology); + if (!original_topology) { goto cleanup; } /* We add all the source streams back in, if any removed streams are already present they will * get used first followed by appending new ones. */ - if (append_all_streams(participant_topology, source_video)) { - ast_stream_topology_free(participant_topology); + if (append_all_streams(sc->topology, source_video)) { ast_stream_topology_free(original_topology); goto cleanup; } @@ -1086,14 +1030,12 @@ static void sfu_topologies_on_source_change(struct ast_bridge_channel *source, s /* And the original existing streams get marked as removed. This causes the remote side to see * a new stream for the source streams. */ - if (remove_all_original_streams(participant_topology, source_video, original_topology)) { - ast_stream_topology_free(participant_topology); + if (remove_all_original_streams(sc->topology, source_video, original_topology)) { ast_stream_topology_free(original_topology); goto cleanup; } - ast_channel_request_stream_topology_change(participant->chan, participant_topology, NULL); - ast_stream_topology_free(participant_topology); + ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL); ast_stream_topology_free(original_topology); } @@ -2144,7 +2086,6 @@ AST_TEST_DEFINE(sfu_remove_destination_streams) { "", 4, { 0, 1, 2, 3 }, }, }; struct ast_stream_topology *orig = NULL; - struct ast_stream_topology *result = NULL; int i; switch (cmd) { @@ -2168,20 +2109,11 @@ AST_TEST_DEFINE(sfu_remove_destination_streams) for (i = 0; i < ARRAY_LEN(removal_results); ++i) { int j; - result = ast_stream_topology_alloc(); - if (!result) { - ast_test_status_update(test, "Unable to allocate result stream topology\n"); - goto end; - } - - if (remove_destination_streams(result, removal_results[i].channel_name, orig)) { - ast_test_status_update(test, "Failure while attempting to remove video streams\n"); - goto end; - } + remove_destination_streams(orig, removal_results[i].channel_name); - if (ast_stream_topology_get_count(result) != removal_results[i].num_streams) { + if (ast_stream_topology_get_count(orig) != removal_results[i].num_streams) { ast_test_status_update(test, "Resulting topology has %d streams, when %d are expected\n", - ast_stream_topology_get_count(result), removal_results[i].num_streams); + ast_stream_topology_get_count(orig), removal_results[i].num_streams); goto end; } @@ -2190,7 +2122,7 @@ AST_TEST_DEFINE(sfu_remove_destination_streams) struct ast_stream *expected; int orig_index; - actual = ast_stream_topology_get_stream(result, j); + actual = ast_stream_topology_get_stream(orig, j); orig_index = removal_results[i].params_index[j]; expected = ast_stream_topology_get_stream(orig, orig_index); @@ -2221,7 +2153,6 @@ AST_TEST_DEFINE(sfu_remove_destination_streams) end: ast_stream_topology_free(orig); - ast_stream_topology_free(result); return res; } diff --git a/bridges/bridge_softmix/include/bridge_softmix_internal.h b/bridges/bridge_softmix/include/bridge_softmix_internal.h index f93e66391594a05ac5313ee29d0ab6cf77c3a302..01e65aa1f8ef5508806320a5f235f4d173e7174c 100644 --- a/bridges/bridge_softmix/include/bridge_softmix_internal.h +++ b/bridges/bridge_softmix/include/bridge_softmix_internal.h @@ -167,6 +167,8 @@ struct softmix_channel { short our_buf[MAX_DATALEN]; /*! Data pertaining to talker mode for video conferencing */ struct video_follow_talker_data video_talker; + /*! The ideal stream topology for the channel */ + struct ast_stream_topology *topology; }; struct softmix_bridge_data {