271 |
271 |
|
272 |
272 |
#endif /* HAVE_CAMV4L2 */
|
273 |
273 |
|
274 |
|
enum PALETTE_TYPE {
|
275 |
|
PALETTE_BGR24 = 1,
|
276 |
|
PALETTE_YVU420,
|
277 |
|
PALETTE_YUV411P,
|
278 |
|
PALETTE_YUYV,
|
279 |
|
PALETTE_UYVY,
|
280 |
|
PALETTE_SBGGR8,
|
281 |
|
PALETTE_SN9C10X,
|
282 |
|
PALETTE_MJPEG,
|
283 |
|
PALETTE_SGBRG
|
284 |
|
};
|
285 |
|
|
286 |
274 |
typedef struct CvCaptureCAM_V4L
|
287 |
275 |
{
|
|
276 |
char* deviceName;
|
288 |
277 |
int deviceHandle;
|
289 |
278 |
int bufferIndex;
|
290 |
279 |
int FirstCapture;
|
|
280 |
|
|
281 |
int width; int height;
|
|
282 |
|
291 |
283 |
struct video_capability capability;
|
292 |
284 |
struct video_window captureWindow;
|
293 |
285 |
struct video_picture imageProperties;
|
... | ... | |
297 |
289 |
IplImage frame;
|
298 |
290 |
|
299 |
291 |
#ifdef HAVE_CAMV4L2
|
300 |
|
enum PALETTE_TYPE palette;
|
|
292 |
unsigned long palette;
|
301 |
293 |
/* V4L2 variables */
|
302 |
294 |
buffer buffers[MAX_V4L_BUFFERS + 1];
|
303 |
295 |
struct v4l2_capability cap;
|
... | ... | |
419 |
411 |
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
420 |
412 |
capture->form.fmt.pix.pixelformat = colorspace;
|
421 |
413 |
capture->form.fmt.pix.field = V4L2_FIELD_ANY;
|
422 |
|
capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
|
423 |
|
capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
|
|
414 |
capture->form.fmt.pix.width = capture->width;
|
|
415 |
capture->form.fmt.pix.height = capture->height;
|
424 |
416 |
|
425 |
417 |
if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
|
426 |
418 |
return -1;
|
... | ... | |
529 |
521 |
|
530 |
522 |
static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture)
|
531 |
523 |
{
|
532 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0)
|
533 |
|
{
|
534 |
|
capture->palette = PALETTE_BGR24;
|
535 |
|
}
|
536 |
|
else
|
537 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0)
|
538 |
|
{
|
539 |
|
capture->palette = PALETTE_YVU420;
|
540 |
|
}
|
541 |
|
else
|
542 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0)
|
543 |
|
{
|
544 |
|
capture->palette = PALETTE_YUV411P;
|
545 |
|
}
|
546 |
|
else
|
|
524 |
unsigned long palettes[] = {V4L2_PIX_FMT_BGR24,
|
|
525 |
V4L2_PIX_FMT_YVU420,
|
|
526 |
V4L2_PIX_FMT_YUV411P,
|
|
527 |
#ifdef HAVE_JPEG
|
|
528 |
#ifdef __USE_GNU
|
|
529 |
V4L2_PIX_FMT_MJPEG,
|
|
530 |
V4L2_PIX_FMT_JPEG,
|
|
531 |
#endif
|
|
532 |
#endif
|
|
533 |
V4L2_PIX_FMT_YUYV,
|
|
534 |
V4L2_PIX_FMT_UYVY,
|
|
535 |
V4L2_PIX_FMT_SN9C10X,
|
|
536 |
V4L2_PIX_FMT_SBGGR8,
|
|
537 |
V4L2_PIX_FMT_SGBRG};
|
|
538 |
|
|
539 |
int paletteCount = sizeof (palettes) / sizeof (unsigned long);
|
547 |
540 |
|
548 |
|
#ifdef HAVE_JPEG
|
549 |
|
#ifdef __USE_GNU
|
550 |
|
/* support for MJPEG is only available with libjpeg and gcc,
|
551 |
|
because it's use libjepg and fmemopen()
|
552 |
|
*/
|
553 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 ||
|
554 |
|
try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0)
|
555 |
|
{
|
556 |
|
capture->palette = PALETTE_MJPEG;
|
557 |
|
}
|
558 |
|
else
|
559 |
|
#endif
|
560 |
|
#endif
|
561 |
|
|
562 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0)
|
563 |
|
{
|
564 |
|
capture->palette = PALETTE_YUYV;
|
565 |
|
}
|
566 |
|
else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0)
|
567 |
|
{
|
568 |
|
capture->palette = PALETTE_UYVY;
|
569 |
|
}
|
570 |
|
else
|
571 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0)
|
572 |
|
{
|
573 |
|
capture->palette = PALETTE_SN9C10X;
|
574 |
|
} else
|
575 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0)
|
576 |
|
{
|
577 |
|
capture->palette = PALETTE_SBGGR8;
|
578 |
|
} else
|
579 |
|
if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG) == 0)
|
580 |
|
{
|
581 |
|
capture->palette = PALETTE_SGBRG;
|
582 |
|
}
|
583 |
|
else
|
584 |
|
{
|
585 |
|
fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
|
586 |
|
icvCloseCAM_V4L(capture);
|
587 |
|
return -1;
|
588 |
|
}
|
589 |
|
|
590 |
|
return 0;
|
591 |
|
|
|
541 |
unsigned long palette = capture->palette;
|
|
542 |
capture->palette = 0;
|
|
543 |
|
|
544 |
/* if a specific format is desired */
|
|
545 |
if (palette) {
|
|
546 |
if (try_palette_v4l2(capture, palette) == 0) {
|
|
547 |
capture->palette = palette;
|
|
548 |
return 0;
|
|
549 |
} else {
|
|
550 |
fprintf(stderr, "HIGHGUI ERROR: V4L2: Desired pixel format not supported by camera\n");
|
|
551 |
}
|
|
552 |
}
|
|
553 |
|
|
554 |
/* keep trying until a supported format is found */
|
|
555 |
for (int i = 0; i < paletteCount; i++) {
|
|
556 |
palette = palettes[i];
|
|
557 |
if (try_palette_v4l2(capture, palette) == 0) {
|
|
558 |
capture->palette = palette;
|
|
559 |
break;
|
|
560 |
}
|
|
561 |
}
|
|
562 |
|
|
563 |
if (capture->palette == 0) {
|
|
564 |
fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
|
|
565 |
icvCloseCAM_V4L(capture);
|
|
566 |
return -1;
|
|
567 |
}
|
|
568 |
return 0;
|
592 |
569 |
}
|
593 |
570 |
|
594 |
571 |
#endif /* HAVE_CAMV4L2 */
|
... | ... | |
799 |
776 |
static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
|
800 |
777 |
{
|
801 |
778 |
int detect_v4l2 = 0;
|
|
779 |
|
|
780 |
capture->deviceName = strdup(deviceName);
|
802 |
781 |
|
803 |
782 |
detect_v4l2 = try_init_v4l2(capture, deviceName);
|
804 |
783 |
|
... | ... | |
879 |
858 |
if (autosetup_capture_mode_v4l2(capture) == -1)
|
880 |
859 |
return -1;
|
881 |
860 |
|
882 |
|
icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
|
|
861 |
icvSetVideoSize(capture, capture->width, capture->height);
|
883 |
862 |
|
884 |
863 |
unsigned int min;
|
885 |
864 |
|
... | ... | |
1130 |
1109 |
fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
|
1131 |
1110 |
return NULL;
|
1132 |
1111 |
}
|
|
1112 |
|
|
1113 |
/* initialize format */
|
|
1114 |
capture->width = DEFAULT_V4L_WIDTH;
|
|
1115 |
capture->height = DEFAULT_V4L_HEIGHT;
|
|
1116 |
capture->palette = 0;
|
|
1117 |
|
1133 |
1118 |
/* Select camera, or rather, V4L video source */
|
1134 |
1119 |
if (index<0) { // Asking for the first device available
|
1135 |
1120 |
for (; autoindex<MAX_CAMERAS;autoindex++)
|
... | ... | |
2125 |
2110 |
{
|
2126 |
2111 |
switch (capture->palette)
|
2127 |
2112 |
{
|
2128 |
|
case PALETTE_BGR24:
|
|
2113 |
case V4L2_PIX_FMT_BGR24:
|
2129 |
2114 |
memcpy((char *)capture->frame.imageData,
|
2130 |
2115 |
(char *)capture->buffers[capture->bufferIndex].start,
|
2131 |
2116 |
capture->frame.imageSize);
|
2132 |
2117 |
break;
|
2133 |
2118 |
|
2134 |
|
case PALETTE_YVU420:
|
|
2119 |
case V4L2_PIX_FMT_YVU420:
|
2135 |
2120 |
yuv420p_to_rgb24(capture->form.fmt.pix.width,
|
2136 |
2121 |
capture->form.fmt.pix.height,
|
2137 |
2122 |
(unsigned char*)(capture->buffers[capture->bufferIndex].start),
|
2138 |
2123 |
(unsigned char*)capture->frame.imageData);
|
2139 |
2124 |
break;
|
2140 |
2125 |
|
2141 |
|
case PALETTE_YUV411P:
|
|
2126 |
case V4L2_PIX_FMT_YUV411P:
|
2142 |
2127 |
yuv411p_to_rgb24(capture->form.fmt.pix.width,
|
2143 |
2128 |
capture->form.fmt.pix.height,
|
2144 |
2129 |
(unsigned char*)(capture->buffers[capture->bufferIndex].start),
|
... | ... | |
2149 |
2134 |
/* support for MJPEG is only available with libjpeg and gcc,
|
2150 |
2135 |
because it's use libjepg and fmemopen()
|
2151 |
2136 |
*/
|
2152 |
|
case PALETTE_MJPEG:
|
|
2137 |
case V4L2_PIX_FMT_MJPEG:
|
|
2138 |
case V4L2_PIX_FMT_JPEG:
|
2153 |
2139 |
if (!mjpeg_to_rgb24(capture->form.fmt.pix.width,
|
2154 |
2140 |
capture->form.fmt.pix.height,
|
2155 |
2141 |
(unsigned char*)(capture->buffers[capture->bufferIndex]
|
... | ... | |
2161 |
2147 |
#endif
|
2162 |
2148 |
#endif
|
2163 |
2149 |
|
2164 |
|
case PALETTE_YUYV:
|
|
2150 |
case V4L2_PIX_FMT_YUYV:
|
2165 |
2151 |
yuyv_to_rgb24(capture->form.fmt.pix.width,
|
2166 |
2152 |
capture->form.fmt.pix.height,
|
2167 |
2153 |
(unsigned char*)(capture->buffers[capture->bufferIndex].start),
|
2168 |
2154 |
(unsigned char*)capture->frame.imageData);
|
2169 |
2155 |
break;
|
2170 |
2156 |
|
2171 |
|
case PALETTE_UYVY:
|
|
2157 |
case V4L2_PIX_FMT_UYVY:
|
2172 |
2158 |
uyvy_to_rgb24(capture->form.fmt.pix.width,
|
2173 |
2159 |
capture->form.fmt.pix.height,
|
2174 |
2160 |
(unsigned char*)(capture->buffers[capture->bufferIndex].start),
|
2175 |
2161 |
(unsigned char*)capture->frame.imageData);
|
2176 |
2162 |
break;
|
2177 |
|
case PALETTE_SBGGR8:
|
|
2163 |
case V4L2_PIX_FMT_SBGGR8:
|
2178 |
2164 |
bayer2rgb24(capture->form.fmt.pix.width,
|
2179 |
2165 |
capture->form.fmt.pix.height,
|
2180 |
2166 |
(unsigned char*)capture->buffers[capture->bufferIndex].start,
|
2181 |
2167 |
(unsigned char*)capture->frame.imageData);
|
2182 |
2168 |
break;
|
2183 |
2169 |
|
2184 |
|
case PALETTE_SN9C10X:
|
|
2170 |
case V4L2_PIX_FMT_SN9C10X:
|
2185 |
2171 |
sonix_decompress_init();
|
2186 |
2172 |
sonix_decompress(capture->form.fmt.pix.width,
|
2187 |
2173 |
capture->form.fmt.pix.height,
|
... | ... | |
2194 |
2180 |
(unsigned char*)capture->frame.imageData);
|
2195 |
2181 |
break;
|
2196 |
2182 |
|
2197 |
|
case PALETTE_SGBRG:
|
|
2183 |
case V4L2_PIX_FMT_SGBRG:
|
2198 |
2184 |
sgbrg2rgb24(capture->form.fmt.pix.width,
|
2199 |
2185 |
capture->form.fmt.pix.height,
|
2200 |
2186 |
(unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
|
... | ... | |
2267 |
2253 |
return capture->form.fmt.pix.width;
|
2268 |
2254 |
case CV_CAP_PROP_FRAME_HEIGHT:
|
2269 |
2255 |
return capture->form.fmt.pix.height;
|
|
2256 |
case CV_CAP_PROP_FORMAT:
|
|
2257 |
return capture->form.fmt.pix.pixelformat;
|
2270 |
2258 |
}
|
2271 |
2259 |
|
2272 |
2260 |
/* initialize the control structure */
|
... | ... | |
2456 |
2444 |
* don't test if the set of the size is ok, because some device
|
2457 |
2445 |
* don't allow changing the size, and we will get the real size
|
2458 |
2446 |
* later */
|
2459 |
|
xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
|
2460 |
|
|
|
2447 |
if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
|
|
2448 |
perror("VIDIOC_S_FMT");
|
|
2449 |
}
|
|
2450 |
|
2461 |
2451 |
/* try to set framerate to 30 fps */
|
2462 |
2452 |
struct v4l2_streamparm setfps;
|
2463 |
2453 |
memset (&setfps, 0, sizeof(struct v4l2_streamparm));
|
... | ... | |
2708 |
2698 |
switch (property_id) {
|
2709 |
2699 |
case CV_CAP_PROP_FRAME_WIDTH:
|
2710 |
2700 |
width = cvRound(value);
|
2711 |
|
if(width !=0 && height != 0) {
|
2712 |
|
retval = icvSetVideoSize( capture, width, height);
|
|
2701 |
capture->width = width;
|
|
2702 |
|
|
2703 |
if (width !=0 && height != 0) {
|
|
2704 |
char deviceName[MAX_DEVICE_DRIVER_NAME];
|
|
2705 |
sprintf(deviceName, "%s", capture->deviceName);
|
|
2706 |
icvCloseCAM_V4L(capture);
|
|
2707 |
_capture_V4L2(capture, deviceName);
|
2713 |
2708 |
width = height = 0;
|
|
2709 |
retval = 0;
|
2714 |
2710 |
}
|
|
2711 |
retval = -1;
|
2715 |
2712 |
break;
|
2716 |
2713 |
case CV_CAP_PROP_FRAME_HEIGHT:
|
2717 |
2714 |
height = cvRound(value);
|
2718 |
|
if(width !=0 && height != 0) {
|
2719 |
|
retval = icvSetVideoSize( capture, width, height);
|
|
2715 |
capture->height = height;
|
|
2716 |
|
|
2717 |
if (width !=0 && height != 0) {
|
|
2718 |
char deviceName[MAX_DEVICE_DRIVER_NAME];
|
|
2719 |
sprintf(deviceName, "%s", capture->deviceName);
|
|
2720 |
icvCloseCAM_V4L(capture);
|
|
2721 |
_capture_V4L2(capture, deviceName);
|
2720 |
2722 |
width = height = 0;
|
|
2723 |
retval = 0;
|
2721 |
2724 |
}
|
|
2725 |
retval = -1;
|
2722 |
2726 |
break;
|
|
2727 |
case CV_CAP_PROP_FORMAT:
|
|
2728 |
capture->palette = value;
|
|
2729 |
char deviceName[MAX_DEVICE_DRIVER_NAME];
|
|
2730 |
sprintf(deviceName, "%s", capture->deviceName);
|
|
2731 |
icvCloseCAM_V4L(capture);
|
|
2732 |
_capture_V4L2(capture, deviceName);
|
|
2733 |
|
|
2734 |
if (value == capture->form.fmt.pix.pixelformat) {
|
|
2735 |
retval = 0;
|
|
2736 |
} else {
|
|
2737 |
retval = -1;
|
|
2738 |
}
|
|
2739 |
|
|
2740 |
break;
|
2723 |
2741 |
case CV_CAP_PROP_BRIGHTNESS:
|
2724 |
2742 |
case CV_CAP_PROP_CONTRAST:
|
2725 |
2743 |
case CV_CAP_PROP_SATURATION:
|