解决方案:Unity调用大华相机SDK采集图像及基本功能设定

优采云 发布时间: 2022-12-01 22:39

  解决方案:Unity调用大华相机SDK采集图像及基本功能设定

  unity平台对视频播放不是很友好,大华的SDK只有ac#版本,并没有专门做unity的SDK。一开始,我尝试使用SDK中的方法获取YUV格式的视频流,接下来说说YUV格式的视频流。转换成unity可以播放的格式,但是这种格式转换经常出问题,很卡,所以用了ump插件播放rtsp视频流,比较流畅。

  ump插件下载链接: 提取码:ahez(仅供学习,请勿商用)

  大华设备rtsp流组成分析:

  rtsp://[用户名]:[密码]@[地址]:[端口]/cam/realmonitor?channel=[id]&subtype=[类型]

  rtsp:// => 协议格式头

  用户名 => 用户名,例如:admin

  密码 => 密码,例如:123456

  address => IPC设备的网络地址,例如:192.168.1.65

  port => IPC设备的RTSP输出端口,默认为554,如果是默认可以留空

  id => 频道号,从1开始。比如频道2,那么channel=2。

  type => 流类型,主流为0(即subtype=0),辅流为1(即subtype=1)。

  原文链接:(原文介绍了大华和海康的rtsp视频流组成,我这里只用大华的,需要海康的请自行查找)

  插件非常简单易用,只需将UniversalMediaPlayer预制件拖放到场景中,修改脚本上的rtsp流,即可观看视频。

  但!由于执法记录仪上没有我们需要的功能,所以我们定制了自己需要的功能,然后对执法记录仪进行了系统升级。结果,升级之后,之前的获取rtsp视频流的功能居然不可用了。联系大华技术部后得出结论,欣赏后不能用rtsp播放视频流,需要的话可以自定义。emm……这就很尴尬了,定制是不可能的,但问题还是要解决。在热心和同步的提示和帮助下,我们采用了使用winform程序播放视频的方法。虽然界面有点丑,但还是完成了需要的功能。

  窗体代码:

  调用大华SDK

  using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using NetSDKCS;

using System.Diagnostics;

using System.Runtime.InteropServices;

using System.IO;

using System;

using System.Collections.Generic;

namespace MeshDaHuaTool

{

public class DaHuaManager

{

#region Field 字段,属性

private const int m_WaitTime = 5000;

private const int SyncFileSize = 5 * 1024 * 1204;

private static fDisConnectCallBack m_DisConnectCallBack;

private static fHaveReConnectCallBack m_ReConnectCallBack;

private static fRealDataCallBackEx2 m_RealDataCallBackEx2;

private static fSnapRevCallBack m_SnapRevCallBack;

private static fAudioDataCallBack m_AudioDataCallBack;

private IntPtr m_LoginID = IntPtr.Zero;

private IntPtr m_TalkID = IntPtr.Zero;

private NET_DEVICEINFO_Ex m_DeviceInfo;

private IntPtr m_RealPlayID = IntPtr.Zero;

private uint m_SnapSerialNum = 1;

private bool m_IsInSave = false;

private bool m_Islogin = false;

//对讲参数

private const int SampleRate = 8000;

private const int AudioBit = 16;

private const int PacketPeriod = 25;

private const int SendAudio = 0;

private const int ReviceAudio = 1;

//回放参数

private IntPtr m_PlayBackID = IntPtr.Zero;

//下载录像参数

IntPtr m_DownloadID = IntPtr.Zero;

fTimeDownLoadPosCallBack m_DownloadPosCallBack;

///

/// 步长速度

///

private int SpeedValue = 4;

///

/// 最大步长速度

///

private const int MaxSpeed = 8;

///

/// 最小步长速度

///

private const int MinSpeed = 1;

///

/// 抓图保存根目录

///

private string m_CaptureImageDirectory;

///

/// 获取SDK错误

///

private string LastError

{

get

{

return NETClient.GetLastError();

}

}

///

/// 是否正在保存视频

///

public bool IsinSave

{

get

{

return m_IsInSave;

}

}

#endregion

#region 回调

public Action OnSucess;

public Action OnError;

public Action OnCaptureSucced;

#endregion

///

/// 初始化

///

public void Init()

{

m_DisConnectCallBack = new fDisConnectCallBack(DisConnectCallBack);

m_ReConnectCallBack = new fHaveReConnectCallBack(ReConnectCallBack);

m_RealDataCallBackEx2 = new fRealDataCallBackEx2(RealDataCallBackEx);

m_SnapRevCallBack = new fSnapRevCallBack(SnapRevCallBack);

m_AudioDataCallBack = new fAudioDataCallBack(AudioDataCallBack);

m_DownloadPosCallBack = new fTimeDownLoadPosCallBack(TimeDownLoadPosCallBack);

try

{

//注册回调函数

NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null);

NETClient.SetAutoReconnect(m_ReConnectCallBack, IntPtr.Zero);

NETClient.SetSnapRevCallBack(m_SnapRevCallBack, IntPtr.Zero);

//抓图路径赋值

m_CaptureImageDirectory = @"C:\img";

if (!Directory.Exists(m_CaptureImageDirectory))

{

Directory.CreateDirectory(m_CaptureImageDirectory);

}

}

catch (Exception ex)

{

OnError?.Invoke(new ErrorArgs(ErrorType.None, ex.Message));

Process.GetCurrentProcess().Kill();

}

}

///

/// 登录大华平台

///

/// IP地址

/// 端口

/// 用户名

/// 密码

public void Login(string ip, ushort port, string username, string password)

{

if (IntPtr.Zero == m_LoginID)

{

m_DeviceInfo = new NET_DEVICEINFO_Ex();

m_LoginID = NETClient.Login(ip, port, username, password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);

if (IntPtr.Zero == m_LoginID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.Login, LastError));

return;

}

OnSucess?.Invoke(ErrorType.Login);

m_Islogin = true;

}

}

