Video Motion Detection Multi Thread Class Used in DVR

-->

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.

Downloads

Download demo project - 124 Kb
Download source - 7 Kb