MFC(vs2013)+opencv+海康SDK_顯示視訊教程
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