Index: modules/highgui/src/cap_v4l.cpp =================================================================== --- modules/highgui/src/cap_v4l.cpp (revision 4854) +++ modules/highgui/src/cap_v4l.cpp (working copy) @@ -271,23 +271,15 @@ #endif /* HAVE_CAMV4L2 */ -enum PALETTE_TYPE { - PALETTE_BGR24 = 1, - PALETTE_YVU420, - PALETTE_YUV411P, - PALETTE_YUYV, - PALETTE_UYVY, - PALETTE_SBGGR8, - PALETTE_SN9C10X, - PALETTE_MJPEG, - PALETTE_SGBRG -}; - typedef struct CvCaptureCAM_V4L { + char* deviceName; int deviceHandle; int bufferIndex; int FirstCapture; + + int width; int height; + struct video_capability capability; struct video_window captureWindow; struct video_picture imageProperties; @@ -297,7 +289,7 @@ IplImage frame; #ifdef HAVE_CAMV4L2 - enum PALETTE_TYPE palette; + unsigned long palette; /* V4L2 variables */ buffer buffers[MAX_V4L_BUFFERS + 1]; struct v4l2_capability cap; @@ -419,8 +411,8 @@ capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; capture->form.fmt.pix.pixelformat = colorspace; capture->form.fmt.pix.field = V4L2_FIELD_ANY; - capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH; - capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT; + capture->form.fmt.pix.width = capture->width; + capture->form.fmt.pix.height = capture->height; if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) return -1; @@ -529,66 +521,51 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { - if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0) - { - capture->palette = PALETTE_BGR24; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0) - { - capture->palette = PALETTE_YVU420; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0) - { - capture->palette = PALETTE_YUV411P; - } - else + unsigned long palettes[] = {V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_YVU420, + V4L2_PIX_FMT_YUV411P, + #ifdef HAVE_JPEG + #ifdef __USE_GNU + V4L2_PIX_FMT_MJPEG, + V4L2_PIX_FMT_JPEG, + #endif + #endif + V4L2_PIX_FMT_YUYV, + V4L2_PIX_FMT_UYVY, + V4L2_PIX_FMT_SN9C10X, + V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGBRG}; + + int paletteCount = sizeof (palettes) / sizeof (unsigned long); -#ifdef HAVE_JPEG -#ifdef __USE_GNU - /* support for MJPEG is only available with libjpeg and gcc, - because it's use libjepg and fmemopen() - */ - if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 || - try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0) - { - capture->palette = PALETTE_MJPEG; - } - else -#endif -#endif - - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0) - { - capture->palette = PALETTE_YUYV; - } - else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0) - { - capture->palette = PALETTE_UYVY; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0) - { - capture->palette = PALETTE_SN9C10X; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0) - { - capture->palette = PALETTE_SBGGR8; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG) == 0) - { - capture->palette = PALETTE_SGBRG; - } - else - { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - return 0; - + unsigned long palette = capture->palette; + capture->palette = 0; + + /* if a specific format is desired */ + if (palette) { + if (try_palette_v4l2(capture, palette) == 0) { + capture->palette = palette; + return 0; + } else { + fprintf(stderr, "HIGHGUI ERROR: V4L2: Desired pixel format not supported by camera\n"); + } + } + + /* keep trying until a supported format is found */ + for (int i = 0; i < paletteCount; i++) { + palette = palettes[i]; + if (try_palette_v4l2(capture, palette) == 0) { + capture->palette = palette; + break; + } + } + + if (capture->palette == 0) { + fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); + icvCloseCAM_V4L(capture); + return -1; + } + return 0; } #endif /* HAVE_CAMV4L2 */ @@ -799,6 +776,8 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) { int detect_v4l2 = 0; + + capture->deviceName = strdup(deviceName); detect_v4l2 = try_init_v4l2(capture, deviceName); @@ -879,7 +858,7 @@ if (autosetup_capture_mode_v4l2(capture) == -1) return -1; - icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); + icvSetVideoSize(capture, capture->width, capture->height); unsigned int min; @@ -1130,6 +1109,12 @@ fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n"); return NULL; } + + /* initialize format */ + capture->width = DEFAULT_V4L_WIDTH; + capture->height = DEFAULT_V4L_HEIGHT; + capture->palette = 0; + /* Select camera, or rather, V4L video source */ if (index<0) { // Asking for the first device available for (; autoindexpalette) { - case PALETTE_BGR24: + case V4L2_PIX_FMT_BGR24: memcpy((char *)capture->frame.imageData, (char *)capture->buffers[capture->bufferIndex].start, capture->frame.imageSize); break; - case PALETTE_YVU420: + case V4L2_PIX_FMT_YVU420: yuv420p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_YUV411P: + case V4L2_PIX_FMT_YUV411P: yuv411p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), @@ -2149,7 +2134,8 @@ /* support for MJPEG is only available with libjpeg and gcc, because it's use libjepg and fmemopen() */ - case PALETTE_MJPEG: + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: if (!mjpeg_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex] @@ -2161,27 +2147,27 @@ #endif #endif - case PALETTE_YUYV: + case V4L2_PIX_FMT_YUYV: yuyv_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_UYVY: + case V4L2_PIX_FMT_UYVY: uyvy_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_SBGGR8: + case V4L2_PIX_FMT_SBGGR8: bayer2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[capture->bufferIndex].start, (unsigned char*)capture->frame.imageData); break; - case PALETTE_SN9C10X: + case V4L2_PIX_FMT_SN9C10X: sonix_decompress_init(); sonix_decompress(capture->form.fmt.pix.width, capture->form.fmt.pix.height, @@ -2194,7 +2180,7 @@ (unsigned char*)capture->frame.imageData); break; - case PALETTE_SGBRG: + case V4L2_PIX_FMT_SGBRG: sgbrg2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, @@ -2267,6 +2253,8 @@ return capture->form.fmt.pix.width; case CV_CAP_PROP_FRAME_HEIGHT: return capture->form.fmt.pix.height; + case CV_CAP_PROP_FORMAT: + return capture->form.fmt.pix.pixelformat; } /* initialize the control structure */ @@ -2456,8 +2444,10 @@ * don't test if the set of the size is ok, because some device * don't allow changing the size, and we will get the real size * later */ - xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form); - + if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) { + perror("VIDIOC_S_FMT"); + } + /* try to set framerate to 30 fps */ struct v4l2_streamparm setfps; memset (&setfps, 0, sizeof(struct v4l2_streamparm)); @@ -2708,18 +2698,46 @@ switch (property_id) { case CV_CAP_PROP_FRAME_WIDTH: width = cvRound(value); - if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->width = width; + + if (width !=0 && height != 0) { + char deviceName[MAX_DEVICE_DRIVER_NAME]; + sprintf(deviceName, "%s", capture->deviceName); + icvCloseCAM_V4L(capture); + _capture_V4L2(capture, deviceName); width = height = 0; + retval = 0; } + retval = -1; break; case CV_CAP_PROP_FRAME_HEIGHT: height = cvRound(value); - if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->height = height; + + if (width !=0 && height != 0) { + char deviceName[MAX_DEVICE_DRIVER_NAME]; + sprintf(deviceName, "%s", capture->deviceName); + icvCloseCAM_V4L(capture); + _capture_V4L2(capture, deviceName); width = height = 0; + retval = 0; } + retval = -1; break; + case CV_CAP_PROP_FORMAT: + capture->palette = value; + char deviceName[MAX_DEVICE_DRIVER_NAME]; + sprintf(deviceName, "%s", capture->deviceName); + icvCloseCAM_V4L(capture); + _capture_V4L2(capture, deviceName); + + if (value == capture->form.fmt.pix.pixelformat) { + retval = 0; + } else { + retval = -1; + } + + break; case CV_CAP_PROP_BRIGHTNESS: case CV_CAP_PROP_CONTRAST: case CV_CAP_PROP_SATURATION: