C# 实现海康摄像头在任意浏览器中预览

两周以来一直研究海康视频在谷歌、火狐等浏览器中的显示问题。在今天终于有了一点小心得。发表出来,希望有问题或者其他建议的老师积极给我建议。

在海康浏览器的平台中,因为他本身只支持在IE或者IE内核中显示,这种问题不能根本性的解决在多浏览器里面的问题,我在网上查找了IE-Tab在谷歌浏览器中显示,但是由于需要用户手动切换浏览模式,所以说用起来不是特别方便。后面研究了一下,可以通过海康PlantFormSdk+TCP协议+Websocket的方式进行推流,在浏览器中通过img显示base64的方式显示视频,通过以上方式基本上可以实现视频同步预览,具体思路如下。

1.服务器端通过使用winform监听方式监听浏览器端连接预览的摄像头,如果为同一个摄像头时,则通过字典的方式对改连接和IP及Socket进行保存,当不同的连接同一个摄像头的时候,通过字典保存多个TCP连接。

2.推流:推流方式采用TCP协议的方式,当前我才用的是每隔500ms,对显示的picturebox进行截屏,在截屏之后,通过代码将截屏的bitmap转换成base64字符串流,通过TCP协议推送当前摄像头连接的网络地址。

3.接受:在web端通过websocket进行接受传输的base64字符串,因为当前比较长,所以我才用的手动分包的方式进行传输。

C winform 调用海康摄像头显示在任意浏览器中

 

图中分别表示三个单例类,一个是网络连接、一个是当前连接及当前运行的线程。

public static void SendMessage(string obj, string data)

{

var max = data.Length % 100 == 0 ? data.Length / 100 : data.Length / 100 + 1;

try

{

int i;

for (i = 0; i < max; i++)

{

string send;

if (i == 0)

{

send = $"0,{data.Length}," + data.Substring(0, 100);

}

else if (i == max - 1 && data.Length % 100 != 0)

{

send = $"{i},0," + data.Substring(i * 100, data.Length % 100);

}

else

{

send = $"{i},0," + data.Substring(i * 100, 100);

}

byte[] msgBuffer = PackageServerData(send);

foreach (Session se in SingleConnect.GetInstance()[obj].Select(t => t.Session))

{

if (se.SockeClient.Connected)

{

try

{

se.SockeClient.Send(msgBuffer, msgBuffer.Length, SocketFlags.None);

}

catch (Exception ex)

{

LogHelper.WriteError("发送数据异常", ex);

}

}

}

}

}

catch (Exception ex)

{

LogHelper.WriteError("相应数据异常", ex);

}

}

这段代码为相应的发送代码。

C winform 调用海康摄像头显示在任意浏览器中

 

调用发送代码的截图方法。

C winform 调用海康摄像头显示在任意浏览器中

 

以上为实时监控图,第一张图为监听的连接,第二张图是在谷歌浏览器中显示的图,第三张图是在winform中显示的图。

文章水平不是很高,希望对大家有所帮助。如果有问题可以直接私聊我

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
实现海康摄像头的实时预览功能,你需要使用海康提供的 SDK 和 API,以下是一个基本的示例代码: ```java import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import com.sun.jna.ptr.ByteByReference; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.NativeLongByReference; import com.sun.jna.ptr.PointerByReference; import com.sun.jna.win32.StdCallLibrary; public class HKCameraPreview { public interface HCNetSDK extends StdCallLibrary { HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary("C:\\Program Files (x86)\\hikvision\\HCNetSDK\\HCNetSDK.dll", HCNetSDK.class); // 登录函数 NativeLong NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword, NET_DVR_DEVICEINFO_V30 lpDeviceInfo); // 预览函数 NativeLong NET_DVR_RealPlay_V40(NativeLong lUserID, NET_DVR_PREVIEWINFO lpPreviewInfo, RealDataCallBack_V30 fRealDataCallBack_V30, Pointer pUser); // 停止预览函数 boolean NET_DVR_StopRealPlay(NativeLong lRealHandle); // 释放 SDK 资源 boolean NET_DVR_Cleanup(); } // 设备信息结构体 public static class NET_DVR_DEVICEINFO_V30 extends Structure { public byte[] sSerialNumber = new byte[48]; public byte byAlarmInPortNum; public byte byAlarmOutPortNum; public byte byDiskNum; public byte byDVRType; public byte byChanNum; public byte byStartChan; public byte byAudioChanNum; public byte byIPChanNum; public byte[] byRes1 = new byte[24]; } // 预览参数结构体 public static class NET_DVR_PREVIEWINFO extends Structure { public NativeLong lChannel; // 预览通道号 public int dwStreamType; // 码流类型:0-主码流,1-子码流,2-码流 3,3-码流 4,4-码流 5,5-码流 6,6-码流 7,7-码流 8,8-码流 9,9-码流 10,10-码流 11,11-码流 12,12-码流 13,13-码流 14,14-码流 15,15-码流 16 public int dwLinkMode; // 连接模式:0- TCP 方式,1- UDP 方式,2- 多播方式,3- RTP 方式,4-RTP/RTSP,5- RTP/HTTP public Pointer hPlayWnd; // 播放窗口的句柄,为 NULL 表示不解码显示 public int bBlocked; // 0- 非阻塞取流,1- 阻塞取流 public int bPassbackRecord; // 0-不启用录像回传,1-启用录像回传 public byte byPreviewMode; // 预览模式:0- 正常预览,1-延迟预览 public byte[] byStreamID = new byte[32]; // 流ID,lChannel为0xffffffff时启用此参数 public byte[] byProtoType = new byte[20]; public int dwDisplayBufNum; // 播放库播放缓冲区最大缓冲帧数 public byte byNPQMode; // NPQ 模式:0- 兼容模式,1- 极简模式(不支持 OSD 和 VCA),2- 增强模式 public byte[] byRes = new byte[215]; } // 实时数据回调函数 public static class RealDataCallBack_V30 implements StdCallCallback { public void invoke(NativeLong lPlayHandle, int dwDataType, ByteByReference pBuffer, int dwBufSize, Pointer pUser) { // 实时数据处理 } } public static void main(String[] args) { HCNetSDK hcNetSDK = HCNetSDK.INSTANCE; NET_DVR_DEVICEINFO_V30 deviceInfo = new NET_DVR_DEVICEINFO_V30(); // 登录设备 NativeLong lUserID = hcNetSDK.NET_DVR_Login_V30("192.168.1.100", (short) 8000, "admin", "password", deviceInfo); if (lUserID.longValue() == -1) { System.out.println("登录失败:" + hcNetSDK.NET_DVR_GetLastError()); return; } // 预览参数 NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO(); previewInfo.lChannel = new NativeLong(1); // 预览通道号 previewInfo.dwStreamType = 0; // 主码流 previewInfo.dwLinkMode = 0; // TCP 方式 previewInfo.hPlayWnd = null; // 不解码显示 previewInfo.bBlocked = 1; // 阻塞取流 previewInfo.bPassbackRecord = 0; // 不启用录像回传 previewInfo.byPreviewMode = 0; // 正常预览 previewInfo.byNPQMode = 0; // 兼容模式 // 启动实时预览 RealDataCallBack_V30 realDataCallBack_V30 = new RealDataCallBack_V30(); NativeLongByReference lRealHandle = new NativeLongByReference(); lRealHandle.setValue(hcNetSDK.NET_DVR_RealPlay_V40(lUserID, previewInfo, realDataCallBack_V30, null)); if (lRealHandle.longValue() == -1) { System.out.println("实时预览失败:" + hcNetSDK.NET_DVR_GetLastError()); hcNetSDK.NET_DVR_Logout(lUserID); hcNetSDK.NET_DVR_Cleanup(); return; } // 等待预览结束 System.out.println("正在预览,按任意键停止..."); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } // 停止实时预览 if (!hcNetSDK.NET_DVR_StopRealPlay(lRealHandle.getValue())) { System.out.println("停止实时预览失败:" + hcNetSDK.NET_DVR_GetLastError()); } // 注销登录并释放 SDK 资源 if (!hcNetSDK.NET_DVR_Logout(lUserID)) { System.out.println("注销登录失败:" + hcNetSDK.NET_DVR_GetLastError()); } if (!hcNetSDK.NET_DVR_Cleanup()) { System.out.println("释放 SDK 资源失败:" + hcNetSDK.NET_DVR_GetLastError()); } } } ``` 上面的代码,我们通过 `NET_DVR_Login_V30()` 函数来登录设备,获取到设备的用户 ID,然后通过 `NET_DVR_RealPlay_V40()` 函数启动实时预览,并使用回调函数 `RealDataCallBack_V30` 处理实时数据。最后,我们使用 `NET_DVR_StopRealPlay()` 函数停止实时预览,并使用 `NET_DVR_Logout()` 函数注销登录,最终使用 `NET_DVR_Cleanup()` 函数释放 SDK 资源。 需要注意的是,以上代码仅供参考,实际使用需要根据海康提供的 SDK 和 API 进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值