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

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