#include <vlc_access.h>
#include <vlc_demux.h>
#include <vlc_input.h>
-#include <vlc_vout.h>
#include <ctype.h>
#include <fcntl.h>
-#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
-#include <sys/soundcard.h>
-
-#ifdef HAVE_ALSA
-# define ALSA_PCM_NEW_HW_PARAMS_API
-# define ALSA_PCM_NEW_SW_PARAMS_API
-# include <alsa/asoundlib.h>
-#endif
-
#include <poll.h>
#ifdef HAVE_LIBV4L2
# include <libv4l2.h>
-#else
-# define v4l2_close close
-# define v4l2_dup dup
-# define v4l2_ioctl ioctl
-# define v4l2_read read
-# define v4l2_mmap mmap
-# define v4l2_munmap munmap
#endif
/*****************************************************************************
#define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
"(0 for autodetect)." )
+#ifdef HAVE_LIBV4L2
+#define LIBV4L2_TEXT N_( "Use libv4l2" )
+#define LIBV4L2_LONGTEXT N_( \
+ "Force usage of the libv4l2 wrapper." )
+#endif
+
#define CTRL_RESET_TEXT N_( "Reset v4l2 controls" )
#define CTRL_RESET_LONGTEXT N_( \
"Reset controls to defaults provided by the v4l2 driver." )
set_section( N_( "Video input" ), NULL )
add_integer( CFG_PREFIX "standard", 0, NULL, STANDARD_TEXT,
- STANDARD_LONGTEXT, false );
- change_integer_list( i_standards_list, psz_standards_list_text, NULL );
+ STANDARD_LONGTEXT, false )
+ change_integer_list( i_standards_list, psz_standards_list_text, NULL )
add_string( CFG_PREFIX "chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
- true );
+ true )
add_integer( CFG_PREFIX "input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT,
- true );
+ true )
add_integer( CFG_PREFIX "audio-input", 0, NULL, AUDIO_INPUT_TEXT,
- AUDIO_INPUT_LONGTEXT, true );
+ AUDIO_INPUT_LONGTEXT, true )
add_integer( CFG_PREFIX "io", IO_METHOD_MMAP, NULL, IOMETHOD_TEXT,
- IOMETHOD_LONGTEXT, true );
- change_integer_list( i_iomethod_list, psz_iomethod_list_text, NULL );
+ IOMETHOD_LONGTEXT, true )
+ change_integer_list( i_iomethod_list, psz_iomethod_list_text, NULL )
add_integer( CFG_PREFIX "width", -1, NULL, WIDTH_TEXT,
- WIDTH_LONGTEXT, true );
+ WIDTH_LONGTEXT, true )
add_integer( CFG_PREFIX "height", -1, NULL, HEIGHT_TEXT,
- HEIGHT_LONGTEXT, true );
+ HEIGHT_LONGTEXT, true )
add_float( CFG_PREFIX "fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, true )
add_integer( CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, NULL,
- CACHING_TEXT, CACHING_LONGTEXT, true );
+ CACHING_TEXT, CACHING_LONGTEXT, true )
+#ifdef HAVE_LIBV4L2
+ add_bool( CFG_PREFIX "use-libv4l2", false, NULL, LIBV4L2_TEXT, LIBV4L2_LONGTEXT, true );
+#endif
set_section( N_( "Tuner" ), NULL )
add_integer( CFG_PREFIX "tuner", 0, NULL, TUNER_TEXT, TUNER_LONGTEXT,
- true );
+ true )
add_integer( CFG_PREFIX "tuner-frequency", -1, NULL, FREQUENCY_TEXT,
- FREQUENCY_LONGTEXT, true );
+ FREQUENCY_LONGTEXT, true )
add_integer( CFG_PREFIX "tuner-audio-mode", -1, NULL, TUNER_AUDIO_MODE_TEXT,
- TUNER_AUDIO_MODE_LONGTEXT, true );
+ TUNER_AUDIO_MODE_LONGTEXT, true )
change_integer_list( i_tuner_audio_modes_list,
- psz_tuner_audio_modes_list_text, 0 );
+ psz_tuner_audio_modes_list_text, 0 )
set_section( N_( "Controls" ),
- N_( "v4l2 driver controls, if supported by your v4l2 driver." ) );
+ N_( "v4l2 driver controls, if supported by your v4l2 driver." ) )
add_bool( CFG_PREFIX "controls-reset", false, NULL, CTRL_RESET_TEXT,
- CTRL_RESET_LONGTEXT, true );
+ CTRL_RESET_LONGTEXT, true )
add_integer( CFG_PREFIX "brightness", -1, NULL, BRIGHTNESS_TEXT,
- BRIGHTNESS_LONGTEXT, true );
+ BRIGHTNESS_LONGTEXT, true )
add_integer( CFG_PREFIX "contrast", -1, NULL, CONTRAST_TEXT,
- CONTRAST_LONGTEXT, true );
+ CONTRAST_LONGTEXT, true )
add_integer( CFG_PREFIX "saturation", -1, NULL, SATURATION_TEXT,
- SATURATION_LONGTEXT, true );
+ SATURATION_LONGTEXT, true )
add_integer( CFG_PREFIX "hue", -1, NULL, HUE_TEXT,
- HUE_LONGTEXT, true );
+ HUE_LONGTEXT, true )
add_integer( CFG_PREFIX "black-level", -1, NULL, BLACKLEVEL_TEXT,
- BLACKLEVEL_LONGTEXT, true );
+ BLACKLEVEL_LONGTEXT, true )
add_integer( CFG_PREFIX "auto-white-balance", -1, NULL,
- AUTOWHITEBALANCE_TEXT, AUTOWHITEBALANCE_LONGTEXT, true );
+ AUTOWHITEBALANCE_TEXT, AUTOWHITEBALANCE_LONGTEXT, true )
add_integer( CFG_PREFIX "do-white-balance", -1, NULL, DOWHITEBALANCE_TEXT,
- DOWHITEBALANCE_LONGTEXT, true );
+ DOWHITEBALANCE_LONGTEXT, true )
add_integer( CFG_PREFIX "red-balance", -1, NULL, REDBALANCE_TEXT,
- REDBALANCE_LONGTEXT, true );
+ REDBALANCE_LONGTEXT, true )
add_integer( CFG_PREFIX "blue-balance", -1, NULL, BLUEBALANCE_TEXT,
- BLUEBALANCE_LONGTEXT, true );
+ BLUEBALANCE_LONGTEXT, true )
add_integer( CFG_PREFIX "gamma", -1, NULL, GAMMA_TEXT,
- GAMMA_LONGTEXT, true );
+ GAMMA_LONGTEXT, true )
add_integer( CFG_PREFIX "exposure", -1, NULL, EXPOSURE_TEXT,
- EXPOSURE_LONGTEXT, true );
+ EXPOSURE_LONGTEXT, true )
add_integer( CFG_PREFIX "autogain", -1, NULL, AUTOGAIN_TEXT,
- AUTOGAIN_LONGTEXT, true );
+ AUTOGAIN_LONGTEXT, true )
add_integer( CFG_PREFIX "gain", -1, NULL, GAIN_TEXT,
- GAIN_LONGTEXT, true );
+ GAIN_LONGTEXT, true )
add_integer( CFG_PREFIX "hflip", -1, NULL, HFLIP_TEXT,
- HFLIP_LONGTEXT, true );
+ HFLIP_LONGTEXT, true )
add_integer( CFG_PREFIX "vflip", -1, NULL, VFLIP_TEXT,
- VFLIP_LONGTEXT, true );
+ VFLIP_LONGTEXT, true )
add_integer( CFG_PREFIX "hcenter", -1, NULL, HCENTER_TEXT,
- HCENTER_LONGTEXT, true );
+ HCENTER_LONGTEXT, true )
add_integer( CFG_PREFIX "vcenter", -1, NULL, VCENTER_TEXT,
- VCENTER_LONGTEXT, true );
+ VCENTER_LONGTEXT, true )
add_integer( CFG_PREFIX "audio-volume", -1, NULL, AUDIO_VOLUME_TEXT,
- AUDIO_VOLUME_LONGTEXT, true );
+ AUDIO_VOLUME_LONGTEXT, true )
add_integer( CFG_PREFIX "audio-balance", -1, NULL, AUDIO_BALANCE_TEXT,
- AUDIO_BALANCE_LONGTEXT, true );
+ AUDIO_BALANCE_LONGTEXT, true )
add_bool( CFG_PREFIX "audio-mute", false, NULL, AUDIO_MUTE_TEXT,
- AUDIO_MUTE_LONGTEXT, true );
+ AUDIO_MUTE_LONGTEXT, true )
add_integer( CFG_PREFIX "audio-bass", -1, NULL, AUDIO_BASS_TEXT,
- AUDIO_BASS_LONGTEXT, true );
+ AUDIO_BASS_LONGTEXT, true )
add_integer( CFG_PREFIX "audio-treble", -1, NULL, AUDIO_TREBLE_TEXT,
- AUDIO_TREBLE_LONGTEXT, true );
+ AUDIO_TREBLE_LONGTEXT, true )
add_integer( CFG_PREFIX "audio-loudness", -1, NULL, AUDIO_LOUDNESS_TEXT,
- AUDIO_LOUDNESS_LONGTEXT, true );
+ AUDIO_LOUDNESS_LONGTEXT, true )
add_string( CFG_PREFIX "set-ctrls", NULL, NULL, S_CTRLS_TEXT,
- S_CTRLS_LONGTEXT, true );
+ S_CTRLS_LONGTEXT, true )
- add_obsolete_string( CFG_PREFIX "dev" );
+ add_obsolete_string( CFG_PREFIX "dev" )
- add_obsolete_string( CFG_PREFIX "adev" );
- add_obsolete_integer( CFG_PREFIX "audio-method" );
- add_obsolete_bool( CFG_PREFIX "stereo" );
- add_obsolete_integer( CFG_PREFIX "samplerate" );
+ add_obsolete_string( CFG_PREFIX "adev" )
+ add_obsolete_integer( CFG_PREFIX "audio-method" )
+ add_obsolete_bool( CFG_PREFIX "stereo" )
+ add_obsolete_integer( CFG_PREFIX "samplerate" )
add_shortcut( "v4l2" )
set_capability( "access_demux", 10 )
set_callbacks( DemuxOpen, DemuxClose )
add_submodule ()
+ add_shortcut( "v4l2" )
add_shortcut( "v4l2c" )
set_description( N_("Video4Linux2 Compressed A/V") )
set_capability( "access", 0 )
static bool ProbeVideoDev( vlc_object_t *, demux_sys_t *,
const char *psz_device );
-static int ControlList( vlc_object_t *, int , bool, bool );
-static int Control( vlc_object_t *, int i_fd,
+static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool );
+static int Control( vlc_object_t *, demux_sys_t *, int i_fd,
const char *psz_name, int i_cid, int i_value );
static int DemuxControlCallback( vlc_object_t *p_this, const char *psz_var,
} 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('?','?','?','?') },
/* Controls */
char *psz_set_ctrls;
+
+
+#ifdef HAVE_LIBV4L2
+ /* */
+ int (*pf_close)( int );
+ int (*pf_dup)( int );
+ int (*pf_ioctl)( int, unsigned long int, ... );
+ 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
};
+#ifdef HAVE_LIBV4L2
+static void use_kernel_v4l2( demux_sys_t *p_sys )
+{
+ p_sys->pf_close = close;
+ p_sys->pf_dup = dup;
+ p_sys->pf_ioctl = ioctl;
+ 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 )
+{
+ p_sys->pf_close = v4l2_close;
+ p_sys->pf_dup = v4l2_dup;
+ p_sys->pf_ioctl = v4l2_ioctl;
+ 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)
+# define v4l2_dup (p_sys->pf_dup)
+# define v4l2_ioctl (p_sys->pf_ioctl)
+# define v4l2_read (p_sys->pf_read)
+# define v4l2_mmap (p_sys->pf_mmap)
+# define v4l2_munmap (p_sys->pf_munmap)
+#else
+# define v4l2_close close
+# define v4l2_dup dup
+# define v4l2_ioctl ioctl
+# define v4l2_read read
+# define v4l2_mmap mmap
+# define v4l2_munmap munmap
+#endif
+
static int FindMainDevice( vlc_object_t *p_this, demux_sys_t *p_sys,
bool b_demux )
{
demux_sys_t *p_sys;
/* Only when selected */
- if( *p_demux->psz_access == '\0' ) return VLC_EGENERIC;
+ if( strcmp( p_demux->psz_access, "v4l2" ) )
+ return VLC_EGENERIC;
/* Set up p_demux */
p_demux->pf_control = DemuxControl;
ParseMRL( p_sys, p_demux->psz_path, (vlc_object_t *) p_demux );
- if( FindMainDevice( p_this, p_sys, true ) != VLC_SUCCESS)
+#ifdef HAVE_LIBV4L2
+ if( !config_GetInt( p_this, CFG_PREFIX "use-libv4l2" ) )
{
- DemuxClose( p_this );
- return VLC_EGENERIC;
+ msg_Dbg( p_this, "Trying direct kernel v4l2" );
+ use_kernel_v4l2( p_sys );
+ if( FindMainDevice( p_this, p_sys, true ) == VLC_SUCCESS)
+ return VLC_SUCCESS;
}
- return VLC_SUCCESS;
+ msg_Dbg( p_this, "Trying libv4l2 wrapper" );
+ use_libv4l2( p_sys );
+#endif
+ if( FindMainDevice( p_this, p_sys, true ) == VLC_SUCCESS)
+ return VLC_SUCCESS;
+
+ DemuxClose( p_this );
+ return VLC_EGENERIC;
}
/*****************************************************************************
/* Only when selected */
if( *p_access->psz_access == '\0' ) return VLC_EGENERIC;
- p_access->pf_read = AccessRead;
- p_access->pf_block = NULL;
- p_access->pf_seek = NULL;
- p_access->pf_control = AccessControl;
- p_access->info.i_update = 0;
- p_access->info.i_size = 0;
- p_access->info.i_pos = 0;
- p_access->info.b_eof = false;
- p_access->info.i_title = 0;
- p_access->info.i_seekpoint = 0;
-
- p_sys = calloc( 1, sizeof( demux_sys_t ) );
- p_access->p_sys = (access_sys_t *) p_sys;
- if( p_sys == NULL ) return VLC_ENOMEM;
+ access_InitFields( p_access );
+ ACCESS_SET_CALLBACKS( AccessRead, NULL, AccessControl, NULL );
+ p_sys = calloc( 1, sizeof( demux_sys_t ));
+ if( !p_sys ) return VLC_ENOMEM;
+ p_access->p_sys = (access_sys_t*)p_sys;
GetV4L2Params( p_sys, (vlc_object_t *) p_access );
ParseMRL( p_sys, p_access->psz_path, (vlc_object_t *) p_access );
- if( FindMainDevice( p_this, p_sys, false ) != VLC_SUCCESS )
+#ifdef HAVE_LIBV4L2
+ if( !config_GetInt( p_this, CFG_PREFIX "use-libv4l2" ) )
{
- AccessClose( p_this );
- return VLC_EGENERIC;
+ msg_Dbg( p_this, "Trying direct kernel v4l2" );
+ use_kernel_v4l2( p_sys );
+ if( FindMainDevice( p_this, p_sys, false ) == VLC_SUCCESS)
+ return VLC_SUCCESS;
}
- return VLC_SUCCESS;
+ msg_Dbg( p_this, "Trying libv4l2 wrapper" );
+ use_libv4l2( p_sys );
+#endif
+ if( FindMainDevice( p_this, p_sys, false ) == VLC_SUCCESS )
+ return VLC_SUCCESS;
+
+ AccessClose( p_this );
+ return VLC_EGENERIC;
}
/*****************************************************************************
*****************************************************************************/
static int AccessControl( access_t *p_access, int i_query, va_list args )
{
- bool *pb_bool;
- int *pi_int;
- int64_t *pi_64;
+ bool *pb_bool;
+ int64_t *pi_64;
demux_sys_t *p_sys = (demux_sys_t *) p_access->p_sys;
switch( i_query )
break;
/* */
- case ACCESS_GET_MTU:
- pi_int = (int*)va_arg( args, int * );
- *pi_int = 0;
- break;
-
case ACCESS_GET_PTS_DELAY:
pi_64 = (int64_t*)va_arg( args, int64_t * );
*pi_64 = (int64_t) p_sys->i_cache * 1000;
{
(void)p_demux;
#ifdef VIDIOC_ENUM_FRAMEINTERVALS
+#ifdef HAVE_LIBV4L2
+ demux_sys_t *p_sys = p_demux->p_sys;
+#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;
{
float f_fps_max = -1.;
#ifdef VIDIOC_ENUM_FRAMESIZES
+#ifdef HAVE_LIBV4L2
+ demux_sys_t *p_sys = p_demux->p_sys;
+#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 )
{
*pi_width = 0;
*pi_height = 0;
#ifdef VIDIOC_ENUM_FRAMESIZES
+#ifdef HAVE_LIBV4L2
+ demux_sys_t *p_sys = p_demux->p_sys;
+#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 )
{
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 )
{
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 */
/* TODO: Move the resolution stuff up here */
/* if MPEG encoder card, no need to do anything else after this */
- ControlList( p_obj, i_fd,
+ 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;
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;
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;
}
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;
/* 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 )
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++ )
/* 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;
int i_standard;
int i_fd;
- int libv4l2_fd;
if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
{
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 */
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++;
/* 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 )
{
* Print a user-class v4l2 control's details, create the relevant variable,
* change the value if needed.
*****************************************************************************/
-static void ControlListPrint( vlc_object_t *p_obj, int i_fd,
+static void ControlListPrint( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
struct v4l2_queryctrl queryctrl,
bool b_reset, bool b_demux )
{
if( b_reset && queryctrl.default_value != control.value )
{
msg_Dbg( p_obj, " reset value to default" );
- Control( p_obj, i_fd, psz_name,
- queryctrl.id, queryctrl.default_value );
+ Control( p_obj, p_sys, i_fd, psz_name,
+ queryctrl.id, queryctrl.default_value );
}
}
else
{
- Control( p_obj, i_fd, psz_name,
- queryctrl.id, i_val );
+ Control( p_obj, p_sys, i_fd, psz_name,
+ queryctrl.id, i_val );
}
}
break;
* List all user-class v4l2 controls, set them to the user specified
* value and create the relevant variables to enable runtime changes
*****************************************************************************/
-static int ControlList( vlc_object_t *p_obj, int i_fd,
+static int ControlList( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
bool b_reset, bool b_demux )
{
struct v4l2_queryctrl queryctrl;
queryctrl.name, queryctrl.id );
break;
}
- ControlListPrint( p_obj, i_fd, queryctrl, b_reset, b_demux );
+ ControlListPrint( p_obj, p_sys, i_fd, queryctrl, b_reset, b_demux );
queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
}
}
continue;
msg_Dbg( p_obj, "Available control: %s (%x)",
queryctrl.name, queryctrl.id );
- ControlListPrint( p_obj, i_fd, queryctrl, b_reset, b_demux );
+ ControlListPrint( p_obj, p_sys, i_fd, queryctrl,
+ b_reset, b_demux );
}
}
continue;
msg_Dbg( p_obj, "Available private control: %s (%x)",
queryctrl.name, queryctrl.id );
- ControlListPrint( p_obj, i_fd, queryctrl, b_reset, b_demux );
+ ControlListPrint( p_obj, p_sys, i_fd, queryctrl,
+ b_reset, b_demux );
}
else
break;
if( !strncasecmp( psz_name, psz_parser, i_maxstrlen ) )
{
- Control( p_obj, i_fd, psz_name, i_cid,
+ Control( p_obj, p_sys, i_fd, psz_name, i_cid,
strtol( ++psz_assign, &psz_parser, 0) );
}
}
/*****************************************************************************
* Reset all user-class v4l2 controls to their default value
*****************************************************************************/
-static int ControlReset( vlc_object_t *p_obj, int i_fd )
+static int ControlReset( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd )
{
struct v4l2_queryctrl queryctrl;
int i_cid;
for( i = 0; controls[i].psz_name != NULL; i++ )
if( controls[i].i_cid == queryctrl.id ) break;
name2var( queryctrl.name );
- Control( p_obj, i_fd,
+ Control( p_obj, p_sys, i_fd,
controls[i].psz_name ? : (const char *)queryctrl.name,
queryctrl.id, queryctrl.default_value );
}
for( i = 0; controls[i].psz_name != NULL; i++ )
if( controls[i].i_cid == queryctrl.id ) break;
name2var( queryctrl.name );
- Control( p_obj, i_fd,
+ Control( p_obj, p_sys, i_fd,
controls[i].psz_name ? : (const char *)queryctrl.name,
queryctrl.id, queryctrl.default_value );
}
&& queryctrl.default_value != control.value )
{
name2var( queryctrl.name );
- Control( p_obj, i_fd, (const char *)queryctrl.name,
+ Control( p_obj, p_sys, i_fd, (const char *)queryctrl.name,
queryctrl.id, queryctrl.default_value );
}
}
/*****************************************************************************
* Issue user-class v4l2 controls
*****************************************************************************/
-static int Control( vlc_object_t *p_obj, int i_fd,
+static int Control( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
const char *psz_name, int i_cid, int i_value )
{
+ (void)p_sys;
struct v4l2_queryctrl queryctrl;
struct v4l2_control control;
struct v4l2_ext_control ext_control;
int i_ret = -1;
- if( i_value >= 0 )
+ if( i_value >= queryctrl.minimum && i_value <= queryctrl.maximum )
{
ext_control.value = i_value;
if( v4l2_ioctl( i_fd, VIDIOC_S_EXT_CTRLS, &ext_controls ) < 0 )
if( i_fd < 0 )
return VLC_EGENERIC;
- Control( p_this, i_fd, psz_var, i_cid, newval.i_int );
+ Control( p_this, p_sys, i_fd, psz_var, i_cid, newval.i_int );
return VLC_EGENERIC;
}
if( i_fd < 0 )
return VLC_EGENERIC;
- ControlReset( p_this, i_fd );
+ ControlReset( p_this, p_sys, i_fd );
return VLC_EGENERIC;
}
if( i_fd < 0 )
return VLC_EGENERIC;
- Control( p_this, i_fd, psz_var, i_cid, newval.i_int );
+ Control( p_this, p_sys, i_fd, psz_var, i_cid, newval.i_int );
return VLC_EGENERIC;
}
if( i_fd < 0 )
return VLC_EGENERIC;
- ControlReset( p_this, i_fd );
+ ControlReset( p_this, p_sys, i_fd );
return VLC_EGENERIC;
}