You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
663 lines
19 KiB
663 lines
19 KiB
using EC.Entity.Video;
|
|
using EC.FFmpegAutoGen;
|
|
using EC.Utils.Config;
|
|
|
|
using ECMonitor.Code;
|
|
using ECMonitor.Code.Config;
|
|
using ECMonitor.Manager;
|
|
using FFmpeg.AutoGen;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using NetMQ.Sockets;
|
|
using NetMQ;
|
|
using EC.Utils.ImageHelpers;
|
|
using EC.Utils;
|
|
|
|
namespace ECMonitor.UC.Videos
|
|
{
|
|
/// <summary>
|
|
/// UCFFmpegPlayer.xaml 的交互逻辑
|
|
/// </summary>
|
|
public partial class UCFFmpegAIBoxPlayer : UserControl, IUCPlayer
|
|
{
|
|
/// <summary>
|
|
/// 视频播放器序号
|
|
/// </summary>
|
|
int _videoIndex = 0;
|
|
private string Message { get; set; }
|
|
private string UcName { get; set; }
|
|
|
|
public MonitorCamera Camera { get; set; }
|
|
public int VideoType { get; set; }
|
|
/// <summary>
|
|
/// 更新时间
|
|
/// </summary>
|
|
private DateTime upDateTime;
|
|
|
|
public event EventHandler OnFromClose;
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
double NormaWidth { get; set; } = 0;
|
|
double NormaHeight { get; set; } = 0;
|
|
/// <summary>
|
|
/// 最大化
|
|
/// </summary>
|
|
bool WindowStateMax { get; set; } = false;
|
|
string inputpath = ConfigHelper.AIInputPath();
|
|
string outpath = ConfigHelper.AIOutPath();
|
|
string _aiServer = ConfigHelper.AISvrServer();
|
|
|
|
|
|
|
|
public UCFFmpegAIBoxPlayer(double width, double height, int videoIndex, bool showCloseButton = true, string aspectRatio = "4:3")
|
|
{
|
|
this.Width = width;
|
|
this.Height = height;
|
|
InitializeComponent();
|
|
this.Name = "UCPlayer" + videoIndex;
|
|
UcName = this.Name;
|
|
this.btnClose.Visibility = showCloseButton ? Visibility.Visible : Visibility.Hidden;
|
|
ReSetSize(width, height);
|
|
ShowMsg("没有视频");
|
|
_videoIndex = videoIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 设置窗体大小
|
|
/// </summary>
|
|
/// <param name="width"></param>
|
|
/// <param name="height"></param>
|
|
public void ReSetSize(double width, double height)
|
|
{
|
|
Width = width;
|
|
Height = height;
|
|
//显示内容
|
|
//double messageWidht = 40;
|
|
//double left = width / 2 - messageWidht / 2;
|
|
//double top = height / 2 - 20;
|
|
////double right = width-(left + messageWidht);
|
|
////double bottom = height / 2 - 10;
|
|
//this.txtShow.Margin = new Thickness(left, top, right, bottom);
|
|
this.imgPlayer.Height = height;
|
|
|
|
SetSelected(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Play(MonitorCamera camera, bool replay = false)
|
|
{
|
|
if (IsPlaying())
|
|
{
|
|
if (replay == false)
|
|
{
|
|
if (camera.Ip == Camera.Ip)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
Stop();
|
|
|
|
}
|
|
Camera = camera;
|
|
if (Camera == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return Play();
|
|
|
|
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
try
|
|
{
|
|
if (_playing == false)
|
|
{
|
|
return;
|
|
}
|
|
_playing = false;
|
|
Camera = null;
|
|
MemoryStream ms = null;
|
|
Task.Factory.StartNew(() => { Thread.Sleep(1000); SetImageSource(ms); _playingSuccess = false; });
|
|
ShowMsg("视频已经关闭");
|
|
OnFromClose?.Invoke(this, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger().Error(ex);
|
|
}
|
|
}
|
|
|
|
public void UPDateTime()
|
|
{
|
|
upDateTime = DateTime.Now;
|
|
|
|
}
|
|
/// <summary>
|
|
/// 判断预警是否接触
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool IsTimeOut()
|
|
{
|
|
DateTime now = DateTime.Now;
|
|
double difSeconds = DateUnit.DateDiffSeconds(upDateTime, now);
|
|
return difSeconds > 6;
|
|
}
|
|
public string GetCameraIp()
|
|
{
|
|
if (Camera != null)
|
|
{
|
|
return Camera.Ip;
|
|
}
|
|
return "";
|
|
}
|
|
/// <summary>
|
|
/// 播放器类型
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public int GetPlayerType()
|
|
{
|
|
return VideoType;
|
|
}
|
|
/// <summary>
|
|
/// 相机
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public MonitorCamera GetCamera()
|
|
{
|
|
return Camera;
|
|
}
|
|
|
|
public UserControl GetControl()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
public string GetMessage()
|
|
{
|
|
return Message;
|
|
}
|
|
|
|
public string GetName()
|
|
{
|
|
return UcName;
|
|
}
|
|
/// <summary>
|
|
/// 是否是空播放器
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool IsNullPlay()
|
|
{
|
|
return Camera == null;
|
|
}
|
|
/// <summary>
|
|
/// 是否播放
|
|
/// </summary>
|
|
bool _playing = false;
|
|
/// <summary>
|
|
/// 播放成功
|
|
/// </summary>
|
|
bool _playingSuccess = false;
|
|
/// <summary>
|
|
/// 是否正在播放
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool IsPlaying()
|
|
{
|
|
if (Camera == null)
|
|
{
|
|
return false;
|
|
}
|
|
return _playing;//&& _playingSuccess;
|
|
}
|
|
private int listIndex = 0;
|
|
public int GetIndex()
|
|
{
|
|
return listIndex;
|
|
}
|
|
|
|
public void SetIndex(int index)
|
|
{
|
|
listIndex = index;
|
|
}
|
|
/// <summary>
|
|
/// 是否显示
|
|
/// </summary>
|
|
private bool IsShow = false;
|
|
|
|
|
|
|
|
public bool GetIsShow()
|
|
{
|
|
return IsShow;
|
|
}
|
|
public void SetIsShow(bool isShow)
|
|
{
|
|
IsShow = isShow;
|
|
}
|
|
|
|
|
|
private void btnClose_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Stop();
|
|
OnFromClose?.Invoke(sender, e);
|
|
}
|
|
|
|
|
|
#region FFmpeg
|
|
|
|
public delegate void dlgtSetImage(MemoryStream ms);
|
|
public delegate void dlgtSetImageByte(byte[] ms);
|
|
void SetImageSource(MemoryStream ms)
|
|
{
|
|
this.imgPlayer.Dispatcher.Invoke(new dlgtSetImage(SetImage), ms);
|
|
}
|
|
void SetImage(MemoryStream ms)
|
|
{
|
|
//if (this.imgPlayer.Dispatcher.CheckAccess())
|
|
//{
|
|
// this.imgPlayer.Dispatcher.Invoke(new dlgtSetImage(setImage), ms);
|
|
// return;
|
|
//}
|
|
ShowMsg("");
|
|
if (ms == null)
|
|
{
|
|
imgPlayer.Source = null; // done!
|
|
return;
|
|
}
|
|
|
|
BitmapImage bi = new BitmapImage();
|
|
bi.BeginInit();
|
|
bi.StreamSource = new MemoryStream(ms.ToArray()); // 不要直接使用 ms
|
|
bi.EndInit();
|
|
// Guid photoID = System.Guid.NewGuid();
|
|
//string photolocation = $"img//" + DateTime.Now.ToString("MMddHHmmssfff") + ".jpg"; //file name
|
|
//FileStream filestream = new FileStream(photolocation, FileMode.Create);
|
|
//JpegBitmapEncoder encoder = new JpegBitmapEncoder();
|
|
//encoder.Frames.Add(BitmapFrame.Create(bi));
|
|
//encoder.Save(filestream);
|
|
|
|
imgPlayer.Source = bi; // done!
|
|
|
|
// ms.Close();
|
|
|
|
//}
|
|
}
|
|
|
|
void SetImageSource(byte[] ms)
|
|
{
|
|
this.imgPlayer.Dispatcher.Invoke(new dlgtSetImageByte(SetImage), ms);
|
|
}
|
|
void SetImage(byte[] ms)
|
|
{
|
|
|
|
ShowMsg("");
|
|
if (ms == null)
|
|
{
|
|
imgPlayer.Source = null; // done!
|
|
return;
|
|
}
|
|
|
|
BitmapImage bi = new BitmapImage();
|
|
bi.BeginInit();
|
|
bi.StreamSource = new MemoryStream(ms); // 不要直接使用 ms
|
|
bi.EndInit();
|
|
//// Guid photoID = System.Guid.NewGuid();
|
|
//string photolocation = $"img//" + DateTime.Now.ToString("MMddHHmmssfff") + ".jpg"; //file name
|
|
//FileStream filestream = new FileStream(photolocation, FileMode.Create);
|
|
//JpegBitmapEncoder encoder = new JpegBitmapEncoder();
|
|
//encoder.Frames.Add(BitmapFrame.Create(bi));
|
|
//encoder.Save(filestream);
|
|
|
|
imgPlayer.Source = bi; // done!
|
|
|
|
// ms.Close();
|
|
|
|
//}
|
|
}
|
|
|
|
public bool Play()
|
|
{
|
|
Message = "";
|
|
try
|
|
{
|
|
Task.Factory.StartNew(() => PlayThread());
|
|
CheckPlaySuccessed();
|
|
|
|
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
ShowMsg(ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
public bool PlayThread()
|
|
{
|
|
if (Camera == null)
|
|
{
|
|
return false;
|
|
}
|
|
_playing = true;
|
|
UPDateTime();
|
|
//string url = "rtsp://admin:hk123456@192.168.1.108:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif";
|
|
// string url = "rtsp://admin:hk123456@192.168.1.65:554/Streaming/Channels/102?transportmode=unicast&profile=Profile_2";
|
|
string url = Camera.RtspURL();
|
|
FFmpegBinariesHelper.RegisterFFmpegBinaries();
|
|
|
|
// Console.WriteLine($"FFmpeg version info: {ffmpeg.av_version_info()}");
|
|
|
|
SetupLogging();
|
|
// ConfigureHWDecoder(out var deviceType);
|
|
|
|
var deviceType = AVHWDeviceType.AV_HWDEVICE_TYPE_DXVA2;
|
|
DecodeAllFramesToImages(deviceType, url);
|
|
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// 判断是否播放成功,因为播放没有返回,只能从有没有图片返回判断
|
|
/// </summary>
|
|
public void CheckPlaySuccessed()
|
|
{
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.Sleep(5000);
|
|
if (_playingSuccess == false)
|
|
{
|
|
_playing = false;
|
|
if (Camera != null)
|
|
{
|
|
ShowMsg(Camera.Ip + "播放失败");
|
|
}
|
|
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
private unsafe void SetupLogging()
|
|
{
|
|
ffmpeg.av_log_set_level(ffmpeg.AV_LOG_VERBOSE);
|
|
|
|
// do not convert to local function
|
|
av_log_set_callback_callback logCallback = (p0, level, format, vl) =>
|
|
{
|
|
if (level > ffmpeg.av_log_get_level()) return;
|
|
|
|
var lineSize = 1024;
|
|
var lineBuffer = stackalloc byte[lineSize];
|
|
var printPrefix = 1;
|
|
ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
|
var line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer);
|
|
|
|
LogFactory.GetLogger().Debug(line);
|
|
|
|
};
|
|
|
|
ffmpeg.av_log_set_callback(logCallback);
|
|
}
|
|
|
|
private unsafe void DecodeAllFramesToImages(AVHWDeviceType HWDevice, string url)
|
|
{
|
|
// decode all frames from url, please not it might local resorce, e.g. string url = "../../sample_mpeg4.mp4";
|
|
//*var url = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4*/"; // be advised this file holds 1440 frames
|
|
|
|
using var vsd = new VideoStreamDecoder(url, HWDevice);
|
|
|
|
Console.WriteLine($"codec name: {vsd.CodecName}");
|
|
|
|
var info = vsd.GetContextInfo();
|
|
info.ToList().ForEach(x => Console.WriteLine($"{x.Key} = {x.Value}"));
|
|
|
|
var sourceSize = vsd.FrameSize;
|
|
var sourcePixelFormat = HWDevice == AVHWDeviceType.AV_HWDEVICE_TYPE_NONE
|
|
? vsd.PixelFormat
|
|
: FFmpegHelper.GetHWPixelFormat(HWDevice);
|
|
var destinationSize = sourceSize;
|
|
var destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_BGR24;
|
|
using var vfc =
|
|
new VideoFrameConverter(sourceSize, sourcePixelFormat, destinationSize, destinationPixelFormat);
|
|
|
|
var frameNumber = 0;
|
|
int imageNumber = 0;
|
|
while (_playing && vsd.TryDecodeNextFrame(out var frame))
|
|
{
|
|
var convertedFrame = vfc.Convert(frame);
|
|
|
|
var bitmap = new Bitmap(convertedFrame.width,
|
|
convertedFrame.height,
|
|
convertedFrame.linesize[0],
|
|
System.Drawing.Imaging.PixelFormat.Format24bppRgb,
|
|
(IntPtr)convertedFrame.data[0]);
|
|
|
|
|
|
//IntPtr hBitmap = bitmap.GetHbitmap();
|
|
//System.Windows.Media.ImageSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty,
|
|
//BitmapSizeOptions.FromEmptyOptions());
|
|
// bitmapSource.Freeze();
|
|
|
|
_playingSuccess = true;
|
|
imageNumber++;
|
|
imageNumber = imageNumber % 100;
|
|
var x = imageNumber % 3;
|
|
if (x == 0)
|
|
{
|
|
continue;
|
|
}
|
|
//if (x==2)
|
|
//{
|
|
// string filename = imageNumber + ".jpg";
|
|
// string fullfileName = inputpath + filename;
|
|
// bitmap.Save(fullfileName, ImageFormat.Jpeg);
|
|
// bitmap.Dispose();
|
|
// PubToAI(filename);
|
|
//}
|
|
if (x == 2)
|
|
{
|
|
PubToAI(bitmap);
|
|
//PubToAI(filename);
|
|
}
|
|
else
|
|
{
|
|
//MemoryStream stream = new MemoryStream();
|
|
//bitmap.Save(stream, ImageFormat.Bmp);
|
|
//SetImageSource(stream);
|
|
//bitmap.Dispose();
|
|
}
|
|
|
|
|
|
Console.WriteLine($"frame: {frameNumber}");
|
|
frameNumber++;
|
|
}
|
|
|
|
}
|
|
|
|
//将Bitmap对象转换成bitmapImage对象
|
|
//public BitmapImage ConvertBitmapToBitmapImage(Bitmap bitmap)
|
|
//{
|
|
// MemoryStream stream = new MemoryStream();
|
|
// bitmap.Save(stream, ImageFormat.Bmp);
|
|
// BitmapImage image = new BitmapImage();
|
|
// image.BeginInit();
|
|
// image.StreamSource = stream;
|
|
// image.EndInit();
|
|
// return image;
|
|
//}
|
|
|
|
|
|
#endregion
|
|
|
|
public void ShowMsg(string message)
|
|
{
|
|
this.txtShow.Dispatcher.Invoke(new Action(() => { this.txtShow.Text = message; }));
|
|
}
|
|
private void Log(string message, bool isErr = false)
|
|
{
|
|
ShowMsg(message);
|
|
}
|
|
public void SetSelected(bool selected)
|
|
{
|
|
Thickness thickness = new Thickness(0);
|
|
if (selected)
|
|
{
|
|
thickness = new Thickness(1);
|
|
}
|
|
this.playerBorder.Dispatcher.Invoke(new Action(() => { playerBorder.BorderThickness = thickness; }));
|
|
|
|
|
|
}
|
|
#region 事件
|
|
public event EventHandler<int> PlayerMouseDown;
|
|
public event EventHandler<int> PlayerMouseDoubleClick;
|
|
|
|
|
|
|
|
|
|
private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
PlayerMouseDown?.Invoke(this, _videoIndex);
|
|
}
|
|
|
|
private void UserControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
|
{
|
|
PlayerMouseDoubleClick?.Invoke(this, _videoIndex);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置最大化
|
|
/// </summary>
|
|
/// <param name="width"></param>
|
|
/// <param name="height"></param>
|
|
/// <returns></returns>
|
|
public bool SetMaximized(double width, double height)
|
|
{
|
|
if (WindowStateMax == false)
|
|
{
|
|
NormaWidth = this.Width;
|
|
NormaHeight = this.Height;
|
|
WindowStateMax = true;
|
|
ReSetSize(width, height);
|
|
|
|
}
|
|
else
|
|
{
|
|
WindowStateMax = false;
|
|
ReSetSize(NormaWidth, NormaHeight);
|
|
}
|
|
return WindowStateMax;
|
|
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ZMQ
|
|
|
|
private void PubToAI(Bitmap inbitmap)
|
|
{
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
try
|
|
{
|
|
if (_playing == false)
|
|
{
|
|
return;
|
|
}
|
|
byte[] data = ImageHelper.ImageToByteArray(inbitmap);
|
|
inbitmap.Dispose();
|
|
if (data == null) return;
|
|
using (var requestSocket = new RequestSocket(_aiServer))
|
|
{
|
|
requestSocket.SendFrame(data);
|
|
var timeout = new TimeSpan(0, 0, 1);
|
|
byte[] recdata = new byte[0];
|
|
bool recSuccess = requestSocket.TryReceiveFrameBytes(timeout, out recdata);
|
|
// byte[] recdata = requestSocket.ReceiveFrameBytes();
|
|
if (recSuccess)
|
|
{
|
|
SetImageSource(recdata);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowMsg(ex.Message);
|
|
LogFactory.GetLogger().Error(ex);
|
|
}
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
//private void PubToAI(string fileName)
|
|
//{
|
|
|
|
// Task.Factory.StartNew(() =>
|
|
// {
|
|
// try
|
|
// {
|
|
// using (var requestSocket = new RequestSocket(_aiServer))
|
|
// {
|
|
// requestSocket.SendFrame(fileName);
|
|
// var recfileName = requestSocket.ReceiveFrameString();
|
|
// string fullFileName = outpath + recfileName;
|
|
// System.Drawing.Image bitmap = System.Drawing.Bitmap.FromFile(fullFileName);
|
|
// MemoryStream stream = new MemoryStream();
|
|
// bitmap.Save(stream, ImageFormat.Bmp);
|
|
// SetImageSource(stream);
|
|
|
|
// }
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// ShowMsg(ex.Message);
|
|
// LogFactory.GetLogger().Error(ex);
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
// }
|
|
#endregion
|
|
}
|
|
}
|
|
|