在项目中需要接入海康设备,因此我们集成了海康Android版本SDK。它分为Device Network SDK和Player SDK。前者用于设备连接、网络通信;后者用于解码、播放。
在APP中,关于海康设备,我们实现了以下功能:添加设备、获取通道、实时预览、远程回放。
接下来我们一个一个来分析如何实现:
首先,登录设备,用到的是这个方法:HCNetSDK.getInstance().NET_DVR_Login_V30(String sDvrIp, int iDvrPort, String sUsername, String sPassword, NET_DVR_DEVICEINFO_V30 deviceInfo)
具体代码实现如下:
HCNetSDK.getInstance().NET_DVR_Init(); //初始化SDKNET_DVR_DEVICEINFO_V30 m_oNetDvrDeviceInfoV30 = new NET_DVR_DEVICEINFO_V30();if (null == m_oNetDvrDeviceInfoV30) { Log.e("Hikvision", "HKNetDvrDeviceInfoV30 new is failed!"); Message msg = Message.obtain(); msg.what = 1; if (!AddDeviceActivity.this.isFinishing()) { msg.obj = getResources().getString(R.string.loginFailed); } handler.sendMessage(msg); return;}int iLogID = HCNetSDK.getInstance().NET_DVR_Login_V30(ipAddress, port, userName, password, m_oNetDvrDeviceInfoV30); //登录设备
接着,获取通道,
如果iLogID不小于0,则登录成功。
获取开始通道号、通道个数,代码如下:
一般情况时,
if(m_oNetDvrDeviceInfoV30.byChanNum > 0) {
m_iStartChan = m_oNetDvrDeviceInfoV30.byStartChan;
m_iChanNum = m_oNetDvrDeviceInfoV30.byChanNum;
} else if(m_oNetDvrDeviceInfoV30.byIPChanNum > 0) {
m_iStartChan = m_oNetDvrDeviceInfoV30.byStartDChan;
m_iChanNum = m_oNetDvrDeviceInfoV30.byIPChanNum + m_oNetDvrDeviceInfoV30.byHighDChanNum * 256;
}
复杂情况时(比如模拟通道和数字通道混合、所获取的通道并不都是valid可用的等)
NET_DVR_IPPARACFG_V40 net_dvr_ipparacfg_v40 = new NET_DVR_IPPARACFG_V40(); //IP Device Resource and IP Channel Resource Configuration
HCNetSDK.getInstance().NET_DVR_GetDVRConfig(iLogID, HCNetSDK.NET_DVR_GET_IPPARACFG_V40, 0, net_dvr_ipparacfg_v40); //Get Device Settings Information
Log.i("Hik_An_CHANNEL_NUM", net_dvr_ipparacfg_v40.dwAChanNum + "");
Log.i("Hik_Di_CHANNEL_NUM", net_dvr_ipparacfg_v40.dwDChanNum + "");
NET_DVR_DIGITAL_CHANNEL_STATE net_dvr_digital_channel_state = new NET_DVR_DIGITAL_CHANNEL_STATE(); //Channel Status
HCNetSDK.getInstance().NET_DVR_GetDVRConfig(iLogID, HCNetSDK.NET_DVR_GET_DIGITAL_CHANNEL_STATE, 0xFFFFFFFF, net_dvr_digital_channel_state);
byte[] byAnalogChanState = net_dvr_digital_channel_state.byAnalogChanState;
byte[] byDigitalChanState = net_dvr_digital_channel_state.byDigitalChanState;
SQLiteDatabase db = mySqliteHelper.getWritableDatabase();
for (int i = 0; i < net_dvr_ipparacfg_v40.dwAChanNum; i++) {
if (byAnalogChanState[i] == 1)
mCount ++;
}
for (int i = 0; i < net_dvr_ipparacfg_v40.dwDChanNum; i++) {
if (byDigitalChanState[i] == 1)
mCount ++;
}
Log.i("Hik_VALID_CHANNEL_NUM", mCount + "");
for (int i = 0; i < net_dvr_ipparacfg_v40.dwAChanNum; i++) {
if (byAnalogChanState[i] == 1)
DbManger.execDataSql(db, "insert into " + Dbutils.TABLE_NAME + "(" +
Dbutils.CAMERA_NAME + "," + Dbutils.CAMERA_ID + "," + Dbutils.SITE_NAME + "," + Dbutils.DEVICE_NAME + ","
+ Dbutils.ADDRESS + "," + Dbutils.TCP + "," + Dbutils.USERNAME + "," + Dbutils.PASSWORD + "," +
Dbutils.CAMERA_NUM + "," + Dbutils.DEVICE_TYPE + ") values('" + "HikCAM " + (i + 1) + "',"
+ (m_oNetDvrDeviceInfoV30.byStartChan + i) + ",'" + site_name + "','" + device_name + "','" + ipAddress + "',"
+ port + ",'" + userName + "','" + password + "'," + mCount + ",'" + "Hikvision Device" + "')");
}
for (int i = 0; i < net_dvr_ipparacfg_v40.dwDChanNum; i++) {
if (byDigitalChanState[i] == 1)
DbManger.execDataSql(db, "insert into " + Dbutils.TABLE_NAME + "(" +
Dbutils.CAMERA_NAME + "," + Dbutils.CAMERA_ID + "," + Dbutils.SITE_NAME + "," + Dbutils.DEVICE_NAME + ","
+ Dbutils.ADDRESS + "," + Dbutils.TCP + "," + Dbutils.USERNAME + "," + Dbutils.PASSWORD + "," +
Dbutils.CAMERA_NUM + "," + Dbutils.DEVICE_TYPE + ") values('" + "HikCAM " + (i + 1) + "',"
+ (net_dvr_ipparacfg_v40.dwStartDChan + i) + ",'" + site_name + "','" + device_name + "','" + ipAddress + "',"
+ port + ",'" + userName + "','" + password + "'," + mCount + ",'" + "Hikvision Device" + "')");
}
//以下处理是针对net_dvr_ipparacfg_v40.dwAChanNum和net_dvr_ipparacfg_v40.dwDChanNum均为0,但是仍然有通道的海康设备
if (net_dvr_ipparacfg_v40.dwAChanNum == 0 && net_dvr_ipparacfg_v40.dwDChanNum == 0) {
if(m_oNetDvrDeviceInfoV30.byChanNum > 0) {
m_iStartChan = m_oNetDvrDeviceInfoV30.byStartChan;
m_iChanNum = m_oNetDvrDeviceInfoV30.byChanNum;
} else if(m_oNetDvrDeviceInfoV30.byIPChanNum > 0) {
m_iStartChan = m_oNetDvrDeviceInfoV30.byStartDChan;
m_iChanNum = m_oNetDvrDeviceInfoV30.byIPChanNum + m_oNetDvrDeviceInfoV30.byHighDChanNum * 256;
}
mCount = m_iChanNum;
for (int i = 0 ; i < m_iChanNum ; i ++) {
int cameraId = m_iStartChan + i;
DbManger.execDataSql(db, "insert into " + Dbutils.TABLE_NAME + "(" +
Dbutils.CAMERA_NAME + "," + Dbutils.CAMERA_ID + "," + Dbutils.SITE_NAME + "," + Dbutils.DEVICE_NAME + ","
+ Dbutils.ADDRESS + "," + Dbutils.TCP + "," + Dbutils.USERNAME + "," + Dbutils.PASSWORD + "," +
Dbutils.CAMERA_NUM + "," + Dbutils.DEVICE_TYPE + ") values('" + "HikCAM " + (i + 1) + "',"
+ cameraId + ",'" + site_name + "','" + device_name + "','" + ipAddress + "',"
+ port + ",'" + userName + "','" + password + "'," + mCount + ",'" + "Hikvision Device" + "')");
}
}
对海康摄像头进行实时预览:用到的方法是HCNetSDK.getInstance().NET_DVR_RealPlay_V40(int var1, NET_DVR_PREVIEWINFO var2, RealPlayCallBack var3)
具体实现代码如下:
用之前登录成功返回的iLogID和之前获取的通道号
NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
previewInfo.lChannel = channelNo; //通道号
previewInfo.dwStreamType = streamType; //码流类型
previewInfo.bBlocked = 1;
RealPlayCallBack fRealDataCallBack = getRealPlayerCbf();
int m_iPlayID = HCNetSDK.getInstance().NET_DVR_RealPlay_V40(iLogID, previewInfo, fRealDataCallBack);
private RealPlayCallBack getRealPlayerCbf() {如果返回的m_iPlayID不小于0,则实时预览成功,于是可以看到海康摄像头的实时视频。
RealPlayCallBack cbf = new RealPlayCallBack() {
public void fRealDataCallBack(int iRealHandle, int iDataType, byte[] pDataBuffer, int iDataSize) {
processRealData(1, iDataType, pDataBuffer, iDataSize, Player.STREAM_REALTIME);
}
};
return cbf;
}
private void processRealData(int iPlayViewNo, int iDataType, byte[] pDataBuffer, int iDataSize, int iStreamMode) {
if (m_bNeedDecode) {
if (HCNetSDK.NET_DVR_SYSHEAD == iDataType) {
m_iPort = Player.getInstance().getPort();
if (m_iPort == -1) {
Log.e(TAG_ERROR, "getPort is failed with: " + Player.getInstance().getLastError(m_iPort));
return;
}
Log.i(TAG, "getPort success with: " + m_iPort);
if (iDataSize > 0) {
if (!Player.getInstance().setStreamOpenMode(m_iPort, iStreamMode)) //set stream mode
{
Log.e(TAG_ERROR, "setStreamOpenMode failed");
return;
}
if (!Player.getInstance().openStream(m_iPort, pDataBuffer, iDataSize, 2 * 1024 * 1024)) //open stream
{
Log.e(TAG_ERROR, "openStream failed");
return;
}
if (!Player.getInstance().play(m_iPort, surfaceView.getHolder())) {
Log.e(TAG_ERROR, "play failed");
return;
}
if (!Player.getInstance().playSound(m_iPort)) {
Log.e(TAG_ERROR, "playSound failed with error code:" + Player.getInstance().getLastError(m_iPort));
return;
}
}
} else {
if (!Player.getInstance().inputData(m_iPort, pDataBuffer, iDataSize)) {
for (int i = 0; i < 4000 && m_iPlaybackID >= 0 && !m_bStopPlayback; i++) {
if (Player.getInstance().inputData(m_iPort, pDataBuffer, iDataSize)) {
break;
}
if (i % 100 == 0) {
Log.e(TAG_ERROR, "inputData failed with: " + Player.getInstance().getLastError(m_iPort) + ", i:" + i);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
停止实时预览,具体实现代码如下:
/**
* 停止实时预览
* @param playId
* @param port
*/
public void stopLive(int playId, int port) {
if (playId >= 0) {
if (HCNetSDK.getInstance().NET_DVR_StopRealPlay(playId)) {
Player.getInstance().stopSound();
if (Player.getInstance().stop(port)) {
if (Player.getInstance().closeStream(port)) {
if (Player.getInstance().freePort(port)) {
Log.i(TAG, "close success");
} else {
Log.e(TAG_ERROR, "freePort is failed!" + port);
}
} else {
Log.e(TAG_ERROR, "closeStream is failed!");
}
} else {
Log.e(TAG_ERROR, "stop is failed!");
}
} else {
Log.e(TAG_ERROR, "StopRealPlay is failed!Err:" + HCNetSDK.getInstance().NET_DVR_GetLastError());
}
}
}
对海康摄像头进行录像回放,我们这里是采用按照时间进行回放,用到的方法是HCNetSDK.getInstance().NET_DVR_PlayBackByTime(int var1, int var2, NET_DVR_TIME var3, NET_DVR_TIME var4)
具体实现代码如下:
用之前登录成功返回的iLogID和之前获取的通道号
NET_DVR_TIME struBegin = new NET_DVR_TIME(); //开始时间
NET_DVR_TIME struEnd = new NET_DVR_TIME(); //结束时间
struBegin.dwYear = bgYear;
struBegin.dwMonth = bgMonth;
struBegin.dwDay = bgDay;
struBegin.dwHour = bgHour;
struBegin.dwMinute = bgMinute;
struBegin.dwSecond = bgSecond;
struEnd.dwYear = endYear;
struEnd.dwMonth = endMonth;
struEnd.dwDay = endDay;
struEnd.dwHour = endHour;
struEnd.dwMinute = endMinute;
struEnd.dwSecond = endSecond;
PlaybackCallBack fPlaybackCallBack = getPlayerbackPlayerCbf();
private PlaybackCallBack getPlayerbackPlayerCbf() {
PlaybackCallBack cbf = new PlaybackCallBack() {
@Override
public void fPlayDataCallBack(int iPlaybackHandle, int iDataType, byte[] pDataBuffer, int iDataSize) {
processRealData(1, iDataType, pDataBuffer, iDataSize, Player.STREAM_FILE);
}
};
return cbf;
}
public void processRealData(int iPlayViewNo, int iDataType, byte[] pDataBuffer, int iDataSize, int iStreamMode) {
if(m_bNeedDecode) {
if(HCNetSDK.NET_DVR_SYSHEAD == iDataType) {
/*if(m_iPort >= 0)
{
return;
}*/
m_iPort = Player.getInstance().getPort();
if(m_iPort == -1) {
Log.e(TAG, "Hikvision getPort is failed with: " + Player.getInstance().getLastError(m_iPort));
return;
}
Log.i(TAG, "Hikvision getPort succ with: " + m_iPort);
if (iDataSize > 0) {
if (!Player.getInstance().setStreamOpenMode(m_iPort, iStreamMode)) { //set stream mode
Log.e(TAG, "Hikvision setStreamOpenMode failed");
return;
}
if (!Player.getInstance().openStream(m_iPort, pDataBuffer, iDataSize, 2*1024*1024)) { //open stream
Log.e(TAG, "Hikvision openStream failed");
return;
}
if (!Player.getInstance().play(m_iPort, surfaceView.getHolder())) {
Log.e(TAG, "Hikvision play failed");
return;
}
if(!Player.getInstance().playSound(m_iPort)) {
Log.e(TAG, "Hikvision playSound failed with error code:" + Player.getInstance().getLastError(m_iPort));
return;
}
}
} else {
if (!Player.getInstance().inputData(m_iPort, pDataBuffer, iDataSize)) {
// Log.e(TAG, "inputData failed with: " + Player.getInstance().getLastError(m_iPort));
for(int i = 0; i < 4000 && m_iPlaybackID >=0 && !m_bStopPlayback; i++) {
if (Player.getInstance().inputData(m_iPort, pDataBuffer, iDataSize)) {
break;
}
if(i % 100 == 0) {
Log.e(TAG, "Hikvision inputData failed with: " + Player.getInstance().getLastError(m_iPort) + ", i:" + i);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
int m_iPlaybackID = HCNetSDK.getInstance().NET_DVR_PlayBackByTime(iLogID, channelNo, struBegin, struEnd);
if(m_iPlaybackID >= 0) {
if(!HCNetSDK.getInstance().NET_DVR_SetPlayDataCallBack(m_iPlaybackID, fPlaybackCallBack)) {
Log.e(TAG, "Hikvision set playback callback failed!");
Message msg = Message.obtain();
msg.what = 1;
if (!PlaybackActivity.this.isFinishing()) {
msg.obj = getResources().getString(R.string.fail_start_playback);
}
handler.sendMessage(msg);
return ;
}
NET_DVR_PLAYBACK_INFO struPlaybackInfo = null ;
if(!HCNetSDK.getInstance().NET_DVR_PlayBackControl_V40(m_iPlaybackID, PlaybackControlCommand.NET_DVR_PLAYSTART, null, 0, struPlaybackInfo)) {
Log.e(TAG, "Hikvision net sdk playback start failed!");
Message msg = Message.obtain();
msg.what = 1;
if (!PlaybackActivity.this.isFinishing()) {
msg.obj = getResources().getString(R.string.fail_start_playback);
}
handler.sendMessage(msg);
return ;
}
m_bStopPlayback = false;
loadFinish = true;
Message msg = Message.obtain();
msg.what = 2;
handler.sendMessage(msg);
Thread thread = new Thread()
{
public void run()
{
int nProgress = -1;
while(true) {
nProgress = HCNetSDK.getInstance().NET_DVR_GetPlayBackPos(m_iPlaybackID);
if(nProgress < 0 || nProgress >= 100) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
thread.start();
} else {
Log.e(TAG, "Hikvision NET_DVR_PlayBackByTime failed, error code: " + HCNetSDK.getInstance().NET_DVR_GetLastError());
}
停止回放,具体实现代码如下:
public void stopPlaybackHikvision() {
m_bStopPlayback = true;
if(!HCNetSDK.getInstance().NET_DVR_StopPlayBack(m_iPlaybackID)) {
Log.e(TAG, "Hikvision net sdk stop playback failed");
}
stopSinglePlayer();
Log.i(TAG, "Hikvision close success");
}
private void stopSinglePlayer() {
Player.getInstance().stopSound();
// player stop play
if (!Player.getInstance().stop(m_iPort)) {
Log.e(TAG, "Hikvision stop is failed!");
return;
}
if(!Player.getInstance().closeStream(m_iPort)) {
Log.e(TAG, "Hikvision closeStream is failed!");
return;
}
if(!Player.getInstance().freePort(m_iPort)) {
Log.e(TAG, "Hikvision freePort is failed!" + m_iPort);
return;
}
m_iPort = -1;
}