1. 问题描写
最近在搭建1个可视传感网,在调试早期就遇到了1个很奇怪的问题:
一样的型号的摄像机,一样的程序,有1部份摄像头正常工作,而有1大部份的不能正常解码显示。这个小demo是我使用海康SDK里面实例写的。文章的最后给出项目的代码,有兴趣的也能够跑跑程序,其实只是1个简单的例程而已,写在这里只是为了方便往后归纳总结。这里使用的海康网络摄像头型号是:DS⑵CD852MF-E。
代码中,摄像头的登录函数为:NET_DVR_Login_V30,播放函数:NET_DVR_RealPlay_V40。

在回调解码函数处设置断点,能跳到此函数中:

但是除ip为192.168.2.21和192.168.2.22这两个网络摄像机,换成其他的摄像机都显示不了。但是另外一方面,网络摄像头的登录没有问题,但是就是没有画面。

单步调试,看到lRealHandle = NET_DVR_RealPlay_V40(lUserID,&struPlayInfo,g_RealDataCallBack_V30,NULL);lRealHandle值为0,表示没有问题的啊…但是在回调函数设置断点却进不去,就说明没有回调解码。跟上面的区分就在这里。但是代码是1模1样的,摄像机型号都是1样的852MF-E,因此不知道问题出在哪里。
2. 解决方法
以上问题可简单描写为,1个可用的程序,但对1部份摄像头硬件可用,这些摄像头型号均是1样的,因此第1时间的想法是查看这些摄像机软件版本或硬件固件版本是不是1致,答案是不是定的:

