diff --git a/videodev-vfw.cc b/videodev-vfw.cc index 872707f..0f8dfb6 100644 --- a/videodev-vfw.cc +++ b/videodev-vfw.cc @@ -23,7 +23,7 @@ VideoDev_VFW::VideoDev_VFW() { VideoDev_VFW::~VideoDev_VFW() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - // if (running > 0) CaptureStop(); + if (running > 0) CaptureStop(); } /* @@ -40,8 +40,7 @@ int VideoDev_VFW::GetDeviceList(std::list *list) { for(int i=0; i < 10; i++) if(capGetDriverDescription(i, name, sizeof(name), desc, sizeof(desc))) { std::string device; - - device = "VFW " + to_string(i) + " " + (string)name + " [" + (string)desc + "]"; + device = "VfW " + to_string(i) + " " + (string)name + " [" + (string)desc + "]"; list->push_back(device); } @@ -58,33 +57,60 @@ int VideoDev_VFW::Open() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); camid = atoi (conf_device.c_str()); - printf ("%s:%d %s opening vfw id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + printf ("%s:%d %s Opening VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); - cap = capCreateCaptureWindow("VFW", WS_CHILD, 0, 0, 0, 0, HWND_MESSAGE, camid); - if(!capDriverConnect(cap, 0)) { - printf ("%s:%d %s could not connect to vfw id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + cap = capCreateCaptureWindow("VfW", /*WS_CHILD|WS_VISIBLE*/0, 0, 0, 0, 0, 0/*HWND_MESSAGE*/, camid); + if(!cap) { + printf ("%s:%d %s Could not open VfW id %d window\n", __FILE__, __LINE__, __FUNCTION__, camid); + return VDEV_STATUS_ERROR; + } + + if(!capDriverConnect(cap, camid)) { + printf ("%s:%d %s Could not connect to VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); return VDEV_STATUS_ERROR; } capDlgVideoFormat(cap); - + + // get current valid width/height BITMAPINFO bi; + int w, h, i = 0; capGetVideoFormat(cap, &bi, sizeof(BITMAPINFO)); - conf_width = bi.bmiHeader.biWidth; - conf_height = bi.bmiHeader.biHeight; - printf ("%s:%d %s current size %dx%d\n", __FILE__, __LINE__, __FUNCTION__, conf_width, conf_height); - - conf_format = convert_from_pixelformat(bi.bmiHeader.biCompression); - printf ("%s:%d %s current format %s\n", __FILE__, __LINE__, __FUNCTION__, conf_format.c_str()); - - switch(bi.bmiHeader.biCompression) { - case MAKEFOURCC('M','J','P','G'): - inframe_pixfmt = V4L2_PIX_FMT_MJPEG; - break; - case MAKEFOURCC('Y','U','Y','2'): - inframe_pixfmt = V4L2_PIX_FMT_YUYV; - break; + w = bi.bmiHeader.biWidth; + h = bi.bmiHeader.biHeight; + printf ("%s:%d %s Current capture size is %dx%d\n", __FILE__, __LINE__, __FUNCTION__, w, h); + inframe_pixfmt = convert_to_pixelformat(conf_format); + + // try to set the configured width/height + if(conf_width != -1) { + bi.bmiHeader.biWidth = conf_width; + 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, 1024}, {1920, 1080}, {-1, -1}}; + + while(sizes[i][0] != -1) { + w = bi.bmiHeader.biWidth = sizes[i][0]; + 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__, w, h, conf_format.c_str()); + if (w >= conf_width && h >= conf_height) { + conf_width = w; + conf_height = h; + } + } + i++; + } + } + + printf ("%s:%d %s Current capture format is %s\n", __FILE__, __LINE__, __FUNCTION__, conf_format.c_str()); return VDEV_STATUS_OK; }; @@ -119,6 +145,7 @@ LRESULT CALLBACK VFW_frame_callback(HWND h, LPVIDEOHDR v) { LRESULT VFW_error_callback(HWND h, int nID, LPCSTR lpsz) { printf("error callback: %d (%s)\n", nID, lpsz); + return TRUE; } /* @@ -130,10 +157,12 @@ int VideoDev_VFW::CaptureStart() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - capSetCallbackOnError(cap, VFW_error_callback); + if(!capSetCallbackOnError(cap, VFW_error_callback)) { + printf ("%s:%d %s Could not set error callback to VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + } if(!capSetCallbackOnFrame(cap, VFW_frame_callback)) { - printf ("%s:%d %s could not set callback to vfw id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + printf ("%s:%d %s Could not set frame callback to VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); } ConvertStart(&cdata, inframe_pixfmt); @@ -150,6 +179,7 @@ int VideoDev_VFW::CaptureStop() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); capCaptureAbort(cap); + capSetCallbackOnError(cap, NULL); capSetCallbackOnFrame(cap, NULL); ConvertStop(&cdata, inframe_pixfmt); return VDEV_STATUS_OK; @@ -176,6 +206,52 @@ int VideoDev_VFW::Grab(VideoFrame *vf) { int VideoDev_VFW::GetDeviceFormats(string device, std::list *formats) { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + camid = atoi (conf_device.c_str()); + cap = capCreateCaptureWindow("VfW", /*WS_CHILD|WS_VISIBLE*/0, 0, 0, 0, 0, 0/*HWND_MESSAGE*/, camid); + if(!cap) { + printf ("%s:%d %s Could not open VfW id %d window\n", __FILE__, __LINE__, __FUNCTION__, camid); + return VDEV_STATUS_ERROR; + } + + if(!capDriverConnect(cap, camid)) { + printf ("%s:%d %s Could not connect to VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); + return VDEV_STATUS_ERROR; + } + + BITMAPINFO bi; + capGetVideoFormat(cap, &bi, sizeof(BITMAPINFO)); + + string vfwformat; + DWORD f = bi.bmiHeader.biCompression; + vfwformat = convert_from_pixelformat(f); + printf ("%s:%d %s Current capture format is %s\n", __FILE__, __LINE__, __FUNCTION__, vfwformat.c_str()); + formats->push_back(vfwformat); + +#if 0 + int i = 0; + DWORD vfwformats[][2] = {{MAKEFOURCC('M','J','P','G'), V4L2_PIX_FMT_MJPEG}, + {MAKEFOURCC('Y','U','V','2'), V4L2_PIX_FMT_YUV2}, + {0, 0}}; + + while(vfwformats[i][0] != 0) { + bi.bmiHeader.biCompression = vfwformats[i][0]; + if(capSetVideoFormat(cap, &bi, sizeof(BITMAPINFO))) { + vfwformat = convert_from_pixelformat(vfwformats[i][1]); + printf ("%s:%d %s Capture format %s works\n", __FILE__, __LINE__, __FUNCTION__, vfwformat.c_str()); + formats->push_back(vfwformat.c_str()); + } + else { + vfwformat = convert_from_pixelformat(vfwformats[i][1]); + printf ("%s:%d %s Capture format %s does not work\n", __FILE__, __LINE__, __FUNCTION__, vfwformat.c_str()); + } + i++; + } +#endif + capDriverDisconnect(cap); + cap = NULL; + camid = -1; + return VDEV_STATUS_OK; } diff --git a/windows.h b/windows.h index 0a26c9c..4f53ba7 100644 --- a/windows.h +++ b/windows.h @@ -66,6 +66,8 @@ extern void strfromd (char* dest, int len, char *fmt,...); #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_YUV2 v4l2_fourcc('Y', 'U', 'V', '2') /* ??? */ + #define v4l2_fourcc(a, b, c, d)\ ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) #define v4l2_fourcc_be(a, b, c, d) (v4l2_fourcc(a, b, c, d) | (1U << 31))