From d7786fa8b15d9ce883ae620212209a40a0c895f6 Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Sun, 19 Feb 2023 01:46:19 +0100 Subject: [PATCH] Video grabbing now works for VfW even without visible preview window --- videodev-vfw.cc | 80 +++++++++++++++++++++++++++++++++++-------------- videodev-vfw.h | 7 +++-- 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/videodev-vfw.cc b/videodev-vfw.cc index de335a8..b0f12ab 100644 --- a/videodev-vfw.cc +++ b/videodev-vfw.cc @@ -113,6 +113,24 @@ int VideoDev_VFW::CreateClass() { return 1; } +/* + * Print driver capabilities. + */ +void VideoDev_VFW::GetCapabilities() { + + CAPDRIVERCAPS caps; + if(!capDriverGetCaps(cap, &caps, sizeof(caps))) { + printf ("%s:%d %s Unable to get driver capabilities\n", __FILE__, __LINE__, __FUNCTION__); + } + else { + printf ("%s:%d %s Id: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.wDeviceIndex); + printf ("%s:%d %s Overlay: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasOverlay); + printf ("%s:%d %s VideoSource Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoSource); + printf ("%s:%d %s VideoFormat Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoFormat); + printf ("%s:%d %s VideoDisplay Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoDisplay); + } +} + /* * The callback is run when an error in the capture driver occurred. */ @@ -129,7 +147,7 @@ LRESULT VFW_status_callback (HWND h, int nID, LPCSTR lpsz) { return TRUE; } -#define USE_PREVIEW 1 +#define USE_PREVIEW 0 /* * Opens the device. @@ -155,18 +173,33 @@ int VideoDev_VFW::Open() { // - the WS_POPUPWINDOW removes window decorations // - it does not need a parent window // - the window MUST be visible, otherwise video grabbing does not work (no callbacks run) +#if USE_PREVIEW hwnd = CreateWindowEx(0, classNameVfW, "CameraPreview", WS_POPUPWINDOW|WS_VISIBLE, 0, 0, 3, 3, NULL, NULL, hinst, NULL); +#else + hwnd = CreateWindowEx(0, classNameVfW, "CameraPreview", WS_POPUPWINDOW|WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, hinst, NULL); +#endif if (!hwnd) { printf ("%s:%d %s Could not create window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); return VDEV_STATUS_ERROR; } +#if USE_PREVIEW if(!ShowWindow(hwnd, SW_SHOW)) { printf ("%s:%d %s Could not show window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); return VDEV_STATUS_ERROR; } +#else + if(!ShowWindow(hwnd, SW_HIDE)) { + printf ("%s:%d %s Could not hide window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); + return VDEV_STATUS_ERROR; + } +#endif // create capture driver window handle, also here minim size is 1x1 +#if USE_PREVIEW cap = capCreateCaptureWindow("VFW", WS_CHILD|WS_VISIBLE, 0, 0, 1, 1, hwnd, camid); +#else + cap = capCreateCaptureWindow("VFW", WS_CHILD, 0, 0, 0, 0, hwnd, camid); +#endif if(!cap) { printf ("%s:%d %s Could not open VFW id %d window\n", __FILE__, __LINE__, __FUNCTION__, camid); return VDEV_STATUS_ERROR; @@ -186,6 +219,9 @@ int VideoDev_VFW::Open() { return VDEV_STATUS_ERROR; } + // check capabilities + GetCapabilities(); + // let the callbacks know this class pointer capSetUserData(cap, this); @@ -198,9 +234,9 @@ int VideoDev_VFW::Open() { printf ("%s:%d %s Could not get VFW capture setup\n", __FILE__, __LINE__, __FUNCTION__); return VDEV_STATUS_ERROR; } - cp.dwRequestMicroSecPerFrame = 33333; + cp.dwRequestMicroSecPerFrame = 10000; // rate in us cp.fMakeUserHitOKToCapture = 0; - cp.wPercentDropForError = 90; + cp.wPercentDropForError = 10; cp.fYield = TRUE; cp.wNumVideoRequested = 1; cp.fCaptureAudio = 0; @@ -292,7 +328,9 @@ int VideoDev_VFW::Close() { LRESULT CALLBACK VFW_frame_callback (HWND h, LPVIDEOHDR v) { VideoDev_VFW * obj = (VideoDev_VFW *)capGetUserData(h); obj->SetFrameBufferSize(v->dwBytesUsed); - memcpy(obj->GetFrameBuffer(), v->lpData, obj->GetFrameBufferSize()); + if (obj->GetFrameBuffer()) { + memcpy(obj->GetFrameBuffer(), v->lpData, obj->GetFrameBufferSize()); + } return TRUE; } @@ -312,6 +350,18 @@ int VideoDev_VFW::CaptureStart() { pixelformat = inframe_pixfmt; +#if USE_PREVIEW + if(!capSetCallbackOnFrame(cap, VFW_frame_callback)) { + printf ("%s:%d %s Could not set frame callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); + return VDEV_STATUS_ERROR; + } +#else + if(!capSetCallbackOnVideoStream(cap, VFW_frame_callback)) { + printf ("%s:%d %s Could not set videostream callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); + return VDEV_STATUS_ERROR; + } +#endif + // disable overlay capOverlay(cap, FALSE); @@ -328,21 +378,6 @@ int VideoDev_VFW::CaptureStart() { } #endif - if(!capSetCallbackOnFrame(cap, VFW_frame_callback)) { - printf ("%s:%d %s Could not set frame callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); - return VDEV_STATUS_ERROR; - } - - if(!capSetCallbackOnVideoStream(cap, VFW_frame_callback)) { - printf ("%s:%d %s Could not set videostream callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); - //return VDEV_STATUS_ERROR; - } - - if(!capSetCallbackOnYield(cap, VFW_frame_callback)) { - printf ("%s:%d %s Could not set yield callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); - //return VDEV_STATUS_ERROR; - } - return VDEV_STATUS_OK; }; @@ -356,10 +391,10 @@ int VideoDev_VFW::CaptureStop() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); capCaptureAbort(cap); - capSetCallbackOnError(cap, NULL); capSetCallbackOnFrame(cap, NULL); capSetCallbackOnVideoStream(cap, NULL); - capSetCallbackOnYield(cap, NULL); + capSetCallbackOnStatus(cap, NULL); + capSetCallbackOnError(cap, NULL); // free inframe memory if (inframe) { @@ -397,6 +432,7 @@ int VideoDev_VFW::Grab(VideoFrameRaw *vf) { if (GetFrameBufferSize() > 0) { LockMutex(); vf->CopyFrom(inframe_pixfmt, inframe_w, inframe_h, GetFrameBufferSize(), inframe); + SetFrameBufferSize(0); UnLockMutex(); } else { @@ -413,7 +449,7 @@ int VideoDev_VFW::Grab(VideoFrameRaw *vf) { int VideoDev_VFW::GetDeviceFormats(string device, std::list *formats) { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - return VDEV_STATUS_OK; + return VDEV_STATUS_OK; } diff --git a/videodev-vfw.h b/videodev-vfw.h index 63d8152..4f10aa4 100644 --- a/videodev-vfw.h +++ b/videodev-vfw.h @@ -28,6 +28,7 @@ private: int CreateClass(); int DestroyClass(); void HandleMessages(); + void GetCapabilities(); void print_error(int err); public: @@ -36,9 +37,9 @@ public: int GetDeviceList(std::list *list); int GetDeviceFormats(string device, std::list *formats); int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; - unsigned char * GetFrameBuffer(void) { return inframe; }; - void SetFrameBufferSize(int s) { vfw_size = s; }; - int GetFrameBufferSize(void) { return vfw_size; }; + unsigned char * GetFrameBuffer(void) { return inframe; }; + void SetFrameBufferSize(int s) { vfw_size = s; }; + int GetFrameBufferSize(void) { return vfw_size; }; }; #endif