]> git.sesse.net Git - vlc/blobdiff - modules/access/v4l/v4l.c
* include/modules_inner.h, include/modules.h: added a shortname field to the module...
[vlc] / modules / access / v4l / v4l.c
index cc0f13c7d60d82e27267d6c6bc2c962b426dff29..edddf6e2b4949e0e31603ba3e319abc10f3675dc 100644 (file)
@@ -1,12 +1,12 @@
 /*****************************************************************************
  * v4l.c : Video4Linux input module for vlc
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: v4l.c,v 1.35 2003/11/26 22:00:56 gbazin Exp $
+ * Copyright (C) 2002-2004 VideoLAN
+ * $Id$
  *
  * Author: Laurent Aimar <fenrir@via.ecp.fr>
  *         Paul Forgey <paulf at aphrodite dot com>
- *         Gildas Bazin <gbazin@netcourrier.com>
+ *         Gildas Bazin <gbazin@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -75,7 +75,7 @@ static void DemuxClose ( vlc_object_t * );
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Allows you to modify the default caching value for v4l streams. This " \
-    "value should be set in miliseconds units." )
+    "value should be set in millisecond units." )
 #define VDEV_TEXT N_("Video device name")
 #define VDEV_LONGTEXT N_( \
     "Specify the name of the video device that will be used. " \
@@ -86,18 +86,15 @@ static void DemuxClose ( vlc_object_t * );
     "If you don't specify anything, no audio device will be used.")
 #define CHROMA_TEXT N_("Video input chroma format")
 #define CHROMA_LONGTEXT N_( \
-    "Force the v4l video device to use a specific chroma format " \
-    "(eg. I420 (default), RV24, etc...)")
+    "Force the Video4Linux video device to use a specific chroma format " \
+    "(eg. I420 (default), RV24, etc.)")
 
 vlc_module_begin();
+    set_shortname( _("Video4Linux") );
     set_description( _("Video4Linux input") );
-    add_category_hint( N_("v4l"), NULL, VLC_TRUE );
+
     add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
-    add_shortcut( "v4l" );
-    set_capability( "access", 10 );
-    set_callbacks( AccessOpen, AccessClose );
-
     add_string( "v4l-vdev", "/dev/video", 0, VDEV_TEXT, VDEV_LONGTEXT,
                 VLC_FALSE );
     add_string( "v4l-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
@@ -105,6 +102,10 @@ vlc_module_begin();
     add_string( "v4l-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
                 VLC_TRUE );
 
+    add_shortcut( "v4l" );
+    set_capability( "access", 10 );
+    set_callbacks( AccessOpen, AccessClose );
+
     add_submodule();
         set_description( _("Video4Linux demuxer") );
         add_shortcut( "v4l" );
@@ -186,6 +187,11 @@ struct access_sys_t
     int i_width;
     int i_height;
 
+    int i_brightness;
+    int i_hue;
+    int i_colour;
+    int i_contrast;
+
     float f_fps;            /* <= 0.0 mean to grab at full rate */
     mtime_t i_video_pts;    /* only used when f_fps > 0 */
 
@@ -289,6 +295,11 @@ static int AccessOpen( vlc_object_t *p_this )
     p_sys->f_fps            = -1.0;
     p_sys->i_video_pts      = -1;
 
+    p_sys->i_brightness     = -1;
+    p_sys->i_hue            = -1;
+    p_sys->i_colour         = -1;
+    p_sys->i_contrast       = -1;
+
     p_sys->b_mjpeg     = VLC_FALSE;
     p_sys->i_decimation = 1;
     p_sys->i_quality = 100;
@@ -577,6 +588,26 @@ static void ParseMRL( input_thread_t *p_input )
                              p_sys->i_height );
                 }
             }
