]> git.sesse.net Git - vlc/blobdiff - modules/access/v4l2.c
Merge commit 'origin/1.0-bugfix'
[vlc] / modules / access / v4l2.c
index 98c729ea0e3c40d269f639d0fd238ab527304835..c6688d6b1114bd4fbc5bdfcf084cd3097b684708 100644 (file)
@@ -339,6 +339,7 @@ vlc_module_begin ()
     set_callbacks( DemuxOpen, DemuxClose )
 
     add_submodule ()
+    add_shortcut( "v4l2" )
     add_shortcut( "v4l2c" )
     set_description( N_("Video4Linux2 Compressed A/V") )
     set_capability( "access", 0 )
@@ -399,35 +400,34 @@ static const struct
 } v4l2chroma_to_fourcc[] =
 {
     /* Raw data types */
-    { V4L2_PIX_FMT_GREY,    VLC_FOURCC('G','R','E','Y'), 0, 0, 0 },
+    { V4L2_PIX_FMT_GREY,    VLC_CODEC_GREY, 0, 0, 0 },
     { V4L2_PIX_FMT_HI240,   VLC_FOURCC('I','2','4','0'), 0, 0, 0 },
-    { V4L2_PIX_FMT_RGB555,  VLC_FOURCC('R','V','1','5'), 0x001f,0x03e0,0x7c00 },
-    { V4L2_PIX_FMT_RGB565,  VLC_FOURCC('R','V','1','6'), 0x001f,0x07e0,0xf800 },
+    { V4L2_PIX_FMT_RGB555,  VLC_CODEC_RGB15, 0x001f,0x03e0,0x7c00 },
+    { V4L2_PIX_FMT_RGB565,  VLC_CODEC_RGB16, 0x001f,0x07e0,0xf800 },
     /* Won't work since we don't know how to handle such gmask values
      * correctly
-    { V4L2_PIX_FMT_RGB555X, VLC_FOURCC('R','V','1','5'), 0x007c,0xe003,0x1f00 },
-    { V4L2_PIX_FMT_RGB565X, VLC_FOURCC('R','V','1','6'), 0x00f8,0xe007,0x1f00 },
+    { V4L2_PIX_FMT_RGB555X, VLC_CODEC_RGB15, 0x007c,0xe003,0x1f00 },
+    { V4L2_PIX_FMT_RGB565X, VLC_CODEC_RGB16, 0x00f8,0xe007,0x1f00 },
     */
-    { V4L2_PIX_FMT_BGR24,   VLC_FOURCC('R','V','2','4'), 0xff0000,0xff00,0xff },
-    { V4L2_PIX_FMT_RGB24,   VLC_FOURCC('R','V','2','4'), 0xff,0xff00,0xff0000 },
-    { V4L2_PIX_FMT_BGR32,   VLC_FOURCC('R','V','3','2'), 0xff0000,0xff00,0xff },
-    { V4L2_PIX_FMT_RGB32,   VLC_FOURCC('R','V','3','2'), 0xff,0xff00,0xff0000 },
-    { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','2'), 0, 0, 0 },
-    { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','V'), 0, 0, 0 },
-    { V4L2_PIX_FMT_UYVY,    VLC_FOURCC('U','Y','V','Y'), 0, 0, 0 },
+    { V4L2_PIX_FMT_BGR24,   VLC_CODEC_RGB24, 0xff0000,0xff00,0xff },
+    { V4L2_PIX_FMT_RGB24,   VLC_CODEC_RGB24, 0xff,0xff00,0xff0000 },
+    { V4L2_PIX_FMT_BGR32,   VLC_CODEC_RGB32, 0xff0000,0xff00,0xff },
+    { V4L2_PIX_FMT_RGB32,   VLC_CODEC_RGB32, 0xff,0xff00,0xff0000 },
+    { V4L2_PIX_FMT_YUYV,    VLC_CODEC_YUYV, 0, 0, 0 },
+    { V4L2_PIX_FMT_UYVY,    VLC_CODEC_UYVY, 0, 0, 0 },
     { V4L2_PIX_FMT_Y41P,    VLC_FOURCC('I','4','1','N'), 0, 0, 0 },
-    { V4L2_PIX_FMT_YUV422P, VLC_FOURCC('I','4','2','2'), 0, 0, 0 },
-    { V4L2_PIX_FMT_YVU420,  VLC_FOURCC('Y','V','1','2'), 0, 0, 0 },
-    { V4L2_PIX_FMT_YUV411P, VLC_FOURCC('I','4','1','1'), 0, 0, 0 },
-    { V4L2_PIX_FMT_YUV410,  VLC_FOURCC('I','4','1','0'), 0, 0, 0 },
+    { V4L2_PIX_FMT_YUV422P, VLC_CODEC_I422, 0, 0, 0 },
+    { V4L2_PIX_FMT_YVU420,  VLC_CODEC_YV12, 0, 0, 0 },
+    { V4L2_PIX_FMT_YUV411P, VLC_CODEC_I411, 0, 0, 0 },
+    { V4L2_PIX_FMT_YUV410,  VLC_CODEC_I410, 0, 0, 0 },
 
     /* Raw data types, not in V4L2 spec but still in videodev2.h and supported
      * by VLC */
-    { V4L2_PIX_FMT_YUV420,  VLC_FOURCC('I','4','2','0'), 0, 0, 0 },
-    /* FIXME { V4L2_PIX_FMT_RGB444,  VLC_FOURCC('R','V','3','2') }, */
+    { V4L2_PIX_FMT_YUV420,  VLC_CODEC_I420, 0, 0, 0 },
+    /* FIXME { V4L2_PIX_FMT_RGB444,  VLC_CODEC_RGB32 }, */
 
     /* Compressed data types */
-    { V4L2_PIX_FMT_MJPEG,   VLC_FOURCC('M','J','P','G'), 0, 0, 0 },
+    { V4L2_PIX_FMT_MJPEG,   VLC_CODEC_MJPG, 0, 0, 0 },
 #if 0
     { V4L2_PIX_FMT_JPEG,    VLC_FOURCC('J','P','E','G') },
     { V4L2_PIX_FMT_DV,      VLC_FOURCC('?','?','?','?') },
@@ -546,6 +546,7 @@ struct demux_sys_t
     ssize_t (*pf_read)( int, void *, size_t );
     void *(*pf_mmap)( void *, size_t, int, int, int, off_t );
     int (*pf_munmap)( void *, size_t );
+    bool b_libv4l2;
 #endif
 };
 
@@ -558,6 +559,7 @@ static void use_kernel_v4l2( demux_sys_t *p_sys )
     p_sys->pf_read = read;
     p_sys->pf_mmap = mmap;
     p_sys->pf_munmap = munmap;
+    p_sys->b_libv4l2 = false;
 }
 
 static void use_libv4l2( demux_sys_t *p_sys )
@@ -568,6 +570,7 @@ static void use_libv4l2( demux_sys_t *p_sys )
     p_sys->pf_read = v4l2_read;
     p_sys->pf_mmap = v4l2_mmap;
     p_sys->pf_munmap = v4l2_munmap;
+    p_sys->b_libv4l2 = true;
 }
 
 #   define v4l2_close (p_sys->pf_close)
