#include "stdafx.h"
#include "VFWImageProcessor.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#pragma comment(lib,"vfw32")
UINT CVFWImageProcessor::m_ValidDriverIndex[MAX_VFW_DEVICES];
USHORT CVFWImageProcessor::m_TotalVideoDrivers = 0;
#define UM_VID_SOURCE (WM_USER+1)
#define UM_VID_FORMAT (WM_USER+2)
#define UM_VID_DISPLAY (WM_USER+3)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVFWImageProcessor::CVFWImageProcessor()
{
m_TransferBitmapInfo = NULL;
m_TransferBitmapInfoSize = 0;
m_hWndVideo = NULL;
m_CaptureThread = NULL;
m_DriverIndex = -1;
memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
}
CVFWImageProcessor::~CVFWImageProcessor()
{
Destroy();
}
/*******************************************************************************
Function : Initialize
Arguments : DriverIndex (input) - Index of VFW driver.
Return : TRUE Success, FALSE Failure
Description: Inititlizes the object for using VFW interface to capture
device.
*******************************************************************************/
BOOL CVFWImageProcessor::Initialize(SHORT DriverIndex)
{
BOOL Ret = FALSE;
SHORT Index;
Destroy();
// Reset any error conditions.
GetPreviousError(NULL,NULL,TRUE);
// This semaphore will temporarily be used to determine when the
// capture thread is ready.
m_ImageReady.ResetEvent();
//
// Create message pump for window messages.
m_CaptureThread = AfxBeginThread(CaptureThreadFunc,(void *) this);
m_CaptureThread->m_bAutoDelete = FALSE;
// Wait for event to determine when capture thread is ready.
::WaitForSingleObject(m_ImageReady, INFINITE);
if (m_hWndVideo)
{
capSetUserData(m_hWndVideo,this);
capSetCallbackOnError(m_hWndVideo,ErrorCallbackProc);
capSetCallbackOnCapControl(m_hWndVideo,ControlCallbackProc);
capSetCallbackOnStatus(m_hWndVideo,StatusCallbackProc);
capSetCallbackOnFrame(m_hWndVideo, FrameCallbackProc);
capSetCallbackOnVideoStream(m_hWndVideo, StreamCallbackProc);
// Construct list of valid video drivers.
// This creates a contiguous virtual driver table.
if (!m_TotalVideoDrivers)
{
char szDeviceName[80];
char szDeviceVersion[80];
for (Index = 0; Index < MAX_VFW_DEVICES; Index++)
{
if (capGetDriverDescription(Index,
szDeviceName,
sizeof(szDeviceName),
szDeviceVersion,
sizeof(szDeviceVersion)))
{
try
{
if (capDriverConnect(m_hWndVideo, Index))
{
m_ValidDriverIndex[m_TotalVideoDrivers] = Index;
m_TotalVideoDrivers++;
capDriverDisconnect(m_hWndVideo);
}
}
catch(CException *Ex)
{
Ex->Delete();
}
catch(...)
{
}
}
}
}
// Reset any error conditions.
GetPreviousError(NULL,NULL,TRUE);
Ret = SetDriver(DriverIndex);
}
if (!Ret)
{
if (m_ErrorID == 0)
m_ErrorID = DV_ERR_NONSPECIFIC;
Destroy();
}
return Ret;
}
/*******************************************************************************
Function : GetCapWindow
Arguments : none
Return : HWND of VFW window.
Description: Used to retrieve the handle used for VFW image processing.
*******************************************************************************/
HWND CVFWImageProcessor::GetCapWindow()
{
return m_hWndVideo;
}
//
// Copy Constructor
//
CVFWImageProcessor::CVFWImageProcessor(const CVFWImageProcessor &CopyFrom)
{
m_TransferBitmapInfo = NULL;
m_TransferBitmapInfoSize = 0;
m_hWndVideo = NULL;
m_CaptureThread = NULL;
m_DriverIndex = -1;
memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
Copy(CopyFrom);
}
//
// Copy class using operator=
//
CVFWImageProcessor &CVFWImageProcessor::operator =(const CVFWImageProcessor &CopyFrom)
{
return Copy(CopyFrom);
}
/*******************************************************************************
Function : Destroy
Arguments : none
Return : none
Description: Closes up the interface for VFW of capture device.
*******************************************************************************/
VOID CVFWImageProcessor::Destroy()
{
// Reset any error conditions.
GetPreviousError(NULL,NULL,TRUE);
if (m_hWndVideo)
{
DisablePreviewVideo();
capCaptureAbort(m_hWndVideo);
capSetCallbackOnError(m_hWndVideo,NULL);
capSetCallbackOnCapControl(m_hWndVideo,NULL);
capSetCallbackOnStatus(m_hWndVideo,NULL);
capSetCallbackOnFrame(m_hWndVideo,NULL);
capSetCallbackOnVideoStream(m_hWndVideo, NULL);
capSetUserData(m_hWndVideo,NULL);
capDriverDisconnect(m_hWndVideo);
}
if (m_CaptureThread)
{
DWORD ExitCode;
INT Timeout = 50; // Tenths of a Second
// Terminate the message queue thread and wait for it to end.
m_CaptureThread->PostThreadMessage(WM_QUIT,0,0);
while(Timeout)
{
GetExitCodeThread(m_CaptureThread->m_hThread, &ExitCode);
if (ExitCode != STILL_ACTIVE)
{
// Thread has ended.
break;
}
else
{
Sleep(100);
}
--Timeout;
}
delete m_CaptureThread;
m_hWndVideo = NULL;
}
m_TransferBitmapInfo = NULL;
m_TransferBitmapInfoSize = 0;
m_hWndVideo = NULL;
m_CaptureThread = NULL;
m_DriverIndex = -1;
memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
}
/*******************************************************************************
Function : CaptureDIB
Arguments : Bitmap (output) - Pointer to bitmap to receive image.
If *Bitmap = NULL, then allocation will
be performed automatically.
BitmapLength (input) - Size of Bitmap if *Bitmap is not NULL.
RetBitmapLength (output) - Actual size of image.
Return : TRUE Success, FALSE Failed.
Description: Captures a DIB image from video capture device.
*******************************************************************************/
BOOL CVFWImageProcessor::CaptureDIB(PBITMAPINFO *Bitmap,
ULONG BitmapLength,
ULONG *RetBitmapLength)
{
BOOL Ret = FALSE;
CSingleLock ImageLockObj(&m_ImageProtect);
DWORD Size = 0;
// Reset any error conditions.
GetPreviousError(NULL,NULL,TRUE);
if (*Bitmap == NULL)
{
AllocDIBImage(Bitmap,&Size);
BitmapLength = Size;
}
else
{
AllocDIBImage(NULL,&Size);
}
if (*Bitmap && Size > 0)
{
if (RetBitmapLength)
{
*RetBitmapLength = Size;
}
// Must assign pointer to class member variable so that the
// callback function can get to it.
ImageLockObj.Lock();
m_TransferBitmapInfo = *Bitmap;
m_TransferBitmapInfoSize = BitmapLength;
ImageLockObj.Unlock();
// Reset event semaphore so we know when an image is ready.
m_ImageReady.ResetEvent();
// S