///

/// 登出

///

public void Logout()

{

if (!m_Islogin)

{

return;

}

//关闭对讲

if (IntPtr.Zero != m_TalkID && IntPtr.Zero != m_LoginID)

{

NETClient.RecordStop(m_LoginID);

NETClient.StopTalk(m_TalkID);

}

if (IsinSave)

{

StopSaveVideo();

}

if (m_RealPlayID != IntPtr.Zero)

{

StopRealPlay();

}

m_Islogin = false;

if (m_LoginID == IntPtr.Zero)

{

OnError?.Invoke(new ErrorArgs(ErrorType.Logout, "m_LoginID zero"));

return;

}

bool result = NETClient.Logout(m_LoginID);

if (!result)

{

OnError?.Invoke(new ErrorArgs(ErrorType.Logout, LastError));

return;

}

m_LoginID = IntPtr.Zero;

m_RealPlayID = IntPtr.Zero;

OnSucess?.Invoke(ErrorType.Logout);

}

///

/// 开始实时播放

///

///

public void StartRealPlay(PictureBox realplay_pictureBox)

{

if (!m_Islogin)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StartRealPlay, "未登录"));

return;

}

if (IntPtr.Zero == m_RealPlayID)

{

// realplay 监视

EM_RealPlayType type = GetRealPlayType();

m_RealPlayID = NETClient.RealPlay(m_LoginID, GetChanel(), realplay_pictureBox.Handle, type);

if (IntPtr.Zero == m_RealPlayID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StartRealPlay, LastError));

return;

}

}

}

///

/// 打开声音

///

public void OpenSound()

{

if (!NETClient.OpenSound(m_RealPlayID))

{

OnError?.Invoke(new ErrorArgs(ErrorType.None, "打开声音错误: " + LastError));

}

}

///

/// 关闭声音

///

public void StopSound()

{

if (!NETClient.CloseSound())

{

OnError?.Invoke(new ErrorArgs(ErrorType.None, "关闭声音失败: " + LastError));

}

}

///

/// 停止播放

///

public void StopRealPlay()

{

if (!m_Islogin)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StopRealPlay, "未登录"));

return;

}

if (IntPtr.Zero == m_RealPlayID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StopRealPlay, "未开始播放,无法停止"));

return;

}

bool ret = NETClient.StopRealPlay(m_RealPlayID);

if (!ret)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StopRealPlay, LastError));

return;

<p>

" />

}

m_RealPlayID = IntPtr.Zero;

