/*****************************************************************************
* 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
#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. " \
"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,
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" );
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 */
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;
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=" ),
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 )
{
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 )
/* 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;
{
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;
}
}
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 */
/* 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;
}
{
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 );
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] );