@@ -1065,7 +1068,7 @@ static int AccessOpen( vlc_object_t * p_this )
     {
         msg_Dbg( p_this, "Trying direct kernel v4l2" );
         use_kernel_v4l2( p_sys );
-        if( FindMainDevice( p_this, p_sys, true ) == VLC_SUCCESS)
+        if( FindMainDevice( p_this, p_sys, false ) == VLC_SUCCESS)
             return VLC_SUCCESS;
     }
 
@@ -1556,7 +1559,7 @@ static float GetMaxFrameRate( demux_t *p_demux, int i_fd,
 #endif
     /* This is new in Linux 2.6.19 */
     struct v4l2_frmivalenum frmival;
-    frmival.index = 0;
+    memset( &frmival, 0, sizeof(frmival) );
     frmival.pixel_format = i_pixel_format;
     frmival.width = i_width;
     frmival.height = i_height;
@@ -1599,7 +1602,7 @@ static float GetAbsoluteMaxFrameRate( demux_t *p_demux, int i_fd,
 #endif
     /* This is new in Linux 2.6.19 */
     struct v4l2_frmsizeenum frmsize;
-    frmsize.index = 0;
+    memset( &frmsize, 0, sizeof(frmsize) );
     frmsize.pixel_format = i_pixel_format;
     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) >= 0 )
     {
@@ -1660,7 +1663,7 @@ static void GetMaxDimensions( demux_t *p_demux, int i_fd,
 #endif
     /* This is new in Linux 2.6.19 */
     struct v4l2_frmsizeenum frmsize;
-    frmsize.index = 0;
+    memset( &frmsize, 0, sizeof(frmsize) );
     frmsize.pixel_format = i_pixel_format;
     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) >= 0 )
     {
@@ -1736,7 +1739,6 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     enum v4l2_buf_type buf_type;
     const char *psz_device = p_sys->psz_device;
     es_format_t es_fmt;
-    int libv4l2_fd;
 
     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
     {
@@ -1751,11 +1753,13 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
        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. */
-    libv4l2_fd = v4l2_fd_open( i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION );
-    if( libv4l2_fd != -1 )
-        i_fd = libv4l2_fd;
-#else
-    libv4l2_fd = i_fd;
+    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
 
     /* Tune the tuner */
@@ -1850,6 +1854,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     ControlList( p_obj, p_sys, i_fd,
                   var_GetBool( p_obj, "v4l2-controls-reset" ), b_demux );
     SetAvailControlsByString( p_obj, p_sys, i_fd );
+
     if( false == b_demux)
     {
         return i_fd;
@@ -1863,7 +1868,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         case IO_METHOD_READ:
             if( !(p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE) )
             {
-                msg_Err( p_demux, "device does not support read i/o" );
+                msg_Err( p_obj, "device does not support read i/o" );
                 goto open_failed;
             }
             break;
@@ -1872,13 +1877,13 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         case IO_METHOD_USERPTR:
             if( !(p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING) )
             {
-                msg_Err( p_demux, "device does not support streaming i/o" );
+                msg_Err( p_obj, "device does not support streaming i/o" );
                 goto open_failed;
             }
             break;
 
         default:
-            msg_Err( p_demux, "io method not supported" );
+            msg_Err( p_obj, "io method not supported" );
             goto open_failed;
     }
 
@@ -1936,7 +1941,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
 
     fmt.fmt.pix.width = p_sys->i_width;
     fmt.fmt.pix.height = p_sys->i_height;
-    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+    fmt.fmt.pix.field = V4L2_FIELD_NONE;
 
     /* Test and set Chroma */
     fmt.fmt.pix.pixelformat = 0;
@@ -1945,9 +1950,10 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
         /* User specified chroma */
         if( strlen( p_sys->psz_requested_chroma ) >= 4 )
         {
-            int i_requested_fourcc = VLC_FOURCC(
+            int i_requested_fourcc = vlc_fourcc_GetCodec( VIDEO_ES,
+                                                          VLC_FOURCC(
                 p_sys->psz_requested_chroma[0], p_sys->psz_requested_chroma[1],
-                p_sys->psz_requested_chroma[2], p_sys->psz_requested_chroma[3] );
+                p_sys->psz_requested_chroma[2], p_sys->psz_requested_chroma[3] ) );
             for( int i = 0; v4l2chroma_to_fourcc[i].i_v4l2 != 0; i++ )
             {
                 if( v4l2chroma_to_fourcc[i].i_fourcc == i_requested_fourcc )
@@ -2004,6 +2010,45 @@ 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;
 
+    /* Check interlacing */
+    if( v4l2_ioctl( i_fd, VIDIOC_G_FMT, &fmt ) < 0 ) {;}
+    switch( fmt.fmt.pix.field )
+    {
+        case V4L2_FIELD_NONE:
+            msg_Dbg( p_demux, "Interlacing setting: progressive" );
+            break;
+        case V4L2_FIELD_TOP:
+            msg_Dbg( p_demux, "Interlacing setting: top field only" );
+            break;
+        case V4L2_FIELD_BOTTOM:
+            msg_Dbg( p_demux, "Interlacing setting: bottom field only" );
+            break;
+        case V4L2_FIELD_INTERLACED:
+            msg_Dbg( p_demux, "Interlacing setting: interleaved (bottom top if M/NTSC, top bottom otherwise)" );
+            break;
+        case V4L2_FIELD_SEQ_TB:
+            msg_Dbg( p_demux, "Interlacing setting: sequential top bottom" );
+            break;
+        case V4L2_FIELD_SEQ_BT:
+            msg_Dbg( p_demux, "Interlacing setting: sequential bottom top" );
+            break;
+        case V4L2_FIELD_ALTERNATE:
+            msg_Dbg( p_demux, "Interlacing setting: alternate fields" );
+            break;
+        case V4L2_FIELD_INTERLACED_TB:
+            msg_Dbg( p_demux, "Interlacing setting: interleaved top bottom" );
+            break;
+        case V4L2_FIELD_INTERLACED_BT:
+            msg_Dbg( p_demux, "Interlacing setting: interleaved bottom top" );
+            break;
+        default:
+            msg_Warn( p_demux, "Interlacing setting: unknown type (%d)",
+                      fmt.fmt.pix.field );
+            break;
+    }
+    if( fmt.fmt.pix.field != V4L2_FIELD_NONE )
+        msg_Warn( p_demux, "Interlaced inputs haven't been tested. Please report any issue." );
+
     /* Look up final fourcc */
     p_sys->i_fourcc = 0;
     for( int i = 0; v4l2chroma_to_fourcc[i].i_fourcc != 0; i++ )
@@ -2031,7 +2076,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
     /* This is new in Linux 2.6.19 */
     /* List supported frame rates */
     struct v4l2_frmivalenum frmival;
-    frmival.index = 0;
+    memset( &frmival, 0, sizeof(frmival) );
     frmival.pixel_format = fmt.fmt.pix.pixelformat;
     frmival.width = p_sys->i_width;
     frmival.height = p_sys->i_height;
@@ -2188,7 +2233,6 @@ static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
     int i_standard;
 
     int i_fd;
-    int libv4l2_fd;
 
     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
     {
@@ -2203,11 +2247,13 @@ static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
        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. */
-    libv4l2_fd = v4l2_fd_open( i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION );
-    if( libv4l2_fd != -1 )
-        i_fd = libv4l2_fd;
-#else
-    libv4l2_fd = i_fd;
+    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
 
     /* Get device capabilites */
@@ -2247,7 +2293,7 @@ static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
     {
         struct v4l2_input t_input;
-        t_input.index = 0;
+        memset( &t_input, 0, sizeof(t_input) );
         while( v4l2_ioctl( i_fd, VIDIOC_ENUMINPUT, &t_input ) >= 0 )
         {
             p_sys->i_input++;
@@ -2453,7 +2499,7 @@ static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
                     /* This is new in Linux 2.6.19 */
                     /* List valid frame sizes for this format */
                     struct v4l2_frmsizeenum frmsize;
-                    frmsize.index = 0;
+                    memset( &frmsize, 0, sizeof(frmsize) );
                     frmsize.pixel_format = p_sys->p_codecs[i_index].pixelformat;
                     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) < 0 )
                     {