OnSucess?.Invoke(ErrorType.StopRealPlay);

}

///

/// 抓图

///

/// false 本地抓图,true 远程抓图

public void CaptureImage(bool isRemote = false)

{

//重新设置远程抓图的回调

NETClient.SetSnapRevCallBack(m_SnapRevCallBack, IntPtr.Zero);

if (!m_Islogin)

{

OnError?.Invoke(new ErrorArgs(ErrorType.CaptureImage, "未登录"));

return;

}

if (isRemote)

{

NET_SNAP_PARAMS asyncSnap = new NET_SNAP_PARAMS();

asyncSnap.Channel = (ushort)GetChanel();

asyncSnap.Quality = 6;

asyncSnap.ImageSize = 2;

asyncSnap.mode = 0;

asyncSnap.InterSnap = 0;

asyncSnap.CmdSerial = m_SnapSerialNum;

bool ret = NETClient.SnapPictureEx(m_LoginID, asyncSnap, IntPtr.Zero);

if (!ret)

{

OnError?.Invoke(new ErrorArgs(ErrorType.CaptureImage, LastError));

return;

}

m_SnapSerialNum++;

}

else

{

if (IntPtr.Zero == m_RealPlayID)

{

Console.WriteLine("没有打开实时预览,无法抓图");

return;

}

string fileName = "local_" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".jpg";

string filePath = @"C:\img" + "\\" + "client_" + fileName;

bool result = NETClient.CapturePicture(m_RealPlayID, filePath, EM_NET_CAPTURE_FORMATS.JPEG);

if (!result)

{

OnError?.Invoke(new ErrorArgs(ErrorType.CaptureImage, LastError));

return;

}

}

}

///

/// 保存视频

///

public void SaveVideo()

{

if (IntPtr.Zero == m_RealPlayID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StartSaveVideo, "未打开预览,无法保存录像"));

return;

}

if (m_IsInSave)

{

OnError?.Invoke(new ErrorArgs(ErrorType.StartSaveVideo, "保存中,不要重复操作"));

return;

}

SaveFileDialog saveFileDialog = new SaveFileDialog();

saveFileDialog.FileName = "video_" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");

saveFileDialog.Filter = "|*.dav";

string path = @"C:\savedata";

if (!Directory.Exists(path))

{

Directory.CreateDirectory(path);

}

saveFileDialog.InitialDirectory = path;

var res = saveFileDialog.ShowDialog();

if (res == System.Windows.Forms.DialogResult.OK)

{

m_IsInSave = NETClient.SaveRealData(m_RealPlayID, saveFileDialog.FileName); //call saverealdata function.

if (!m_IsInSave)

{

saveFileDialog.Dispose();

OnError?.Invoke(new ErrorArgs(ErrorType.StartSaveVideo, LastError));

}

OnSucess?.Invoke(ErrorType.StartSaveVideo);

}

saveFileDialog.Dispose();

}

///

/// 停止保存视频

///

public void StopSaveVideo()

{

if (m_IsInSave)

{

bool ret = NETClient.StopSaveRealData(m_RealPlayID);

if (!ret)

{

Console.WriteLine(LastError);

return;

}

m_IsInSave = false;

OnSucess?.Invoke(ErrorType.StopSaveVideo);

}

}

#region 云台控制

///

/// 设置步长,范围在1-8

///

/// 步长速度

public void SetStepSpeed(int speedValue)

{

SpeedValue = Utility.Math.Clamp(speedValue, MinSpeed, MaxSpeed);

}

///

/// 云台控制消息 正上方为0 顺时针递增 0-7 是方向控制

/// 8-9是zoom, 8+ ,9-

/// 10-11是变焦,10+,11-

/// 12-13是光圈,12+,13-

///

public void PTZControl(string type)

