7575import java .util .concurrent .ConcurrentHashMap ;
7676import java .util .concurrent .ExecutorService ;
7777import java .util .concurrent .Executors ;
78+ import java .util .concurrent .Semaphore ;
79+ import java .util .concurrent .locks .Condition ;
7880import java .util .regex .Matcher ;
7981import java .util .regex .Pattern ;
8082
8890import io .antmedia .webrtcandroidframework .websocket .Broadcast ;
8991import io .antmedia .webrtcandroidframework .websocket .Subscriber ;
9092import io .antmedia .webrtcandroidframework .websocket .WebSocketHandler ;
93+ import java .util .concurrent .locks .ReentrantLock ;
94+
9195
9296public class WebRTCClient implements IWebRTCClient , AntMediaSignallingEvents {
9397 private static final String TAG = "WebRTCClient" ;
@@ -100,6 +104,7 @@ public enum Mode {
100104 public static final String VIDEO_ROTATION_EXT_LINE = "a=extmap:3 urn:3gpp:video-orientation\r \n " ;
101105 public static final String USER_REVOKED_CAPTURE_SCREEN_PERMISSION = "User revoked permission to capture the screen." ;
102106 public static int STAT_CALLBACK_PERIOD = 1000 ;
107+ private final Semaphore releaseLock = new Semaphore (1 );
103108
104109 protected final ProxyVideoSink localVideoSink = new ProxyVideoSink ();
105110 protected final List <ProxyVideoSink > remoteVideoSinks = new ArrayList <>();
@@ -248,7 +253,6 @@ public void setQueuedRemoteCandidates(List<IceCandidate> queuedRemoteCandidates)
248253 public static final long PEER_RECONNECTION_RETRY_DELAY_MS = 10000 ;
249254
250255 private boolean released = false ;
251-
252256 private String roomId ;
253257
254258 private BlackFrameSender blackFrameSender ;
@@ -1014,6 +1018,11 @@ public void publish(String streamId) {
10141018
10151019 public void publish (String streamId , String token , boolean videoCallEnabled , boolean audioCallEnabled ,
10161020 String subscriberId , String subscriberCode , String streamName , String mainTrackId ) {
1021+ try {
1022+ releaseLock .acquire ();
1023+ } catch (InterruptedException e ) {
1024+ throw new RuntimeException (e );
1025+ }
10171026 Log .i (TAG , "Publish: " + streamId );
10181027
10191028 this .handler .post (() -> {
@@ -1026,6 +1035,7 @@ public void publish(String streamId, String token, boolean videoCallEnabled, boo
10261035 init ();
10271036
10281037 if (!PermissionHandler .checkPublishPermissions (config .activity , config .bluetoothEnabled , videoCallEnabled || this .config .videoCallEnabled )){
1038+ releaseLock .release ();
10291039 Toast .makeText (config .activity ,"Publish permissions not granted. Cant publish." , Toast .LENGTH_LONG ).show ();
10301040 Log .e (TAG ,"Publish permissions not granted. Cant publish." );
10311041 return ;
@@ -1039,6 +1049,7 @@ public void publish(String streamId, String token, boolean videoCallEnabled, boo
10391049 } else {
10401050 Log .w (TAG , "Websocket is not connected. Set publish requested. It will be processed when ws is connected." );
10411051 }
1052+ releaseLock .release ();
10421053 }
10431054
10441055 private void createPeerInfo (String streamId , String token , boolean videoCallEnabled , boolean audioCallEnabled , String subscriberId , String subscriberName , String subscriberCode , String streamName , String mainTrackId , String metaData , boolean disableTracksByDefault , Mode mode ) {
@@ -1067,6 +1078,11 @@ public void play(String streamId, String[] tracks) {
10671078
10681079 @ Override
10691080 public void play (PlayParams params ) {
1081+ try {
1082+ releaseLock .acquire ();
1083+ } catch (InterruptedException e ) {
1084+ throw new RuntimeException (e );
1085+ }
10701086 Log .i (TAG , "Play: " + params .getStreamId ());
10711087 this .handler .post (() -> {
10721088 if (config .webRTCListener != null ) {
@@ -1082,6 +1098,7 @@ public void play(PlayParams params) {
10821098 if (!PermissionHandler .checkPlayPermissions (config .activity , config .bluetoothEnabled )){
10831099 Toast .makeText (config .activity ,"Play permissions not granted. Cant play." , Toast .LENGTH_LONG ).show ();
10841100 Log .e (TAG ,"Play permissions not granted. Cant play." );
1101+ releaseLock .release ();
10851102 return ;
10861103 }
10871104
@@ -1095,6 +1112,7 @@ public void play(PlayParams params) {
10951112 } else {
10961113 Log .w (TAG , "Websocket is not connected. Set play requested. It will be processed when ws is connected." );
10971114 }
1115+ releaseLock .release ();
10981116 }
10991117
11001118 public void play (String streamId , String token , String [] tracks , String subscriberId , String subscriberCode , String viewerInfo ) {
@@ -1119,8 +1137,12 @@ public void sendPushNotification(String subscriberId, String authToken, JSONObje
11191137 }
11201138
11211139 public void join (String streamId , String token ) {
1140+ try {
1141+ releaseLock .acquire ();
1142+ } catch (InterruptedException e ) {
1143+ throw new RuntimeException (e );
1144+ }
11221145 Log .e (TAG , "Join: " + streamId );
1123-
11241146 this .handler .post (() -> {
11251147 if (config .webRTCListener != null ) {
11261148 config .webRTCListener .onJoinAttempt (streamId );
@@ -1136,6 +1158,7 @@ public void join(String streamId, String token) {
11361158
11371159
11381160 wsHandler .joinToPeer (streamId , token );
1161+ releaseLock .release ();
11391162 }
11401163
11411164 public void getTrackList (String streamId , String token ) {
@@ -1184,36 +1207,48 @@ public void onAudioManagerDevicesChanged(
11841207
11851208 // Disconnect from remote resources, dispose of local resources, and exit.
11861209 public void release (boolean closeWebsocket ) {
1187- released = true ;
1188- Log .i (getClass ().getSimpleName (), "Releasing resources" );
1210+ executor .execute (()->{
1211+ try {
1212+ releaseLock .acquire ();
1213+ } catch (InterruptedException e ) {
1214+ throw new RuntimeException (e );
1215+ }
11891216
1190- if (closeWebsocket && wsHandler != null ) {
1191- wsHandler .disconnect (true );
1192- wsHandler .stopReconnector ();
1193- wsHandler = null ;
1194- }
1195- if (config .localVideoRenderer != null ) {
1196- releaseRenderer (config .localVideoRenderer , localVideoTrack , localVideoSink );
1197- }
1217+ if (released ) {
1218+ releaseLock .release ();
1219+ return ;
1220+ }
1221+ released = true ;
1222+ Log .i (getClass ().getSimpleName (), "Releasing resources" );
11981223
1199- releaseRemoteRenderers ();
1224+ if (closeWebsocket && wsHandler != null ) {
1225+ wsHandler .disconnect (true );
1226+ wsHandler .stopReconnector ();
1227+ wsHandler = null ;
1228+ }
1229+ if (config .localVideoRenderer != null ) {
1230+ releaseRenderer (config .localVideoRenderer , localVideoTrack , localVideoSink );
1231+ }
12001232
1201- localVideoTrack = null ;
1202- localAudioTrack = null ;
1233+ releaseRemoteRenderers ();
12031234
1204- remoteVideoSinks .clear ();
1235+ localVideoTrack = null ;
1236+ localAudioTrack = null ;
12051237
1238+ remoteVideoSinks .clear ();
12061239
1207- if (audioManager != null ) {
1208- audioManager .stop ();
1209- audioManager = null ;
1210- }
12111240
1212- config .webRTCListener .onShutdown ();
1241+ mainHandler .post (()->{
1242+ if (audioManager != null ) {
1243+ audioManager .stop ();
1244+ audioManager = null ;
1245+ }
1246+ });
1247+
1248+ config .webRTCListener .onShutdown ();
1249+
1250+ closeInternal ();
12131251
1214- mainHandler .post (() -> {
1215- //if closeInternal works before releasing renderer, app stucks
1216- executor .execute (this ::closeInternal );
12171252 });
12181253
12191254 }
@@ -2279,6 +2314,7 @@ public void closeInternal() {
22792314 peerReconnectionHandler .removeCallbacksAndMessages (null );
22802315 publishReconnectionHandler .removeCallbacksAndMessages (null );
22812316 playReconnectionHandler .removeCallbacksAndMessages (null );
2317+ releaseLock .release ();
22822318 }
22832319
22842320 private void clearStatsCollector (){
0 commit comments