From e489f29d0fd8f40683ff7294f4f2060f6bbe0a5e Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Tue, 12 Apr 2016 01:00:37 -0400 Subject: [PATCH] v4l/libv4l: allow opening device by name - Allows using non-default device names such as /dev/v4l/by-path/pci-0000:00:1d.0-usb-0:1.1:1.0-video-index0 --- modules/videoio/src/cap.cpp | 5 +++ modules/videoio/src/cap_libv4l.cpp | 56 ++++++++++++++++++++++-------- modules/videoio/src/cap_v4l.cpp | 53 ++++++++++++++++++---------- modules/videoio/src/precomp.hpp | 1 + 4 files changed, 81 insertions(+), 34 deletions(-) diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 3211badea..40682abf1 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -292,6 +292,11 @@ CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, in result = cvCreateFileCapture_VFW (filename); if (apiPreference) break; #endif +#if defined HAVE_LIBV4L || defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO + if (!result) + result = cvCreateCameraCapture_V4L(filename); + if (apiPreference) break; +#endif case CV_CAP_MSMF: #ifdef HAVE_MSMF diff --git a/modules/videoio/src/cap_libv4l.cpp b/modules/videoio/src/cap_libv4l.cpp index 46fac9528..3fabc2e48 100644 --- a/modules/videoio/src/cap_libv4l.cpp +++ b/modules/videoio/src/cap_libv4l.cpp @@ -350,6 +350,7 @@ typedef struct CvCaptureCAM_V4L } CvCaptureCAM_V4L; +static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (const char* deviceName); static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ); static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture ); @@ -416,7 +417,7 @@ static void icvInitCapture_V4L() { }; /* End icvInitCapture_V4L */ -static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName) +static int try_init_v4l(CvCaptureCAM_V4L* capture, const char *deviceName) { @@ -460,7 +461,7 @@ static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName) } -static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) +static int try_init_v4l2(CvCaptureCAM_V4L* capture, const char *deviceName) { // if detect = -1 then unable to open device @@ -662,7 +663,7 @@ static inline int channels_for_mode(int mode) } } -static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) +static int _capture_V4L2 (CvCaptureCAM_V4L *capture, const char *deviceName) { int detect_v4l2 = 0; @@ -870,7 +871,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) }; /* End _capture_V4L2 */ -static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) +static int _capture_V4L (CvCaptureCAM_V4L *capture, const char *deviceName) { int detect_v4l = 0; @@ -1041,17 +1042,6 @@ 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; - } - -#ifdef USE_TEMP_BUFFER - capture->buffers[MAX_V4L_BUFFERS].start = NULL; -#endif /* Select camera, or rather, V4L video source */ if (index<0) { // Asking for the first device available @@ -1065,9 +1055,26 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) } /* Print the CameraNumber at the end of the string with a width of one character */ sprintf(deviceName, "/dev/video%1d", index); + return icvCaptureFromCAM_V4L(deviceName); +} + +static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (const char* deviceName) +{ + /* 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; + } + +#ifdef USE_TEMP_BUFFER + capture->buffers[MAX_V4L_BUFFERS].start = NULL; +#endif /* 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. */ capture->FirstCapture = 1; @@ -1905,6 +1912,7 @@ public: virtual ~CvCaptureCAM_V4L_CPP() { close(); } virtual bool open( int index ); + virtual bool open( const char* deviceName ); virtual void close(); virtual double getProperty(int) const; @@ -1923,6 +1931,13 @@ bool CvCaptureCAM_V4L_CPP::open( int index ) return captureV4L != 0; } +bool CvCaptureCAM_V4L_CPP::open( const char* deviceName ) +{ + close(); + captureV4L = icvCaptureFromCAM_V4L(deviceName); + return captureV4L != 0; +} + void CvCaptureCAM_V4L_CPP::close() { if( captureV4L ) @@ -1963,4 +1978,15 @@ CvCapture* cvCreateCameraCapture_V4L( int index ) return 0; } +CvCapture* cvCreateCameraCapture_V4L( const char * deviceName ) +{ + CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP; + + if( capture->open( deviceName )) + return (CvCapture*)capture; + + delete capture; + return 0; +} + #endif diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 36dd928ec..324400359 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -270,12 +270,12 @@ struct CvCaptureCAM_V4L : public CvCapture int deviceHandle; int bufferIndex; int FirstCapture; + String deviceName; char *memoryMap; IplImage frame; __u32 palette; - int index; int width, height; __u32 fps; bool convert_rgb; @@ -298,6 +298,7 @@ struct CvCaptureCAM_V4L : public CvCapture Range focus, brightness, contrast, saturation, hue, gain, exposure; bool open(int _index); + bool open(const char* deviceName); virtual double getProperty(int) const; virtual bool setProperty(int, double); @@ -392,7 +393,7 @@ static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) return capture->palette == capture->form.fmt.pix.pixelformat; } -static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) +static int try_init_v4l2(CvCaptureCAM_V4L* capture, const char *deviceName) { // Test device for V4L2 compability // Return value: @@ -600,10 +601,7 @@ static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { static int _capture_V4L2 (CvCaptureCAM_V4L *capture) { - 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); - + const char* deviceName = capture->deviceName.c_str(); if (try_init_v4l2(capture, deviceName) != 1) { /* init of the v4l2 device is not OK */ return -1; @@ -761,17 +759,16 @@ 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; + String deviceName = capture->deviceName; icvCloseCAM_V4L(capture); - capture->index = index; + capture->deviceName = deviceName; return _capture_V4L2(capture) == 1; } bool CvCaptureCAM_V4L::open(int _index) { int autoindex = 0; - - index = -1; // set the capture to closed state + char _deviceName[MAX_DEVICE_DRIVER_NAME]; if (!numCameras) icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */ @@ -796,14 +793,21 @@ bool CvCaptureCAM_V4L::open(int _index) autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera } - index = _index; - FirstCapture = 1; - width = DEFAULT_V4L_WIDTH; - height = DEFAULT_V4L_HEIGHT; - fps = DEFAULT_V4L_FPS; - convert_rgb = true; + /* Print the CameraNumber at the end of the string with a width of one character */ + sprintf(_deviceName, "/dev/video%1d", _index); + return open(_deviceName); +} - return _capture_V4L2(this) == 1; +bool CvCaptureCAM_V4L::open(const char* _deviceName) +{ + FirstCapture = 1; + width = DEFAULT_V4L_WIDTH; + height = DEFAULT_V4L_HEIGHT; + fps = DEFAULT_V4L_FPS; + convert_rgb = true; + deviceName = _deviceName; + + return _capture_V4L2(this) == 1; } static int read_frame_v4l2(CvCaptureCAM_V4L* capture) { @@ -1753,7 +1757,7 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ /* Deallocate space - Hopefully, no leaks */ - if (capture->index > -1) + if (!capture->deviceName.empty()) { if (capture->deviceHandle != -1) { @@ -1782,7 +1786,7 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){ if (capture->frame.imageData) cvFree(&capture->frame.imageData); - capture->index = -1; // flag that the capture is closed + capture->deviceName.clear(); // flag that the capture is closed } }; @@ -1819,4 +1823,15 @@ CvCapture* cvCreateCameraCapture_V4L( int index ) return NULL; } +CvCapture* cvCreateCameraCapture_V4L( const char * deviceName ) +{ + cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L(); + + if(capture->open( deviceName )) + return capture; + + delete capture; + return NULL; +} + #endif diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index 442eaa19a..45ce1a1f6 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -102,6 +102,7 @@ struct CvVideoWriter }; CvCapture * cvCreateCameraCapture_V4L( int index ); +CvCapture * cvCreateCameraCapture_V4L( const char* deviceName ); CvCapture * cvCreateCameraCapture_DC1394( int index ); CvCapture * cvCreateCameraCapture_DC1394_2( int index ); CvCapture* cvCreateCameraCapture_MIL( int index );