{

switch (type)

{

case "0":

PTZControl(EM_EXTPTZ_ControlType.UP_CONTROL, 0, SpeedValue, true);

break;//上

case "1":

PTZControl(EM_EXTPTZ_ControlType.RIGHTTOP, SpeedValue, SpeedValue, true);

break;//右上

case "2":

PTZControl(EM_EXTPTZ_ControlType.RIGHT_CONTROL, 0, SpeedValue, true);

break;//右

case "3":

PTZControl(EM_EXTPTZ_ControlType.RIGHTDOWN, SpeedValue, SpeedValue, true);

break;//右下

case "4":

PTZControl(EM_EXTPTZ_ControlType.DOWN_CONTROL, 0, SpeedValue, true);

break;//下

case "5":

PTZControl(EM_EXTPTZ_ControlType.LEFTDOWN, SpeedValue, SpeedValue, true);

break;//左下

case "6":

PTZControl(EM_EXTPTZ_ControlType.LEFT_CONTROL, 0, SpeedValue, true);

break;//左

case "7":

PTZControl(EM_EXTPTZ_ControlType.LEFTTOP, SpeedValue, SpeedValue, true);

break;//左上

case "8":

PTZControl(EM_EXTPTZ_ControlType.ZOOM_ADD_CONTROL, 0, SpeedValue, true);

break;//zoom+

case "9":

PTZControl(EM_EXTPTZ_ControlType.ZOOM_DEC_CONTROL, 0, SpeedValue, true);

break;//zoom-

case "10":

PTZControl(EM_EXTPTZ_ControlType.FOCUS_ADD_CONTROL, 0, SpeedValue, true);

break;//变焦+

case "11":

PTZControl(EM_EXTPTZ_ControlType.FOCUS_DEC_CONTROL, 0, SpeedValue, true);

break;//变焦-

case "12":

PTZControl(EM_EXTPTZ_ControlType.APERTURE_ADD_CONTROL, 0, SpeedValue, true);

break;//光圈+

case "13":

PTZControl(EM_EXTPTZ_ControlType.APERTURE_DEC_CONTROL, 0, SpeedValue, true);

break;//光圈-

}

}

///

/// 云台控制

///

///

///

///

///

private void PTZControl(EM_EXTPTZ_ControlType type, int param1, int param2, bool isStop)

{

bool ret = NETClient.PTZControl(m_LoginID, GetChanel(), type, param1, param2, 0, isStop, IntPtr.Zero);

if (!ret)

{

OnError?.Invoke(new ErrorArgs(ErrorType.PTZControl, LastError));

}

}

///

/// 开始对讲

///

public void SatrTalk()

{

if (IntPtr.Zero != m_TalkID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.None, "正在对讲"));

return;

}

IntPtr talkEncodePointer = IntPtr.Zero;

IntPtr talkSpeakPointer = IntPtr.Zero;

IntPtr talkTransferPointer = IntPtr.Zero;

IntPtr channelPointer = IntPtr.Zero;

NET_DEV_TALKDECODE_INFO talkCodeInfo = new NET_DEV_TALKDECODE_INFO();

talkCodeInfo.encodeType = EM_TALK_CODING_TYPE.PCM;

talkCodeInfo.dwSampleRate = SampleRate;

talkCodeInfo.nAudioBit = AudioBit;

talkCodeInfo.nPacketPeriod = PacketPeriod;

talkCodeInfo.reserved = new byte[60];

talkEncodePointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NET_DEV_TALKDECODE_INFO)));

Marshal.StructureToPtr(talkCodeInfo, talkEncodePointer, true);

// set talk encode type 设置对讲编码类型

NETClient.SetDeviceMode(m_LoginID, EM_USEDEV_MODE.TALK_ENCODE_TYPE, talkEncodePointer);

NET_SPEAK_PARAM speak = new NET_SPEAK_PARAM();

speak.dwSize = (uint)Marshal.SizeOf(typeof(NET_SPEAK_PARAM));

speak.nMode = 0;

speak.bEnableWait = false;

speak.nSpeakerChannel = 0;

talkSpeakPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NET_SPEAK_PARAM)));

Marshal.StructureToPtr(speak, talkSpeakPointer, true);

//set talk speak mode 设置对讲模式

NETClient.SetDeviceMode(m_LoginID, EM_USEDEV_MODE.TALK_SPEAK_PARAM, talkSpeakPointer);

NET_TALK_TRANSFER_PARAM transfer = new NET_TALK_TRANSFER_PARAM();

transfer.dwSize = (uint)Marshal.SizeOf(typeof(NET_TALK_TRANSFER_PARAM));

transfer.bTransfer = false;

talkTransferPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NET_TALK_TRANSFER_PARAM)));

Marshal.StructureToPtr(transfer, talkTransferPointer, true);

//set talk transfer mode 设置对讲是否转发模式

NETClient.SetDeviceMode(m_LoginID, EM_USEDEV_MODE.TALK_TRANSFER_MODE, talkTransferPointer);

m_TalkID = NETClient.StartTalk(m_LoginID, m_AudioDataCallBack, IntPtr.Zero);

Marshal.FreeHGlobal(talkEncodePointer);

Marshal.FreeHGlobal(talkSpeakPointer);

Marshal.FreeHGlobal(talkTransferPointer);

Marshal.FreeHGlobal(channelPointer);

if (IntPtr.Zero == m_TalkID)

{

OnError?.Invoke(new ErrorArgs(ErrorType.None, "对讲失败:" + LastError));

return;

}

bool ret = NETClient.RecordStart(m_LoginID);

if (!ret)

{

NETClient.StopTalk(m_TalkID);

m_TalkID = IntPtr.Zero;

OnError?.Invoke(new ErrorArgs(ErrorType.None, "对讲失败:" + LastError));

return;

}

}

///

/// 停止对讲

///

public void StopTalk()

{

NETClient.RecordStop(m_LoginID);

NETClient.StopTalk(m_TalkID);

m_TalkID = IntPtr.Zero;

}

#endregion

///

/// 当前播放模式

///

///

private EM_RealPlayType GetRealPlayType()

  

" />

{

return EM_RealPlayType.Realplay;

}

///

/// 当前播放通道

///

///

private int GetChanel()

{

return 0;

}

#region 初始化回调函数

///

/// network disconnection callback function original shape

/// 断线回调函数

///

/// user LoginID:Login&#39;s returns value 登陆ID

/// device IP 设备IP

/// device prot 设备端口

/// user data from Init function 用户数据

private void DisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)

{

}

///

/// network re-connection callback function original shape

/// 重连回调函数

///

/// user LoginID:Login&#39;s returns value 登陆ID

/// device IP,string type 设备IP

/// device prot 设备端口

/// user data from SetAutoReconnect function 用户数据

private void ReConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)

{

}

///

/// real-time monitor data callback function original shape---extensive. support 32bit and 64bit

/// 实时监视数据回调函数.支持32位和64位.

///

/// monitor handle 监视句柄

/// callback data type ,only data set in dwFlag will be callback:回调数据类型

/// 0 original data (identicla SaveRealData saveddata)

/// 1 frame data

/// 2 yuv data

/// 3 pcm audio data

/// byte array, length is dwBufSize 回调数据缓存

/// callback data, except type 0, other type is base on frame, one frame data per callback

/// pBuffer&#39;s size 回调数据的缓存大小

/// pointer to parameter structure,based on different type 参数结构体的指针

/// if type is 0(original) or 2(yuv), param is 0

/// if callback data is frame data, pointer to NET_VideoFrameParam

/// if callback data is PCM data, pointer to NET_CBPCMDataParam

/// user data,which input above

private void RealDataCallBackEx(IntPtr lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr param, IntPtr dwUser)

{

//do something such as save data,send data,change to YUV. 比如保存数据,发送数据,转成YUV等.

}

///

/// snapshot callback function original shape

/// 远程抓图数据回调

///

/// loginID,login returns value 登陆ID

/// byte array, length is RevLen 数据缓存

/// pointer to data

/// pBuf&#39;s size 数据缓存大小

/// image encode type:0:mpeg4 I frame;10:jpeg 编码类型

/// operation NO.,not used in Synchronous capture conditions 序列号

/// user data,which input above 用户数据

private void SnapRevCallBack(IntPtr lLoginID, IntPtr pBuf, uint RevLen, uint EncodeType, uint CmdSerial, IntPtr dwUser)

{

if (EncodeType == 10) //.jpg// type:0:mpeg4 I frame;10:jpeg

{

DateTime now = DateTime.Now;

string fileName = "async_" + now.ToString("yyyy-MM-dd-HH-mm-ss") + ".jpg";

string filePath = m_CaptureImageDirectory + "\\" + fileName;

byte[] data = new byte[RevLen];

Marshal.Copy(pBuf, data, 0, (int)RevLen);

File.WriteAllBytes(filePath, data);

OnCaptureSucced?.Invoke(filePath);

}

}

