MFC(vs2013)+opencv+海康SDK显示视频教程
本文主要说明用vs2013的MFC,调用海康的SDK,显示海康网络摄像机。全文主要分为两大部分,第一部分是vs2013的属性配置;第二部分是一个调用的程序实例。
第一部分:vs2013工程环境配置
本部分分为两大大模块:opencv的配置,MFC工程调用海康SDK的配置
1.1,opencv的配置
参考本博客的另一篇oepncv配置文章,
文章题目:Opencv配置环境_win7_64_Opencv3.1_vs2013
网址:http://blog.csdn.net/naibozhuan3744/article/details/78560744
1.2,MFC工程调用海康SDK的配置
1.2.1将编译换平台换成x64,如下图所示:
1.2.2【配置属性】-【VC++目录】-【包含目录】添加SDK的include(将头文件文件夹改为include),如下图所示
1.2.3【配置属性】-【VC++目录】-【库目录】添加SDK的lib(将库文件改为lib),添加两个库文件如下图所示:
1.2.4【链接器】-【输入】-【附加依赖项】添加lib文件中的.lib文件,如下所示:
opencv_world310d.lib
GdiPlus.lib
HCCore.lib
HCNetSDK.lib
PlayCtrl.lib
HCAlarm.lib
HCGeneralCfgMgr.lib
HCPreview.lib
1.2.5将lib文件夹下(包括子文件)所有内容复制到当前工程的debug目录下(注意:是全部复制,并且是所有的dll和lib文件放在debug目录下),如下图所示:
第二部分:一个调用的程序实例
2.1在主对话框创建一个按钮test,然后双击该按钮,在按钮函数里面添加如下程序:(现在主对话框头文件包含如下图所示头文件和命名空间)
intInitResult1 = NET_DVR_Init(); //初始化
NET_DVR_SetConnectTime(2000,1);
NET_DVR_SetReconnect(10000,true);
LONG lUserID;
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
lUserID =NET_DVR_Login_V30("192.168.22.234", 8000,"admin","jk123456", &struDeviceInfo);
LONG lRealPlayHandle;
cvNamedWindow("Mywindow", 0); //启动预览
cvNamedWindow("IPCamera", 0);
HWND h = (HWND)cvGetWindowHandle("Mywindow"); //如何h==0,则创建窗口失败
NET_DVR_PREVIEWINFO struPlayInfo = { 0 }; //回调数据流
struPlayInfo.hPlayWnd= h; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空
struPlayInfo.lChannel= 1; //预览通道号
struPlayInfo.dwStreamType= 0; //0-主码流,1-子码流,2-码流3,3-码流4,以此类推
struPlayInfo.dwLinkMode= 0; //0- TCP方式,1- UDP方式,2-多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
lRealPlayHandle =NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, fRealDataCallBack,NULL);//视频的播放主要是回调函数一直在循环,才会有持续的视频显示
waitKey(0);
Sleep(0); //阻止程序退出Sleep(-1)
NET_DVR_StopRealPlay(lRealPlayHandle);
NET_DVR_Logout(lUserID);
NET_DVR_Cleanup();
注意:IP地址修改成摄像机的IP地址,账号密码也要修改成激活摄像机时的账号密码!!!
2.2在按钮函数的上面,添加如下程序:
LONG nPort =-1;
volatile intgbHandling = 3;
//解码回调视频为YUV数据(YV12),音频为PCM数据
void CALLBACK DecCBFun(longnPort,char * pBuf, long nSize,FRAME_INFO *pFrameInfo, long nReserved1, long nReserved2)
{
if (gbHandling)
{
gbHandling--;
return;
}
longlFrameType = pFrameInfo->nType;
if(lFrameType == T_YV12)
{
Mat pImg(pFrameInfo->nHeight,pFrameInfo->nWidth,CV_8UC3);
Mat src(pFrameInfo->nHeight +pFrameInfo->nHeight/ 2,pFrameInfo->nWidth, CV_8UC1, pBuf);
cvtColor(src,pImg, CV_YUV2BGR_YV12);
// Sleep(-1);
imshow("IPCamera", pImg);
//waitKey(1);
}
gbHandling = 3;
}
///实时流回调
void CALLBACK fRealDataCallBack(LONGlRealHandle,DWORDdwDataType,BYTE *pBuffer,DWORDdwBufSize,void *pUser)
{
//AfxMessageBox("----------回调函数--------%d\n", time(NULL) * 10);
switch (dwDataType)
{
case NET_DVR_SYSHEAD://系统头
if(!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号
{
break;
}
//m_iPort = lPort; //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放
if (dwBufSize> 0)
{
if(!PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME)) //设置实时流播放模式
{
break;
}
if(!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 10 * 1024 * 1024)) //打开流接口
{
break;
}
if(!PlayM4_Play(nPort, NULL)) //播放开始
{
break;
}
if(!PlayM4_SetDecCallBack(nPort, DecCBFun))
{
break;
}
}
break;
case NET_DVR_STREAMDATA: //码流数据
if (dwBufSize> 0 && nPort != -1)
{
if(!PlayM4_InputData(nPort, pBuffer, dwBufSize))
{
cout<< "error" << PlayM4_GetLastError(nPort) << endl;
break;
}
}
break;
default://其他数据
if (dwBufSize> 0 && nPort != -1)
{
if(!PlayM4_InputData(nPort, pBuffer, dwBufSize))
{
break;
}
}
break;
}
}
void CALLBACK g_ExceptionCallBack(DWORDdwType,LONGlUserID,LONGlHandle,void *pUser)
{
chartempbuf[256] = { 0 };
switch (dwType)
{
case EXCEPTION_RECONNECT: //预览时重连
printf("----------reconnect--------%d\n", time(NULL));
break;
default:
break;
}
}
如下图所示:
2.4运行后,如下图所示:
参考内容:
http://blog.csdn.net/shakevincent/article/details/51490197
http://blog.csdn.net/u013105549/article/details/50493069