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.
275 lines
9.1 KiB
275 lines
9.1 KiB
1 year ago
|
using System.Runtime.InteropServices;
|
||
|
using System.Text;
|
||
|
|
||
|
namespace EC.Util.CameraSDK;
|
||
|
|
||
|
public class HiKSdk : ICameraSdk
|
||
|
{
|
||
|
#region Fields
|
||
|
|
||
|
private int LoginId { get; set; } = -1;
|
||
|
|
||
|
private int Channel { get; } = 1;
|
||
|
|
||
|
#endregion Fields
|
||
|
|
||
|
public HiKSdk(CameraInfo cameraInfo) : base(cameraInfo)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#region Base Method
|
||
|
|
||
|
public override bool Init()
|
||
|
{
|
||
|
bool ret = ConnectSuccess();
|
||
|
if (ret) return true;
|
||
|
HiKOriSdk.NET_DVR_USER_LOGIN_INFO loginInfo = new()
|
||
|
{
|
||
|
bUseAsynLogin = false,
|
||
|
sDeviceAddress = new byte[129],
|
||
|
wPort = (ushort)CameraInfo.Port,
|
||
|
sUserName = new byte[64],
|
||
|
sPassword = new byte[64]
|
||
|
};
|
||
|
Encoding.Default.GetBytes(CameraInfo.Ip).CopyTo(loginInfo.sDeviceAddress, 0);
|
||
|
Encoding.Default.GetBytes(CameraInfo.UserName).CopyTo(loginInfo.sUserName, 0);
|
||
|
Encoding.Default.GetBytes(CameraInfo.Password).CopyTo(loginInfo.sPassword, 0);
|
||
|
HiKOriSdk.NET_DVR_DEVICEINFO_V40 deviceInfo = new();
|
||
|
LoginId = HiKOriSdk.NET_DVR_Login_V40(ref loginInfo, ref deviceInfo);
|
||
|
ret = ConnectSuccess();
|
||
|
if (ret) HiKOriSdk.NET_DVR_SetReconnect(10000, 1);
|
||
|
else BuildException();
|
||
|
//HiKOriSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new();
|
||
|
//LoginId = HiKOriSDK.NET_DVR_Login_V30(CameraInfo.Ip, CameraInfo.Port, CameraInfo.UserName, CameraInfo.Password, ref deviceInfo);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
public override bool Destory()
|
||
|
{
|
||
|
bool ret = ConnectSuccess();
|
||
|
if (!ret) return true;
|
||
|
ret = HiKOriSdk.NET_DVR_Logout(LoginId);
|
||
|
if (ret) LoginId = -1;
|
||
|
else BuildException();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
public override bool ConnectSuccess()
|
||
|
{
|
||
|
return LoginId >= 0;
|
||
|
}
|
||
|
|
||
|
internal override void BuildException()
|
||
|
{
|
||
|
uint errCode = HiKOriSdk.NET_DVR_GetLastError();
|
||
|
if (errCode == 0) return;
|
||
|
throw CameraException.New(CameraInfo, (int)errCode);
|
||
|
}
|
||
|
|
||
|
private void BuildPlayCtrlException(int nPort)
|
||
|
{
|
||
|
string err = $"PlayCtrlSdk failed, error code={PlayCtrlSdk.PlayM4_GetLastError(nPort)}";
|
||
|
throw CameraException.New(CameraInfo, -1, err);
|
||
|
}
|
||
|
|
||
|
#endregion Base Method
|
||
|
|
||
|
#region Ptz Method
|
||
|
|
||
|
private static class GPIParams
|
||
|
{
|
||
|
public static int Size { get; private set; }
|
||
|
public static Type Type { get; private set; }
|
||
|
|
||
|
static GPIParams()
|
||
|
{
|
||
|
HiKOriSdk.NET_DVR_PTZPOS ptzPos = new();
|
||
|
Size = Marshal.SizeOf(ptzPos);
|
||
|
Type = ptzPos.GetType();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override PtzInfo GetPtzInfo()
|
||
|
{
|
||
|
bool ret = ConnectSuccess();
|
||
|
if (!ret) return PtzInfo.Default;
|
||
|
|
||
|
HiKOriSdk.NET_DVR_PTZPOS entity = new();
|
||
|
int dwSize = GPIParams.Size;
|
||
|
uint dwReturned = 0;
|
||
|
IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize);
|
||
|
Marshal.StructureToPtr(entity, ptrBuf, true);
|
||
|
try
|
||
|
{
|
||
|
ret = HiKOriSdk.NET_DVR_GetDVRConfig(LoginId, HiKOriSdk.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned);
|
||
|
if (!ret) { BuildException(); return PtzInfo.Default; }
|
||
|
object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type);
|
||
|
if (objBuf == null) return PtzInfo.Default;
|
||
|
entity = (HiKOriSdk.NET_DVR_PTZPOS)objBuf;
|
||
|
return PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Marshal.FreeHGlobal(ptrBuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool TryGetPtzInfo(out PtzInfo ptzInfo)
|
||
|
{
|
||
|
bool ret = ConnectSuccess();
|
||
|
if (!ret) { ptzInfo = PtzInfo.Default; return false; }
|
||
|
|
||
|
HiKOriSdk.NET_DVR_PTZPOS entity = new();
|
||
|
int dwSize = GPIParams.Size;
|
||
|
uint dwReturned = 0;
|
||
|
IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize);
|
||
|
Marshal.StructureToPtr(entity, ptrBuf, true);
|
||
|
try
|
||
|
{
|
||
|
ret = HiKOriSdk.NET_DVR_GetDVRConfig(LoginId, HiKOriSdk.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned);
|
||
|
if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; }
|
||
|
object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type);
|
||
|
if (objBuf == null) { ptzInfo = PtzInfo.Default; return false; }
|
||
|
entity = (HiKOriSdk.NET_DVR_PTZPOS)objBuf;
|
||
|
ptzInfo = PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos);
|
||
|
return true;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Marshal.FreeHGlobal(ptrBuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool PtzMove(int cmd, int stop, int speed)
|
||
|
{
|
||
|
if (!ConnectSuccess()) return false;
|
||
|
bool ret = HiKOriSdk.NET_DVR_PTZControlWithSpeed_Other(LoginId, Channel, (uint)cmd, (uint)stop, (uint)speed);
|
||
|
if (!ret) BuildException();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
public override bool PtzPreset(int cmd, int presetId)
|
||
|
{
|
||
|
if (!ConnectSuccess()) return false;
|
||
|
bool ret = HiKOriSdk.NET_DVR_PTZPreset_Other(LoginId, Channel, (uint)cmd, (uint)presetId);
|
||
|
if (!ret) BuildException();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#endregion Ptz Method
|
||
|
|
||
|
#region Video Method
|
||
|
|
||
|
private int RealplayHandle { get; set; } = -1;
|
||
|
|
||
|
private int RealpalyPort { get; set; } = -1;
|
||
|
|
||
|
private IntPtr Hwnd { get; set; }
|
||
|
|
||
|
public override void StartPlay(IntPtr hwnd)
|
||
|
{
|
||
|
if (!ConnectSuccess() || IsPlaying()) return;
|
||
|
Hwnd = hwnd;
|
||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StartPlayWindows();
|
||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StartPlayLinux();
|
||
|
else Hwnd = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
private void StartPlayWindows()
|
||
|
{
|
||
|
HiKOriSdk.NET_DVR_PREVIEWINFO previewInfo = new()
|
||
|
{
|
||
|
hPlayWnd = Hwnd, //预览窗口
|
||
|
lChannel = 1, //预览的设备通道
|
||
|
dwStreamType = 0, //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
|
||
|
dwLinkMode = 0, //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
|
||
|
bBlocked = true, //0- 非阻塞取流,1- 阻塞取流
|
||
|
};
|
||
|
IntPtr pUser = new(); //用户数据
|
||
|
RealplayHandle = HiKOriSdk.NET_DVR_RealPlay_V40(LoginId, ref previewInfo, null, pUser);
|
||
|
if (RealplayHandle < 0) BuildException();
|
||
|
}
|
||
|
|
||
|
private void StartPlayLinux()
|
||
|
{
|
||
|
if (RealpalyPort < 0)
|
||
|
{
|
||
|
int nPort = -1;
|
||
|
bool ret = PlayCtrlSdk.PlayM4_GetPort(ref nPort);
|
||
|
if (!ret) BuildPlayCtrlException(nPort);
|
||
|
RealpalyPort = nPort;
|
||
|
}
|
||
|
HiKOriSdk.NET_DVR_PREVIEWINFO previewInfo = new()
|
||
|
{
|
||
|
hPlayWnd = IntPtr.Zero, //预览窗口
|
||
|
lChannel = 1, //预览的设备通道
|
||
|
dwStreamType = 0, //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
|
||
|
dwLinkMode = 0, //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
|
||
|
bBlocked = true, //0- 非阻塞取流,1- 阻塞取流
|
||
|
};
|
||
|
RealplayHandle = HiKOriSdk.NET_DVR_RealPlay_V40(LoginId, ref previewInfo, RealDataCallBack, IntPtr.Zero);
|
||
|
if (RealplayHandle < 0) BuildException();
|
||
|
}
|
||
|
|
||
|
private void RealDataCallBack(int lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser)
|
||
|
{
|
||
|
if (dwBufSize <= 0) return;
|
||
|
switch (dwDataType)
|
||
|
{
|
||
|
case HiKOriSdk.NET_DVR_SYSHEAD:
|
||
|
try
|
||
|
{
|
||
|
PlayCtrlSdk.PlayM4_SetStreamOpenMode(RealpalyPort, 0);
|
||
|
PlayCtrlSdk.PlayM4_OpenStream(RealpalyPort, pBuffer, dwBufSize, 2 * 1024 * 1024);
|
||
|
if (!PlayCtrlSdk.PlayM4_Play(RealpalyPort, Hwnd)) BuildPlayCtrlException(RealpalyPort);
|
||
|
}
|
||
|
catch (Exception)
|
||
|
{
|
||
|
StopPlay();
|
||
|
throw;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HiKOriSdk.NET_DVR_STREAMDATA:
|
||
|
PlayCtrlSdk.PlayM4_InputData(RealpalyPort, pBuffer, dwBufSize);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void StopPlay()
|
||
|
{
|
||
|
if (!IsPlaying()) return;
|
||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StopPlayWindows();
|
||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StopPlayLinux();
|
||
|
Hwnd = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
public void StopPlayWindows()
|
||
|
{
|
||
|
bool ret = HiKOriSdk.NET_DVR_StopRealPlay(RealplayHandle);
|
||
|
RealplayHandle = -1;
|
||
|
if (!ret) BuildException();
|
||
|
}
|
||
|
|
||
|
public void StopPlayLinux()
|
||
|
{
|
||
|
bool ret = HiKOriSdk.NET_DVR_StopRealPlay(RealplayHandle);
|
||
|
RealplayHandle = -1;
|
||
|
if (RealpalyPort >= 0)
|
||
|
{
|
||
|
//if(!PlayCtrlSdk.PlayM4_Stop(RealpalyPort)) BuildPlayCtrlException(RealpalyPort);
|
||
|
PlayCtrlSdk.PlayM4_Stop(RealpalyPort);
|
||
|
PlayCtrlSdk.PlayM4_CloseStream(RealpalyPort);
|
||
|
PlayCtrlSdk.PlayM4_FreePort(RealpalyPort);
|
||
|
RealpalyPort = -1;
|
||
|
}
|
||
|
if (!ret) BuildException();
|
||
|
}
|
||
|
|
||
|
public override bool IsPlaying()
|
||
|
{
|
||
|
return RealplayHandle >= 0;
|
||
|
}
|
||
|
|
||
|
#endregion Video Method
|
||
|
}
|