From 92f7ddf2f9e63eab1da9f8f134407a5e5b3d7dfa Mon Sep 17 00:00:00 2001 From: Benjamin Pracht <bigben@videolan.org> Date: Sun, 27 Aug 2006 17:06:30 +0000 Subject: [PATCH] * Some more probing * The debug output from a v4l2 capable webcam with this would help... --- modules/access/v4l2.c | 180 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 33 deletions(-) diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c index 53f36be657d9..81a26c3aae30 100644 --- a/modules/access/v4l2.c +++ b/modules/access/v4l2.c @@ -53,6 +53,10 @@ static void Close( vlc_object_t * ); #define DEV_LONGTEXT N_( \ "Name of the device to use. " \ "If you don't specify anything, /dev/video0 will be used.") +#define INPUT_TEXT N_( "Input" ) +#define INPUT_LONGTEXT N_( \ + "Input of the card to use (Usually, 0 = tuner, " \ + "1 = composite, 2 = svideo)." ) vlc_module_begin(); @@ -63,6 +67,8 @@ vlc_module_begin(); add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT, VLC_FALSE ); + add_integer( "v4l2-input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT, + VLC_TRUE ); add_shortcut( "v4l2" ); set_capability( "access_demux", 10 ); @@ -73,10 +79,13 @@ vlc_module_end(); * Access: local prototypes *****************************************************************************/ -static int Demux ( demux_t * ); +static int DemuxMMAP( demux_t * ); static int Control( demux_t *, int, va_list ); -static int OpenDev( demux_t * ); +static int ProbeDev( demux_t * ); +static int OpenVideoDev( demux_t * ); + +static block_t *GrabVideo( demux_t * ); struct demux_sys_t { @@ -88,6 +97,7 @@ struct demux_sys_t int i_input; struct v4l2_input *p_inputs; + int i_selected_input; int i_audio; /* V4L2 devices cannot have more than 32 audio inputs */ @@ -95,6 +105,9 @@ struct demux_sys_t int i_tuner; struct v4l2_tuner *p_tuners; + + int i_codec; + struct v4l2_fmtdesc *p_codecs; }; /***************************************************************************** @@ -111,7 +124,6 @@ static int Open( vlc_object_t *p_this ) demux_sys_t sys; /* Set up p_demux */ - p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->info.i_update = 0; p_demux->info.i_title = 0; @@ -123,7 +135,9 @@ static int Open( vlc_object_t *p_this ) p_sys->psz_device = var_CreateGetString( p_demux, "v4l2-dev" ); - if( OpenDev( p_demux ) < 0 ) return VLC_EGENERIC; + if( ProbeDev( p_demux ) < 0 ) return VLC_EGENERIC; + + if( OpenVideoDev( p_demux ) < 0 ) return VLC_EGENERIC; return VLC_SUCCESS; } @@ -136,8 +150,12 @@ static void Close( vlc_object_t *p_this ) demux_t *p_demux = (demux_t *)p_this; demux_sys_t *p_sys = p_demux->p_sys; + if( p_sys->i_fd_video >= 0 ) close( p_sys->i_fd_video ); + if( p_sys->psz_device ) free( p_sys->psz_device ); if( p_sys->p_inputs ) free( p_sys->p_inputs ); + if( p_sys->p_tuners ) free( p_sys->p_tuners ); + if( p_sys->p_codecs ) free( p_sys->p_codecs ); free( p_sys ); } @@ -152,17 +170,77 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) /***************************************************************************** * Demux: *****************************************************************************/ -static int Demux( demux_t *p_demux ) +static int DemuxMMAP( demux_t *p_demux ) { } /***************************************************************************** - * OpenDev: open the device and probe for capabilities + * OpenVideoDev: open and set up the video device and probe for capabilities *****************************************************************************/ -int OpenDev( demux_t *p_demux ) +int OpenVideoDev( demux_t *p_demux ) { - int i_device_index; + int i_fd; + demux_sys_t *p_sys = p_demux->p_sys; + + if( ( i_fd = open( p_sys->psz_device, O_RDWR ) ) < 0 ) + { + msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) ); + goto open_failed; + } + + p_sys->i_fd_video = i_fd; + + if( p_sys->i_selected_input = var_CreateGetInteger( p_demux, "v4l2-input" ) + > p_sys->i_input ) + { + msg_Warn( p_demux, "invalid input. Using the default one" ); + p_sys->i_selected_input = 0; + } + + if( ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_selected_input ) < 0 ) + { + msg_Err( p_demux, "cannot set input (%s)", strerror( errno ) ); + goto open_failed; + } + + if( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING ) + { + struct v4l2_requestbuffers reqbuf; + + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + reqbuf.count = 0; + + if( ioctl( i_fd, VIDIOC_REQBUFS, &reqbuf ) < 0 ) + { + msg_Err( p_demux, "cannot initiate I/O operation (%s). " + "Only MMAP is supported at the moment", strerror( errno ) ); + goto open_failed; + } + p_demux->pf_demux = DemuxMMAP; + } + else + { + msg_Warn( p_demux, "I/O method not supported at the moment" ); + goto open_failed; + } + + return VLC_SUCCESS; + +open_failed: + if( i_fd ) close( i_fd ); + p_sys->i_fd_video = 0; + return VLC_EGENERIC; + +} + +/***************************************************************************** + * ProbeDev: probe for capabilities + *****************************************************************************/ +int ProbeDev( demux_t *p_demux ) +{ + int i_index; int i_fd; demux_sys_t *p_sys = p_demux->p_sys; @@ -189,14 +267,14 @@ int OpenDev( demux_t *p_demux ) p_sys->dev_cap.version & 0xFF, p_sys->dev_cap.bus_info ); - msg_Dbg( p_demux, "The device has the capabilities: (%c) Video Capure, " + msg_Dbg( p_demux, "the device has the capabilities: (%c) Video Capure, " "(%c) Audio, " "(%c) Tuner", ( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE ? 'X':' '), ( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO ? 'X':' '), ( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER ? 'X':' ') ); - msg_Dbg( p_demux, "Supported I/O methods are: (%c) Read/Write, " + msg_Dbg( p_demux, "supported I/O methods are: (%c) Read/Write, " "(%c) Streaming, " "(%c) Asynchronous", ( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ), @@ -218,20 +296,20 @@ int OpenDev( demux_t *p_demux ) if( !p_sys->p_inputs ) goto open_failed; memset( p_sys->p_inputs, 0, sizeof( struct v4l2_input ) ); - for( i_device_index = 0; i_device_index < p_sys->i_input; i_device_index++ ) + for( i_index = 0; i_index < p_sys->i_input; i_index++ ) { - p_sys->p_inputs[i_device_index].index = i_device_index; + p_sys->p_inputs[i_index].index = i_index; - if( ioctl( i_fd, VIDIOC_ENUMINPUT, &p_sys->p_inputs[i_device_index] ) ) + if( ioctl( i_fd, VIDIOC_ENUMINPUT, &p_sys->p_inputs[i_index] ) ) { msg_Err( p_demux, "cannot get video input characteristics (%s)", strerror( errno ) ); goto open_failed; } - msg_Dbg( p_demux, "Video input %i (%s) has type: %s", - i_device_index, - p_sys->p_inputs[i_device_index].name, - p_sys->p_inputs[i_device_index].type + msg_Dbg( p_demux, "video input %i (%s) has type: %s", + i_index, + p_sys->p_inputs[i_index].name, + p_sys->p_inputs[i_index].type == V4L2_INPUT_TYPE_TUNER ? "Tuner adapter" : "External analog input" ); @@ -239,9 +317,9 @@ int OpenDev( demux_t *p_demux ) } /* initialize the structures for the ioctls */ - for( i_device_index = 0; i_device_index < 32; i_device_index++ ) + for( i_index = 0; i_index < 32; i_index++ ) { - p_sys->p_audios[i_device_index].index = i_device_index; + p_sys->p_audios[i_index].index = i_index; } /* Probe audio inputs */ @@ -258,7 +336,7 @@ int OpenDev( demux_t *p_demux ) goto open_failed; } - msg_Dbg( p_demux, "Audio device %i (%s) is %s", + msg_Dbg( p_demux, "audio device %i (%s) is %s", p_sys->i_audio, p_sys->p_audios[p_sys->i_audio].name, p_sys->p_audios[p_sys->i_audio].capability & @@ -271,8 +349,7 @@ int OpenDev( demux_t *p_demux ) if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER ) { - struct v4l2_tuner tuner; - memset( &tuner, 0, sizeof( struct v4l2_tuner ) ); + struct v4l2_tuner tuner = {}; while( ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) >= 0 ) { @@ -284,34 +361,71 @@ int OpenDev( demux_t *p_demux ) if( !p_sys->p_tuners ) goto open_failed; memset( p_sys->p_tuners, 0, sizeof( struct v4l2_tuner ) ); - for( i_device_index = 0; i_device_index < p_sys->i_tuner; i_device_index++ ) + for( i_index = 0; i_index < p_sys->i_tuner; i_index++ ) { - p_sys->p_tuners[i_device_index].index = i_device_index; + p_sys->p_tuners[i_index].index = i_index; - if( ioctl( i_fd, VIDIOC_G_TUNER, &p_sys->p_tuners[i_device_index] ) ) + if( ioctl( i_fd, VIDIOC_G_TUNER, &p_sys->p_tuners[i_index] ) ) { msg_Err( p_demux, "cannot get tuner characteristics (%s)", strerror( errno ) ); goto open_failed; } - msg_Dbg( p_demux, "Tuner %i (%s) has type: %s, " + msg_Dbg( p_demux, "tuner %i (%s) has type: %s, " "frequency range: %.1f %s -> %.1f %s", - i_device_index, - p_sys->p_tuners[i_device_index].name, - p_sys->p_tuners[i_device_index].type + i_index, + p_sys->p_tuners[i_index].name, + p_sys->p_tuners[i_index].type == V4L2_TUNER_RADIO ? "Radio" : "Analog TV", - p_sys->p_tuners[i_device_index].rangelow * 62.5, - p_sys->p_tuners[i_device_index].capability & + p_sys->p_tuners[i_index].rangelow * 62.5, + p_sys->p_tuners[i_index].capability & V4L2_TUNER_CAP_LOW ? "Hz" : "kHz", - p_sys->p_tuners[i_device_index].rangehigh * 62.5, - p_sys->p_tuners[i_device_index].capability & + p_sys->p_tuners[i_index].rangehigh * 62.5, + p_sys->p_tuners[i_index].capability & V4L2_TUNER_CAP_LOW ? "Hz" : "kHz" ); } } + /* Probe for available chromas */ + if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE ) + { + struct v4l2_fmtdesc codec = {}; + + i_index = 0; + codec.index = i_index; + codec.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + while( ioctl( i_fd, VIDIOC_ENUM_FMT, &codec ) >= 0 ) + { + i_index++; + codec.index = i_index; + } + + p_sys->i_codec = i_index; + + p_sys->p_codecs = malloc( p_sys->i_codec * sizeof( struct v4l2_fmtdesc ) ); + memset( p_sys->p_codecs, 0, p_sys->i_codec * sizeof( struct v4l2_fmtdesc ) ); + + for( i_index = 0; i_index < p_sys->i_codec; i_index++ ) + { + p_sys->p_codecs[i_index].index = i_index; + p_sys->p_codecs[i_index].type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if( ioctl( i_fd, VIDIOC_ENUM_FMT, &p_sys->p_codecs[i_index] ) < 0 ) + { + msg_Err( p_demux, "cannot get codec description (%s)", strerror( errno ) ); + goto open_failed; + } + + msg_Dbg( p_demux, "device supports Codec %s", + p_sys->p_codecs[i_index].description ); + } + } + + if( i_fd >= 0 ) close( i_fd ); return VLC_SUCCESS; -- GitLab