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;
}
}
}
}
}