–>
Environment: VC++
Introduction
In Digital Video Recording (DVR) System, one most important feature is the Video Motion Detection. Most DVR is consisted by multi video capture cards. The card number sometime will be up to 16. In order to make the system working more effectively and quickly, the best way is using Multi Thread method and each thread cooperate with one video capture card. In this way, system can monitor up 16 video motion alarm and not reduce the system performance.
System Frame
In DVR system, there are three layers in the software structure. The lowest one is the Video Capture Card drivers and sound card drivers; the middle one is the DLL and COM units; so the top one can be realized by different language such as VC, Delphi and VB.
In Video Motion Detection middleware realization, first, design one multi thread class to realize the functions. Secondly, wrap this class by the Dynamic Link Library (DLL).
Wrapped DLL Implementation
This DLL wrapper intended for simplified function using. This DLL can support the basic video motion detection functionality, such as Sample Step Number setting, Comparison value setting, Comparison Percent Number setting, Save BMP picture or Warning if video motion detected.
How to use this DLL in your application
- Create video motion detection objects one by one by using WnWd_CreateHWDrv.
- Set the comparison parameter by call WnWd_SetCmpStepXY, WnWd_SetCmpStepYUV and WnWd_SetCmpPercent.
- Call WnWd_SetCurrentCard to specify one video card.
- Call WnWd_StartHWDrv to start this video card video comparison work.
- Call WnWd_SuspendHWDrv to stop this video card video comparison work.
- Call WnWd_KillHWDrv to kill all video motion detection objects.
Multi Thread Video Motion Detection Class Analysis
How to create the thread
To create one thread need two steps. First, Create one video motion detection object by calling this multi thread class constructor. Secondly, Create this object’s thread by calling CWinThread::CreateThread.
// This Constructor is used to create an object & initialize it. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Video Motion Detection Class Construction and initialization //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CWnDrv::CWnDrv( CWnd* pWnd, WORD wHWCardNo, BYTE* lpImage, BITMAPINFO* lpDIBHdr) { m_hDatProcThread = NULL ; if( !wnwd_SystemInit(wHWCardNo,lpImage,lpDIBHdr) ) PRINTF("(WnWizard)Initializing Error" ); } // In here create a real thread and set the priority of it. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Create This Video Motion Detection Thread //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CWnDrv::CreateThread( DWORD dwCreateFlags, UINT nStackSize, LPSECURITY_ATTRIBUTES lpSecurityAttrs ) { DWORD dwThreadID; m_DatProcMilliSecond = 0; m_hDatProcThread = ::CreateThread( NULL, 0, (unsigned long (__stdcall *) (void *))DatProcThreadInitialProc, this, CREATE_SUSPENDED, &dwThreadID); if( m_hDatProcThread ) ::SetThreadPriority(m_hDatProcThread, THREAD_PRIORITY_HIGHEST); return TRUE ; }
How to define the thread function
The thread function must be run forever, because if the function is returned, this thread will exit too. The function wnwd_VImgIsMotify() in here is used to judge the motion detection.
// In here define the thread function. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Begin This Video Motion Detection Thread to Monitor the Video Motion //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CWnDrv::DatProcThreadProc(void) { for (;;) { ::WaitForSingleObject( m_hDatProcThread, m_DatProcMilliSecond); if( wnwd_VImgIsMotify() ) { m_WarnStatus = TRUE; // warning if(m_bIsWarn ) MessageBeep( MB_ICONEXCLAMATION ); //write BMP if(m_bIsSave ) { char pTemp[100] , pTempA[100] ; strcpy(pTempA, "C:\\"); sprintf(pTemp,"MotionDetect%d", m_wHWCurrentCardNum); strcat(pTempA, pTemp); wnwd_SaveBMP((char *)((const char*)pTempA)); } } else m_WarnStatus = FALSE; } }
How to realize the video motion detection
This function sample the real time video frame image, convert to YUV format and compare to the prior one, if the result is larger than the comparison value, count the number. At last, if the counted number is larger than the comparison percent number, motion detection alarm and replace this value to the prior one.
// In here define how to compare the video frame image. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Compare the realtime(m_pYUV) YUV value to the saved(m_pYUVSample) // YUV value and saved the new value into the old one if motion detect //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CWnDrv::wnwd_VImgIsMotify() { DWORD i , Count =0L; memcpy(m_pBtImageBak, m_pBtImage,m_lVImgSize); switch(m_iVGABits) { case CF_RGB15 : wnwd_RGB15_toYUV(m_pBtImageBak, m_pYUV, m_lImgWid, m_lImgHei, m_wStepX, m_wStepY ); break ; case CF_RGB16 : wnwd_RGB16_toYUV(m_pBtImageBak, m_pYUV, m_lImgWid, m_lImgHei, m_wStepX, m_wStepY ); break ; case CF_RGB24 : wnwd_RGB24_toYUV(m_pBtImageBak, m_pYUV, m_lImgWid, m_lImgHei, m_wStepX, m_wStepY ); break ; case CF_RGB32 : wnwd_RGB32_toYUV(m_pBtImageBak, m_pYUV, m_lImgWid, m_lImgHei, m_wStepX, m_wStepY ); break ; } #define Yi m_pYUV[i] #define Ui m_pYUV[i+1] #define Vi m_pYUV[i+2] #define Ys m_pYUVSample[i] #define Us m_pYUVSample[i+1] #define Vs m_pYUVSample[i+2] for(i=0 ; i < m_lYUVSize; i+=3) { if( abs(Yi - Ys ) > m_cStepY || //Y abs(Ui - Us ) > m_cStepU || //CB abs(Vi - Vs ) > m_cStepV ) //CR Count ++; if( Count > m_lYUVSampleSize ) break ; } if( Count > m_lYUVSampleSize ) { memcpy(m_pYUVSample , m_pYUV , m_lYUVSize ); return TRUE ; } return FALSE ; }
Demo programs
Included is one demo program in common workspace file. Project was compiled and tested with MSVC++ 5.0 & 6.0. WnWizard.dll uses CWnDrv class for real time video motion detection. The CWnDrv is a whole multi thread class and can be wrapped in another way, such as COM.