+            else if( !strncmp( psz_parser, "brightness=", strlen( "brightness=" ) ) )
+            {
+                p_sys->i_brightness = strtol( psz_parser + strlen( "brightness=" ),
+                                              &psz_parser, 0 );
+            }
+            else if( !strncmp( psz_parser, "colour=", strlen( "colour=" ) ) )
+            {
+                p_sys->i_colour = strtol( psz_parser + strlen( "colour=" ),
+                                          &psz_parser, 0 );
+            }
+            else if( !strncmp( psz_parser, "hue=", strlen( "hue=" ) ) )
+            {
+                p_sys->i_hue = strtol( psz_parser + strlen( "hue=" ), 
+                                       &psz_parser, 0 );
+            }
+            else if( !strncmp( psz_parser, "contrast=", strlen( "contrast=" ) ) )
+            {
+                p_sys->i_contrast = strtol( psz_parser + strlen( "contrast=" ),
+                                            &psz_parser, 0 );
+            }
             else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
             {
                 p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ),
@@ -927,6 +958,37 @@ int OpenVideoDev( input_thread_t *p_input, char *psz_device )
 
     if( !p_sys->b_mjpeg )
     {
+        /* set hue/color/.. */
+        if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
+        {
+            struct video_picture vid_picture = p_sys->vid_picture;
+
+            if( p_sys->i_brightness >= 0 && p_sys->i_brightness < 65536 )
+            {
+                vid_picture.brightness = p_sys->i_brightness;
+            }
+            if( p_sys->i_colour >= 0 && p_sys->i_colour < 65536 )
+            {
+                vid_picture.colour = p_sys->i_colour;
+            }
+            if( p_sys->i_hue >= 0 && p_sys->i_hue < 65536 )
+            {
+                vid_picture.hue = p_sys->i_hue;
+            }
+            if( p_sys->i_contrast  >= 0 && p_sys->i_contrast < 65536 )
+            {
+                vid_picture.contrast = p_sys->i_contrast;
+            }
+            if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
+            {
+                msg_Dbg( p_input, "v4l device uses brightness: %d", vid_picture.brightness );
+                msg_Dbg( p_input, "v4l device uses colour: %d", vid_picture.colour );
+                msg_Dbg( p_input, "v4l device uses hue: %d", vid_picture.hue );
+                msg_Dbg( p_input, "v4l device uses contrast: %d", vid_picture.contrast );
+                p_sys->vid_picture = vid_picture;
+            }
+        }
+
         /* Find out video format used by device */
         if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
         {
@@ -1228,31 +1290,38 @@ static int GrabAudio( input_thread_t * p_input,
 static uint8_t *GrabCapture( input_thread_t *p_input )
 {
     access_sys_t *p_sys = p_input->p_access_data;
-    p_sys->vid_mmap.frame = ( p_sys->i_frame_pos + 1 ) %
-                            p_sys->vid_mbuf.frames;
-    for( ;; )
+    int i_captured_frame = p_sys->i_frame_pos;
+
+    p_sys->vid_mmap.frame = (p_sys->i_frame_pos + 1) % p_sys->vid_mbuf.frames;
+
+    while( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
     {
-        if( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) >= 0 )
+        if( errno != EAGAIN )
         {
-            break;
+            msg_Err( p_input, "failed capturing new frame" );
+            return NULL;
         }
 
-        if( errno != EAGAIN )
+        if( p_input->b_die )
         {
-            msg_Err( p_input, "failed while grabbing new frame" );
-            return( NULL );
+            return NULL;
         }
-        msg_Dbg( p_input, "another try ?" );
-    }
 
-    //msg_Warn( p_input, "grab a new frame" );
+        msg_Dbg( p_input, "grab failed, trying again" );
+    }
 
-    while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 &&
-           ( errno == EAGAIN || errno == EINTR ) );
+    while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 )
+    {
+        if( errno != EAGAIN && errno != EINTR )    
+        {
+            msg_Err( p_input, "failed syncing new frame" );
+            return NULL;
+        }
+    }
 
     p_sys->i_frame_pos = p_sys->vid_mmap.frame;
     /* leave i_video_frame_size alone */
-    return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
+    return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[i_captured_frame];
 }
 
 static uint8_t *GrabMJPEG( input_thread_t *p_input )
@@ -1266,12 +1335,27 @@ static uint8_t *GrabMJPEG( input_thread_t *p_input )
 
     /* re-queue the last frame we sync'd */
     if( p_sys->i_frame_pos != -1 )
