📄 vfw.cxx
字号:
BOOL PVideoInputDevice::IsCapturing()
{
return isCapturingNow;
}
BOOL PVideoInputDevice::SetFrameRate(unsigned rate)
{
if (!PVideoDevice::SetFrameRate(rate))
return FALSE;
BOOL running = IsCapturing();
if (running)
Stop();
CAPTUREPARMS parms;
memset(&parms, 0, sizeof(parms));
if (!capCaptureGetSetup(hCaptureWindow, &parms, sizeof(parms))) {
lastError = ::GetLastError();
PTRACE(1, "capCaptureGetSetup: failed - " << lastError);
return FALSE;
}
parms.dwRequestMicroSecPerFrame = 100000000 / frameRate;
parms.fMakeUserHitOKToCapture = FALSE;
parms.wPercentDropForError = 100;
parms.fCaptureAudio = FALSE;
parms.fAbortLeftMouse = FALSE;
parms.fAbortRightMouse = FALSE;
parms.fLimitEnabled = FALSE;
if (!capCaptureSetSetup(hCaptureWindow, &parms, sizeof(parms))) {
lastError = ::GetLastError();
PTRACE(1, "capCaptureSetSetup: failed - " << lastError);
return FALSE;
}
if (running)
return Start();
return TRUE;
}
BOOL PVideoInputDevice::SetFrameSize(unsigned width, unsigned height)
{
BOOL running = IsCapturing();
if (running)
Stop();
::SetWindowPos(hCaptureWindow, NULL, 0, 0,
width + GetSystemMetrics(SM_CXFIXEDFRAME),
height + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFIXEDFRAME),
SWP_NOMOVE|SWP_NOACTIVATE);
PCapStatus status(hCaptureWindow);
if (status.IsOK()) {
frameWidth = status.uiImageWidth;
frameHeight = status.uiImageHeight;
}
if (running)
return Start();
return TRUE;
}
BOOL PVideoInputDevice::VerifyHardwareFrameSize(unsigned width, unsigned height)
{
return TRUE;
}
BOOL PVideoInputDevice::SetColourFormat(const PString & colourFmt)
{
BOOL running = IsCapturing();
if (running)
Stop();
PString oldFormat = colourFormat;
if (!PVideoDevice::SetColourFormat(colourFmt))
return FALSE;
PVideoDeviceBitmap bitmapInfo(frameWidth, frameHeight, colourFmt);
if (!bitmapInfo.ApplyFormat(hCaptureWindow)) {
lastError = ::GetLastError();
PTRACE(1, "capSetVideoFormat: failed - " << lastError);
PVideoDevice::SetColourFormat(oldFormat);
return FALSE;
}
if (running)
return Start();
return TRUE;
}
PStringList PVideoInputDevice::GetInputDeviceNames()
{
PStringList list;
for (WORD devId = 0; devId < 10; devId++) {
char name[100];
char version[200];
if (capGetDriverDescription(devId, name, sizeof(name), version, sizeof(version)))
list.AppendString(name);
}
return list;
}
PINDEX PVideoInputDevice::GetMaxFrameBytes()
{
if (!IsOpen())
return 0;
PINDEX size = PVideoDeviceBitmap(hCaptureWindow)->bmiHeader.biSizeImage;
if (converter != NULL && size < converter->GetMaxDstFrameBytes())
return converter->GetMaxDstFrameBytes();
return size;
}
BOOL PVideoInputDevice::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
{
return GetFrameDataNoDelay(buffer, bytesReturned);
}
BOOL PVideoInputDevice::GetFrameDataNoDelay(BYTE * buffer, PINDEX * bytesReturned)
{
if (!frameAvailable.Wait(1000))
return FALSE;
lastFrameMutex.Wait();
if (lastFramePtr != NULL) {
if (converter != NULL)
converter->Convert(lastFramePtr, buffer, bytesReturned);
else {
memcpy(buffer, lastFramePtr, lastFrameSize);
if (bytesReturned != NULL)
*bytesReturned = lastFrameSize;
}
}
lastFrameMutex.Signal();
#if STEP_GRAB_CAPTURE
if (isCapturingNow)
capGrabFrameNoStop(hCaptureWindow);
#endif
return TRUE;
}
LRESULT CALLBACK PVideoInputDevice::ErrorHandler(HWND hWnd, int id, LPCSTR err)
{
if (hWnd == NULL)
return FALSE;
return ((PVideoInputDevice *)capGetUserData(hWnd))->HandleError(id, err);
}
LRESULT PVideoInputDevice::HandleError(int id, LPCSTR err)
{
if (id != 0) {
PTRACE(1, "ErrorHandler: [id="<< id << "] " << err);
}
return TRUE;
}
LRESULT CALLBACK PVideoInputDevice::VideoHandler(HWND hWnd, LPVIDEOHDR vh)
{
if (hWnd == NULL)
return FALSE;
return ((PVideoInputDevice *)capGetUserData(hWnd))->HandleVideo(vh);
}
LRESULT PVideoInputDevice::HandleVideo(LPVIDEOHDR vh)
{
if ((vh->dwFlags&(VHDR_DONE|VHDR_KEYFRAME)) != 0) {
lastFrameMutex.Wait();
lastFramePtr = vh->lpData;
lastFrameSize = vh->dwBytesUsed;
if (lastFrameSize == 0)
lastFrameSize = vh->dwBufferLength;
lastFrameMutex.Signal();
frameAvailable.Signal();
}
return TRUE;
}
BOOL PVideoInputDevice::InitialiseCapture()
{
if ((hCaptureWindow = capCreateCaptureWindow("Capture Window",
WS_POPUP | WS_CAPTION,
CW_USEDEFAULT, CW_USEDEFAULT,
frameWidth + GetSystemMetrics(SM_CXFIXEDFRAME),
frameHeight + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFIXEDFRAME),
(HWND)0,
0)) == NULL) {
lastError = ::GetLastError();
PTRACE(1, "capCreateCaptureWindow: failed");
return FALSE;
}
capSetCallbackOnError(hCaptureWindow, ErrorHandler);
#if STEP_GRAB_CAPTURE
if (!capSetCallbackOnFrame(hCaptureWindow, VideoHandler)) {
#else
if (!capSetCallbackOnVideoStream(hCaptureWindow, VideoHandler)) {
#endif
lastError = ::GetLastError();
PTRACE(1, "capSetCallbackOnVideoStream: failed - " << lastError);
return FALSE;
}
WORD devId;
if (deviceName.GetLength() == 1 && isdigit(deviceName[0]))
devId = (WORD)(deviceName[0] - '0');
else {
for (devId = 0; devId < 10; devId++) {
char name[100];
char version[200];
if (capGetDriverDescription(devId, name, sizeof(name), version, sizeof(version)) &&
(deviceName *= name))
break;
}
}
// Use first driver available.
if (!capDriverConnect(hCaptureWindow, devId)) {
lastError = ::GetLastError();
PTRACE(1, "capDriverConnect: failed - " << lastError);
return FALSE;
}
capSetUserData(hCaptureWindow, this);
CAPDRIVERCAPS driverCaps;
memset(&driverCaps, 0, sizeof(driverCaps));
if (!capDriverGetCaps(hCaptureWindow, &driverCaps, sizeof(driverCaps))) {
lastError = ::GetLastError();
PTRACE(1, "capGetDriverCaps: failed - " << lastError);
return FALSE;
}
/*
if (driverCaps.fHasOverlay)
capOverlay(hCaptureWindow, TRUE);
else {
capPreviewRate(hCaptureWindow, 66);
capPreview(hCaptureWindow, TRUE);
}
*/
capPreview(hCaptureWindow, FALSE);
if (!SetFrameRate(frameRate))
return FALSE;
return SetColourFormat(colourFormat);
}
void PVideoInputDevice::HandleCapture()
{
BOOL initSucceeded = InitialiseCapture();
if (initSucceeded) {
threadStarted.Signal();
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
::DispatchMessage(&msg);
}
capDriverDisconnect(hCaptureWindow);
capSetUserData(hCaptureWindow, NULL);
capSetCallbackOnError(hCaptureWindow, NULL);
capSetCallbackOnVideoStream(hCaptureWindow, NULL);
DestroyWindow(hCaptureWindow);
hCaptureWindow = NULL;
// Signal the other thread we have completed, even if have error
if (!initSucceeded)
threadStarted.Signal();
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -