예제 #1
0
        public void Display(IBitmapFrame Frame)
        {
            if (Frame is RepeatFrame)
            {
                return;
            }

            if (!IsVisible)
            {
                Frame.Dispose();
                return;
            }

            var win = MainWindow.Instance;

            win.Dispatcher.Invoke(() =>
            {
                win.DisplayImage.Image = null;

                _lastFrame?.Dispose();
                _lastFrame = Frame;

                Frame = Frame.Unwrap();

                switch (Frame)
                {
                case DrawingFrame drawingFrame:
                    try
                    {
                        // TODO: Preview is not shown during Webcam only recordings
                        // This check swallows errors
                        var h = drawingFrame.Bitmap.Height;

                        if (h == 0)
                        {
                            return;
                        }
                    }
                    catch { return; }

                    win.WinFormsHost.Visibility = Visibility.Visible;
                    win.DisplayImage.Image      = drawingFrame.Bitmap;
                    break;

                case Texture2DFrame texture2DFrame:
                    win.WinFormsHost.Visibility = Visibility.Collapsed;
                    if (_d3D9PreviewAssister == null)
                    {
                        _d3D9PreviewAssister = new D3D9PreviewAssister(ServiceProvider.Get <IPlatformServices>());
                        _texture             = _d3D9PreviewAssister.GetSharedTexture(texture2DFrame.PreviewTexture);

                        using var surface = _texture.GetSurfaceLevel(0);
                        _backBufferPtr    = surface.NativePointer;
                    }

                    Invalidate(_backBufferPtr, texture2DFrame.Width, texture2DFrame.Height);
                    break;
                }
            });
        }
예제 #2
0
        public void Display(IBitmapFrame Frame)
        {
            if (Frame is RepeatFrame)
            {
                return;
            }

            if (!IsVisible)
            {
                Frame.Dispose();
                return;
            }

            _previewWindow.Dispatcher.Invoke(() =>
            {
                _previewWindow.DisplayImage.Image = null;

                _lastFrame?.Dispose();
                _lastFrame = Frame;

                Frame = Frame.Unwrap();

                switch (Frame)
                {
                case DrawingFrame drawingFrame:
                    _previewWindow.WinFormsHost.Visibility = Visibility.Visible;
                    _previewWindow.DisplayImage.Image      = drawingFrame.Bitmap;
                    break;

                case Texture2DFrame texture2DFrame:
                    _previewWindow.WinFormsHost.Visibility = Visibility.Collapsed;
                    if (_d3D9PreviewAssister == null)
                    {
                        _d3D9PreviewAssister = new D3D9PreviewAssister(ServiceProvider.Get <IPlatformServices>());
                        _texture             = _d3D9PreviewAssister.GetSharedTexture(texture2DFrame.PreviewTexture);

                        using (var surface = _texture.GetSurfaceLevel(0))
                        {
                            _backBufferPtr = surface.NativePointer;
                        }
                    }

                    Invalidate(_backBufferPtr, texture2DFrame.Width, texture2DFrame.Height);
                    break;
                }
            });
        }
예제 #3
0
        /// <summary>
        /// Writes an Image frame.
        /// </summary>
        public void WriteFrame(IBitmapFrame Frame)
        {
            if (_ffmpegProcess.HasExited)
            {
                Frame.Dispose();
                throw new FFmpegException(_ffmpegProcess.ExitCode);
            }

            if (_firstFrame)
            {
                if (!_ffmpegIn.WaitForConnection(5000))
                {
                    throw new Exception("Cannot connect Video pipe to FFmpeg");
                }

                _firstFrame = false;
            }

            _lastFrameTask?.Wait();

            if (!(Frame is RepeatFrame))
            {
                using (Frame)
                {
                    if (Frame.Unwrap() is INV12Frame nv12Frame)
                    {
                        nv12Frame.CopyNV12To(_videoBuffer);
                    }
                    else
                    {
                        Frame.CopyTo(_videoBuffer);
                    }
                }
            }

            try
            {
                _lastFrameTask = _ffmpegIn.WriteAsync(_videoBuffer, 0, _videoBuffer.Length);
            }
            catch (Exception e) when(_ffmpegProcess.HasExited)
            {
                throw new FFmpegException(_ffmpegProcess.ExitCode, e);
            }
        }
예제 #4
0
        /// <summary>
        /// Writes an Image frame.
        /// </summary>
        public void WriteFrame(IBitmapFrame Frame)
        {
            if (_ffmpegProcess.HasExited)
            {
                Frame.Dispose();
                throw new FFmpegException(_ffmpegProcess.ExitCode);
            }

            if (_firstFrame)
            {
                if (!_ffmpegIn.WaitForConnection(5000))
                {
                    throw new Exception("Cannot connect Video pipe to FFmpeg");
                }

                _firstFrame = false;
            }

            if (_lastFrameTask == null)
            {
                _lastFrameTask = Task.CompletedTask;
            }

            if (!(Frame is RepeatFrame))
            {
                using (Frame)
                {
                    if (Frame.Unwrap() is INV12Frame nv12Frame)
                    {
                        nv12Frame.CopyNV12To(_videoBuffer);
                    }
                    else
                    {
                        Frame.CopyTo(_videoBuffer);
                    }
                }
            }

            // Drop frames if semaphore cannot be acquired soon enough.
            // Frames are dropped mostly in the beginning of recording till atleast one audio frame is received.
            if (!_spVideo.Wait(_spTimeout))
            {
                ++_skippedFrames;
                _frameStreak = 0;
                return;
            }

            // Most of the drops happen in beginning of video, once that stops, sync can be done.
            if (!_initialStability)
            {
                ++_frameStreak;
                if (_frameStreak > FrameStreakThreshold)
                {
                    _initialStability = true;
                }
            }

            try
            {
                // Check if last write failed.
                if (_lastFrameTask != null && _lastFrameTask.IsFaulted)
                {
                    _lastFrameTask.Wait();
                }

                _lastFrameTask = _lastFrameTask.ContinueWith(async M =>
                {
                    try
                    {
                        await _ffmpegIn.WriteAsync(_videoBuffer, 0, _videoBuffer.Length);
                    }
                    finally
                    {
                        _spVideo.Release();
                    }
                });
            }
            catch (Exception e) when(_ffmpegProcess.HasExited)
            {
                throw new FFmpegException(_ffmpegProcess.ExitCode, e);
            }
        }