protected override void OnDispose(bool isDisposing) { if (isDisposing) { if (_queue.Count != VideoFrameQueueSize) { Debug.WriteLine("VideoRenderer is being disposed while frames are still being encoded."); } var videoTrack = VideoTrack; if (videoTrack != null) { videoTrack.LocalVideoFrameProcessed -= OnLocalVideoFrameProcessed; } _frameTable.Values.DisposeAll(); ThreadLock3D?.Dispose(); DeviceDXGI?.Dispose(); Device3D?.Dispose(); FactoryDXGI?.Dispose(); _sdlWindow?.Dispose(); } }
public VideoRenderer(VideoTrack videoTrack, RendererOptions options) { VideoTrack = videoTrack; VideoFrameWidth = options.VideoFrameWidth; VideoFrameHeight = options.VideoFrameHeight; VideoFrameQueueSize = options.VideoFrameQueueSize; videoTrack.LocalVideoFrameProcessed += OnLocalVideoFrameProcessed; // _onMissedFrame = options.OnMissedFrame ?? OnMissedFrame; bool debug = options.CreationFlags.HasFlag(D3D11.DeviceCreationFlags.Debug); FactoryDXGI = new DXGI.Factory2(debug); // Find the requested adapter. using (var adapters = FactoryDXGI.Adapters.ToDisposableList()) { var adapter = adapters.First(a => a.Description.VendorId == options.AdapterVendorId); Device3D = new D3D11.Device(adapter, options.CreationFlags, options.FeatureLevels); DeviceDXGI = Device3D.QueryInterface <DXGI.Device>(); // We need to access D3D11 on multiple threads, so enable multi-threading ThreadLock3D = Device3D.ImmediateContext.QueryInterface <D3D11.Multithread>(); ThreadLock3D.SetMultithreadProtected(true); if (options.PreviewWindowOptions != null) { var width = options.PreviewWindowOptions.Width ?? VideoFrameWidth; var height = options.PreviewWindowOptions.Height ?? width * VideoFrameHeight / VideoFrameWidth; _sdlWindow = new SdlWindow("WebRTC server preview", width, height); // SwapChain description var desc = new DXGI.SwapChainDescription1() { BufferCount = 2, AlphaMode = DXGI.AlphaMode.Unspecified, Format = DXGI.Format.B8G8R8A8_UNorm, Width = VideoFrameWidth, Height = VideoFrameHeight, Scaling = DXGI.Scaling.Stretch, Stereo = false, Flags = DXGI.SwapChainFlags.AllowTearing | DXGI.SwapChainFlags.FrameLatencyWaitAbleObject, Usage = DXGI.Usage.RenderTargetOutput, SampleDescription = new DXGI.SampleDescription(1, 0), SwapEffect = DXGI.SwapEffect.FlipDiscard, }; SwapChain = new DXGI.SwapChain1(FactoryDXGI, Device3D, _sdlWindow.NativeHandle, ref desc); using (var swapChain2 = SwapChain.QueryInterface <DXGI.SwapChain2>()) { var value = swapChain2.MaximumFrameLatency; swapChain2.MaximumFrameLatency = 1; } } } }