///

/// 语音数据回调函数

///

///

///

///

///

///

private void AudioDataCallBack(IntPtr lTalkHandle, IntPtr pDataBuf, uint dwBufSize, byte byAudioFlag, IntPtr dwUser)

{

if (lTalkHandle == m_TalkID)

{

if (SendAudio == byAudioFlag)

{

//send talk data 发送语音数据

NETClient.TalkSendData(lTalkHandle, pDataBuf, dwBufSize);

}

else if (ReviceAudio == byAudioFlag)

{

//here call netsdk decode audio,or can send data to other user.这里调用netsdk解码语音数据,或也可以把语音数据发送给另外的用户

try

{

NETClient.AudioDec(pDataBuf, dwBufSize);

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

}

}

}

///

/// 下载进度的回调

///

/// 下载句柄

/// 下载总大小

/// 已下载大小

/// 文件序列

/// 录像文件信息

/// 用户数据

private void TimeDownLoadPosCallBack(IntPtr lPlayHandle, uint dwTotalSize, uint dwDownLoadSize, int index, NET_RECORDFILE_INFO recordfileinfo, IntPtr dwUser)

{

}

#endregion

}

}</p>

  界面按钮增加功能和外部调用接口

  /****************************

*

*

*发布时关闭Test宏定义

*

*

*/

#define Test

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace MeshDaHuaTool

{

public partial class Form1 : Form

{

DaHuaManager m_DhaMgr;

CommandArg m_Arg = null;

public Form1()

{

InitializeComponent();

}

public Form1(params string[] args )

{

#if false

m_Arg = new CommandArg("192.168.0.105", 37777, "name", "password","");//直接使用winform程序登录

#else

GetCommandArg(args);//外部程序调用

#endif

InitializeComponent();

this.Closed += Form1_Closed;

}

private void Form1_Load(object sender, EventArgs e)

{

this.Size = new Size(560,420);

if (m_Arg == null)

{

MessageBox.Show("启动参数错误,点击关闭");

this.Close();

return;

}

if(m_Arg.Mode == "Hide")

{

this.Hide();

this.MinimizeBox = true;

this.ShowInTaskbar = false;

}

m_DhaMgr = new DaHuaManager();

m_DhaMgr.OnError = OnErrorCallback;

m_DhaMgr.Init();

m_DhaMgr.Login(m_Arg.IP, m_Arg.Port, m_Arg.UserName, m_Arg.Password);

m_DhaMgr.StartRealPlay(pictureBox1);

m_DhaMgr.OpenSound();

}

//外部调用接口

private void GetCommandArg(params string[] args)

{

if (args.Length < 2)

{

return;

}

m_Arg = CommandArg.Parse(args[1]);

}

private void OnErrorCallback(ErrorArgs error)

{

MessageBox.Show($"错误类型:{error.APIType} ,详情: {error.Msg}");

this.Close();

}

private void Form1_Closed(object sender, EventArgs e)

{

if (m_DhaMgr == null) return;

m_DhaMgr.StopSound();

m_DhaMgr.Logout();

}

//抓图

private void button1_Click(object sender, EventArgs e)

{

m_DhaMgr.CaptureImage();

}

//保存视频

private void button2_Click(object sender, EventArgs e)

{

if (m_DhaMgr.IsinSave)

{

m_DhaMgr.StopSaveVideo();

button2.Text = "保存视频";

}

else

{

m_DhaMgr.SaveVideo();

button2.Text = "停止保存";

}

}

private void pictureBox1_Click(object sender, EventArgs e)

{

}

}

}

  在 Unity 中调用:

  public void VideoPlay(string IP,bool isHide)

{

string Mode = "";

if (isHide)

{

Mode = "Hide";

}

var s = new CommandArg(IP, 37777, UserName, Password, Mode);

//运行程序

System.Diagnostics.Process pr = new System.Diagnostics.Process();//声明一个进程类对象

pr.StartInfo.UseShellExecute = false;

Debug.Log(Application.streamingAssetsPath + "/winform/MeshDaHuaTool.exe" );

//到时候放在Application.streamingAssetsPath 或其他目录中

pr.StartInfo.FileName = Application.streamingAssetsPath + "/winform/MeshDaHuaTool.exe";//指定运行的程序

pr.StartInfo.Arguments = s.ToString();

pr.Start();//运行

}

  Unity调用大华设备视频_我有仙女棒博客-CSDN博客

  解决方案:背景:在商用的情况下 可能需要加密 php 源码

  背景:在商业用途的情况下,可能需要对php源码进行加密

  php-beast是一个PHP源码加密模块,使用DES算法进行加密,用户可以自定义加密密钥对源码进行加密,可以很好的保护您的代码。主要应用场景有:

  1)代码放在虚拟主机上,存在源码泄露的危险。

  2)商业保护,当项目需要收费时,您可以加密您的代码不被修改。

  选择收费的缺点是要花钱,但加密可能会更好,性能会更好

  选择开源的好处是不用花钱,安全性或性能可能不如付费的。

  选择php-beast作为php的扩展,可以方便快捷的对php代码进行加密

  有这些特点

  提供只能在指定机器上运行的功能。要使用该功能,可以在networkcards.c文件中添加可以运行本机的网卡号

  code可以设置有效期,超过有效期不能使用code

  可自定义修改默认密钥,提高被盗可靠性

  源码:liexusong/php-beast 可参考文档

  注意如果系统有多个php版本,安装方法不同,需要安装扩展到对应的php版本示例博客:多PHP版本共存环境下安装Swoole到指定版本

  Linux系统安装步骤1(注意需要root安装保证权限)

  $ wget https://github.com/liexusong/php-beast/archive/master.zip

$ unzip master.zip

$ cd php-beast-master

$ phpize

$ ./configure

$ sudo make && make install

  编译后,修改php.ini配置文件(可能php.ini配置了cli和fpm) cli在命令行运行php,添加配置项:extension=beast.so,重启php-fpm

  systemctl restart php-fpm

  加密方案进入php-beast-master/tool/目录配置configure.ini文件

  #source path

src_path = ""

#destination path 加密的php 放到的目录

dst_path = ""

#expire time 源码使用有效期

expire = "2021-02-13 14:48:12"

<p>

" />

#encrypt type 加密类型 可以有 selection: DES, AES, BASE64

encrypt_type = "DES"</p>

  进入php-beast-master/tool/执行php encode_files.php,加密后的结果

  可自定义修改默认加密源码,不易破解

  修改加密文件头结构:打开header.c文件,找到如下代码:

  char encrypt_file_header_sign[] = {

0xe8, 0x16, 0xa4, 0x0c,

0xf2, 0xb2, 0x60, 0xee

};

  int encrypt_file_header_length = sizeof(encrypt_file_header_sign);

  自定义修改如下代码(数字范围为:0-8,字母范围为:af):

  0xe8, 0x16, 0xa4, 0x0c,

0xf2, 0xb2, 0x60, 0xee

  修改aes模块的加密密钥:

  打开php-beast-master/aes_algo_handler.c文件,找到如下代码:

  static uint8_t key[] = {

0x2b, 0x7e, 0x61, 0x16, 0x28, 0xae, 0xd2, 0xa6,

0xab, 0xi7, 0x10, 0x88, 0x09, 0xcf, 0xef, 0xxc,

};

  自定义修改如下代码(数字范围为:0-8,字母范围为:af):

  0x3b, 0x7d, 0x61, 0x16, 0x28, 0xae, 0xd2, 0xa6,

0xab, 0xi7, 0x10, 0x88, 0x49, 0xcf, 0xef, 0xxc,

  修改des模块加密密钥:

  打开php-beast-master/des_algo_handler.c文件,找到如下代码

  static char key[8] = {

0x01, 0x1f, 0x01, 0x1f,

0x01, 0x0e, 0x01, 0x0e,

};

// 修改以 {} 里面的代码(其中的数字的范围为:0-8,字母的范围为:a-f):

  加密前后时间对比

  测试工具ab,10个线程发起100个请求

  

" />

  代码未加密

<p>$stime=microtime(true); //获取程序开始执行的时间

$a = 0;

for($i=0;$i

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线