[WebRTC] Fix destroy bug and code clean (#3476)
authorHaesu Gwon <haesu.gwon@samsung.com>
Tue, 31 Aug 2021 07:29:15 +0000 (16:29 +0900)
committerGitHub <noreply@github.com>
Tue, 31 Aug 2021 07:29:15 +0000 (16:29 +0900)
* [WebRTC] Fix destroy bug and code clean

src/Tizen.Multimedia.Remoting/Interop/Interop.WebRTC.cs
src/Tizen.Multimedia.Remoting/WebRTC/MediaSource.cs
src/Tizen.Multimedia.Remoting/WebRTC/WebRTC.Events.cs
src/Tizen.Multimedia.Remoting/WebRTC/WebRTC.cs

index 41606ba..d6bac08 100755 (executable)
@@ -279,8 +279,7 @@ internal static partial class Interop
 
     internal class WebRTCHandle : SafeHandle
     {
-        protected WebRTCHandle()
-          : base(IntPtr.Zero, true)
+        protected WebRTCHandle() : base(IntPtr.Zero, true)
         {
         }
 
@@ -291,12 +290,11 @@ internal static partial class Interop
             var ret = NativeWebRTC.Destroy(handle);
             if (ret != WebRTCErrorCode.None)
             {
-                return true;
+                Log.Debug(GetType().FullName, $"Failed to release native {GetType().Name}");
+                return false;
             }
 
-            Log.Debug(GetType().FullName, $"Failed to release native {GetType().Name}");
-            return false;
+            return true;
         }
     }
-
 }
index 1da2934..438e296 100755 (executable)
@@ -227,7 +227,7 @@ namespace Tizen.Multimedia.Remoting
         private uint SetDisplay(Display display)
             => display.ApplyTo(this);
 
-        private void ReplaceDisplay(Display newDisplay)
+        internal void ReplaceDisplay(Display newDisplay)
         {
             _display?.SetOwner(null);
             _display = newDisplay;
index db4a80c..52e86ba 100755 (executable)
@@ -168,11 +168,25 @@ namespace Tizen.Multimedia.Remoting
             RegisterDataChannelCreatedCallback();
         }
 
+        private void UnregisterEvents()
+        {
+            UnregisterErrorOccurredCallback();
+            UnregisterStateChangedCallback();
+            UnregisterIceGatheringStateChangedCallback();
+            UnregisterSignalingStateChangedCallback();
+            UnregisterPeerConnectionStateChangedCallback();
+            UnregisterIceConnectionStateChangedCallback();
+            UnregisterNegotiationNeededCallback();
+            UnregisterIceCandidateCallback();
+            UnregisterTrackAddedCallback();
+            UnregisterDataChannelCreatedCallback();
+        }
+
         private void RegisterErrorOccurredCallback()
         {
             _webRtcErrorOccurredCallback = (handle, error, state, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"{error}, {state}");
+                // Log.Info(WebRTCLog.Tag, $"{error}, {state}");
 
                 ErrorOccurred?.Invoke(this, new WebRTCErrorOccurredEventArgs((WebRTCError)error, state));
             };
@@ -181,11 +195,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set error occurred callback.");
         }
 
+        private void UnregisterErrorOccurredCallback()
+        {
+            NativeWebRTC.UnsetErrorOccurredCb(Handle).
+                ThrowIfFailed("Failed to unset error occurred callback.");
+        }
+
         private void RegisterStateChangedCallback()
         {
             _webRtcStateChangedCallback = (handle, previous, current, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"{previous}, {current}");
+                // Log.Info(WebRTCLog.Tag, $"{previous}, {current}");
 
                 StateChanged?.Invoke(this, new WebRTCStateChangedEventArgs(previous, current));
             };
@@ -194,11 +214,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set state changed callback.");
         }
 
+        private void UnregisterStateChangedCallback()
+        {
+            NativeWebRTC.UnsetStateChangedCb(Handle).
+                ThrowIfFailed("Failed to unset state changed callback.");
+        }
+
         private void RegisterIceGatheringStateChangedCallback()
         {
             _webRtcIceGatheringStateChangedCallback = (handle, state, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Ice gathering state : {state}");
+                // Log.Info(WebRTCLog.Tag, $"Ice gathering state : {state}");
 
                 IceGatheringStateChanged?.Invoke(this, new WebRTCIceGatheringStateChangedEventArgs(state));
             };
@@ -207,11 +233,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set Ice gathering state changed callback.");
         }
 
+        private void UnregisterIceGatheringStateChangedCallback()
+        {
+            NativeWebRTC.UnsetIceGatheringStateChangedCb(Handle).
+                ThrowIfFailed("Failed to unset Ice gathering state changed callback.");
+        }
+
         private void RegisterSignalingStateChangedCallback()
         {
             _webRtcSignalingStateChangedCallback = (handle, state, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Signaling state : {state}");
+                // Log.Info(WebRTCLog.Tag, $"Signaling state : {state}");
 
                 SignalingStateChanged?.Invoke(this, new WebRTCSignalingStateChangedEventArgs(state));
             };
@@ -220,6 +252,12 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set signaling state changed callback.");
         }
 
+        private void UnregisterSignalingStateChangedCallback()
+        {
+            NativeWebRTC.UnsetSignalingStateChangedCb(Handle).
+                ThrowIfFailed("Failed to unset signaling state changed callback.");
+        }
+
         private void RegisterPeerConnectionStateChangedCallback()
         {
             _webRtcPeerConnectionStateChangedCallback = (handle, state, _) =>
@@ -233,11 +271,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set peer connection state changed callback.");
         }
 
+        private void UnregisterPeerConnectionStateChangedCallback()
+        {
+            NativeWebRTC.UnsetPeerConnectionStateChangedCb(Handle).
+                ThrowIfFailed("Failed to unset peer connection state changed callback.");
+        }
+
         private void RegisterIceConnectionStateChangedCallback()
         {
             _webRtcIceConnectionStateChangedCallback = (handle, state, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Ice connection state : {state}");
+                // Log.Info(WebRTCLog.Tag, $"Ice connection state : {state}");
 
                 IceConnectionStateChanged?.Invoke(this, new WebRTCIceConnectionStateChangedEventArgs(state));
             };
@@ -246,6 +290,12 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set ICE connection state changed callback.");
         }
 
+        private void UnregisterIceConnectionStateChangedCallback()
+        {
+            NativeWebRTC.UnsetIceConnectionStateChangedCb(Handle).
+                ThrowIfFailed("Failed to unset ICE connection state changed callback.");
+        }
+
         private void RegisterNegotiationNeededCallback()
         {
             _webRtcNegotiationNeededCallback = (handle, _) =>
@@ -257,6 +307,12 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set negotiation needed callback.");
         }
 
+        private void UnregisterNegotiationNeededCallback()
+        {
+            NativeWebRTC.UnsetNegotiationNeededCb(Handle).
+                ThrowIfFailed("Failed to unset negotiation needed callback.");
+        }
+
         private void RegisterIceCandidateCallback()
         {
             _webRtcIceCandidateCallback = (handle, candidate, _) =>
@@ -268,11 +324,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set ice candidate callback.");
         }
 
+        private void UnregisterIceCandidateCallback()
+        {
+            NativeWebRTC.UnsetIceCandidateCb(Handle).
+                ThrowIfFailed("Failed to unset ice candidate callback.");
+        }
+
         private void RegisterTrackAddedCallback()
         {
             _webRtcTrackAddedCallback = (handle, type, id, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
+                // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
 
                 TrackAdded?.Invoke(this, new WebRTCTrackAddedEventArgs(new MediaStreamTrack(this, type, id)));
             };
@@ -281,11 +343,17 @@ namespace Tizen.Multimedia.Remoting
                 ThrowIfFailed("Failed to set track added callback.");
         }
 
