using Accord.Video.FFMPEG; using AIDiagnosisDemo.Infrastucture; using AIDiagnosisDemo.Settings; using System; using System.Drawing; using System.Threading; using System.Windows; namespace AIDiagnosisDemo.Service { internal class FileVideoPlayer : IPlayer { private string _filepath; private VideoFileReader _videoFileReader; private Thread _playThread; private bool _pausing; private int _startTickCount; private int _displayCount; private int _fps; private readonly object _videoReaderLocker = new object(); private volatile int _frameIntervalTime = 0; private volatile int _frameCount = 0; private volatile int _frameIndex = 0; /// /// 接收到图像输入的事件 /// public event EventHandler InputFrameReceived; /// /// FPS变更的事件 /// public event EventHandler FPSChanged; /// /// FileVideoPlayer构造函数 /// /// 文件路径 public FileVideoPlayer(string filepath) { _filepath = filepath; } /// /// 播放 /// /// 播放成功为True,播放失败为False public bool Play() { if (!SettingConfig.Instance.IsVideo) { if (ImagePlay()) { return true; } else { return false; } } else { if (VideoPlay()) { return true; } else { return false; } } } private bool ImagePlay() { try { if (string.IsNullOrEmpty(_filepath)) { Logger.Info("Image File Path is Empty!!!"); return false; } var bitmap = new Bitmap(_filepath); OnNewFrame(bitmap); bitmap.Dispose(); return true; } catch (Exception ex) { Logger.Info($"Image Play Error: {ex} "); return false; } } private void OnNewFrame(Bitmap e) { InputFrameReceived?.Invoke(this, e); } private bool VideoPlay() { try { if (string.IsNullOrEmpty(_filepath)) { Logger.Info("Video File Path is Empty!!!"); return false; } _videoFileReader = new VideoFileReader(); _videoFileReader.Open(_filepath); var frameRate = _videoFileReader.FrameRate.ToDouble(); _frameIntervalTime = (int)(1000 / frameRate); _frameCount = (int)_videoFileReader.FrameCount; StartPlayThread(); return true; } catch { return false; } } private void DoVideoPlay() { _startTickCount = -1; while (!_pausing) { Bitmap bitmap = null; lock (_videoReaderLocker) { try { bitmap = _videoFileReader?.ReadVideoFrame(_frameIndex); } catch (Exception ex) { MessageBox.Show($"ReadVideoFrame Error:{ex}"); } } if (bitmap == null) { break; } OnNewFrame(bitmap); var timeUsed = Environment.TickCount - _startTickCount; bitmap.Dispose(); if (_startTickCount == -1) { _displayCount = 0; _startTickCount = Environment.TickCount; } else { var currentTickCount = Environment.TickCount; var fpsTimeUsed = currentTickCount - _startTickCount; _displayCount++; if (fpsTimeUsed > 1000) { var fps = (int)((double)_displayCount / fpsTimeUsed * 1000); if (_fps != fps) { _fps = fps; FPSChanged?.Invoke(this, _fps); } _startTickCount = currentTickCount; _displayCount = 0; } } var waitTime = _frameIntervalTime - timeUsed; Thread.Sleep(waitTime < 0 ? 1 : waitTime); // 如果到尾了,就从头开始 if (_frameIndex == _frameCount - 1) { _frameIndex = 0; } else { _frameIndex += 1; } } } /// /// 暂停播放 /// public void Pause() { if (SettingConfig.Instance.IsVideo) { _pausing = true; } } /// /// 继续播放 /// public void Continue() { if (SettingConfig.Instance.IsVideo) { StartPlayThread(); } } private void StartPlayThread() { _pausing = false; if (_playThread == null || !_playThread.IsAlive) { _playThread = new Thread(() => DoVideoPlay()) { IsBackground = true, Name = "AIDiagnosisDemo_FileVideoPlay", }; _playThread.Start(); } } /// /// 停止播放 /// public void Stop() { _pausing = true; lock (_videoReaderLocker) { if (_videoFileReader != null) { _videoFileReader.Close(); _videoFileReader.Dispose(); _videoFileReader = null; } } } } }