@ -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 ;
}