-        while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT, &p_sys->i_frame_pos ) < 0 &&
-                ( errno == EAGAIN || errno == EINTR ) );
+    {
+        while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT,
+                                       &p_sys->i_frame_pos ) < 0 )
+        {
+            if( errno != EAGAIN && errno != EINTR )    
+            {
+                msg_Err( p_input, "failed capturing new frame" );
+                return NULL;
+            }
+        }
+    }
 
     /* sync on the next frame */
-    while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 &&
-            ( errno == EAGAIN || errno == EINTR ) );
+    while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 )
+    {
+        if( errno != EAGAIN && errno != EINTR )    
+        {
+            msg_Err( p_input, "failed syncing new frame" );
+            return NULL;
+        }
+    }
 
     p_sys->i_frame_pos = sync.frame;
     p_frame = p_sys->p_video_mmap + p_sys->mjpeg_buffers.size * sync.frame;
@@ -1355,10 +1439,10 @@ static int GrabVideo( input_thread_t * p_input,
     {
         mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);
 
-        /* Dif we wait long enougth ? */
+        /* Did we wait long enougth ? */
         if( p_sys->i_video_pts + i_dur > mdate() )
         {
-            return VLC_EGENERIC;
+            return VLC_ETIMEOUT;
         }
     }
 
@@ -1449,17 +1533,29 @@ static int Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
             GrabAudio( p_input, &p_sys->p_data,
                        &p_sys->i_data_size, &i_pts ) != VLC_SUCCESS )
         {
+            int i_ret = VLC_ETIMEOUT;
+
             /* Try grabbing video frame */
             i_stream = 0;
-            if( p_sys->fd_video < 0 ||
-                GrabVideo( p_input, &p_sys->p_data,
-                           &p_sys->i_data_size, &i_pts ) != VLC_SUCCESS )
+            if( p_sys->fd_video > 0 )
+            {
+                i_ret = GrabVideo( p_input, &p_sys->p_data,
+                                   &p_sys->i_data_size, &i_pts );
+            }
+
+            /* No video or timeout */
+            if( i_ret == VLC_ETIMEOUT )
             {
                 /* Sleep so we do not consume all the cpu, 10ms seems
                  * like a good value (100fps) */
                 msleep( 10000 );
                 continue;
             }
+            else if( i_ret != VLC_SUCCESS )
+            {
+                msg_Err( p_input, "Error during capture!" );
+                return -1;
+            }
         }
 
         /* create pseudo header */
@@ -1501,14 +1597,11 @@ static int DemuxOpen( vlc_object_t *p_this )
     /* a little test to see if it's a v4l stream */
     if( stream_Peek( p_input->s, &p_peek, 8 ) < 8 )
     {
-        msg_Warn( p_input, "v4l plugin discarded (cannot peek)" );
         return VLC_EGENERIC;
     }
 
-    if( strncmp( p_peek, ".v4l", 4 ) ||
-        ( i_es = GetDWBE( &p_peek[4] ) ) <= 0 )
+    if( strncmp( p_peek, ".v4l", 4 ) || ( i_es = GetDWBE( &p_peek[4] ) ) <= 0 )
     {
-        msg_Warn( p_input, "v4l plugin discarded (not a valid stream)" );
         return VLC_EGENERIC;
     }
 
@@ -1517,7 +1610,7 @@ static int DemuxOpen( vlc_object_t *p_this )
     {
         vlc_mutex_unlock( &p_input->stream.stream_lock );
         msg_Err( p_input, "cannot init stream" );
-        return( VLC_EGENERIC );
+        return VLC_EGENERIC;
     }
     p_input->stream.i_mux_rate =  0 / 50;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
@@ -1541,8 +1634,8 @@ static int DemuxOpen( vlc_object_t *p_this )
 
         if( !strncmp( p_peek, "auds", 4 ) )
         {
-            es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( p_peek[4], p_peek[5],
-                                                        p_peek[6], p_peek[7] ) );
+            es_format_Init( &fmt, AUDIO_ES,
+                VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) );
 
             fmt.audio.i_channels = GetDWBE( &p_peek[8] );
             fmt.audio.i_rate = GetDWBE( &p_peek[12] );