關鍵點:
NET_DVR_Login_V30NET_DVR_RealPlay_V30,註冊碼流回調 fRealDataCallBackPlayM4 解碼DecCBFun 中將 YV12 轉 RGB,存入全局幀隊列 g_frameList(加鎖保護)// 解碼回調:YV12 轉 RGB
void CALLBACK DecCBFun(long nPort, char* pBuf, long nSize, FRAME_INFO* pFrameInfo, ...) {
if (pFrameInfo->nType == T_YV12) {
// YV12 轉 YUV (IplImage)
// cvCvtColor YCrCb2RGB
Mat frame(pImg); // 轉 Mat
EnterCriticalSection(&g_cs_frameList);
g_frameList.push_back(frame);
LeaveCriticalSection(&g_cs_frameList);
}
}
// 碼流回調:送入播放庫
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize, ...) {
switch (dwDataType) {
case NET_DVR_SYSHEAD:
PlayM4_GetPort(&nPort);
PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024*1024);
PlayM4_SetDecCallBack(nPort, DecCBFun);
PlayM4_Play(nPort, hWnd);
break;
case NET_DVR_STREAMDATA:
PlayM4_InputData(nPort, pBuffer, dwBufSize);
break;
}
}
// 主函數:啟動讀取線程,主循環取幀
unsigned readCamera(void* param) {
NET_DVR_Init();
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
LONG lUserID = NET_DVR_Login_V30("192.168.2.64", 8000, "admin", "a123456789", &struDeviceInfo);
NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);
NET_DVR_CLIENTINFO ClientInfo = {1, NULL, 0, NULL};
LONG lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE);
Sleep(-1); // 保持線程
// 清理...
return 0;
}
int main() {
InitializeCriticalSection(&g_cs_frameList);
_beginthreadex(NULL, 0, readCamera, NULL, 0, &threadID);
while (true) {
EnterCriticalSection(&g_cs_frameList);
if (!g_frameList.empty()) {
Mat frame = g_frameList.front(); g_frameList.pop_front();
// imshow / 處理
}
LeaveCriticalSection(&g_cs_frameList);
}
}