📄 capture_process.cpp
字号:
#include "stdafx.h"
#include "Capture_Process.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#pragma comment(lib,"vfw32")
UINT CCapture_Main::m_ValidDriverIndex[MAX_VFW_DEVICES];
USHORT CCapture_Main::m_TotalVideoDrivers = 0;
#define UM_VID_SOURCE (WM_USER+1)
#define UM_VID_FORMAT (WM_USER+2)
#define UM_VID_DISPLAY (WM_USER+3)
//下面为视频处理函数
CCapture_Main::CCapture_Main()
{
m_TransferBitmapInfo = NULL;
m_TransferBitmapInfoSize = 0;
m_hWndVideo = NULL;
m_CaptureThread = NULL;
m_DriverIndex = -1;
memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
}
CCapture_Main::~CCapture_Main()
{
Destroy();
}
//视频采集初始化
BOOL CCapture_Main::Initialize(SHORT DriverIndex)
{
BOOL Ret = FALSE;
SHORT Index;
Destroy();
m_ImageReady.ResetEvent();
m_CaptureThread = AfxBeginThread(CaptureThreadFunc,(void *) this);
m_CaptureThread->m_bAutoDelete = FALSE;
::WaitForSingleObject(m_ImageReady, INFINITE);
if (m_hWndVideo)
{
capSetUserData(m_hWndVideo,this);
capSetCallbackOnStatus(m_hWndVideo,StatusCallbackProc);
capSetCallbackOnVideoStream(m_hWndVideo, StreamCallbackProc);
capSetCallbackOnCapControl(m_hWndVideo,ControlCallbackProc);//
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(...)
{
}
}
}
}
Ret = SetDriver(DriverIndex);
}
return Ret;
}
CCapture_Main::CCapture_Main(const CCapture_Main &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);
}
//释放函数
VOID CCapture_Main::Destroy()
{
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;
m_CaptureThread->PostThreadMessage(WM_QUIT,0,0);
while(Timeout)
{
GetExitCodeThread(m_CaptureThread->m_hThread, &ExitCode);
if (ExitCode != STILL_ACTIVE)
{
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));
}
//录像录制函数//录在c盘根目录下
BOOL CCapture_Main::CaptureAVI(LPCTSTR Filename,FLOAT FramesPerSec,ULONG Duration,UINT Quality)
{
BOOL Ret = FALSE;
CAPTUREPARMS OrigCapParms;
CAPTUREPARMS CapParms;
capCaptureGetSetup(m_hWndVideo,&OrigCapParms,sizeof(OrigCapParms));
CapParms = OrigCapParms;
CapParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 / FramesPerSec);
CapParms.fLimitEnabled = TRUE;
CapParms.wTimeLimit = Duration;
CapParms.fYield = FALSE;
CapParms.wPercentDropForError = 100; //Quality;
capCaptureSetSetup(m_hWndVideo, &CapParms, sizeof(CapParms));
Ret = capCaptureSequence(m_hWndVideo);
if (Ret)
{
Ret = capFileSaveAs(m_hWndVideo, Filename);
}
capCaptureSetSetup(m_hWndVideo, &OrigCapParms, sizeof (OrigCapParms));
return Ret;
}
CCapture_Main &CCapture_Main::Copy(const CCapture_Main &CopyFrom)
{
INT DeviceIdx;
if (&CopyFrom != this)
{
Destroy();
if (CopyFrom.m_hWndVideo)
{
CAPDRIVERCAPS DriverCaps;
capDriverGetCaps(CopyFrom.m_hWndVideo,&DriverCaps,sizeof(DriverCaps));
for (DeviceIdx=0;DeviceIdx<MAX_VFW_DEVICES;++DeviceIdx)
{
if (m_ValidDriverIndex[DeviceIdx] == DriverCaps.wDeviceIndex)
{
Initialize(DeviceIdx);
break;
}
}
}
}
return *this;
}
//设置驱动程序
BOOL CCapture_Main::SetDriver(SHORT DriverIndex)
{
BOOL Ret = TRUE;
CAPTUREPARMS CapParms = {0};
if (DriverIndex >= m_TotalVideoDrivers)
{
Ret = FALSE;
//m_ErrorID = DV_ERR_BADDEVICEID;
}
if (m_hWndVideo && m_DriverIndex != DriverIndex && Ret)
{
if (GetParent(m_hWndVideo) != NULL)
capPreview(m_hWndVideo,FALSE);
DisablePreviewVideo();
capCaptureAbort(m_hWndVideo);
Ret = capDriverConnect(m_hWndVideo, m_ValidDriverIndex[DriverIndex]);
if (Ret)
{
capGetVideoFormat(m_hWndVideo,(PBITMAPINFO) &m_BitmapInfoHeader,sizeof(m_BitmapInfoHeader));
capCaptureGetSetup(m_hWndVideo,&CapParms,sizeof(CapParms));
CapParms.fAbortLeftMouse = FALSE;
CapParms.fAbortRightMouse = FALSE;
CapParms.fYield = TRUE;
CapParms.fCaptureAudio = FALSE;
CapParms.wPercentDropForError = 100;
capCaptureSetSetup(m_hWndVideo,&CapParms,sizeof(CapParms));
m_DriverIndex = DriverIndex;
if (GetParent(m_hWndVideo) != NULL)
capPreview(m_hWndVideo,TRUE);
}
}
/* if (!Ret && m_ErrorID == 0)
{
m_ErrorID = DV_ERR_NONSPECIFIC;
}*/
return Ret;
}
//是否允许视频采集
BOOL CCapture_Main::EnablePreviewVideo(HWND Parent, INT x, INT y, INT PreviewRate)
{
return EnablePreviewVideo(Parent,
x,y,
m_BitmapInfoHeader.biWidth,
m_BitmapInfoHeader.biHeight,
PreviewRate);
}
//对采集的窗体进行子窗体大小位置
BOOL CCapture_Main::EnablePreviewVideo(HWND Parent, INT x, INT y, INT Width, INT Height, INT PreviewRate)
{
//将视频窗口设置为当前窗口的子页
SetParent(m_hWndVideo,Parent);
SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);
//这个函数为窗口指定新位置和状态。它也可改变窗口在内部窗口列表中的位
SetWindowPos(m_hWndVideo,NULL,x,y,
Width,
Height,
SWP_NOZORDER);
ShowWindow(m_hWndVideo,SW_SHOW);
//发送给捕捉窗口来设置在预览模式下帧的显示频率
capPreviewRate(m_hWndVideo, PreviewRate);
return capPreview(m_hWndVideo,TRUE);//进行视频播放
}
BOOL CCapture_Main::DisablePreviewVideo()
{
//进行视频断开
// BOOL Ret = capPreview(m_hWndVideo,FALSE);
// return Ret;
BOOL Ret = capPreview(m_hWndVideo,FALSE);
SetWindowPos(m_hWndVideo,NULL,0,0,0,0,SWP_NOZORDER);
SetParent(m_hWndVideo,NULL);
SetWindowLong(m_hWndVideo,GWL_STYLE,WS_POPUP);
return Ret;
}
// 得到捕捉窗口的硬件的性能
BOOL CCapture_Main::DriverGetCaps(CAPDRIVERCAPS *Caps)
{
return capDriverGetCaps(m_hWndVideo,Caps,sizeof(*Caps));
}
//综合设定
BOOL CCapture_Main::DlgVideoSource()
{
return PostThreadMessage(m_CaptureThread->m_nThreadID,UM_VID_SOURCE,0,0);
}
//视频格式设定
BOOL CCapture_Main::DlgVideoFormat()
{
return PostThreadMessage(m_CaptureThread->m_nThreadID,UM_VID_FORMAT,0,0);
}
//进行视频采集
BOOL CCapture_Main::DlgVideoDisplay()
{
return PostThreadMessage(m_CaptureThread->m_nThreadID,UM_VID_DISPLAY,0,0);
}
//把从帧缓存中复制出图像存为设备无关位图书馆(DIB),应用程序也可
//以使用这两个单帧捕捉消息来编辑帧序列,
//或者创建一个慢速摄影序列
//捕取对图像的大小
ULONG CCapture_Main::CalcBitmapSize(const BITMAPINFOHEADER &bmiHeader)
{
ULONG Size = 0;
if (bmiHeader.biSizeImage == 0)
{
Size = bmiHeader.biWidth *
bmiHeader.biHeight *
bmiHeader.biBitCount / 8;
}
else
{
Size = bmiHeader.biSizeImage;
}
return Size;
}
/* BOOL Capture_LX(CCapture_Main &ImageProc, LPCTSTR Filename)
{
ULONG Length = 0;
CFile File;
BOOL Ret = FALSE;
CHAR Ext[_MAX_EXT];
_splitpath(Filename,NULL,NULL,NULL,Ext);
if (stricmp(Ext,".avi") == 0)
{
Ret = ImageProc.CaptureAVI(Filename,4.0,10,10);
}
return Ret;
}
*/
ULONG CCapture_Main::CalcBitmapInfoSize(const BITMAPINFOHEADER &bmiHeader)
{
UINT bmiSize = (bmiHeader.biSize != 0) ? bmiHeader.biSize : sizeof(BITMAPINFOHEADER);
return bmiSize + bmiHeader.biClrUsed * sizeof (RGBQUAD);
}
static LRESULT CALLBACK StatusCallbackProc(HWND hWnd, int nID, LPCSTR lpsz)
{
CCapture_Main *VFWObj = (CCapture_Main *) capGetUserData(hWnd);
switch(nID)
{
case IDS_CAP_BEGIN:
break;
case IDS_CAP_END:
break;
}
return (LRESULT) TRUE;
}
static LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
{
CCapture_Main *VFWObj = (CCapture_Main *) capGetUserData(hWnd);
LRESULT Ret = TRUE;
if (VFWObj)
{
if (!VFWObj->m_hWndVideo)
{
Ret = FALSE;
}
else
{
CSingleLock ImageLockObj(&VFWObj->m_ImageProtect, TRUE);
if (VFWObj->m_TransferBitmapInfo)
{
ULONG Size;
VFWObj->m_TransferBitmapInfo->bmiHeader = VFWObj->m_BitmapInfoHeader;
Size = min(VFWObj->m_TransferBitmapInfoSize - VFWObj->CalcBitmapInfoSize(VFWObj->m_TransferBitmapInfo->bmiHeader),
lpVHdr->dwBytesUsed);
memcpy(((CHAR *) VFWObj->m_TransferBitmapInfo) + VFWObj->CalcBitmapInfoSize(VFWObj->m_TransferBitmapInfo->bmiHeader),
lpVHdr->lpData,
Size);
}
ImageLockObj.Unlock();
VFWObj->m_ImageReady.SetEvent();
}
}
else
{
Ret = FALSE;
}
return Ret;
}
static LRESULT CALLBACK StreamCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
{
CCapture_Main *VFWObj = (CCapture_Main *) capGetUserData(hWnd);
LRESULT Ret = TRUE;
return Ret;
}
static UINT CaptureThreadFunc(VOID *pCVFWImageProcessor)
{
CCapture_Main *pImageProc = (CCapture_Main *) pCVFWImageProcessor;
UINT Ret = 0;
HWND VideoWindow;
MSG Msg;
VideoWindow = capCreateCaptureWindow(NULL,WS_POPUP,
0,0,
1,1,0,0);
pImageProc->m_hWndVideo = VideoWindow;
pImageProc->m_ImageReady.SetEvent();
while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
switch(Msg.message)
{
case UM_VID_SOURCE:
capDlgVideoSource(pImageProc->m_hWndVideo);
break;
case UM_VID_FORMAT:
capDlgVideoFormat(pImageProc->m_hWndVideo);
break;
case UM_VID_DISPLAY:
capDlgVideoDisplay(pImageProc->m_hWndVideo);
break;
}
}
Ret = Msg.wParam;
if (VideoWindow)
{
DestroyWindow(VideoWindow);
}
return Ret;
}
BOOL CCapture_Main::PICPIC() //将图片放到剪贴板
{
SendMessage(m_hWndVideo, WM_CAP_EDIT_COPY, 0, 0);
// SendMessage(m_hWndVideo, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0);
return true;
}
static LRESULT CALLBACK ControlCallbackProc(HWND hWnd, int nState)
{
CCapture_Main *VFWObj = (CCapture_Main *) capGetUserData(hWnd);
LRESULT Ret = TRUE;
switch(nState)
{
case CONTROLCALLBACK_PREROLL:
if (VFWObj)
{
VFWObj->m_CancelCapture.ResetEvent();
}
Ret = TRUE;
break;
case CONTROLCALLBACK_CAPTURING:
// if m_CancelCapture is posted, then we cancel AVI capture by returning FALSE.
if (VFWObj)
{
Ret = (::WaitForSingleObject(VFWObj->m_CancelCapture,0) != WAIT_OBJECT_0);
if (!Ret)
TRACE("Callback Canceled Capture\n");
}
break;
}
return Ret;
}
BOOL CCapture_Main::VideoCompress()//视频压缩
{
SendMessage(m_hWndVideo, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -