[vlc-devel] [PATCH 1/2] V4L2: Open devices only once.

Thierry Reding thierry.reding at avionic-design.de
Thu Aug 4 09:53:51 CEST 2011


Instead of opening the device once for probing purposes and opening it
again when it has been determined suitable, this commit takes the file
descriptor obtained during probing and passes it to the initialization
function.
---
 modules/access/v4l2.c |  105 +++++++++++++++++++------------------------------
 1 files changed, 40 insertions(+), 65 deletions(-)

diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c
index 98bd116..f074a9c 100644
--- a/modules/access/v4l2.c
+++ b/modules/access/v4l2.c
@@ -415,8 +415,8 @@ static block_t* ProcessVideoFrame( vlc_object_t *p_demux, uint8_t *p_frame, size
 static bool IsPixelFormatSupported( demux_t *p_demux,
                                           unsigned int i_pixelformat );
 
-static int OpenVideoDev( vlc_object_t *, demux_sys_t *, bool );
-static bool ProbeVideoDev( vlc_object_t *, demux_sys_t *,
+static int InitVideoDev( vlc_object_t *, demux_sys_t *, bool );
+static int ProbeVideoDev( vlc_object_t *, demux_sys_t *,
                                  const char *psz_device );
 
 static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool );
@@ -645,10 +645,11 @@ static int FindMainDevice( vlc_object_t *p_this, demux_sys_t *p_sys,
     /* TODO: if using default device, loop through all /dev/video* until
      * one works */
     msg_Dbg( p_this, "opening device '%s'", p_sys->psz_device );
-    if( ProbeVideoDev( p_this, p_sys, p_sys->psz_device ) )
+    p_sys->i_fd = ProbeVideoDev( p_this, p_sys, p_sys->psz_device );
+    if( p_sys->i_fd >= 0 )
     {
         msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device );
-        p_sys->i_fd = OpenVideoDev( p_this, p_sys, b_demux );
+        InitVideoDev( p_this, p_sys, b_demux );
     }
 
     if( p_sys->i_fd < 0 ) return VLC_EGENERIC;
@@ -1823,51 +1824,27 @@ static void GetMaxDimensions( demux_t *p_demux, int i_fd,
 }
 
 /*****************************************************************************
- * OpenVideoDev: open and set up the video device and probe for capabilities
+ * InitVideoDev: set up the video device and probe for capabilities
  *****************************************************************************/
-static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
+static int InitVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
 {
-    int i_fd;
     struct v4l2_cropcap cropcap;
     struct v4l2_crop crop;
     struct v4l2_format fmt;
     unsigned int i_min;
     enum v4l2_buf_type buf_type;
-    const char *psz_device = p_sys->psz_device;
     es_format_t es_fmt;
 
-    if( ( i_fd = v4l2_open( psz_device, O_RDWR ) ) < 0 )
-    {
-        msg_Err( p_obj, "cannot open device (%m)" );
-        goto open_failed;
-    }
-
-#ifdef HAVE_LIBV4L2
-    /* Note the v4l2_xxx functions are designed so that if they get passed an
-       unknown fd, the will behave exactly as their regular xxx counterparts,
-       so if v4l2_fd_open fails, we continue as normal (missing the libv4l2
-       custom cam format to normal formats conversion). Chances are big we will
-       still fail then though, as normally v4l2_fd_open only fails if the
-       device is not a v4l2 device. */
-    if( p_sys->b_libv4l2 )
-    {
-        int libv4l2_fd;
-        libv4l2_fd = v4l2_fd_open( i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION );
-        if( libv4l2_fd != -1 )
-            i_fd = libv4l2_fd;
-    }
-#endif
-
     /* Select standard */
 
     if( p_sys->i_selected_standard_id != V4L2_STD_UNKNOWN )
     {
-        if( v4l2_ioctl( i_fd, VIDIOC_S_STD, &p_sys->i_selected_standard_id ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_STD, &p_sys->i_selected_standard_id ) < 0 )
         {
             msg_Err( p_obj, "cannot set standard (%m)" );
             goto open_failed;
         }
-        if( v4l2_ioctl( i_fd, VIDIOC_G_STD, &p_sys->i_selected_standard_id ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_G_STD, &p_sys->i_selected_standard_id ) < 0 )
         {
             msg_Err( p_obj, "cannot get standard (%m). This should never happen!" );
             goto open_failed;
@@ -1896,7 +1873,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         frequency.tuner = p_sys->i_cur_tuner;
         frequency.type = p_sys->p_tuners[p_sys->i_cur_tuner].type;
         frequency.frequency = p_sys->i_frequency / 62.5;
-        if( v4l2_ioctl( i_fd, VIDIOC_S_FREQUENCY, &frequency ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FREQUENCY, &frequency ) < 0 )
         {
             msg_Err( p_obj, "cannot set tuner frequency (%m)" );
             goto open_failed;
@@ -1916,7 +1893,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         memset( &tuner, 0, sizeof( tuner ) );
         tuner.index = p_sys->i_cur_tuner;
         tuner.audmode = p_sys->i_audio_mode;
-        if( v4l2_ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_TUNER, &tuner ) < 0 )
         {
             msg_Err( p_obj, "cannot set tuner audio mode (%m)" );
             goto open_failed;
@@ -1932,7 +1909,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         p_sys->i_selected_input = 0;
     }
 
-    if( v4l2_ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_selected_input ) < 0 )
+    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_INPUT, &p_sys->i_selected_input ) < 0 )
     {
         msg_Err( p_obj, "cannot set input (%m)" );
         goto open_failed;
@@ -1949,7 +1926,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
             p_sys->i_selected_audio_input = 0;
         }
 
-        if( v4l2_ioctl( i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_selected_audio_input] ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_selected_audio_input] ) < 0 )
         {
             msg_Err( p_obj, "cannot set audio input (%m)" );
             goto open_failed;
@@ -1960,9 +1937,9 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
 
     /* TODO: Move the resolution stuff up here */
     /* if MPEG encoder card, no need to do anything else after this */
-    ControlList( p_obj, p_sys, i_fd,
+    ControlList( p_obj, p_sys, p_sys->i_fd,
                   var_GetBool( p_obj, "v4l2-controls-reset" ), b_demux );
-    SetAvailControlsByString( p_obj, p_sys, i_fd );
+    SetAvailControlsByString( p_obj, p_sys, p_sys->i_fd );
 
     /* Verify device support for the various IO methods */
     switch( p_sys->io )
@@ -1997,13 +1974,13 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     /* Reset Cropping */
     memset( &cropcap, 0, sizeof(cropcap) );
     cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if( v4l2_ioctl( i_fd, VIDIOC_CROPCAP, &cropcap ) >= 0 )
+    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_CROPCAP, &cropcap ) >= 0 )
     {
         crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
         crop.c = cropcap.defrect; /* reset to default */
         if( crop.c.width > 0 && crop.c.height > 0 ) /* Fix for fm tuners */
         {
-            if( v4l2_ioctl( i_fd, VIDIOC_S_CROP, &crop ) < 0 )
+            if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_CROP, &crop ) < 0 )
             {
                 switch( errno )
                 {
@@ -2025,7 +2002,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     if( p_sys->i_width <= 0 || p_sys->i_height <= 0 )
     {
         /* Use current width and height settings */
-        if( v4l2_ioctl( i_fd, VIDIOC_G_FMT, &fmt ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_G_FMT, &fmt ) < 0 )
         {
             msg_Err( p_obj, "Cannot get default width and height." );
             goto open_failed;
@@ -2073,10 +2050,10 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
             bool b_error = !IsPixelFormatSupported( p_demux, fmt.fmt.pix.pixelformat );
             if( !b_error && fmt.fmt.pix.pixelformat )
             {
-                if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
+                if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
                 {
                     fmt.fmt.pix.field = V4L2_FIELD_ANY;
-                    if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
+                    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
                     {
                         fmt.fmt.pix.field = V4L2_FIELD_NONE;
                         b_error = true;
@@ -2100,10 +2077,10 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
                 fmt.fmt.pix.pixelformat = p_chroma_fallbacks[i];
                 if( IsPixelFormatSupported( p_demux, fmt.fmt.pix.pixelformat ) )
                 {
-                    if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
+                    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
                         break;
                     fmt.fmt.pix.field = V4L2_FIELD_ANY;
-                    if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
+                    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
                         break;
                     fmt.fmt.pix.field = V4L2_FIELD_NONE;
                 }
@@ -2119,12 +2096,12 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         {
             if( p_sys->f_fps <= 0 )
             {
-                p_sys->f_fps = GetAbsoluteMaxFrameRate( p_demux, i_fd,
+                p_sys->f_fps = GetAbsoluteMaxFrameRate( p_demux, p_sys->i_fd,
                                                         fmt.fmt.pix.pixelformat );
                 msg_Dbg( p_demux, "Found maximum framerate of %f", p_sys->f_fps );
             }
             uint32_t i_width, i_height;
-            GetMaxDimensions( p_demux, i_fd,
+            GetMaxDimensions( p_demux, p_sys->i_fd,
                               fmt.fmt.pix.pixelformat, p_sys->f_fps,
                               &i_width, &i_height );
             if( i_width || i_height )
@@ -2133,7 +2110,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
                                   "of %ux%u", p_sys->f_fps, i_width, i_height );
                 fmt.fmt.pix.width = i_width;
                 fmt.fmt.pix.height = i_height;
-                if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
+                if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
                 {
                     msg_Err( p_obj, "Cannot set size to optimal dimensions "
                                     "%ux%u", i_width, i_height );
@@ -2151,7 +2128,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     p_sys->i_width = fmt.fmt.pix.width;
     p_sys->i_height = fmt.fmt.pix.height;
 
-    if( v4l2_ioctl( i_fd, VIDIOC_G_FMT, &fmt ) < 0 ) {;}
+    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_G_FMT, &fmt ) < 0 ) {;}
     /* Print extra info */
     msg_Dbg( p_obj, "Driver requires at most %d bytes to store a complete image", fmt.fmt.pix.sizeimage );
     /* Check interlacing */
@@ -2228,7 +2205,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     frmival.pixel_format = fmt.fmt.pix.pixelformat;
     frmival.width = p_sys->i_width;
     frmival.height = p_sys->i_height;
-    if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 )
+    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 )
     {
         char psz_fourcc[5];
         memset( &psz_fourcc, 0, sizeof( psz_fourcc ) );
@@ -2244,7 +2221,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
                              frmival.discrete.numerator,
                              frmival.discrete.denominator );
                     frmival.index++;
-                } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 );
+                } while( v4l2_ioctl( p_sys->i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 );
                 break;
             case V4L2_FRMIVAL_TYPE_STEPWISE:
                 msg_Dbg( p_obj, "    supported frame intervals: %d/%d to "
@@ -2277,11 +2254,11 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         break;
 
     case IO_METHOD_MMAP:
-        if( InitMmap( p_obj, p_sys, i_fd ) != VLC_SUCCESS ) goto open_failed;
+        if( InitMmap( p_obj, p_sys, p_sys->i_fd ) != VLC_SUCCESS ) goto open_failed;
         break;
 
     case IO_METHOD_USERPTR:
-        if( InitUserP( p_obj, p_sys, i_fd, fmt.fmt.pix.sizeimage ) != VLC_SUCCESS ) goto open_failed;
+        if( InitUserP( p_obj, p_sys, p_sys->i_fd, fmt.fmt.pix.sizeimage ) != VLC_SUCCESS ) goto open_failed;
         break;
 
     default:
@@ -2327,7 +2304,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
             buf.memory = V4L2_MEMORY_MMAP;
             buf.index = i;
 
-            if( v4l2_ioctl( i_fd, VIDIOC_QBUF, &buf ) < 0 )
+            if( v4l2_ioctl( p_sys->i_fd, VIDIOC_QBUF, &buf ) < 0 )
             {
                 msg_Err( p_obj, "VIDIOC_QBUF failed" );
                 goto open_failed;
@@ -2335,7 +2312,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         }
 
         buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-        if( v4l2_ioctl( i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
         {
             msg_Err( p_obj, "VIDIOC_STREAMON failed" );
             goto open_failed;
@@ -2355,7 +2332,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
             buf.m.userptr = (unsigned long)p_sys->p_buffers[i].start;
             buf.length = p_sys->p_buffers[i].length;
 
-            if( v4l2_ioctl( i_fd, VIDIOC_QBUF, &buf ) < 0 )
+            if( v4l2_ioctl( p_sys->i_fd, VIDIOC_QBUF, &buf ) < 0 )
             {
                 msg_Err( p_obj, "VIDIOC_QBUF failed" );
                 goto open_failed;
@@ -2363,7 +2340,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         }
 
         buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-        if( v4l2_ioctl( i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
+        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
         {
             msg_Err( p_obj, "VIDIOC_STREAMON failed" );
             goto open_failed;
@@ -2382,18 +2359,18 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         msg_Dbg( p_obj, "User set fps=%f", p_sys->f_fps );
     }
 
-    return i_fd;
+    return VLC_SUCCESS;
 
 open_failed:
-    if( i_fd >= 0 ) v4l2_close( i_fd );
-    return -1;
+    if( p_sys->i_fd >= 0 ) v4l2_close( p_sys->i_fd );
+    return VLC_EGENERIC;
 
 }
 
 /*****************************************************************************
  * ProbeVideoDev: probe video for capabilities
  *****************************************************************************/
-static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
+static int ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
                                  const char *psz_device )
 {
     int i_fd;
@@ -2751,14 +2728,12 @@ static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
         }
     }
 
-
-    if( i_fd >= 0 ) v4l2_close( i_fd );
-    return true;
+    return i_fd;
 
 open_failed:
 
     if( i_fd >= 0 ) v4l2_close( i_fd );
-    return false;
+    return VLC_EGENERIC;
 
 }
 
-- 
1.7.6




More information about the vlc-devel mailing list