From a581ddd896275587d52af7000e41441eb2ffd444 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 24 Oct 2015 01:45:44 +0200 Subject: [PATCH 1/8] remove support of Video4Linux1 API the last kernel that allowed compiling this code was 2.6.37 which was released almost 5 Years ago. So probably it does not get much testing any more. Furthermore even back then one was better off using the V4L2 API. The only change touching currently used code is the removal of the global V4L2_SUPPORT variable. --- modules/videoio/CMakeLists.txt | 2 +- modules/videoio/src/cap_v4l.cpp | 658 +------------------------------- 2 files changed, 8 insertions(+), 652 deletions(-) diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 9e91a8a60f..77a37da7d5 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -101,7 +101,7 @@ endif(HAVE_UNICAP) if(HAVE_LIBV4L) list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_libv4l.cpp) -elseif(HAVE_CAMV4L OR HAVE_CAMV4L2 OR HAVE_VIDEOIO) +elseif(HAVE_CAMV4L2 OR HAVE_VIDEOIO) list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_v4l.cpp) endif() diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index fc9f6e06a8..0643e238eb 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -209,7 +209,7 @@ make & enjoy! #include "precomp.hpp" -#if !defined WIN32 && (defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) +#if !defined WIN32 && (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) #define CLEAR(x) memset (&(x), 0, sizeof (x)) @@ -221,10 +221,6 @@ make & enjoy! #include #include -#ifdef HAVE_CAMV4L -#include -#endif - #include #include #include @@ -237,8 +233,8 @@ make & enjoy! #endif #ifdef HAVE_VIDEOIO +// NetBSD compability layer with V4L2 #include -#define HAVE_CAMV4L2 #endif /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */ @@ -260,9 +256,6 @@ make & enjoy! #define MAX_DEVICE_DRIVER_NAME 80 /* Device Capture Objects */ - -#ifdef HAVE_CAMV4L2 - /* V4L2 structure */ struct buffer { @@ -272,24 +265,15 @@ struct buffer static unsigned int n_buffers = 0; -#endif /* HAVE_CAMV4L2 */ - typedef struct CvCaptureCAM_V4L { int deviceHandle; int bufferIndex; int FirstCapture; -#ifdef HAVE_CAMV4L - struct video_capability capability; - struct video_window captureWindow; - struct video_picture imageProperties; - struct video_mbuf memoryBuffer; - struct video_mmap *mmaps; -#endif /* HAVE_CAMV4L */ + char *memoryMap; IplImage frame; -#ifdef HAVE_CAMV4L2 __u32 palette; int index; int width, height; @@ -336,17 +320,10 @@ typedef struct CvCaptureCAM_V4L return cv::Range(0, 255); } } -#endif /* HAVE_CAMV4L2 */ } CvCaptureCAM_V4L; -#ifdef HAVE_CAMV4L2 - -int V4L2_SUPPORT = 0; - -#endif /* HAVE_CAMV4L2 */ - static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ); static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture ); @@ -390,29 +367,6 @@ static void icvInitCapture_V4L() { }; /* End icvInitCapture_V4L */ -#ifdef HAVE_CAMV4L - -static int -try_palette(int fd, - struct video_picture *cam_pic, - int pal, - int depth) -{ - cam_pic->palette = pal; - cam_pic->depth = depth; - if (ioctl(fd, VIDIOCSPICT, cam_pic) < 0) - return 0; - if (ioctl(fd, VIDIOCGPICT, cam_pic) < 0) - return 0; - if (cam_pic->palette == pal) - return 1; - return 0; -} - -#endif /* HAVE_CAMV4L */ - -#ifdef HAVE_CAMV4L2 - static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) { CLEAR (capture->form); @@ -429,54 +383,6 @@ static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) return capture->palette == capture->form.fmt.pix.pixelformat; } -#endif /* HAVE_CAMV4L2 */ - -#ifdef HAVE_CAMV4L - -static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName) -{ - - // if detect = -1 then unable to open device - // if detect = 0 then detected nothing - // if detect = 1 then V4L device - int detect = 0; - - - // Test device for V4L compability - - /* Test using an open to see if this new device name really does exists. */ - /* No matter what the name - it still must be opened! */ - capture->deviceHandle = open(deviceName, O_RDWR); - - if (capture->deviceHandle == 0) - { - detect = -1; - - icvCloseCAM_V4L(capture); - } - - if (detect == 0) - { - /* Query the newly opened device for its capabilities */ - if (ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0) - { - detect = 0; - icvCloseCAM_V4L(capture); - } - else - { - detect = 1; - } - } - - return detect; - -} - -#endif /* HAVE_CAMV4L */ - -#ifdef HAVE_CAMV4L2 - static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) { // Test device for V4L2 compability @@ -564,47 +470,6 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { return -1; } -#endif /* HAVE_CAMV4L2 */ - -#ifdef HAVE_CAMV4L - -static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture) -{ - - if(ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - /* Yet MORE things that might have to be changes with your frame capture card */ - /* This sets the scale to the center of a 2^16 number */ - if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_RGB24, 24)) { - //printf("negotiated palette RGB24\n"); - } - else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420P, 16)) { - //printf("negotiated palette YUV420P\n"); - } - else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420, 16)) { - //printf("negotiated palette YUV420\n"); - } - else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV411P, 16)) { - //printf("negotiated palette YUV420P\n"); - } - else { - fprintf(stderr, "VIDEOIO ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - return 0; - -} - -#endif /* HAVE_CAMV4L */ - -#ifdef HAVE_CAMV4L2 - static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id) { CLEAR (cap->queryctrl); @@ -725,9 +590,6 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) return -1; } - /* starting from here, we assume we are in V4L2 mode */ - V4L2_SUPPORT = 1; - /* V4L2 control variables are zero (memset above) */ /* Scan V4L2 controls */ @@ -887,130 +749,6 @@ static int v4l2_reset( CvCaptureCAM_V4L* capture) { return _capture_V4L2(capture); } -#endif /* HAVE_CAMV4L2 */ - -#ifdef HAVE_CAMV4L - -static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) -{ - int detect_v4l = 0; - - detect_v4l = try_init_v4l(capture, deviceName); - - if ((detect_v4l == -1) - ) - { - fprintf (stderr, "VIDEOIO ERROR: V4L" - ": device %s: Unable to open for READ ONLY\n", deviceName); - - return -1; - } - - if ((detect_v4l <= 0) - ) - { - fprintf (stderr, "VIDEOIO ERROR: V4L" - ": device %s: Unable to query number of channels\n", deviceName); - - return -1; - } - - { - if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) { - /* Nope. */ - fprintf( stderr, "VIDEOIO ERROR: V4L: " - "device %s is unable to capture video memory.\n",deviceName); - icvCloseCAM_V4L(capture); - return -1; - } - - } - - - /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources - have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1. - I myself am using a simple NTSC video input capture card that uses the value of 1. - If you are not in North America or have a different video standard, you WILL have to change - the following settings and recompile/reinstall. This set of settings is based on - the most commonly encountered input video source types (like my bttv card) */ - - { - - if(capture->capability.channels>0) { - - struct video_channel selectedChannel; - memset(&selectedChannel, 0, sizeof(selectedChannel)); - - selectedChannel.channel=CHANNEL_NUMBER; - if (ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) { - /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */ -// selectedChannel.norm = VIDEO_MODE_NTSC; - if (ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) { - /* Could not set selected channel - Oh well */ - //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name); - } /* End if */ - } /* End if */ - } /* End if */ - - } - - { - - if(ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) { - fprintf( stderr, "VIDEOIO ERROR: V4L: " - "Could not obtain specifics of capture window.\n\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - } - - { - - if (autosetup_capture_mode_v4l(capture) == -1) - return -1; - - } - - { - - ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer); - capture->memoryMap = (char *)mmap(0, - capture->memoryBuffer.size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - capture->deviceHandle, - 0); - if (capture->memoryMap == MAP_FAILED) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno)); - icvCloseCAM_V4L(capture); - } - - /* Set up video_mmap structure pointing to this memory mapped area so each image may be - retrieved from an index value */ - capture->mmaps = (struct video_mmap *) - (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap))); - if (!capture->mmaps) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - } - - /* Set up Image data */ - cvInitImageHeader( &capture->frame, - cvSize( capture->captureWindow.width, - capture->captureWindow.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - /* Allocate space for RGBA data */ - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); - - return 1; -}; /* End _capture_V4L */ - -#endif /* HAVE_CAMV4L */ - static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) { static int autoindex; @@ -1051,8 +789,6 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) /* Present the routines needed for V4L funtionality. They are inserted as part of the standard set of cv calls promoting transparency. "Vector Table" insertion. */ capture->FirstCapture = 1; - -#ifdef HAVE_CAMV4L2 capture->width = DEFAULT_V4L_WIDTH; capture->height = DEFAULT_V4L_HEIGHT; capture->fps = DEFAULT_V4L_FPS; @@ -1060,27 +796,11 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) if (_capture_V4L2 (capture) == -1) { icvCloseCAM_V4L(capture); - V4L2_SUPPORT = 0; -#endif /* HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - char deviceName[MAX_DEVICE_DRIVER_NAME]; - /* Print the CameraNumber at the end of the string with a width of one character */ - sprintf(deviceName, "/dev/video%1d", capture->index); - - if (_capture_V4L (capture, deviceName) == -1) { - icvCloseCAM_V4L(capture); - return NULL; - } -#endif /* HAVE_CAMV4L */ -#ifdef HAVE_CAMV4L2 } -#endif /* HAVE_CAMV4L2 */ return capture; }; /* End icvOpenCAM_V4L */ -#ifdef HAVE_CAMV4L2 - static int read_frame_v4l2(CvCaptureCAM_V4L* capture) { struct v4l2_buffer buf; @@ -1169,21 +889,13 @@ static void mainloop_v4l2(CvCaptureCAM_V4L* capture) { } } -#endif /* HAVE_CAMV4L2 */ - static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { - if (capture->FirstCapture) { /* Some general initialization must take place the first time through */ /* This is just a technicality, but all buffers must be filled up before any staggered SYNC is applied. SO, filler up. (see V4L HowTo) */ -#ifdef HAVE_CAMV4L2 - -#ifdef HAVE_CAMV4L - if (V4L2_SUPPORT == 1) -#endif { for (capture->bufferIndex = 0; @@ -1214,77 +926,18 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { return 0; } } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - for (capture->bufferIndex = 0; - capture->bufferIndex < (capture->memoryBuffer.frames-1); - ++capture->bufferIndex) { - capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex; - capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width; - capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height; - capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette; - - if (ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n"); - return 0; - } - } - - } -#endif /* HAVE_CAMV4L */ - -#if defined(V4L_ABORT_BADJPEG) && defined(HAVE_CAMV4L2) - if (V4L2_SUPPORT == 1) - { +#if defined(V4L_ABORT_BADJPEG) // skip first frame. it is often bad -- this is unnotied in traditional apps, // but could be fatal if bad jpeg is enabled mainloop_v4l2(capture); - } #endif /* preparation is ok */ capture->FirstCapture = 0; } -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { - - mainloop_v4l2(capture); - - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex; - capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width; - capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height; - capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette; - - if (ioctl (capture->deviceHandle, VIDIOCMCAPTURE, - &capture->mmaps[capture->bufferIndex]) == -1) { - /* capture is on the way, so just exit */ - return 1; - } - - ++capture->bufferIndex; - if (capture->bufferIndex == capture->memoryBuffer.frames) { - capture->bufferIndex = 0; - } - - } -#endif /* HAVE_CAMV4L */ + mainloop_v4l2(capture); return(1); } @@ -1441,63 +1094,6 @@ yuv420p_to_rgb24(int width, int height, } } -// Consider a YUV420 image of 6x2 pixels. -// -// A B C D U1 U2 -// I J K L V1 V2 -// -// The U1/V1 samples correspond to the ABIJ pixels. -// U2/V2 samples correspond to the CDKL pixels. -// -/* Converts from interlaced YUV420 to RGB24. */ -/* [FD] untested... */ -#ifdef HAVE_CAMV4L -static void -yuv420_to_rgb24(int width, int height, - unsigned char *pIn0, unsigned char *pOut0) -{ - const int bytes = 24 >> 3; - int i, j, y00, y01, y10, y11, u, v; - unsigned char *pY = pIn0; - unsigned char *pU = pY + 4; - unsigned char *pV = pU + width; - unsigned char *pOut = pOut0; - - for (j = 0; j <= height - 2; j += 2) { - for (i = 0; i <= width - 4; i += 4) { - y00 = *pY; - y01 = *(pY + 1); - y10 = *(pY + width); - y11 = *(pY + width + 1); - u = (*pU++) - 128; - v = (*pV++) - 128; - - move_420_block(y00, y01, y10, y11, u, v, - width, pOut); - - pY += 2; - pOut += 2 * bytes; - - y00 = *pY; - y01 = *(pY + 1); - y10 = *(pY + width); - y11 = *(pY + width + 1); - u = (*pU++) - 128; - v = (*pV++) - 128; - - move_420_block(y00, y01, y10, y11, u, v, - width, pOut); - - pY += 4; // skip UV - pOut += 2 * bytes; - - } - pY += width; - pOut += width * bytes; - } -} -#endif //HAVE_CAMV4L - // Consider a YUV411P image of 8x2 pixels. // // A plane of Y values as before. @@ -1549,7 +1145,6 @@ yuv411p_to_rgb24(int width, int height, #define SAT(c) \ if (c & (~255)) { if (c < 0) c = 0; else c = 255; } -#ifdef HAVE_CAMV4L2 static void yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) { using namespace cv; @@ -1602,8 +1197,6 @@ uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) } } } -#endif //HAVE_CAMV4L2 - #ifdef HAVE_JPEG /* convert from mjpeg to rgb24 */ @@ -1624,8 +1217,6 @@ mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* * Takafumi Mizuno * */ - -#ifdef HAVE_CAMV4L2 static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst) { long int i; @@ -1969,30 +1560,9 @@ static int sonix_decompress(int width, int height, unsigned char *inp, unsigned return 0; } -#endif //HAVE_CAMV4L2 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { - -#ifdef HAVE_CAMV4L2 -#ifdef HAVE_CAMV4L - if (V4L2_SUPPORT == 0) - { - /* [FD] this really belongs here */ - if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); - } - } -#endif /* HAVE_CAMV4L */ -#endif /* HAVE_CAMV4L2 */ - - /* Now get what has already been captured as a IplImage return */ - - /* First, reallocate imageData if the frame size changed */ - -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { + /* Now get what has already been captured as a IplImage return */ // we need memory iff convert_rgb is true bool recreate_frame = capture->frame_allocated != capture->convert_rgb; @@ -2008,31 +1578,6 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { v4l2_create_frame(capture); } - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - if((capture->frame.width != capture->mmaps[capture->bufferIndex].width) - || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) { - cvFree(&capture->frame.imageData); - cvInitImageHeader( &capture->frame, - cvSize( capture->captureWindow.width, - capture->captureWindow.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); - } - - } -#endif /* HAVE_CAMV4L */ - -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { if(!capture->convert_rgb) { capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start; return &capture->frame; @@ -2117,56 +1662,12 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)capture->frame.imageData); break; } - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - switch(capture->imageProperties.palette) - { - case VIDEO_PALETTE_RGB24: - memcpy((char *)capture->frame.imageData, - (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]), - capture->frame.imageSize); - break; - case VIDEO_PALETTE_YUV420P: - yuv420p_to_rgb24(capture->captureWindow.width, - capture->captureWindow.height, - (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]), - (unsigned char*)capture->frame.imageData); - break; - case VIDEO_PALETTE_YUV420: - yuv420_to_rgb24(capture->captureWindow.width, - capture->captureWindow.height, - (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]), - (unsigned char*)capture->frame.imageData); - break; - case VIDEO_PALETTE_YUV411P: - yuv411p_to_rgb24(capture->captureWindow.width, - capture->captureWindow.height, - (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]), - (unsigned char*)capture->frame.imageData); - break; - default: - fprintf( stderr, - "VIDEOIO ERROR: V4L: Cannot convert from palette %d to RGB\n", - capture->imageProperties.palette); - return 0; - } - - } -#endif /* HAVE_CAMV4L */ - - return(&capture->frame); + return(&capture->frame); } static inline __u32 capPropertyToV4L2(int prop) { switch (prop) { -#ifdef HAVE_CAMV4L2 case CV_CAP_PROP_BRIGHTNESS: return V4L2_CID_BRIGHTNESS; case CV_CAP_PROP_CONTRAST: @@ -2183,7 +1684,6 @@ static inline __u32 capPropertyToV4L2(int prop) { return V4L2_CID_FOCUS_AUTO; case CV_CAP_PROP_FOCUS: return V4L2_CID_FOCUS_ABSOLUTE; -#endif default: return -1; } @@ -2191,12 +1691,6 @@ static inline __u32 capPropertyToV4L2(int prop) { static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, int property_id ) { - -#ifdef HAVE_CAMV4L2 - -#ifdef HAVE_CAMV4L - if (V4L2_SUPPORT == 1) -#endif { CLEAR (capture->form); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -2295,70 +1789,6 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return ((float)capture->control.value - range.start) / range.size(); } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - int retval = -1; - - if (ioctl (capture->deviceHandle, - VIDIOCGWIN, &capture->captureWindow) < 0) { - fprintf (stderr, - "VIDEOIO ERROR: V4L: " - "Unable to determine size of incoming image\n"); - icvCloseCAM_V4L(capture); - return -1; - } - - switch (property_id) { - case CV_CAP_PROP_FRAME_WIDTH: - retval = capture->captureWindow.width; - break; - case CV_CAP_PROP_FRAME_HEIGHT: - retval = capture->captureWindow.height; - break; - case CV_CAP_PROP_BRIGHTNESS: - retval = capture->imageProperties.brightness; - break; - case CV_CAP_PROP_CONTRAST: - retval = capture->imageProperties.contrast; - break; - case CV_CAP_PROP_SATURATION: - retval = capture->imageProperties.colour; - break; - case CV_CAP_PROP_HUE: - retval = capture->imageProperties.hue; - break; - case CV_CAP_PROP_GAIN: - fprintf(stderr, - "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); - return -1; - break; - case CV_CAP_PROP_EXPOSURE: - fprintf(stderr, - "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); - return -1; - break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L: getting property #%d is not supported\n", - property_id); - } - - if (retval == -1) { - /* there was a problem */ - return -1; - } - - /* all was OK, so convert to 0.0 - 1.0 range, and return the value */ - return float (retval) / 0xFFFF; - - } -#endif /* HAVE_CAMV4L */ - }; static int icvSetControl (CvCaptureCAM_V4L* capture, @@ -2371,10 +1801,6 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, value = 1.0; } -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { /* initialisations */ __u32 v4l2id = capPropertyToV4L2(property_id); @@ -2400,57 +1826,6 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, perror ("VIDIOC_S_CTRL"); return -1; } - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - int v4l_value; - - /* scale the value to the wanted integer one */ - v4l_value = (int)(0xFFFF * value); - - switch (property_id) { - case CV_CAP_PROP_BRIGHTNESS: - capture->imageProperties.brightness = v4l_value; - break; - case CV_CAP_PROP_CONTRAST: - capture->imageProperties.contrast = v4l_value; - break; - case CV_CAP_PROP_SATURATION: - capture->imageProperties.colour = v4l_value; - break; - case CV_CAP_PROP_HUE: - capture->imageProperties.hue = v4l_value; - break; - case CV_CAP_PROP_GAIN: - fprintf(stderr, - "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); - return -1; - case CV_CAP_PROP_EXPOSURE: - fprintf(stderr, - "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); - return -1; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L: property #%d is not supported\n", - property_id); - return -1; - } - - if (ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) - < 0) - { - fprintf(stderr, - "VIDEOIO ERROR: V4L: Unable to set video informations\n"); - icvCloseCAM_V4L(capture); - return -1; - } - } -#endif /* HAVE_CAMV4L */ /* all was OK */ return 0; @@ -2509,11 +1884,6 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ if (capture) { - -#ifdef HAVE_CAMV4L2 - if (V4L2_SUPPORT == 1) -#endif /* HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L2 { capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) { @@ -2533,20 +1903,6 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ capture->buffers[MAX_V4L_BUFFERS].start = 0; } } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - if (capture->mmaps) - free(capture->mmaps); - if (capture->memoryMap) - munmap(capture->memoryMap, capture->memoryBuffer.size); - - } -#endif /* HAVE_CAMV4L */ if (capture->deviceHandle != -1) close(capture->deviceHandle); From 93d6e800b6b815d4e72f7c22dade731142214d34 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 24 Oct 2015 02:07:26 +0200 Subject: [PATCH 2/8] v4l: Fixed memory leaks and inconsistent status return values by updating to c++ coding conventions - const correctness - use bool as return value - use explicit initialization instead of CLEAR macro/ memset - use cv namespace --- modules/videoio/src/cap_v4l.cpp | 191 +++++++++++++++----------------- 1 file changed, 87 insertions(+), 104 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 0643e238eb..c3d09547fe 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -211,8 +211,6 @@ make & enjoy! #if !defined WIN32 && (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) -#define CLEAR(x) memset (&(x), 0, sizeof (x)) - #include #include #include @@ -255,6 +253,8 @@ make & enjoy! #define MAX_DEVICE_DRIVER_NAME 80 +namespace cv { + /* Device Capture Objects */ /* V4L2 structure */ struct buffer @@ -265,7 +265,7 @@ struct buffer static unsigned int n_buffers = 0; -typedef struct CvCaptureCAM_V4L +struct CvCaptureCAM_V4L { int deviceHandle; int bufferIndex; @@ -283,22 +283,21 @@ typedef struct CvCaptureCAM_V4L /* V4L2 variables */ buffer buffers[MAX_V4L_BUFFERS + 1]; - struct v4l2_capability cap; - struct v4l2_input inp; - struct v4l2_format form; - struct v4l2_crop crop; - struct v4l2_cropcap cropcap; - struct v4l2_requestbuffers req; - struct v4l2_control control; - enum v4l2_buf_type type; - struct v4l2_queryctrl queryctrl; - - struct timeval timestamp; + v4l2_capability cap; + v4l2_input inp; + v4l2_format form; + v4l2_crop crop; + v4l2_cropcap cropcap; + v4l2_requestbuffers req; + v4l2_buf_type type; + v4l2_queryctrl queryctrl; + + timeval timestamp; /* V4L2 control variables */ - cv::Range focus, brightness, contrast, saturation, hue, gain, exposure; + Range focus, brightness, contrast, saturation, hue, gain, exposure; - cv::Range getRange(int property_id) { + Range getRange(int property_id) const { switch (property_id) { case CV_CAP_PROP_BRIGHTNESS: return brightness; @@ -315,21 +314,21 @@ typedef struct CvCaptureCAM_V4L case CV_CAP_PROP_FOCUS: return focus; case CV_CAP_PROP_AUTOFOCUS: - return cv::Range(0, 1); + return Range(0, 1); default: - return cv::Range(0, 255); + return Range(0, 255); } } -} -CvCaptureCAM_V4L; + ~CvCaptureCAM_V4L(); +}; static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ); -static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture ); +static bool icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture ); static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int ); -static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id ); +static double icvGetPropertyCAM_V4L( const CvCaptureCAM_V4L* capture, int property_id ); static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ); /*********************** Implementations ***************************************/ @@ -337,6 +336,10 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, static int numCameras = 0; static int indexList = 0; +CvCaptureCAM_V4L::~CvCaptureCAM_V4L() { + icvCloseCAM_V4L(this); +} + /* Simple test program: Find number of Video Sources available. Start from 0 and go to MAX_CAMERAS while checking for the device with that name. If it fails on the first attempt of /dev/video0, then check if /dev/video is valid. @@ -369,8 +372,7 @@ static void icvInitCapture_V4L() { static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) { - CLEAR (capture->form); - + capture->form = v4l2_format(); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; capture->form.fmt.pix.pixelformat = capture->palette; capture->form.fmt.pix.field = V4L2_FIELD_ANY; @@ -404,7 +406,7 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) return -1; } - CLEAR (capture->cap); + capture->cap = v4l2_capability(); if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap)) { #ifndef NDEBUG @@ -425,7 +427,7 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) } /* Query information about current input */ - CLEAR (capture->inp); + capture->inp = v4l2_input(); capture->inp.index = deviceIndex; if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp)) { @@ -472,7 +474,7 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id) { - CLEAR (cap->queryctrl); + cap->queryctrl= v4l2_queryctrl(); cap->queryctrl.id = id; if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl)) @@ -485,7 +487,7 @@ static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id) if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) return; - cv::Range range(cap->queryctrl.minimum, cap->queryctrl.maximum); + Range range(cap->queryctrl.minimum, cap->queryctrl.maximum); switch(cap->queryctrl.id) { case V4L2_CID_BRIGHTNESS: @@ -534,8 +536,7 @@ static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) } static int v4l2_set_fps(CvCaptureCAM_V4L* capture) { - v4l2_streamparm setfps; - CLEAR(setfps); + v4l2_streamparm setfps = v4l2_streamparm(); setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; setfps.parm.capture.timeperframe.numerator = 1; setfps.parm.capture.timeperframe.denominator = capture->fps; @@ -610,7 +611,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) the most commonly encountered input video source types (like my bttv card) */ if(capture->inp.index > 0) { - CLEAR (capture->inp); + capture->inp = v4l2_input(); capture->inp.index = CHANNEL_NUMBER; /* Set only channel number to CHANNEL_NUMBER */ /* V4L2 have a status field from selected video mode */ @@ -623,7 +624,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) } /* End if */ /* Find Window info */ - CLEAR (capture->form); + capture->form = v4l2_format(); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { @@ -651,7 +652,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) if (capture->form.fmt.pix.sizeimage < min) capture->form.fmt.pix.sizeimage = min; - CLEAR (capture->req); + capture->req = v4l2_requestbuffers(); unsigned int buffer_number = DEFAULT_V4L_BUFFERS; @@ -693,10 +694,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers) { - struct v4l2_buffer buf; - - CLEAR (buf); - + v4l2_buffer buf = v4l2_buffer(); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; @@ -744,15 +742,14 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) * this method closes and re-opens the device to re-start the stream. * this also causes buffers to be reallocated if the frame size was changed. */ -static int v4l2_reset( CvCaptureCAM_V4L* capture) { +static bool v4l2_reset( CvCaptureCAM_V4L* capture) { icvCloseCAM_V4L(capture); - return _capture_V4L2(capture); + return _capture_V4L2(capture) == 1; } static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) { - static int autoindex; - autoindex = 0; + int autoindex = 0; if (!numCameras) icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */ @@ -765,13 +762,7 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index); return NULL; /* Did someone ask for not correct video source number? */ } - /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL - the handles for V4L processing */ - CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L)); - if (!capture) { - fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n"); - return NULL; - } + /* Select camera, or rather, V4L video source */ if (index<0) { // Asking for the first device available for (; autoindexindex = index; - /* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */ - memset(capture,0,sizeof(CvCaptureCAM_V4L)); - /* Present the routines needed for V4L funtionality. They are inserted as part of - the standard set of cv calls promoting transparency. "Vector Table" insertion. */ + CvCaptureCAM_V4L* capture = new CvCaptureCAM_V4L(); // will throw on OOM + capture->index = index; capture->FirstCapture = 1; capture->width = DEFAULT_V4L_WIDTH; capture->height = DEFAULT_V4L_HEIGHT; @@ -796,15 +784,15 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) if (_capture_V4L2 (capture) == -1) { icvCloseCAM_V4L(capture); + delete capture; + return NULL; } return capture; }; /* End icvOpenCAM_V4L */ static int read_frame_v4l2(CvCaptureCAM_V4L* capture) { - struct v4l2_buffer buf; - - CLEAR (buf); + v4l2_buffer buf = v4l2_buffer(); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; @@ -889,7 +877,7 @@ static void mainloop_v4l2(CvCaptureCAM_V4L* capture) { } } -static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { +static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { if (capture->FirstCapture) { /* Some general initialization must take place the first time through */ @@ -903,9 +891,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { ++capture->bufferIndex) { - struct v4l2_buffer buf; - - CLEAR (buf); + v4l2_buffer buf = v4l2_buffer(); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; @@ -913,7 +899,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) { perror ("VIDIOC_QBUF"); - return 0; + return false; } } @@ -923,7 +909,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { &capture->type)) { /* error enabling the stream */ perror ("VIDIOC_STREAMON"); - return 0; + return false; } } @@ -939,7 +925,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { mainloop_v4l2(capture); - return(1); + return true; } /* @@ -1147,7 +1133,6 @@ yuv411p_to_rgb24(int width, int height, static void yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) { - using namespace cv; cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), COLOR_YUV2BGR_YUYV); } @@ -1202,7 +1187,6 @@ uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) /* convert from mjpeg to rgb24 */ static bool mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* dst) { - using namespace cv; Mat temp = cvarrToMat(dst); imdecode(Mat(1, length, CV_8U, src), IMREAD_COLOR, &temp); return temp.data && temp.cols == width && temp.rows == height; @@ -1689,12 +1673,12 @@ static inline __u32 capPropertyToV4L2(int prop) { } } -static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, +static double icvGetPropertyCAM_V4L (const CvCaptureCAM_V4L* capture, int property_id ) { { - CLEAR (capture->form); - capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { + v4l2_format form; + form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &form)) { /* display an error message, and return an error code */ perror ("VIDIOC_G_FMT"); return -1; @@ -1702,9 +1686,9 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, switch (property_id) { case CV_CAP_PROP_FRAME_WIDTH: - return capture->form.fmt.pix.width; + return form.fmt.pix.width; case CV_CAP_PROP_FRAME_HEIGHT: - return capture->form.fmt.pix.height; + return form.fmt.pix.height; case CV_CAP_PROP_FOURCC: case CV_CAP_PROP_MODE: return capture->palette; @@ -1715,8 +1699,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, } if(property_id == CV_CAP_PROP_FPS) { - struct v4l2_streamparm sp; - CLEAR(sp); + v4l2_streamparm sp = v4l2_streamparm(); sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){ fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n"); @@ -1745,10 +1728,10 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return -1; } - capture->control.id = v4l2id; + v4l2_control control = {v4l2id, 0}; if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL, - &capture->control)) { + &control)) { fprintf( stderr, "VIDEOIO ERROR: V4L2: "); switch (property_id) { @@ -1783,15 +1766,15 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, } /* get the min/max values */ - cv::Range range = capture->getRange(property_id); + Range range = capture->getRange(property_id); /* all was OK, so convert to 0.0 - 1.0 range, and return the value */ - return ((float)capture->control.value - range.start) / range.size(); + return ((double)control.value - range.start) / range.size(); } }; -static int icvSetControl (CvCaptureCAM_V4L* capture, +static bool icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) { /* limitation of the input value */ @@ -1810,32 +1793,30 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, property_id); return -1; } - /* set which control we want to set */ - CLEAR (capture->control); - capture->control.id = v4l2id; /* get the min/max values */ - cv::Range range = capture->getRange(property_id); + Range range = capture->getRange(property_id); - /* set the value we want to set to the scaled the value */ - capture->control.value = (int)(value * range.size() + range.start); + /* scale the value we want to set */ + value = value * range.size() + range.start; + + /* set which control we want to set */ + v4l2_control control = {v4l2id, int(value)}; /* The driver may clamp the value or return ERANGE, ignored here */ - if (-1 == ioctl (capture->deviceHandle, - VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) { + if (-1 == ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &control) && errno != ERANGE) { perror ("VIDIOC_S_CTRL"); - return -1; + return false; } - /* all was OK */ - return 0; - + /* all was OK */ + return true; } static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ){ static int width = 0, height = 0; - int retval = 0; + bool retval = false; bool possible; /* two subsequent calls setting WIDTH and HEIGHT will change @@ -1847,7 +1828,7 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, if(width !=0 && height != 0) { capture->width = width; capture->height = height; - retval = v4l2_reset( capture); + retval = v4l2_reset(capture); width = height = 0; } break; @@ -1856,19 +1837,19 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, if(width !=0 && height != 0) { capture->width = width; capture->height = height; - retval = v4l2_reset( capture); + retval = v4l2_reset(capture); width = height = 0; } break; case CV_CAP_PROP_FPS: capture->fps = value; - retval = v4l2_reset( capture); + retval = v4l2_reset(capture); break; case CV_CAP_PROP_CONVERT_RGB: // returns "0" for formats we do not know how to map to IplImage possible = v4l2_num_channels(capture->palette); capture->convert_rgb = bool(value) && possible; - retval = !possible && bool(value) ? -1 : 0; + retval = possible || !bool(value); break; default: retval = icvSetControl(capture, property_id, value); @@ -1913,14 +1894,14 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ }; -class CvCaptureCAM_V4L_CPP : CvCapture +class CvCaptureCAM_V4L_CPP : public CvCapture { public: CvCaptureCAM_V4L_CPP() { captureV4L = 0; } virtual ~CvCaptureCAM_V4L_CPP() { close(); } - virtual bool open( int index ); - virtual void close(); + bool open( int index ); + void close(); virtual double getProperty(int) const; virtual bool setProperty(int, double); @@ -1942,14 +1923,14 @@ void CvCaptureCAM_V4L_CPP::close() { if( captureV4L ) { - icvCloseCAM_V4L( captureV4L ); - cvFree( &captureV4L ); + delete captureV4L; + captureV4L = NULL; } } bool CvCaptureCAM_V4L_CPP::grabFrame() { - return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false; + return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) : false; } IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int) @@ -1964,15 +1945,17 @@ double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value ) { - return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false; + return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) : false; } +} // end namespace cv + CvCapture* cvCreateCameraCapture_V4L( int index ) { - CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP; + cv::CvCaptureCAM_V4L_CPP* capture = new cv::CvCaptureCAM_V4L_CPP; if( capture->open( index )) - return (CvCapture*)capture; + return capture; delete capture; return 0; From f50817120e52e34adccd0452992cad1926bab7d1 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 24 Oct 2015 14:11:47 +0200 Subject: [PATCH 3/8] v4l: remove needless CvCaptureCAM_V4L_CPP wrapper possible source of memory leaks and unneeded complexity --- modules/videoio/src/cap_v4l.cpp | 126 +++++++++++++------------------- 1 file changed, 49 insertions(+), 77 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index c3d09547fe..c15ac000ff 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -265,7 +265,7 @@ struct buffer static unsigned int n_buffers = 0; -struct CvCaptureCAM_V4L +struct CvCaptureCAM_V4L : public CvCapture { int deviceHandle; int bufferIndex; @@ -297,6 +297,13 @@ struct CvCaptureCAM_V4L /* V4L2 control variables */ Range focus, brightness, contrast, saturation, hue, gain, exposure; + bool open(int _index); + + virtual double getProperty(int) const; + virtual bool setProperty(int, double); + virtual bool grabFrame(); + virtual IplImage* retrieveFrame(int); + Range getRange(int property_id) const { switch (property_id) { case CV_CAP_PROP_BRIGHTNESS: @@ -320,7 +327,7 @@ struct CvCaptureCAM_V4L } } - ~CvCaptureCAM_V4L(); + virtual ~CvCaptureCAM_V4L(); }; static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ); @@ -743,53 +750,50 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) * this also causes buffers to be reallocated if the frame size was changed. */ static bool v4l2_reset( CvCaptureCAM_V4L* capture) { + int index = capture->index; icvCloseCAM_V4L(capture); + capture->index = index; return _capture_V4L2(capture) == 1; } -static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) +bool CvCaptureCAM_V4L::open(int _index) { int autoindex = 0; + index = -1; // set the capture to closed state + if (!numCameras) icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */ if (!numCameras) - return NULL; /* Are there any /dev/video input sources? */ + return false; /* Are there any /dev/video input sources? */ //search index in indexList - if ( (index>-1) && ! ((1 << index) & indexList) ) + if ( (_index>-1) && ! ((1 << _index) & indexList) ) { - fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index); - return NULL; /* Did someone ask for not correct video source number? */ + fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",_index); + return false; /* Did someone ask for not correct video source number? */ } /* Select camera, or rather, V4L video source */ - if (index<0) { // Asking for the first device available + if (_index<0) { // Asking for the first device available for (; autoindexindex = index; - capture->FirstCapture = 1; - capture->width = DEFAULT_V4L_WIDTH; - capture->height = DEFAULT_V4L_HEIGHT; - capture->fps = DEFAULT_V4L_FPS; - capture->convert_rgb = true; - - if (_capture_V4L2 (capture) == -1) { - icvCloseCAM_V4L(capture); - delete capture; - return NULL; - } + index = _index; + FirstCapture = 1; + width = DEFAULT_V4L_WIDTH; + height = DEFAULT_V4L_HEIGHT; + fps = DEFAULT_V4L_FPS; + convert_rgb = true; - return capture; -}; /* End icvOpenCAM_V4L */ + return _capture_V4L2(this) == 1; +} static int read_frame_v4l2(CvCaptureCAM_V4L* capture) { v4l2_buffer buf = v4l2_buffer(); @@ -1863,12 +1867,13 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ /* Deallocate space - Hopefully, no leaks */ - if (capture) + if (capture->index > -1) { + if (capture->deviceHandle != -1) { - capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) { - perror ("Unable to stop the stream."); + capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) { + perror ("Unable to stop the stream"); } for (unsigned int n_buffers_ = 0; n_buffers_ < capture->req.count; ++n_buffers_) @@ -1888,77 +1893,44 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ if (capture->deviceHandle != -1) close(capture->deviceHandle); - if (capture->frame.imageData) cvFree(&capture->frame.imageData); - //cvFree((void **)capture); - } -}; - - -class CvCaptureCAM_V4L_CPP : public CvCapture -{ -public: - CvCaptureCAM_V4L_CPP() { captureV4L = 0; } - virtual ~CvCaptureCAM_V4L_CPP() { close(); } + if (capture->frame.imageData) + cvFree(&capture->frame.imageData); - bool open( int index ); - void close(); - - virtual double getProperty(int) const; - virtual bool setProperty(int, double); - virtual bool grabFrame(); - virtual IplImage* retrieveFrame(int); -protected: - - CvCaptureCAM_V4L* captureV4L; + capture->index = -1; // flag that the capture is closed + } }; -bool CvCaptureCAM_V4L_CPP::open( int index ) +bool CvCaptureCAM_V4L::grabFrame() { - close(); - captureV4L = icvCaptureFromCAM_V4L(index); - return captureV4L != 0; + return icvGrabFrameCAM_V4L( this ); } -void CvCaptureCAM_V4L_CPP::close() +IplImage* CvCaptureCAM_V4L::retrieveFrame(int) { - if( captureV4L ) - { - delete captureV4L; - captureV4L = NULL; - } + return icvRetrieveFrameCAM_V4L( this, 0 ); } -bool CvCaptureCAM_V4L_CPP::grabFrame() +double CvCaptureCAM_V4L::getProperty( int propId ) const { - return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) : false; + return icvGetPropertyCAM_V4L( this, propId ); } -IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int) +bool CvCaptureCAM_V4L::setProperty( int propId, double value ) { - return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0; -} - -double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const -{ - return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0; -} - -bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value ) -{ - return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) : false; + return icvSetPropertyCAM_V4L( this, propId, value ); } } // end namespace cv CvCapture* cvCreateCameraCapture_V4L( int index ) { - cv::CvCaptureCAM_V4L_CPP* capture = new cv::CvCaptureCAM_V4L_CPP; + cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L(); - if( capture->open( index )) + if(capture->open(index)) return capture; delete capture; - return 0; + return NULL; } #endif From 8527d895bb65405897cc16f6d9a9d58bc24a6553 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 24 Oct 2015 18:31:57 +0200 Subject: [PATCH 4/8] replace rgb24_to_rgb24 by tested cvtColor internally using ipp this conversion is now roughly 2x faster. also add RGB/ BGR formats to allowed zero copy access. --- modules/videoio/src/cap_v4l.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index c15ac000ff..f4ffa45b3d 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -558,6 +558,9 @@ static int v4l2_num_channels(__u32 palette) { case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: return 2; + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + return 3; default: return 0; } @@ -1366,16 +1369,10 @@ static void sgbrg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, uns } } -static void +static inline void rgb24_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) { - const int size = width * height; - for(int i = 0; i < size; ++i, src += 3, dst += 3) - { - *(dst + 0) = *(src + 2); - *(dst + 1) = *(src + 1); - *(dst + 2) = *(src + 0); - } + cvtColor(Mat(height, width, CV_8UC3, src), Mat(height, width, CV_8UC3, dst), COLOR_RGB2BGR); } #define CLAMP(x) ((x)<0?0:((x)>255)?255:(x)) From ad68b7963058f5369f801f870324f084edbde566 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 31 Oct 2015 23:48:23 +0100 Subject: [PATCH 5/8] replace yuv420p_to_rgb24 by tested and conformant cvtColor Conversion was not ITU 601 conformant. Also add YVU420 format to allowed zero copy access. --- modules/videoio/src/cap_v4l.cpp | 96 +++++---------------------------- 1 file changed, 14 insertions(+), 82 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index f4ffa45b3d..6a7f8cc57a 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -552,6 +552,7 @@ static int v4l2_set_fps(CvCaptureCAM_V4L* capture) { static int v4l2_num_channels(__u32 palette) { switch(palette) { + case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_MJPEG: case V4L2_PIX_FMT_JPEG: return 1; @@ -571,10 +572,17 @@ static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { int channels = 3; if (!capture->convert_rgb) { - if (capture->palette == V4L2_PIX_FMT_MJPEG || capture->palette == V4L2_PIX_FMT_JPEG) { + channels = v4l2_num_channels(capture->palette); + + switch(capture->palette) { + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: size = CvSize(capture->buffers[capture->bufferIndex].length, 1); + break; + case V4L2_PIX_FMT_YVU420: + size.height = size.height * 3 / 2; // "1.5" channels + break; } - channels = v4l2_num_channels(capture->palette); } /* Set up Image data */ @@ -964,45 +972,6 @@ static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */ #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16))) -static inline void -move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, - int rowPixels, unsigned char * rgb) -{ - const int rvScale = 91881; - const int guScale = -22553; - const int gvScale = -46801; - const int buScale = 116129; - const int yScale = 65536; - int r, g, b; - - g = guScale * u + gvScale * v; -// if (force_rgb) { -// r = buScale * u; -// b = rvScale * v; -// } else { - r = rvScale * v; - b = buScale * u; -// } - - yTL *= yScale; yTR *= yScale; - yBL *= yScale; yBR *= yScale; - - /* Write out top two pixels */ - rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); - rgb[2] = LIMIT(r+yTL); - - rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); - rgb[5] = LIMIT(r+yTR); - - /* Skip down to next line to write out bottom two pixels */ - rgb += 3 * rowPixels; - rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); - rgb[2] = LIMIT(r+yBL); - - rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); - rgb[5] = LIMIT(r+yBR); -} - static inline void move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v, int /*rowPixels*/, unsigned char * rgb) @@ -1042,49 +1011,12 @@ move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v, rgb[5] = LIMIT(r+yBR); } -// Consider a YUV420P image of 8x2 pixels. -// -// A plane of Y values A B C D E F G H -// I J K L M N O P -// -// A plane of U values 1 2 3 4 -// A plane of V values 1 2 3 4 .... -// -// The U1/V1 samples correspond to the ABIJ pixels. -// U2/V2 samples correspond to the CDKL pixels. -// /* Converts from planar YUV420P to RGB24. */ -static void -yuv420p_to_rgb24(int width, int height, - unsigned char *pIn0, unsigned char *pOut0) +static inline void +yuv420p_to_rgb24(int width, int height, uchar* src, uchar* dst) { - const int numpix = width * height; - const int bytes = 24 >> 3; - int i, j, y00, y01, y10, y11, u, v; - unsigned char *pY = pIn0; - unsigned char *pU = pY + numpix; - unsigned char *pV = pU + numpix / 4; - unsigned char *pOut = pOut0; - - for (j = 0; j <= height - 2; j += 2) { - for (i = 0; i <= width - 2; i += 2) { - y00 = *pY; - y01 = *(pY + 1); - y10 = *(pY + width); - y11 = *(pY + width + 1); - u = (*pU++) - 128; - v = (*pV++) - 128; - - move_420_block(y00, y01, y10, y11, u, v, - width, pOut); - - pY += 2; - pOut += 2 * bytes; - - } - pY += width; - pOut += width * bytes; - } + cvtColor(Mat(height * 3 / 2, width, CV_8U, src), Mat(height, width, CV_8UC3, dst), + COLOR_YUV2BGR_YV12); } // Consider a YUV411P image of 8x2 pixels. From 05f52b697fb38f8442d5fd9e571711a83d6e2e56 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 31 Oct 2015 23:56:15 +0100 Subject: [PATCH 6/8] replace uyvy_to_rgb24 by tested and conformant cvtColor --- modules/videoio/src/cap_v4l.cpp | 49 ++------------------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 6a7f8cc57a..00f6b21b1a 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1066,60 +1066,17 @@ yuv411p_to_rgb24(int width, int height, } /* convert from 4:2:2 YUYV interlaced to RGB24 */ -/* based on ccvt_yuyv_bgr32() from camstream */ -#define SAT(c) \ - if (c & (~255)) { if (c < 0) c = 0; else c = 255; } - static void yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) { cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), COLOR_YUV2BGR_YUYV); } -static void +static inline void uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) { - unsigned char *s; - unsigned char *d; - int l, c; - int r, g, b, cr, cg, cb, y1, y2; - - l = height; - s = src; - d = dst; - while (l--) { - c = width >> 1; - while (c--) { - cb = ((*s - 128) * 454) >> 8; - cg = (*s++ - 128) * 88; - y1 = *s++; - cr = ((*s - 128) * 359) >> 8; - cg = (cg + (*s++ - 128) * 183) >> 8; - y2 = *s++; - - r = y1 + cr; - b = y1 + cb; - g = y1 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - - r = y2 + cr; - b = y2 + cb; - g = y2 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - } - } + cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), + COLOR_YUV2BGR_UYVY); } #ifdef HAVE_JPEG From 955f489621f675a2fc37bce15cbda0430ac1a2af Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sun, 1 Nov 2015 11:41:26 +0100 Subject: [PATCH 7/8] make CV_CAP_PROP_FORMAT consider the current channel count --- modules/videoio/src/cap_v4l.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 00f6b21b1a..36dd928ec4 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1583,7 +1583,7 @@ static double icvGetPropertyCAM_V4L (const CvCaptureCAM_V4L* capture, case CV_CAP_PROP_MODE: return capture->palette; case CV_CAP_PROP_FORMAT: - return CV_8UC3; + return CV_MAKETYPE(CV_8U, capture->frame.nChannels); case CV_CAP_PROP_CONVERT_RGB: return capture->convert_rgb; } From 84f9578fbb490fd3c9b2b2f3fb43fc17e7c93b00 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 1 Dec 2015 13:12:32 +0300 Subject: [PATCH 8/8] ippicv: update 20151201 (9.0.1) --- 3rdparty/ippicv/downloader.cmake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/3rdparty/ippicv/downloader.cmake b/3rdparty/ippicv/downloader.cmake index 0a3a4119c1..a6016dbe10 100644 --- a/3rdparty/ippicv/downloader.cmake +++ b/3rdparty/ippicv/downloader.cmake @@ -7,24 +7,24 @@ function(_icv_downloader) # Commit SHA in the opencv_3rdparty repo - set(IPPICV_BINARIES_COMMIT "3d41df448b589aa076d9d27ace344d3ef709e4b9") + set(IPPICV_BINARIES_COMMIT "81a676001ca8075ada498583e4166079e5744668") # Define actual ICV versions if(APPLE) - set(OPENCV_ICV_PACKAGE_NAME "ippicv_macosx_20141027.tgz") - set(OPENCV_ICV_PACKAGE_HASH "9662fe0694a67e59491a0dcc82fa26e0") + set(OPENCV_ICV_PACKAGE_NAME "ippicv_macosx_20151201.tgz") + set(OPENCV_ICV_PACKAGE_HASH "4ff1fde9a7cfdfe7250bfcd8334e0f2f") set(OPENCV_ICV_PLATFORM "macosx") set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_osx") elseif(UNIX) if(ANDROID AND NOT (ANDROID_ABI STREQUAL x86 OR ANDROID_ABI STREQUAL x86_64)) return() endif() - set(OPENCV_ICV_PACKAGE_NAME "ippicv_linux_20141027.tgz") - set(OPENCV_ICV_PACKAGE_HASH "8b449a536a2157bcad08a2b9f266828b") + set(OPENCV_ICV_PACKAGE_NAME "ippicv_linux_20151201.tgz") + set(OPENCV_ICV_PACKAGE_HASH "808b791a6eac9ed78d32a7666804320e") set(OPENCV_ICV_PLATFORM "linux") set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_lnx") elseif(WIN32 AND NOT ARM) - set(OPENCV_ICV_PACKAGE_NAME "ippicv_windows_20141027.zip") - set(OPENCV_ICV_PACKAGE_HASH "b59f865d1ba16e8c84124e19d78eec57") + set(OPENCV_ICV_PACKAGE_NAME "ippicv_windows_20151201.zip") + set(OPENCV_ICV_PACKAGE_HASH "04e81ce5d0e329c3fbc606ae32cad44d") set(OPENCV_ICV_PLATFORM "windows") set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_win") else()