+        private void UnregisterTrackAddedCallback()
+        {
+            NativeWebRTC.UnsetTrackAddedCb(Handle).
+                ThrowIfFailed("Failed to unset track added callback.");
+        }
+
         private void RegisterAudioFrameEncodedCallback()
         {
             _webRtcAudioFrameEncodedCallback = (handle, type, id, packet, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
+                // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
 
                 _audioFrameEncoded?.Invoke(this,
                     new WebRTCFrameEncodedEventArgs(new MediaStreamTrack(this, type, id), MediaPacket.From(packet)));
@@ -305,7 +373,7 @@ namespace Tizen.Multimedia.Remoting
         {
             _webRtcVideoFrameEncodedCallback = (handle, type, id, packet, _) =>
             {
-                Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
+                // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]");
 
                 _videoFrameEncoded?.Invoke(this,
                     new WebRTCFrameEncodedEventArgs(new MediaStreamTrack(this, type, id), MediaPacket.From(packet)));
@@ -325,7 +393,7 @@ namespace Tizen.Multimedia.Remoting
         {
             _webRtcDataChannelCreatedCallback = (handle, dataChannelHandle, _) =>
             {
-                Log.Debug(WebRTCLog.Tag, "Invoked");
+                // Log.Debug(WebRTCLog.Tag, "Invoked");
 
                 DataChannel?.Invoke(this, new WebRTCDataChannelEventArgs(dataChannelHandle));
             };
@@ -333,5 +401,11 @@ namespace Tizen.Multimedia.Remoting
             NativeDataChannel.SetCreatedByPeerCb(Handle, _webRtcDataChannelCreatedCallback).
                 ThrowIfFailed("Failed to set data channel created callback.");
         }
+
+        private void UnregisterDataChannelCreatedCallback()
+        {
+            NativeDataChannel.UnsetCreatedByPeerCb(Handle).
+                ThrowIfFailed("Failed to unset data channel created callback.");
+        }
     }
 }
index 53b9844..a6a5815 100755 (executable)
  */
 
 using System;
-using System.Threading.Tasks;
 using System.Collections.ObjectModel;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
 using Tizen.Applications;
 using static Interop;
 
@@ -112,10 +113,13 @@ namespace Tizen.Multimedia.Remoting
             {
                 try
                 {
+                    Log.Info(WebRTCLog.Tag, "Detach sources");
                     foreach (var source in _source)
                     {
+                        source.ReplaceDisplay(null);
                         source.DetachFrom(this);
                     }
+                    _source.Clear();
                     _source = null;
                 }
                 catch (Exception ex)
@@ -123,8 +127,10 @@ namespace Tizen.Multimedia.Remoting
                     Log.Error(WebRTCLog.Tag, ex.ToString());
                 }
             }
+
             if (_handle != null)
             {
+                UnregisterEvents();
                 _handle.Dispose();
                 _disposed = true;
             }
@@ -148,7 +154,7 @@ namespace Tizen.Multimedia.Remoting
         /// <remarks>
         /// The WebRTC must be in the <see cref="WebRTCState.Idle"/> state.<br/>
         /// The WebRTC state will be <see cref="WebRTCState.Negotiating"/> state.<br/>
-        /// <see cref="StateChanged"/> event will be invoked when the state is changed to <see cref="WebRTCState.Negotiating"/> internally.
+        /// The user should check whether <see cref="State" /> is changed to <see cref="WebRTCState.Negotiating"/> state or not.
         /// </remarks>
         /// <exception cref="InvalidOperationException">The WebRTC is not in the valid state.</exception>
         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
@@ -165,12 +171,12 @@ namespace Tizen.Multimedia.Remoting
         }
 
         /// <summary>
-        /// Starts the WebRTC.
+        /// Starts the WebRTC asynchronously.
         /// </summary>
         /// <remarks>
         /// The WebRTC must be in the <see cref="WebRTCState.Idle"/> state.<br/>
         /// The WebRTC state will be <see cref="WebRTCState.Negotiating"/> state.<br/>
-        /// This ensures that <see cref="StateChanged" /> event will be invoked with <see cref="WebRTCState.Negotiating"/> state.
+        /// This ensures that <see cref="State" /> is changed to <see cref="WebRTCState.Negotiating"/> state.
         /// </remarks>
         /// <exception cref="InvalidOperationException">The WebRTC is not in the valid state.</exception>
         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
@@ -197,7 +203,8 @@ namespace Tizen.Multimedia.Remoting
 
                 NativeWebRTC.Start(Handle).ThrowIfFailed("Failed to start the WebRTC");
 
-                await tcs.Task;
+                await tcs.Task.ConfigureAwait(false);
+                await Task.Yield();
             }
             finally
             {
@@ -210,7 +217,8 @@ namespace Tizen.Multimedia.Remoting
         /// </summary>
         /// <remarks>
         /// The WebRTC must be in the <see cref="WebRTCState.Negotiating"/> or <see cref="WebRTCState.Playing"/> state.<br/>
-        /// The WebRTC state will be <see cref="WebRTCState.Idle"/> state.
+        /// The WebRTC state will be <see cref="WebRTCState.Idle"/> state.<br/>
+        /// The user should check whether <see cref="State" /> is changed to <see cref="WebRTCState.Idle"/> state or not.
         /// </remarks>
         /// <exception cref="InvalidOperationException">The WebRTC is not in the valid state.</exception>
         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
@@ -248,7 +256,9 @@ namespace Tizen.Multimedia.Remoting
             ValidateWebRTCState(WebRTCState.Negotiating);
 
             var bundle_ = bundle?.SafeBundleHandle ?? new SafeBundleHandle();
-            NativeWebRTC.CreateSDPOffer(Handle, bundle_, out string offer).ThrowIfFailed("Failed to create offer");
+
+            NativeWebRTC.CreateSDPOffer(Handle, bundle_, out string offer).
+                    ThrowIfFailed("Failed to create offer");
 
             return offer;
         }
@@ -288,7 +298,8 @@ namespace Tizen.Multimedia.Remoting
 
             var bundle_ = bundle?.SafeBundleHandle ?? new SafeBundleHandle();
 
-            NativeWebRTC.CreateSDPAnswer(Handle, bundle_, out string answer).ThrowIfFailed("Failed to create answer");
+            NativeWebRTC.CreateSDPAnswer(Handle, bundle_, out string answer).
+                    ThrowIfFailed("Failed to create answer");
 
             return answer;
         }