/// <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); }
/// <summary> /// Create a new local video track backed by an existing external video source. /// The track can be added to a peer connection by setting the <see cref="Transceiver.LocalVideoTrack"/> /// property. /// </summary> /// <param name="trackName">Name of the new local video track.</param> /// <param name="source">External video track source providing some video frames to the track.</param> /// <returns>The newly created local video track.</returns> /// <seealso cref="Transceiver.LocalVideoTrack"/> public static LocalVideoTrack CreateFromExternalSource(string trackName, ExternalVideoTrackSource source) { if (string.IsNullOrEmpty(trackName)) { trackName = Guid.NewGuid().ToString(); } // Create interop wrappers var track = new LocalVideoTrack(trackName, source); // Parse settings var config = new PeerConnectionInterop.LocalVideoTrackFromExternalSourceInteropInitConfig(trackName, source); // Create native implementation objects uint res = LocalVideoTrackInterop.LocalVideoTrack_CreateFromExternalSource(config, out LocalVideoTrackHandle trackHandle); Utils.ThrowOnErrorCode(res); track.SetHandle(trackHandle); return(track); }
/// <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(); }
/// <inheritdoc/> protected override void RemoveRef() { LocalVideoTrackInterop.LocalVideoTrack_RemoveRef(_nativeHandle); }