1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-04 09:11:33 +02:00

* Some more probing

* The debug output from a v4l2 capable webcam with this would help...
This commit is contained in:
Benjamin Pracht 2006-08-27 17:06:30 +00:00
parent ba42d61b37
commit 92f7ddf2f9

View File

@ -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;