69,369
社区成员
发帖
与我相关
我的任务
分享
// gcc WinMain.c -o WinMain -luser32 -lgdi32 -lvfw32
#include <stdio.h>
#include <Windows.h>
#include <vfw.h>
// 转载来源: https://github.com/godspeed1989/Win32CameraCapture
#define MAX_CAMERA_INDEX 10
static HWND m_hCapWnd[MAX_CAMERA_INDEX];
static CAPDRIVERCAPS m_CapDrvCap[MAX_CAMERA_INDEX];
static CAPSTATUS m_CapStatus[MAX_CAMERA_INDEX];
static CAPTUREPARMS m_Parms[MAX_CAMERA_INDEX];
UINT cm_print_driver_list()
{
UINT wIndex, wCameraCnt;
WCHAR szDriverName[80];
WCHAR szDriverVersion[80];
wCameraCnt = 0;
for (wIndex = 0; wIndex < MAX_CAMERA_INDEX; wIndex++)
{
if( TRUE == capGetDriverDescriptionW (wIndex,
szDriverName, sizeof(szDriverName),
szDriverVersion, sizeof(szDriverVersion)) )
{
wprintf(L"[%d] %s - %s\n", wIndex, szDriverName, szDriverVersion);
wCameraCnt++;
}
}
return wCameraCnt;
}
static BOOL cm_open_internal(UINT idx, HWND hwParent)
{
// 创建窗口句柄
m_hCapWnd[idx] = capCreateCaptureWindow("Camera Preview Window", WS_CHILD | WS_VISIBLE, 0, 0, 20000, 20000, hwParent, 0);
if (!m_hCapWnd)
{
printf("m_hCapWnd failed !!!\n");
return FALSE;
}
// 连接第idx号驱动器
else if (TRUE == capDriverConnect(m_hCapWnd[idx], idx))
{
capOverlay(m_hCapWnd[idx], FALSE);
capPreview(m_hCapWnd[idx], FALSE);
// 得到驱动器的性能
memset(&m_CapDrvCap[idx], 0, sizeof(CAPDRIVERCAPS));
if (FALSE == capDriverGetCaps(m_hCapWnd[idx], &m_CapDrvCap[idx], sizeof(CAPDRIVERCAPS)))
{
printf("capDriverGetCaps failed !!!\n");
}
else if (m_CapDrvCap[idx].fCaptureInitialized)
{
// 初始化成功
return TRUE;
}
else
{
printf("fCaptureInitialized failed !!!\n");
}
}
else
{
printf("connect failed !!!\n");
}
//capCaptureStop(m_hCapWnd[idx]); // 停止捕捉
//capDriverDisconnect(m_hCapWnd[idx]);
//DestroyWindow(m_hCapWnd[idx]);
return FALSE;
}
void cm_close(UINT idx)
{
capCaptureStop(m_hCapWnd[idx]);
capCaptureAbort(m_hCapWnd[idx]); // 停止捕获
capDriverDisconnect(m_hCapWnd[idx]); // 断开捕捉器与驱动器的连接
DestroyWindow(m_hCapWnd[idx]);
}
BOOL cm_open(UINT idx, HWND hwParent)
{
BOOL ret = TRUE;
int n = 0;
do
{
printf("%d try to open %d\n", n, idx);
Sleep(500);
ret = cm_open_internal(idx, hwParent);
n++;
} while(FALSE == ret && n < 5);
if (FALSE == ret)
{
printf("open failed !!!\n");
}
return ret;
}
BOOL cm_get_param(UINT idx, int *width, int *height, int *frame_rate)
{
BOOL ret = TRUE;
// 得到设置参数
ret = capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
if (FALSE == ret)
{
printf("capCaptureGetSetup failed !!!\n");
return ret;
}
// 得到驱动器状态
ret = capGetStatus(m_hCapWnd[idx], &m_CapStatus[idx], sizeof(CAPSTATUS));
if (FALSE == ret)
{
printf("capGetStatus failed !!!\n");
return ret;
}
*width = (int)m_CapStatus[idx].uiImageWidth;
*height = (int)m_CapStatus[idx].uiImageHeight;
*frame_rate = (int)1000000 / (int)m_Parms[idx].dwRequestMicroSecPerFrame;
return ret;
}
BOOL cm_grab_to_bmp(UINT idx, WCHAR *file)
{
BOOL ret = TRUE;
// 截获当前图像
ret = capGrabFrame(m_hCapWnd[idx]);
if (FALSE == ret)
{
printf("capGrabFrame failed !!!\n");
return ret;
}
// 保存到文件
ret = capFileSaveDIB(m_hCapWnd[idx], file);
if (FALSE == ret)
{
printf("capFileSaveDIB failed !!!\n");
return ret;
}
return ret;
}
BOOL cm_grab_to_clipboard(UINT idx)
{
BOOL ret = TRUE;
// 截获当前图像
ret = capGrabFrame(m_hCapWnd[idx]);
if (FALSE == ret)
{
printf("capGrabFrame failed !!!\n");
return ret;
}
// 保存到剪贴板
ret = capEditCopy(m_hCapWnd[idx]);
if (FALSE == ret)
{
printf("capEditCopy failed !!!\n");
return ret;
}
return ret;
}
//LRESULT CALLBACK StreamCallbackProc(HWND hCapWnd, LPVIDEOHDR lphdr)
//{
// return (LRESULT)TRUE;
//}
BOOL cm_start_record(UINT idx, WCHAR *file)
{
BOOL ret = TRUE;
// 视频流回调函数
//ret = capSetCallbackOnVideoStream(m_hCapWnd[idx], StreamCallbackProc);
//if (FALSE == ret)
//{
// printf("capSetCallbackOnVideoStream failed !!!\n");
// return ret;
//}
// 设置捕获参数
capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
m_Parms[idx].fYield = TRUE; // 后台运行
m_Parms[idx].fCaptureAudio = FALSE; // 无声音
m_Parms[idx].wTimeLimit = FALSE; // 无时间限制
capCaptureSetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
// 设置捕获视频的文件
capFileSetCaptureFile(m_hCapWnd[idx], file);
// 开始录像线程
ret = capCaptureSequence(m_hCapWnd[idx]);
if (FALSE == ret)
{
printf("capCaptureSequence failed !!!\n");
return ret;
}
return ret;
}
void cm_stop_record(UINT idx)
{
//capSetCallbackOnVideoStream(m_hCapWnd[idx], NULL);
capCaptureStop(m_hCapWnd[idx]);
capCaptureAbort(m_hCapWnd[idx]);
}
// 转载部分结束
void cm_update_frame(UINT idx) {
capGrabFrame(m_hCapWnd[idx]);
}
#define BASE_WINDOW_CLASS_NAME "CameraCaptureWindowClass"
#define BASE_WINDOW_NAME "Camera Capture Window"
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(EXIT_SUCCESS);
break;
case WM_TIMER:
cm_update_frame(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
ATOM My_RegisterClass(HINSTANCE hInstance) {
WNDCLASSA WndClass;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.lpszClassName = BASE_WINDOW_CLASS_NAME;
WndClass.lpszMenuName = NULL;
WndClass.style = 0;
return RegisterClassA(&WndClass);
}
HWND My_CreateWindow(HINSTANCE hInstance) {
return CreateWindowA(
BASE_WINDOW_CLASS_NAME,
BASE_WINDOW_NAME,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
}
int My_CycleMessage(void) {
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return (int)msg.wParam;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
int nRet;
My_RegisterClass(hInstance);
hwnd = My_CreateWindow(hInstance);
UpdateWindow(hwnd);
{
cm_print_driver_list();
cm_open(0, hwnd);
{
char str[128];
int nWidth, nHeight, nFramerate;
cm_get_param(0, &nWidth, &nHeight, &nFramerate);
sprintf(str, BASE_WINDOW_NAME " - (%d x %d) %d Hz", nWidth, nHeight, nFramerate);
SetWindowTextA(hwnd, str);
}
UpdateWindow(hwnd);
Sleep(1000);
cm_grab_to_bmp(0, "output.bmp");
SetTimer(hwnd, 123, 200, NULL);
//cm_close(0);
}
nRet = My_CycleMessage();
cm_close(0);
return nRet;
}