因此我又试了多个摄像机,只要是v2.0 build 100521 和v4.0 build 090220,这样的都能显示,但是其他的软件版本都显示不了。1时半会要更新软件或固件版本也是1大工程,因此继续查阅SDK开发文档,发现其实可以查看装备登录预览的SDK日志,在代码中,只需在SDK初始化后调用NET_DVR_SetLogToFile()函数便可保存日志信息。启用写日志文件的函数定义以下:
BOOL NET_DVR_SetLogToFile(
DWORD nLogLevel,char *strLogDir,BOOL bAutoDel
);
其中,nLogLevel 表示日志的等级(默许为0):0-表示关闭日志,1-表示只输出ERROR毛病日志,2-输出ERROR毛病信息和DEBUG调试信息,3-输出ERROR毛病信息、DEBUG调试信息和INFO普通讯息等所有信息;
strLogDir 表示日志文件的路径,windows默许值为”C:SdkLog”;linux默许值”/home/sdklog/”;
bAutoDel 表示是不是删除超越的文件数,默许值为TRUE。
生成日志文件,发现实际上是缺少了必要的dll文件。
SDK V4.3.0.6
[
2015⑴0⑵0 14:58:00.599][
INF] version:This hcnetsdk version is 4.3.0.6 Version 2014
_07_22.
SDK V4.3.0.6[
2015⑴0⑵0 14:58:00.599][
INF]
logonDev1 192.168.3.22:8000 in
[
2015⑴0⑵0 14:58:00.601][
INF] Private connect 192.168.3.22:8000 sock=496 this=0xf115e8 cmd=0x10000 port=30473
[
2015⑴0⑵0 14:58:00.601][
INF] OpenCommandConnection ptr=0xf115e8 id=4096
[
2015⑴0⑵0 14:58:00.601][
INF] [SendCommandWithRecv] this=0xf115e8,cmd_id=0x1000,cmd=0x10000
[
2015⑴0⑵0 14:58:00.615][
INF] [CloseCommandConnection] this=0xf115e8,cmd_id=0x1000
[
2015⑴0⑵0 14:58:00.615][
INF] StopLinkInConnection sock=496 this=0xf115e8,command=0x10000
[
2015⑴0⑵0 14:58:00.620][
INF]
logonDev1 192.168.3.22:8000 in
[
2015⑴0⑵0 14:58:00.630][
INF] Private connect 192.168.3.22:8000 sock=496 this=0xf115e8 cmd=0x10010 port=30474
[
2015⑴0⑵0 14:58:00.630][
INF] OpenCommandConnection ptr=0xf115e8 id=8192
[
2015⑴0⑵0 14:58:00.630][
INF] [SendCommandWithRecv] this=0xf115e8,cmd_id=0x2000,cmd=0x10010
[
2015⑴0⑵0 14:58:00.631][
DBG] MainStream 0xf0
[
2015⑴0⑵0 14:58:00.631][
INF] SubStream 0x0,RTP/RTSP[0],Private and RTSP[0],streamPacketType[0x0]
[
2015⑴0⑵0 14:58:00.631][
INF] [CloseCommandConnection] this=0xf115e8,cmd_id=0x2000
[
2015⑴0⑵0 14:58:00.631][
INF] StopLinkInConnection sock=496 this=0xf115e8,command=0x10010
[
2015⑴0⑵0 14:58:00.636][
INF]
logonDev1 192.168.3.22:8000 out,dev_ver=020220090317,protocol=0xf0f0 sn=DS2CD852MF-E0020100721BCCH401124400WC
[
2015⑴0⑵0 14:58:00.636][
INF] [UserCtrlInstance::AddUser] m
_nCurrentUserIndex=0,i=0,m_nTotalUserNum=1
[
2015⑴0⑵0 14:58:00.636][
INF] Login success. UserID=0,DevIP=192.168.3.22
[
2015⑴0⑵0 14:58:02.095][
DBG] BaseEngine[class CNetPreviewSession / 1 / 1]::AllocSession[0] get instance[00F177C0]
[
2015⑴0⑵0 14:58:02.095][
INF] Preview Session=0 channel[1],UserID[0]
[
2015⑴0⑵0 14:58:02.095][
DBG] [0] userid[0] this[f177c0]PreviewStart in block[0] cbreal[1
3018cf]stand[0] userdatap[0] dw[0],hwnd[1905a2]
[
2015⑴0⑵0 14:58:02.095][
INF] StreamMode[0],StreamProtocol[0xf0f0]
[
2015⑴0⑵0 14:58:02.095][
DBG] [0] PreviewStart out
[
2015⑴0⑵0 14:58:02.095][
DBG] [
0][
192.168.3.22:8000]preview LinkToDvr
[
2015⑴0⑵0 14:58:02.095][
INF] StreamMode[0],StreamProtocol[0xf0f0]
[
2015⑴0⑵0 14:58:02.125][
ERR] GlobalCtrl load [E:Herbert Project单个摄像机解码并
显示DebugStreamTransClient.dll] with sdk path
Failed and get handle[0]
[
2015⑴0⑵0 14:58:02.129][
ERR] Load StreamTransClient
Failed[syserr: 126]
[
2015⑴0⑵0 14:58:02.129][
ERR] Preview Session=0 link proto=4
[
2015⑴0⑵0 14:58:02.129][
ERR] [0] preview MainPreview link
Failed!!!
[
2015⑴0⑵0 14:58:02.129][
DBG] userid[0] Preview[0] AysoNonBlockThread callback exception
[
2015⑴0⑵0 14:58:09.918][
INF] [0]PreviewStop begin
[
2015⑴0⑵0 14:58:09.918][
DBG] [0] NetPreview SessionStop in,player nPort[⑴]
[
2015⑴0⑵0 14:58:09.918][
ERR] (IExchangeProxy::RigisterCommandIndex)this preview[0] is not registered.
[
2015⑴0⑵0 14:58:09.918][
DBG] [0] NetPreview SessionStop out
[
2015⑴0⑵0 14:58:09.918][
DBG] BaseEngine[class CNetPreviewSession / 512 / 1 / 1]::DestroySessionByIndex[0] instance[00F177C0]
[
2015⑴0⑵0 14:58:12.274][
DBG] FiniSDK begin SDK fini[1]
[
2015⑴0⑵0 14:58:12.274][
DBG] [0] DelUser CurrentUserIndex ⑴ total[0]
[
2015⑴0⑵0 14:58:13.135][
DBG] stop time thread
后面的操作就很简单了,在海康的SDK库文件中找到StreamTransClient.dll和SystemTransform.dll并添加到工程项目底下,问题解决。
3. 项目部份代码
上传时发现文件过大,因此只贴出部份代码:
#include "stdafx.h" #include "SingleCamApp.h" #include "SingleCamDlg.h" #include "afxdialogex.h" #include "HCNetSDK.h" #include "plaympeg4.h" #ifdef _DEBUG #define new DEBUG_NEW #endif LONG nPort = -
1;
HWND hPlayWnd = NULL; LONG lUserID = -
1;
LONG lRealHandle = -
1;
CString IPToStr(DWORD dwIP);
void CALLBACK DecCBFun(
long nPort,
char * pBuf,
long nSize,FRAME_INFO * pFrameInfo,
long nReserved1,
long nReserved2);
void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,
void* dwUser);
CSingleCamDlg::CSingleCamDlg(CWnd* pParent )
: CDialogEx(CSingleCamDlg::IDD,pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSingleCamDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX,IDC_CAM_IP,m_ctrlDeviceIP); }
BEGIN_MESSAGE_MAP(CSingleCamDlg,CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_Login,&CSingleCamDlg::OnBnClickedBtnLogin)
ON_BN_CLICKED(IDC_BTN_PlayCam,&CSingleCamDlg::OnBnClickedBtnPlaycam)
ON_BN_CLICKED(IDC_BTN_StopCam,&CSingleCamDlg::OnBnClickedBtnStopcam)
END_MESSAGE_MAP()
BOOL CSingleCamDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); SetIcon(m_hIcon,TRUE); SetIcon(m_hIcon,FALSE); NET_DVR_Init();
isLogin = FALSE;
isPlaying = FALSE;
hPlayWnd = GetDlgItem(IDC_ViewWindow)->m_hWnd; m_ctrlDeviceIP.SetAddress(
192,
168,
2,
21);
GetDlgItem(IDC_BTN_PlayCam)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_StopCam)->EnableWindow(FALSE);
return TRUE; }
void CSingleCamDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(
this); SendMessage(WM_ICONERASEBKGND,reinterpret_cast(dc.GetSafeHdc()),
0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon +
1) /
2;
int y = (rect.Height() - cyIcon +
1) /
2; dc.DrawIcon(x,y,m_hIcon);
}
else {
CDialogEx::OnPaint();
}
}
HCURSOR CSingleCamDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
} CString IPToStr(DWORD dwIP)
{
CString strIP = _T(
"");
WORD add1,add2,add3,add4;
add1=(WORD)(dwIP&
255);
add2=(WORD)((dwIP>>
8)&
255);
add3=(WORD)((dwIP>>
16)&
255);
add4=(WORD)((dwIP>>
24)&
255);
strIP.Format(
"%d.%d.%d.%d",add4,add1);
return strIP;
}
void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle,
void* dwUser)
{
switch (dwDataType)
{
case NET_DVR_SYSHEAD:
if (!PlayM4_GetPort(&nPort)) {
break;
}
if (dwBufSize >
0)
{
if (!PlayM4_SetStreamOpenMode(nPort,STREAME_REALTIME)) {
break;
}
if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,
1024*
1024)) {
break;
}
if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))
{
break;
}
if (!PlayM4_SetDisplayBuf(nPort,
4)) {
break;
}
if (!PlayM4_Play(nPort,hPlayWnd)) {
break;
}
}
case NET_DVR_STREAMDATA:
if (dwBufSize >
0 && nPort != -
1)
if (!PlayM4_InputData(nPort,dwBufSize))
break;
}
}
void CALLBACK DecCBFun(
long nPort,
long nReserved2)
{
}
void CSingleCamDlg::OnBnClickedBtnLogin() {
if (isLogin) {
NET_DVR_
logout(lUserID);
isLogin = FALSE;
GetDlgItem(IDC_BTN_Login)->SetWindowTextA(
"登录");
GetDlgItem(IDC_BTN_PlayCam)->EnableWindow(FALSE); }
else {
char DeviceIP[
16] = {
0};
DWORD dwDeviceIP =
0;
m_ctrlDeviceIP.GetAddress(dwDeviceIP);
CString csTemp = IPToStr(dwDeviceIP);
sprintf_s(DeviceIP,
"%s",csTemp.GetBuffer(
0));
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
lUserID = NET_DVR_Login_V30(DeviceIP,
8000,
"admin",
"12345",&struDeviceInfo);
if (lUserID <
0) {
AfxMessage
Box(
"登录失败!");
isLogin = FALSE;
}
else {
isLogin = TRUE;
GetDlgItem(IDC_BTN_Login)->SetWindowTextA(
"注销"); GetDlgItem(IDC_BTN_PlayCam)->EnableWindow(TRUE); }
}
}
void CSingleCamDlg::OnBnClickedBtnPlaycam() {
NET_DVR_PREVIEWINFO struPlayInfo = {
0};
struPlayInfo.hPlayWnd = NULL; struPlayInfo.lChannel =
1; struPlayInfo.dwStreamType =
0; struPlayInfo.dwLinkMode =
0; lRealHandle = NET_DVR_RealPlay_V40(lUserID,NULL);
if (lRealHandle <
0)
{
AfxMessage
Box(
"播放失败!");
isPlaying = FALSE; }
else {
GetDlgItem(IDC_BTN_Login)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_PlayCam)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_StopCam)->EnableWindow(TRUE); isPlaying = TRUE;
}
}
void CSingleCamDlg::OnBnClickedBtnStopcam() {
NET_DVR_StopRealPlay(lRealHandle); PlayM4_Stop(nPort);
PlayM4_CloseStream(nPort);
PlayM4_FreePort(nPort);
GetDlgItem(IDC_BTN_Login)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_PlayCam)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_StopCam)->EnableWindow(FALSE); }