海康SDK取流提取H264裸流并存入队列的Java实现
使用Java语言从海康SDK取流并提取H264裸流存入队列
本文将介绍如何使用Java语言调用海康SDK,从海康摄像机获取视频流,并从中提取H264裸流,存入到队列中进行后续处理。
实现步骤
-
导入海康SDK相关的jar包,例如
hkjvmsdk.jar、hkplayctrl.jar等。 -
初始化SDK,包括设备登录、获取通道号等。
-
创建播放器对象,并设置播放器的回调函数,用于接收海康SDK传来的视频数据。
-
在回调函数中,判断数据类型是否为H264格式,如果是,则将数据存入队列中。
-
在主程序中,循环从队列中取出数据进行处理,例如保存到文件中。
代码示例
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class HKSdkDemo {
// 海康SDK相关接口
public interface HCNetSDK extends StdCallLibrary {
boolean NET_DVR_Init();
boolean NET_DVR_Cleanup();
boolean NET_DVR_SetConnectTime(int dwWaitTime, int dwTryTimes);
boolean NET_DVR_SetReconnect(int dwInterval, boolean bEnableRecon);
NativeLong NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword,
HCNetSDK.NET_DVR_DEVICEINFO_V30 lpDeviceInfo);
boolean NET_DVR_Logout(NativeLong lUserID);
NativeLong NET_DVR_RealPlay_V40(NativeLong lUserID,
HCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo,
HCNetSDK.REALDATACALLBACK_V30 fRealDataCallBack_V30,
Pointer pUser);
boolean NET_DVR_StopRealPlay(NativeLong lRealHandle);
boolean NET_DVR_MakeKeyFrame(NativeLong lUserID, NativeLong lChannel);
boolean NET_DVR_SetStandardDataCallBack(NativeLong lRealHandle,
HCNetSDK.STANDARDDATACALLBACK fStdDataCallback,
Pointer pUserData);
interface REALDATACALLBACK_V30 extends StdCallCallback {
void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser);
}
interface STANDARDDATACALLBACK extends StdCallCallback {
void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser);
}
class NET_DVR_DEVICEINFO_V30 extends Structure {
byte[] sSerialNumber = new byte[48];
byte byAlarmInPortNum;
byte byAlarmOutPortNum;
byte byDiskNum;
byte byDVRType;
byte byChanNum;
byte byStartChan;
byte byAudioChanNum;
byte byIPChanNum;
byte[] byRes1 = new byte[24];
Pointer struDeviceV30 = null;
byte[] byRes2 = new byte[128];
}
class NET_DVR_PREVIEWINFO extends Structure {
public NativeLong lChannel;
public int dwStreamType;
public int dwLinkMode;
public Pointer hPlayWnd;
public boolean bBlocked;
public boolean bPassbackRecord;
public byte byPreviewMode;
public byte[] byRes = new byte[255];
}
}
private static class HkSdkManager {
private HCNetSDK hcNetSDK;
private NativeLong lUserID;
private BlockingQueue<byte[]> queue;
public HkSdkManager(String ip, short port, String username, String password, int channelNum) {
hcNetSDK = HCNetSDK.INSTANCE;
queue = new LinkedBlockingQueue<>();
// 初始化sdk
hcNetSDK.NET_DVR_Init();
hcNetSDK.NET_DVR_SetConnectTime(3000, 1);
hcNetSDK.NET_DVR_SetReconnect(10000, true);
// 登录设备
HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
lUserID = hcNetSDK.NET_DVR_Login_V30(ip, port, username, password, deviceInfo);
// 创建播放器对象
HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
previewInfo.lChannel = new NativeLong(channelNum);
previewInfo.dwStreamType = 0;
previewInfo.dwLinkMode = 0;
previewInfo.hPlayWnd = null;
previewInfo.bBlocked = true;
previewInfo.bPassbackRecord = false;
previewInfo.byPreviewMode = 0;
NativeLongByReference lRealHandle = new NativeLongByReference();
lRealHandle.setValue(new NativeLong(-1));
HCNetSDK.REALDATACALLBACK_V30 realDataCallback = new HCNetSDK.REALDATACALLBACK_V30() {
@Override
public void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser) {
// 判断数据类型是否为H264格式
if (dwDataType == 1) {
byte[] data = pBuffer.getByteArray(0, dwBufSize);
queue.offer(data); // 存入队列
}
}
};
hcNetSDK.NET_DVR_RealPlay_V40(lUserID, previewInfo, realDataCallback, null);
// 设置播放器的标准数据回调函数
HCNetSDK.STANDARDDATACALLBACK stdDataCallback = new HCNetSDK.STANDARDDATACALLBACK() {
@Override
public void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser) {
}
};
hcNetSDK.NET_DVR_SetStandardDataCallBack(lRealHandle.getValue(), stdDataCallback, null);
}
public byte[] takeData() throws InterruptedException {
return queue.take();
}
public void release() {
// 停止播放器
hcNetSDK.NET_DVR_StopRealPlay(lUserID);
// 登出设备
hcNetSDK.NET_DVR_Logout(lUserID);
// 释放sdk资源
hcNetSDK.NET_DVR_Cleanup();
}
}
public static void main(String[] args) {
String ip = "192.168.1.1";
short port = 8000;
String username = "admin";
String password = "admin123";
int channelNum = 1;
HkSdkManager hkSdkManager = new HkSdkManager(ip, port, username, password, channelNum);
try {
while (true) {
byte[] data = hkSdkManager.takeData(); // 从队列中取出数据
// 处理数据,例如保存到文件中
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
hkSdkManager.release();
}
}
}
代码说明
-
HCNetSDK接口: 该接口定义了与海康SDK交互的函数,例如设备登录、获取视频流、停止播放等。
-
HkSdkManager: 该类封装了海康SDK的调用逻辑,包括设备登录、获取视频流、提取H264裸流并存入队列等操作。
-
REALDATACALLBACK_V30: 该回调函数用于接收海康SDK传来的视频数据,并判断数据类型是否为H264格式,如果是则将数据存入队列中。
-
STANDARDDATACALLBACK: 该回调函数用于接收海康SDK传来的标准数据,例如时间戳、报警信息等。
-
takeData: 该方法从队列中取出H264裸流数据。
-
release: 该方法用于释放海康SDK资源,包括停止播放器、登出设备等。
注意事项
-
请确保已安装海康SDK,并配置好环境变量。
-
请确保已获取设备的IP地址、端口号、用户名和密码。
-
请确保已配置正确的通道号。
-
请根据实际需求修改代码中的数据处理逻辑。
总结
本文介绍了如何使用Java语言调用海康SDK,从海康摄像机获取视频流,并从中提取H264裸流,存入到队列中进行后续处理。文章包含详细的步骤、代码示例和相关说明,帮助开发者快速上手海康SDK开发。
原文地址: https://www.cveoy.top/t/topic/n0W6 著作权归作者所有。请勿转载和采集!