/// <inheritdoc/> protected override void Dispose(bool disposing) { if (_nativeHandle != IntPtr.Zero) { // Unregister the callbacks if (_selfHandle != IntPtr.Zero) { LocalVideoTrackInterop.LocalVideoTrack_RegisterI420AFrameCallback(_nativeHandle, null, IntPtr.Zero); LocalVideoTrackInterop.LocalVideoTrack_RegisterARGBFrameCallback(_nativeHandle, null, IntPtr.Zero); GCHandle.FromIntPtr(_selfHandle).Free(); if (disposing) { _interopCallbackArgs = null; } _selfHandle = IntPtr.Zero; } // Remove the track from the peer connection, and release the reference // to the peer connection. if (!_nativePeerHandle.IsClosed) { PeerConnectionInterop.PeerConnection_RemoveLocalVideoTrack(_nativePeerHandle, _nativeHandle); _nativePeerHandle.Close(); } } if (disposing) { PeerConnection = null; } base.Dispose(disposing); }
/// <inheritdoc/> public void Dispose() { if (_nativeHandle.IsClosed) { return; } // Remove the track from the peer connection, if any PeerConnection?.RemoveLocalVideoTrack(this); Debug.Assert(PeerConnection == null); // see OnTrackRemoved // Unregister interop callbacks if (_selfHandle != IntPtr.Zero) { LocalVideoTrackInterop.LocalVideoTrack_RegisterI420AFrameCallback(_nativeHandle, null, IntPtr.Zero); LocalVideoTrackInterop.LocalVideoTrack_RegisterArgb32FrameCallback(_nativeHandle, null, IntPtr.Zero); Utils.ReleaseWrapperRef(_selfHandle); _selfHandle = IntPtr.Zero; _interopCallbackArgs = null; } // Currently there is a 1:1 mapping between track and source, so the track owns its // source and must dipose of it. Source?.Dispose(); // Destroy the native object. This may be delayed if a P/Invoke callback is underway, // but will be handled at some point anyway, even if the managed instance is gone. _nativeHandle.Dispose(); }
private void RegisterInteropCallbacks() { _interopCallbackArgs = new LocalVideoTrackInterop.InteropCallbackArgs() { Track = this, I420AFrameCallback = LocalVideoTrackInterop.I420AFrameCallback, Argb32FrameCallback = LocalVideoTrackInterop.Argb32FrameCallback, }; _selfHandle = Utils.MakeWrapperRef(this); LocalVideoTrackInterop.LocalVideoTrack_RegisterI420AFrameCallback( _nativeHandle, _interopCallbackArgs.I420AFrameCallback, _selfHandle); LocalVideoTrackInterop.LocalVideoTrack_RegisterArgb32FrameCallback( _nativeHandle, _interopCallbackArgs.Argb32FrameCallback, _selfHandle); }
/// <inheritdoc/> public void Dispose() { if (_nativeHandle.IsClosed) { return; } // Notify the source if (Source != null) { Source.OnTrackRemovedFromSource(this); Source = null; } // Remove the track from the peer connection, if any if (Transceiver != null) { Debug.Assert(PeerConnection != null); Debug.Assert(Transceiver.LocalTrack == this); Transceiver.LocalVideoTrack = null; } Debug.Assert(PeerConnection == null); Debug.Assert(Transceiver == null); // Unregister interop callbacks if (_selfHandle != IntPtr.Zero) { LocalVideoTrackInterop.LocalVideoTrack_RegisterI420AFrameCallback(_nativeHandle, null, IntPtr.Zero); LocalVideoTrackInterop.LocalVideoTrack_RegisterArgb32FrameCallback(_nativeHandle, null, IntPtr.Zero); Utils.ReleaseWrapperRef(_selfHandle); _selfHandle = IntPtr.Zero; _interopCallbackArgs = null; } // Destroy the native object. This may be delayed if a P/Invoke callback is underway, // but will be handled at some point anyway, even if the managed instance is gone. _nativeHandle.Dispose(); }