From ec7caf8b226ce4d561579da0b85f3e67b78fb70e Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Sat, 18 Feb 2023 23:31:26 +0100 Subject: [PATCH 1/6] Added some more documentation. Larger previews, e.g. 1280x720 seem possible. --- videodev-vfw.cc | 309 +++++++++++++++++++++++++++++++----------------- videodev-vfw.h | 11 +- 2 files changed, 208 insertions(+), 112 deletions(-) diff --git a/videodev-vfw.cc b/videodev-vfw.cc index 5ff7665..de335a8 100644 --- a/videodev-vfw.cc +++ b/videodev-vfw.cc @@ -1,5 +1,6 @@ /* - * module to read video data from vfw. + * Module to grab video data from VfW interface. The interface is + * poorly documented for which some odd comments maybe found here. */ #include "config.h" @@ -15,26 +16,36 @@ #include "convert.h" #include "videodev-vfw.h" +static char classNameVfW[] = "VFW-Class"; + +/* + * Constructor + */ VideoDev_VFW::VideoDev_VFW() { - printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - hwnd = cap = NULL; - camid = -1; - inframe_pixfmt = 0x0; - inframe_w = -1; - inframe_h = -1; - inframe = NULL; - inframe_size = 0; - vfw_size = 0; + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + hwnd = cap = NULL; + camid = -1; + inframe_pixfmt = 0x0; + inframe_w = -1; + inframe_h = -1; + inframe = NULL; + inframe_size = 0; + vfw_size = 0; + hclass = NULL; + hinst = NULL; }; - +/* + * Destructor + */ VideoDev_VFW::~VideoDev_VFW() { - printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - if (running > 0) CaptureStop(); + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + if (running > 0) + CaptureStop(); } /* - * check for connected devices and return the result in a list. + * Check for connected devices and returns the result in a list. */ int VideoDev_VFW::GetDeviceList(std::list *list) { @@ -43,9 +54,11 @@ int VideoDev_VFW::GetDeviceList(std::list *list) { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); if (list == NULL) return VDEV_STATUS_ERROR; - + + // go through a list of 10 (maximum number defined by VfW) for(int i=0; i < 10; i++) if(capGetDriverDescription(i, name, sizeof(name), desc, sizeof(desc))) { + // create a driver for the return list std::string device; device = "VFW " + to_string(i) + " " + (string)name + " [" + (string)desc + "]"; printf ("%s:%d %s Found device '%s'\n", __FILE__, __LINE__, __FUNCTION__, device.c_str()); @@ -56,57 +69,118 @@ int VideoDev_VFW::GetDeviceList(std::list *list) { } /* - * Open Device - * prepare the buffer + * Destroy and unregister window class. */ -int VideoDev_VFW::Open() { +int VideoDev_VFW::DestroyClass() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + if (hclass) { + if(!UnregisterClass(classNameVfW, hinst)) { + printf ("%s:%d %s Could not unregister VFW class\n", __FILE__, __LINE__, __FUNCTION__); + return 0; + } + free (hclass); + hclass = NULL; + } + return 1; +} + +/* + * Create and register window class. + */ +int VideoDev_VFW::CreateClass() { + + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + if (hclass) return 1; + + hclass = (WNDCLASSEX *)malloc(sizeof(WNDCLASSEX)); + hclass->hInstance = hinst; + hclass->lpszClassName = classNameVfW; + hclass->lpfnWndProc = DefWindowProc; + hclass->style = CS_DBLCLKS; + hclass->cbSize = sizeof(WNDCLASSEX); + hclass->hIcon = LoadIcon(NULL,IDI_APPLICATION); + hclass->hIconSm = LoadIcon(NULL,IDI_APPLICATION); + hclass->hCursor = LoadCursor(NULL,IDC_ARROW); + hclass->lpszMenuName = NULL; + hclass->cbClsExtra = 0; + hclass->cbWndExtra = 0; + hclass->hbrBackground = (HBRUSH)COLOR_BACKGROUND; + + if(!RegisterClassEx (hclass)) { + printf ("%s:%d %s Could not register VFW class\n", __FILE__, __LINE__, __FUNCTION__); + return 0; + } + return 1; +} + +/* + * The callback is run when an error in the capture driver occurred. + */ +LRESULT VFW_error_callback (HWND h, int nID, LPCSTR lpsz) { + printf("%s:%d %s id=%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, nID, lpsz); + return TRUE; +} - static int first = 1; +/* + * The callback is run when a status update in the capture driver occurred. + */ +LRESULT VFW_status_callback (HWND h, int nID, LPCSTR lpsz) { + printf("%s:%d %s id=%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, nID, lpsz); + return TRUE; +} + +#define USE_PREVIEW 1 + +/* + * Opens the device. + */ +int VideoDev_VFW::Open() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + // extract camera id from device name camid = atoi (conf_device.c_str()); printf ("%s:%d %s Opening VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); - // create parent window - //HWND main_hwnd = (HWND)GDK_WINDOW_HWND (gtk_widget_get_window (GTK_WIDGET(main_window))); - HINSTANCE hinst = GetModuleHandle(NULL); - char classNameVfW[] = "VFW-Class"; - - if (first) { - WNDCLASSEX hclass; - hclass.hInstance=hinst; - hclass.lpszClassName=classNameVfW; - hclass.lpfnWndProc=DefWindowProc; - hclass.style=CS_DBLCLKS; - hclass.cbSize=sizeof(WNDCLASSEX); - hclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); - hclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION); - hclass.hCursor=LoadCursor(NULL,IDC_ARROW); - hclass.lpszMenuName=NULL; - hclass.cbClsExtra=0; - hclass.cbWndExtra=0; - hclass.hbrBackground=(HBRUSH)COLOR_BACKGROUND; - - if(!RegisterClassEx(&hclass)) { - printf ("%s:%d %s Could not register VFW class\n", __FILE__, __LINE__, __FUNCTION__); - return VDEV_STATUS_ERROR; - } - first = 0; - } + // find application instance handle for later use + hinst = GetModuleHandle(NULL); + + // create and register window class + if (!CreateClass()) + return VDEV_STATUS_ERROR; + + // now create the parent window for capture devicey + // some notes: + // - the minimum possible size of 3x3 + // - 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) hwnd = CreateWindowEx(0, classNameVfW, "CameraPreview", WS_POPUPWINDOW|WS_VISIBLE, 0, 0, 3, 3, NULL, NULL, hinst, NULL); - if (hwnd == NULL) { + if (!hwnd) { printf ("%s:%d %s Could not create window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); return VDEV_STATUS_ERROR; } - ShowWindow(hwnd, SW_SHOW); - - // connect to driver + if(!ShowWindow(hwnd, SW_SHOW)) { + printf ("%s:%d %s Could not show window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); + return VDEV_STATUS_ERROR; + } + + // create capture driver window handle, also here minim size is 1x1 cap = capCreateCaptureWindow("VFW", WS_CHILD|WS_VISIBLE, 0, 0, 1, 1, hwnd, camid); if(!cap) { printf ("%s:%d %s Could not open VFW id %d window\n", __FILE__, __LINE__, __FUNCTION__, camid); return VDEV_STATUS_ERROR; } + if(!capSetCallbackOnStatus(cap, VFW_status_callback)) { + printf ("%s:%d %s Could not set status callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); + return VDEV_STATUS_ERROR; + } + if(!capSetCallbackOnError(cap, VFW_error_callback)) { + printf ("%s:%d %s Could not set error callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); + return VDEV_STATUS_ERROR; + } + + // connect to driver if(!capDriverConnect(cap, camid)) { printf ("%s:%d %s Could not connect to VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); return VDEV_STATUS_ERROR; @@ -115,9 +189,13 @@ int VideoDev_VFW::Open() { // let the callbacks know this class pointer capSetUserData(cap, this); + // set video source, capture format and size + capDlgVideoSource(cap); + capDlgVideoFormat(cap); + CAPTUREPARMS cp; if(!capCaptureGetSetup(cap, &cp, sizeof(cp))) { - printf ("%s:%d %s Could not get VFW setup\n", __FILE__, __LINE__, __FUNCTION__); + printf ("%s:%d %s Could not get VFW capture setup\n", __FILE__, __LINE__, __FUNCTION__); return VDEV_STATUS_ERROR; } cp.dwRequestMicroSecPerFrame = 33333; @@ -131,20 +209,10 @@ int VideoDev_VFW::Open() { cp.fAbortRightMouse = 0; cp.fLimitEnabled = 0; if(!capCaptureSetSetup(cap, &cp, sizeof(cp))) { - printf ("%s:%d %s Could not set VFW setup\n", __FILE__, __LINE__, __FUNCTION__); + printf ("%s:%d %s Could not set VFW capture setup\n", __FILE__, __LINE__, __FUNCTION__); return VDEV_STATUS_ERROR; } - capOverlay(cap, 0); - capPreviewRate(cap, 10); // rate in ms - capPreviewScale(cap, 0); - capPreview(cap, TRUE); - //capCaptureSequenceNoFile(cap); - - // set video source, capture format and size - capDlgVideoSource(cap); - capDlgVideoFormat(cap); - // get current valid width/height BITMAPINFO bi; int i = 0; @@ -158,14 +226,15 @@ int VideoDev_VFW::Open() { // try to set the configured width/height if(conf_width != -1) { - bi.bmiHeader.biWidth = conf_width; - bi.bmiHeader.biHeight = conf_height; + inframe_w = bi.bmiHeader.biWidth = conf_width; + inframe_h = bi.bmiHeader.biHeight = conf_height; bi.bmiHeader.biCompression = inframe_pixfmt; if(!capSetVideoFormat(cap, &bi, sizeof(BITMAPINFO))) { printf ("%s:%d %s Could not set capture size %dx%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, conf_width, conf_height, conf_format.c_str()); return VDEV_STATUS_ERROR; } } + // find out maximum resolution else { int sizes[][2] = {{320, 240}, {640, 480}, {800, 600}, {1024, 768}, {1280, 720}, {1280, 1024}, {1920, 1080}, {-1, -1}}; @@ -175,18 +244,18 @@ int VideoDev_VFW::Open() { inframe_h = bi.bmiHeader.biHeight = sizes[i][1]; bi.bmiHeader.biCompression = inframe_pixfmt; if(capSetVideoFormat(cap, &bi, sizeof(BITMAPINFO))) { - printf ("%s:%d %s Resolution %dx%d (%s) works\n", __FILE__, __LINE__, __FUNCTION__, inframe_w, inframe_h, conf_format.c_str()); - if (inframe_w >= conf_width && inframe_h >= conf_height) { - conf_width = inframe_w; - conf_height = inframe_h; - } + printf ("%s:%d %s Resolution %dx%d (%s) works\n", __FILE__, __LINE__, __FUNCTION__, inframe_w, inframe_h, conf_format.c_str()); + if (inframe_w >= conf_width && inframe_h >= conf_height) { + conf_width = inframe_w; + conf_height = inframe_h; + } } i++; } } // translate this special format to what our convert functions can work with - if(inframe_pixfmt == V4L2_PIX_FMT_YUY2) { + if (inframe_pixfmt == V4L2_PIX_FMT_YUY2) { inframe_pixfmt = V4L2_PIX_FMT_YUYV; } @@ -195,8 +264,7 @@ int VideoDev_VFW::Open() { /* - * Close Device - * Free videobuffer + * Close the device. */ int VideoDev_VFW::Close() { @@ -207,6 +275,7 @@ int VideoDev_VFW::Close() { DestroyWindow(hwnd); hwnd = cap = NULL; } + DestroyClass(); return VDEV_STATUS_OK; }; @@ -216,22 +285,21 @@ int VideoDev_VFW::Close() { * VideoGrabbing */ -LRESULT CALLBACK VFW_frame_callback(HWND h, LPVIDEOHDR v) { +/* + * The callback is run when a new frame is available. It copies the + * available data into the framebuffer of the class instance. + */ +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()); return TRUE; } -LRESULT VFW_error_callback(HWND h, int nID, LPCSTR lpsz) { - printf("%s:%d %s id=%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, nID, lpsz); - return TRUE; -} - /* - * prepare inframe for raw picture data, will hold a video frame with 16bit per channel or BGR32/BGR24 - * inframe size = 4*W*H - * send the start capture signal to the cam + * Prepare inframe for raw picture data, will hold a video frame with + * maximum size of inframe size = 4*W*H. Setup capture + * callbacks. Then send the start capture signal to the camera. */ int VideoDev_VFW::CaptureStart() { @@ -240,41 +308,53 @@ int VideoDev_VFW::CaptureStart() { // allocate memory for frame data if (inframe != NULL) free (inframe); inframe_size = 4 * inframe_w * inframe_h; - inframe = (unsigned char*) malloc(inframe_size); + inframe = (unsigned char *) malloc(inframe_size); pixelformat = inframe_pixfmt; - if(!capSetCallbackOnError(cap, VFW_error_callback)) { - printf ("%s:%d %s Could not set error callback to VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + // disable overlay + capOverlay(cap, FALSE); + +#if USE_PREVIEW + // use preview window for grabbing + capPreviewRate (cap, 10); // rate in ms + capPreviewScale (cap, FALSE); + capPreview (cap, TRUE); +#else + // otherwise use other capture + capPreview (cap, FALSE); + if(!capCaptureSequenceNoFile (cap)) { + printf ("%s:%d %s Could not start capture (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError()); + } +#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\n", __FILE__, __LINE__, __FUNCTION__, camid); - return VDEV_STATUS_ERROR; + 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 Cmould not set yield callback to VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); - return VDEV_STATUS_ERROR; + printf ("%s:%d %s Could not set yield callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError()); + //return VDEV_STATUS_ERROR; } - - if(!capSetCallbackOnFrame(cap, VFW_frame_callback)) { - printf ("%s:%d %s Could not set frame callback to VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); - return VDEV_STATUS_ERROR; - } - + return VDEV_STATUS_OK; }; /* - * free inbuffer + * Stop capture and free framebuffer. */ int VideoDev_VFW::CaptureStop() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + capCaptureAbort(cap); capSetCallbackOnError(cap, NULL); capSetCallbackOnFrame(cap, NULL); @@ -292,35 +372,47 @@ int VideoDev_VFW::CaptureStop() { }; /* - * try to grab one frame and convert it into RGB32. - * If something goes wrong return an error code. - * Return code VDEV_STATUS_AGAIN is not an error. There was no video image ready to read. + * This function needed to continue running the capture window. */ -// FIXME: SVBGetVideoData needs to be outside of Lock/UnLockMutex - using inside thread inbuffer -int VideoDev_VFW::Grab(VideoFrameRaw *vf) { +void VideoDev_VFW::HandleMessages() { + MSG msg; + while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} - MSG msg; - while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - if (inframe == NULL) return VDEV_STATUS_ERROR; +/* + * Try to grab one frame and copy it into raw video buffer. If + * something goes wrong return an error code. Return code + * VDEV_STATUS_AGAIN is not an error. There was no video image ready + * to read. + */ +int VideoDev_VFW::Grab(VideoFrameRaw *vf) { + + HandleMessages(); + if (inframe == NULL) return VDEV_STATUS_ERROR; if (GetFrameBufferSize() > 0) { LockMutex(); vf->CopyFrom(inframe_pixfmt, inframe_w, inframe_h, GetFrameBufferSize(), inframe); UnLockMutex(); } + else { + return VDEV_STATUS_AGAIN; + } return VDEV_STATUS_OK; } - +/* + * For VfW this seems difficult / impossible to obtain the supported + * video formats, but they must be selected via capDlgVideoFormat(). + */ int VideoDev_VFW::GetDeviceFormats(string device, std::list *formats) { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - return VDEV_STATUS_OK; } @@ -334,7 +426,6 @@ int VideoDev_VFW::GetDeviceFormats(string device, std::list *formats) { * set video control identified by id */ int VideoDev_VFW::SetDevCtrl(unsigned int id, int value) { - return VDEV_STATUS_OK; }; diff --git a/videodev-vfw.h b/videodev-vfw.h index 0ec3908..63d8152 100644 --- a/videodev-vfw.h +++ b/videodev-vfw.h @@ -7,14 +7,16 @@ class VideoDev_VFW: public VideoDev { private: unsigned char *inframe; - int inframe_size; + int inframe_size; int inframe_w, inframe_h; int inframe_pixfmt; - int vfw_size; + int vfw_size; ConvertData cdata; int camid; - HWND cap, hwnd; + HWND cap, hwnd; + WNDCLASSEX * hclass; + HINSTANCE hinst; int Grab(VideoFrameRaw *vf); int Open(); @@ -23,6 +25,9 @@ private: int CaptureStop(); int SetDevCtrl(unsigned int id, int value); int GetDevCtrl(unsigned int id, int *value); + int CreateClass(); + int DestroyClass(); + void HandleMessages(); void print_error(int err); public: From d7786fa8b15d9ce883ae620212209a40a0c895f6 Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Sun, 19 Feb 2023 01:46:19 +0100 Subject: [PATCH 2/6] 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 From 12c144a77acc8a531e0d4449a6c6d0273f62adaf Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Mon, 20 Feb 2023 22:37:24 +0100 Subject: [PATCH 3/6] Videodump reading now also works in Windows --- videodev-dumpfile.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/videodev-dumpfile.cc b/videodev-dumpfile.cc index 02b0e8c..2d33aff 100644 --- a/videodev-dumpfile.cc +++ b/videodev-dumpfile.cc @@ -121,7 +121,7 @@ int VideoDev_Dumpfile::Open() { } filesize = s.st_size; - if ((fd = open(fname.c_str(), O_RDONLY)) == -1) { + if ((fd = open(fname.c_str(), O_RDONLY | O_BINARY)) == -1) { printf ("%s:%d could not open file '%s' error:%s\n", __FILE__, __LINE__, fname.c_str(), strerror(errno)); return VDEV_STATUS_ERROR; } @@ -267,9 +267,8 @@ int VideoDev_Dumpfile::ReadFrame() { // // read frame if (read (fd, inbuf, 4*2) != 4*2) { - printf ("%s:%d could not read frame header\n", __FILE__, __LINE__); + printf ("%s:%d could not read frame header: %s\n", __FILE__, __LINE__, strerror(errno)); Close(); - } filepos += (4*2); inframe_size = ntohl(inbuf[0]); @@ -291,10 +290,9 @@ int VideoDev_Dumpfile::ReadFrame() { printf ("%s:%d cloud not allocate enought memory\n", __FILE__, __LINE__); return VDEV_CBSTATUS_ERROR; } - if (read (fd, inframe, inframe_size) != inframe_size) { - printf ("%s:%d could not read frame\n", __FILE__, __LINE__); - Close(); + printf ("%s:%d could not read frame: %s\n", __FILE__, __LINE__, strerror(errno)); + Close(); } filepos += inframe_size; From 94155b3ba411939a46b0753006762a1594fdd90a Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Mon, 20 Feb 2023 22:38:15 +0100 Subject: [PATCH 4/6] Reduced calibration times to 5sec from 10sec --- posctl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posctl.cc b/posctl.cc index af0a733..97d1873 100644 --- a/posctl.cc +++ b/posctl.cc @@ -60,7 +60,7 @@ void axis_history_add(int axis, double diff, double out) { } #define CALIB_MAXSPEED 1.0 -#define CALIB_DURATION_DELTA 10.0 +#define CALIB_DURATION_DELTA 5.0 #define CALIB_DURATION_AXIS (CALIB_DURATION_DELTA / CALIB_MAXSPEED) void posctl_gui_update(); From 5c05d1b7f99f2a30d7de13753e4ae08f23492a7a Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Mon, 20 Feb 2023 22:39:19 +0100 Subject: [PATCH 5/6] Removed video source / format dialog calls in the Open() function --- videodev-vfw.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/videodev-vfw.cc b/videodev-vfw.cc index b0f12ab..ef2dcdc 100644 --- a/videodev-vfw.cc +++ b/videodev-vfw.cc @@ -226,8 +226,8 @@ int VideoDev_VFW::Open() { capSetUserData(cap, this); // set video source, capture format and size - capDlgVideoSource(cap); - capDlgVideoFormat(cap); + //capDlgVideoSource(cap); + //capDlgVideoFormat(cap); CAPTUREPARMS cp; if(!capCaptureGetSetup(cap, &cp, sizeof(cp))) { @@ -426,7 +426,9 @@ void VideoDev_VFW::HandleMessages() { */ int VideoDev_VFW::Grab(VideoFrameRaw *vf) { + // Do not know exactly why, but needed to translate/dispatch window message HandleMessages(); + if (inframe == NULL) return VDEV_STATUS_ERROR; if (GetFrameBufferSize() > 0) { From bc11438ee344636a0d127abedd4b3e2843b51c0c Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Thu, 4 May 2023 20:07:11 +0200 Subject: [PATCH 6/6] linux will compile again. O_BINARY does only exist in the windows world. --- .gitignore | 1 + Makefile | 24 ++++++++++++++++++------ Makefile.config | 12 ------------ videodev-dumpfile.cc | 4 ++++ 4 files changed, 23 insertions(+), 18 deletions(-) delete mode 100644 Makefile.config diff --git a/.gitignore b/.gitignore index a6e30ac..1a0b348 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ simpleskycam *~ U2SM200C-AST_Cfg_A.bin U2SM200C-AST_Cfg_SAVE.bin +gmon.out diff --git a/Makefile b/Makefile index bf912d2..42aec55 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION = 0.0.1 APP = simpleskycam -include Makefile.config +-include Makefile.config -include Makefile.rules OBJECTS := $(OBJECTS) gui.oo main.oo error.oo debug.oo \ @@ -47,15 +47,24 @@ endif - - ifeq ($(TARGET),) -noconfig: configlinux help +noconfig: defaultconfig help endif - all: Makefile.rules $(TARGET) +defaultconfig: +ifeq ($(MAKEFILE_CONFIG),) + echo "MAKEFILE_CONFIG = 1" > Makefile.config + echo "" >> Makefile.config + echo "USE_SVBONY = 1" >> Makefile.config + echo "USE_DNG = 1" >> Makefile.config + echo "USE_SER = 1" >> Makefile.config + echo "" >> Makefile.config + echo "DEBUG_ANGLES = 0" >> Makefile.config + echo "DEBUG_POSCTL = 0" >> Makefile.config +endif + help: echo "set up configuration" echo " make configlinux to generate the linix build" @@ -148,6 +157,9 @@ $(TARGET): $(OBJECTS) .cc.oo : $(INCLUDES) $(CPP) -o $@ -c $(CPPFLAGS) $< +cleanall: clean + rm -rf Makefile.config + clean: rm -f *.o *.oo *.c~ *.h~ *.cc~ *.ui~ $(APP) Makefile~ rm -rf config.h @@ -159,7 +171,7 @@ clean: rm -rf U2SM200C-AST_Cfg_SAVE.bin rm -rf SimpleSkyCam-$(VERSION) -dist: clean +dist: cleanall rm -rf $(DISTNAME) mkdir $(DISTNAME) cp Makefile* $(DISTNAME) diff --git a/Makefile.config b/Makefile.config deleted file mode 100644 index f5defc9..0000000 --- a/Makefile.config +++ /dev/null @@ -1,12 +0,0 @@ - -# -# configurations should be made in here. -# set one of these variables to 0 to disable the function. -# -USE_SVBONY = 1 -USE_DNG = 1 -USE_SER = 1 - -DEBUG_ANGLES = 0 -DEBUG_POSCTL = 0 - diff --git a/videodev-dumpfile.cc b/videodev-dumpfile.cc index 2d33aff..7f0f98a 100644 --- a/videodev-dumpfile.cc +++ b/videodev-dumpfile.cc @@ -121,7 +121,11 @@ int VideoDev_Dumpfile::Open() { } filesize = s.st_size; +#ifdef BUILD_WINDOWS if ((fd = open(fname.c_str(), O_RDONLY | O_BINARY)) == -1) { +#else + if ((fd = open(fname.c_str(), O_RDONLY)) == -1) { +#endif printf ("%s:%d could not open file '%s' error:%s\n", __FILE__, __LINE__, fname.c_str(), strerror(errno)); return VDEV_STATUS_ERROR; }