海康威视4g卡直连获取视频流
0.背景简介
- 由于之前实现了NVR视频流对接,目前因为项目需要,设备与服务器不在同一个网段,无法通过局域网传输视频,为了节约成本,不想使用萤石云等平台。于是进行直连开发。
- 有四种对接方法:
-
专网网络,4G网卡有固定IP地址,可以直接使用我们设备网络SDK开发包,下载地址:
https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10&id=5cda5902f47ae80dd41a54b7
直接对接设备,和局域网有线网络连接的方式一样。
-
4G网卡没有固定IP地址,使用我们现有平台软件比如ISC或者云曜等平台,设备注册到平台上,然后您的软件和平台软件对接,从平台获取需要的数据。
-
4G网卡没有固定IP地址,不使用我司平台软件,自己开发平台程序,可以通过ISUP SDK,下载地址:
https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10&id=18e1e779efed4593bfceba6703d7f6a8
ISUP SDK是服务器和设备之间交互的接口,不包含服务器和服务器之间、客户端和服务器之间的交互功能,比如网页客户端、手机客户端,需要服务器自行转发的。
-
使用设备集成网关,下载地址:
https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10&id=f893fd659ea143e7bb75bf05de2730ce
有固定IP地址的服务器安装运行网关,设备使用ISUP协议接入网关,您的程序通过HTTP/HTTPS、RTSP协议和网关对接。
1. 我这里4g直连使用的是ISUPSDK,直接在官网获取资源即可
- 网址海康ISUPSDK资源包
我这里都下载下来进行开发,我需要先在win11上开发,然后部署到linux服务器,区别不大,主要是依赖包的替换
打开压缩包可以看到以下文件
- doc目录是开发文档,我提炼了一些重要的摘要
- 首先,我们要熟悉流程,与传统的服务器去获取视频流不同,直连协议采用的是设备主动注册到服务器,可以看到以下流程图。
注册的地址是在摄像头的后端地址进行配置,需要ip或则域名,在海康后台联系客服将4g卡定向到ip或者域名,然后在设备的管理后台配置ISUP地址。如图所示:
现在可以选择5.0
根据demo进行测试
在demo文件夹下可以看到有一个javademo文件夹
打开项目后可以在主函数中看到以下代码
进入startPlayBackListen方法可以看到
public void startPlayBackListen()
{
//回放监听
if (fPLAYBACK_NEWLINK_CB == null) {
fPLAYBACK_NEWLINK_CB = new PLAYBACK_NEWLINK_CB();
}
System.arraycopy(propertiesUtil.readValue("SmsBackServerListenIP").getBytes(), 0, struPlayBackListen.struIPAdress.szIP, 0, propertiesUtil.readValue("SmsBackServerListenIP").length());
struPlayBackListen.struIPAdress.wPort = Short.parseShort(propertiesUtil.readValue("SmsBackServerListenPort")); //流媒体服务器监听端口
struPlayBackListen.fnNewLinkCB = fPLAYBACK_NEWLINK_CB;
struPlayBackListen.byLinkMode = 0; //0- TCP方式,1- UDP方式
if (m_lPlayBackLinkHandle < 0) {
m_lPlayBackListenHandle = hCEhomeStream.NET_ESTREAM_StartListenPlayBack(struPlayBackListen);
if (m_lPlayBackListenHandle < -1) {
System.out.println("NET_ESTREAM_StartListenPlayBack failed, error code:" + hCEhomeStream.NET_ESTREAM_GetLastError());
hCEhomeStream.NET_ESTREAM_Fini();
return;
} else {
String BackStreamListenInfo = new String(struPlayBackListen.struIPAdress.szIP).trim() + "_" + struPlayBackListen.struIPAdress.wPort;
System.out.println("回放流媒体服务:" + BackStreamListenInfo + ",NET_ESTREAM_StartListenPlayBack succeed");
}
}
}
这个代码是添加监听,真正的获取流则在RealPlay()
public class FPREVIEW_DATA_CB implements HCISUPStream.PREVIEW_DATA_CB {
//实时流回调函数/
public void invoke(int iPreviewHandle, HCISUPStream.NET_EHOME_PREVIEW_CB_MSG pPreviewCBMsg, Pointer pUserData) {
if (Count == 100) {//降低打印频率
System.out.println("FPREVIEW_DATA_CB callback, data length:" + pPreviewCBMsg.dwDataLen);
Count = 0;
}
Count++;
//播放库SDK解码显示在win窗口上,
switch (pPreviewCBMsg.byDataType) {
case HCNetSDK.NET_DVR_SYSHEAD: //系统头
boolean b_port = playCtrl.PlayM4_GetPort(m_lPort);
if (b_port == false) //获取播放库未使用的通道号
{
break;
}
if (pPreviewCBMsg.dwDataLen > 0) {
if (!playCtrl.PlayM4_SetStreamOpenMode(m_lPort.getValue(), PlayCtrl.STREAME_REALTIME)) //设置实时流播放模式
{
break;
}
if (!playCtrl.PlayM4_OpenStream(m_lPort.getValue(), pPreviewCBMsg.pRecvdata, pPreviewCBMsg.dwDataLen, 1024 * 1024)) //打开流接口
{
break;
}
W32API.HWND hwnd = new W32API.HWND(Native.getComponentPointer(IsupTest.panelRealplay));
if (!playCtrl.PlayM4_Play(m_lPort.getValue(), hwnd)) //播放开始
{
break;
}
}
case HCNetSDK.NET_DVR_STREAMDATA: //码流数据
if ((pPreviewCBMsg.dwDataLen > 0) && (m_lPort.getValue() != -1)) {
if (!playCtrl.PlayM4_InputData(m_lPort.getValue(), pPreviewCBMsg.pRecvdata, pPreviewCBMsg.dwDataLen)) //输入流数据
{
break;
}
}
}
//如果仅需取码流数据,可以使用以下注释部分代码,获取码流数据保存成文件
try {
m_file = new FileOutputStream(file, true);
long offset = 0;
ByteBuffer buffers = pPreviewCBMsg.pRecvdata.getByteBuffer(offset, pPreviewCBMsg.dwDataLen);
byte [] bytes = new byte[pPreviewCBMsg.dwDataLen];
buffers.rewind();
buffers.get(bytes);
m_file.write(bytes);
m_file.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
到了这一步就可以获取流进行处理了,后面就不做赘述了。欢迎各位大佬留言!!!!