/* * module to read video data from vfw. */ #include "config.h" #include #include #include #include #include #include #include "convert.h" #include "videodev-vfw.h" VideoDev_VFW::VideoDev_VFW() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); cap = NULL; }; VideoDev_VFW::~VideoDev_VFW() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); if (running > 0) CaptureStop(); } /* * check for connected devices and return the result in a list. */ int VideoDev_VFW::GetDeviceList(std::list *list) { char name[256]; char desc[256]; printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); if (list == NULL) return VDEV_STATUS_ERROR; 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 + "]"; list->push_back(device); } return VDEV_STATUS_OK; } /* * Open Device * prepare the buffer */ 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); 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)); 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; }; /* * Close Device * Free videobuffer */ int VideoDev_VFW::Close() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); capDriverDisconnect(cap); return VDEV_STATUS_OK; }; /***************************************************************************************************** * VideoGrabbing */ int VFW_frame_size; unsigned char VFW_frame_buffer[640*480*3]; LRESULT CALLBACK VFW_frame_callback(HWND h, LPVIDEOHDR v) { VFW_frame_size = v->dwBytesUsed; printf("frame callback: %d bytes\n", VFW_frame_size); memcpy(VFW_frame_buffer, v->lpData, VFW_frame_size); return TRUE; } LRESULT VFW_error_callback(HWND h, int nID, LPCSTR lpsz) { printf("error callback: %d (%s)\n", 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 */ int VideoDev_VFW::CaptureStart() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); 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 frame callback to VfW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid); } ConvertStart(&cdata, inframe_pixfmt); return VDEV_STATUS_OK; }; /* * free inbuffer */ 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; }; /* * 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. */ // FIXME: SVBGetVideoData needs to be outside of Lock/UnLockMutex - using inside thread inbuffer int VideoDev_VFW::Grab(VideoFrame *vf) { //if (inframe == NULL) return VDEV_STATUS_ERROR; LockMutex(); Convert(&cdata, vf, VFW_frame_buffer, VFW_frame_size, inframe_pixfmt, conf_width, conf_height); UnLockMutex(); return VDEV_STATUS_OK; } 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; } /***************************************************************************************************** * Controls */ /* * set video control identified by id */ int VideoDev_VFW::SetDevCtrl(unsigned int id, int value) { return VDEV_STATUS_OK; }; /* * get video control identified by id */ int VideoDev_VFW::GetDevCtrl(unsigned int id, int *value) { return VDEV_STATUS_OK; };