Commit 92f7ddf2 authored by Benjamin Pracht's avatar Benjamin Pracht

* Some more probing

* The debug output from a v4l2 capable webcam with this would help...
parent ba42d61b
...@@ -53,6 +53,10 @@ static void Close( vlc_object_t * ); ...@@ -53,6 +53,10 @@ static void Close( vlc_object_t * );
#define DEV_LONGTEXT N_( \ #define DEV_LONGTEXT N_( \
"Name of the device to use. " \ "Name of the device to use. " \
"If you don't specify anything, /dev/video0 will be used.") "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(); vlc_module_begin();
...@@ -63,6 +67,8 @@ vlc_module_begin(); ...@@ -63,6 +67,8 @@ vlc_module_begin();
add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT, add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT,
VLC_FALSE ); VLC_FALSE );
add_integer( "v4l2-input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT,
VLC_TRUE );
add_shortcut( "v4l2" ); add_shortcut( "v4l2" );
set_capability( "access_demux", 10 ); set_capability( "access_demux", 10 );
...@@ -73,10 +79,13 @@ vlc_module_end(); ...@@ -73,10 +79,13 @@ vlc_module_end();
* Access: local prototypes * Access: local prototypes
*****************************************************************************/ *****************************************************************************/
static int Demux ( demux_t * ); static int DemuxMMAP( demux_t * );
static int Control( demux_t *, int, va_list ); 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 struct demux_sys_t
{ {
...@@ -88,6 +97,7 @@ struct demux_sys_t ...@@ -88,6 +97,7 @@ struct demux_sys_t
int i_input; int i_input;
struct v4l2_input *p_inputs; struct v4l2_input *p_inputs;
int i_selected_input;
int i_audio; int i_audio;
/* V4L2 devices cannot have more than 32 audio inputs */ /* V4L2 devices cannot have more than 32 audio inputs */
...@@ -95,6 +105,9 @@ struct demux_sys_t ...@@ -95,6 +105,9 @@ struct demux_sys_t
int i_tuner; int i_tuner;
struct v4l2_tuner *p_tuners; 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 ) ...@@ -111,7 +124,6 @@ static int Open( vlc_object_t *p_this )
demux_sys_t sys; demux_sys_t sys;
/* Set up p_demux */ /* Set up p_demux */
p_demux->pf_demux = Demux;
p_demux->pf_control = Control; p_demux->pf_control = Control;
p_demux->info.i_update = 0; p_demux->info.i_update = 0;
p_demux->info.i_title = 0; p_demux->info.i_title = 0;
...@@ -123,7 +135,9 @@ static int Open( vlc_object_t *p_this ) ...@@ -123,7 +135,9 @@ static int Open( vlc_object_t *p_this )
p_sys->psz_device = var_CreateGetString( p_demux, "v4l2-dev" ); 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; return VLC_SUCCESS;
} }
...@@ -136,8 +150,12 @@ static void Close( vlc_object_t *p_this ) ...@@ -136,8 +150,12 @@ static void Close( vlc_object_t *p_this )
demux_t *p_demux = (demux_t *)p_this; demux_t *p_demux = (demux_t *)p_this;
demux_sys_t *p_sys = p_demux->p_sys; 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->psz_device ) free( p_sys->psz_device );
if( p_sys->p_inputs ) free( p_sys->p_inputs ); 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 ); free( p_sys );
} }
...@@ -152,17 +170,77 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -152,17 +170,77 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
/***************************************************************************** /*****************************************************************************
* Demux: * 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; int i_fd;
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
...@@ -189,14 +267,14 @@ int OpenDev( demux_t *p_demux ) ...@@ -189,14 +267,14 @@ int OpenDev( demux_t *p_demux )
p_sys->dev_cap.version & 0xFF, p_sys->dev_cap.version & 0xFF,
p_sys->dev_cap.bus_info ); 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) Audio, "
"(%c) Tuner", "(%c) Tuner",
( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE ? 'X':' '), ( 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_AUDIO ? 'X':' '),
( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER ? '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) Streaming, "
"(%c) Asynchronous", "(%c) Asynchronous",
( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ), ( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ),
...@@ -218,20 +296,20 @@ int OpenDev( demux_t *p_demux ) ...@@ -218,20 +296,20 @@ int OpenDev( demux_t *p_demux )
if( !p_sys->p_inputs ) goto open_failed; if( !p_sys->p_inputs ) goto open_failed;
memset( p_sys->p_inputs, 0, sizeof( struct v4l2_input ) ); 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)", msg_Err( p_demux, "cannot get video input characteristics (%s)",
strerror( errno ) ); strerror( errno ) );
goto open_failed; goto open_failed;
} }
msg_Dbg( p_demux, "Video input %i (%s) has type: %s", msg_Dbg( p_demux, "video input %i (%s) has type: %s",
i_device_index, i_index,
p_sys->p_inputs[i_device_index].name, p_sys->p_inputs[i_index].name,
p_sys->p_inputs[i_device_index].type p_sys->p_inputs[i_index].type
== V4L2_INPUT_TYPE_TUNER ? == V4L2_INPUT_TYPE_TUNER ?
"Tuner adapter" : "Tuner adapter" :
"External analog input" ); "External analog input" );
...@@ -239,9 +317,9 @@ int OpenDev( demux_t *p_demux ) ...@@ -239,9 +317,9 @@ int OpenDev( demux_t *p_demux )
} }
/* initialize the structures for the ioctls */ /* 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 */ /* Probe audio inputs */
...@@ -258,7 +336,7 @@ int OpenDev( demux_t *p_demux ) ...@@ -258,7 +336,7 @@ int OpenDev( demux_t *p_demux )
goto open_failed; 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->i_audio,
p_sys->p_audios[p_sys->i_audio].name, p_sys->p_audios[p_sys->i_audio].name,
p_sys->p_audios[p_sys->i_audio].capability & p_sys->p_audios[p_sys->i_audio].capability &
...@@ -271,8 +349,7 @@ int OpenDev( demux_t *p_demux ) ...@@ -271,8 +349,7 @@ int OpenDev( demux_t *p_demux )
if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER ) if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER )
{ {
struct v4l2_tuner tuner; struct v4l2_tuner tuner = {};
memset( &tuner, 0, sizeof( struct v4l2_tuner ) );
while( ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) >= 0 ) while( ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) >= 0 )
{ {
...@@ -284,34 +361,71 @@ int OpenDev( demux_t *p_demux ) ...@@ -284,34 +361,71 @@ int OpenDev( demux_t *p_demux )
if( !p_sys->p_tuners ) goto open_failed; if( !p_sys->p_tuners ) goto open_failed;
memset( p_sys->p_tuners, 0, sizeof( struct v4l2_tuner ) ); 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)", msg_Err( p_demux, "cannot get tuner characteristics (%s)",
strerror( errno ) ); strerror( errno ) );
goto open_failed; 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", "frequency range: %.1f %s -> %.1f %s",
i_device_index, i_index,
p_sys->p_tuners[i_device_index].name, p_sys->p_tuners[i_index].name,
p_sys->p_tuners[i_device_index].type p_sys->p_tuners[i_index].type
== V4L2_TUNER_RADIO ? == V4L2_TUNER_RADIO ?
"Radio" : "Analog TV", "Radio" : "Analog TV",
p_sys->p_tuners[i_device_index].rangelow * 62.5, p_sys->p_tuners[i_index].rangelow * 62.5,
p_sys->p_tuners[i_device_index].capability & p_sys->p_tuners[i_index].capability &
V4L2_TUNER_CAP_LOW ? V4L2_TUNER_CAP_LOW ?
"Hz" : "kHz", "Hz" : "kHz",
p_sys->p_tuners[i_device_index].rangehigh * 62.5, p_sys->p_tuners[i_index].rangehigh * 62.5,
p_sys->p_tuners[i_device_index].capability & p_sys->p_tuners[i_index].capability &
V4L2_TUNER_CAP_LOW ? V4L2_TUNER_CAP_LOW ?
"Hz" : "kHz" ); "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 ); if( i_fd >= 0 ) close( i_fd );
return VLC_SUCCESS; return VLC_SUCCESS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment