[vlc-devel] [PATCH 2/2] V4L2: Add support for radio devices.

Rémi Denis-Courmont remi at remlab.net
Thu Aug 4 11:21:35 CEST 2011


   Hello,

Do I get this right that this is meant to control analog audio tuners but
the data is fetched with an ALSA input slave?

Comments inline...

On Thu,  4 Aug 2011 09:53:52 +0200, Thierry Reding
<thierry.reding at avionic-design.de> wrote:
> ---
>  modules/access/v4l2.c |  130
>  ++++++++++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 122 insertions(+), 8 deletions(-)
> 
> diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c
> index f074a9c..eec8f09 100644
> --- a/modules/access/v4l2.c
> +++ b/modules/access/v4l2.c
> @@ -416,8 +416,10 @@ static bool IsPixelFormatSupported( demux_t
*p_demux,
>                                            unsigned int i_pixelformat );
>  
>  static int InitVideoDev( vlc_object_t *, demux_sys_t *, bool );
> -static int ProbeVideoDev( vlc_object_t *, demux_sys_t *,
> +static int InitRadioDev( vlc_object_t *, demux_sys_t *, bool );
> +static int ProbeDev( vlc_object_t *, demux_sys_t *,
>                                   const char *psz_device );
> +static bool IsRadioDev( demux_sys_t *p_sys );
>  
>  static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool
);
>  static int Control( vlc_object_t *, demux_sys_t *, int i_fd,
> @@ -645,11 +647,19 @@ static int FindMainDevice( vlc_object_t *p_this,
> demux_sys_t *p_sys,
>      /* TODO: if using default device, loop through all /dev/video*
until
>       * one works */
>      msg_Dbg( p_this, "opening device '%s'", p_sys->psz_device );
> -    p_sys->i_fd = ProbeVideoDev( p_this, p_sys, p_sys->psz_device );
> +    p_sys->i_fd = ProbeDev( p_this, p_sys, p_sys->psz_device );
>      if( p_sys->i_fd >= 0 )
>      {
> -        msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device );
> -        InitVideoDev( p_this, p_sys, b_demux );
> +        if( IsRadioDev( p_sys ) )
> +        {
> +            msg_Dbg( p_this, "'%s' is a radio device",
p_sys->psz_device
> );
> +            InitRadioDev( p_this, p_sys, b_demux );
> +        }
> +        else
> +        {
> +            msg_Dbg( p_this, "'%s' is a video device",
p_sys->psz_device
> );
> +            InitVideoDev( p_this, p_sys, b_demux );
> +        }
>      }
>  
>      if( p_sys->i_fd < 0 ) return VLC_EGENERIC;
> @@ -1035,6 +1045,9 @@ static void DemuxClose( vlc_object_t *p_this )
>      demux_t     *p_demux = (demux_t *)p_this;
>      demux_sys_t *p_sys   = p_demux->p_sys;
>  
> +    if( IsRadioDev( p_sys ) )
> +        goto common;
> +

IMHO, a separate "access_demux" radio sub-module with dedicated Open and
Close functions would be cleaner. In fact, it seems like there is not that
much common code, so you might even consider creating a completely new
plug-in. What do you think?

>      /* Stop video capture */
>      if( p_sys->i_fd >= 0 )
>      {
> @@ -1099,6 +1112,7 @@ static void DemuxClose( vlc_object_t *p_this )
>          free( p_sys->p_buffers );
>      }
>  
> +common:
>      CommonClose( p_this, p_sys );
>  }
>  
> @@ -1268,7 +1282,10 @@ static block_t *AccessRead( access_t * p_access )
>  
>      /* Wait for data */
>      if( poll( &fd, 1, 500 ) > 0 ) /* Timeout after 0.5 seconds since I
>      don't know if pf_demux can be blocking. */
> -        return GrabVideo( VLC_OBJECT(p_access), p_sys );
> +    {
> +        if( !IsRadioDev( p_sys ) )
> +            return GrabVideo( VLC_OBJECT(p_access), p_sys );
> +    }
>  
>      return NULL;
>  }

If there is never going to be any data, then AccessOpen() should fail. So
AccessRead() should never be reached to begin with.

> @@ -1335,7 +1352,7 @@ static int Demux( demux_t *p_demux )
>              return -1;
>          }
>  
> -    if( fd.revents )
> +    if( fd.revents && !IsRadioDev( p_sys ) )
>      {
>           block_t *p_block = GrabVideo( VLC_OBJECT(p_demux), p_sys );
>           if( p_block )

poll() should be used if events are not dealt with. I guess you can just
set pf_demux to NULL, as in access/screen/xcb.c.

> @@ -2368,9 +2385,98 @@ open_failed:
>  }
>  
> 
/*****************************************************************************
> - * ProbeVideoDev: probe video for capabilities
> + * InitRadioDev: set up the radio device and probe for capabilities
> +
>
*****************************************************************************/
> +static int InitRadioDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool
> b_demux )
> +{
> +    /* Tune the tuner */
> +    if( p_sys->i_frequency >= 0 )
> +    {
> +        if( p_sys->i_cur_tuner < 0 || (unsigned)p_sys->i_cur_tuner >=
> p_sys->i_tuner )
> +        {
> +            msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
> +            goto open_failed;
> +        }
> +        struct v4l2_frequency frequency;
> +        memset( &frequency, 0, sizeof( frequency ) );
> +        frequency.tuner = p_sys->i_cur_tuner;
> +        frequency.type = p_sys->p_tuners[p_sys->i_cur_tuner].type;
> +        frequency.frequency = p_sys->i_frequency / 62.5;
> +        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FREQUENCY, &frequency ) <
0
> )
> +        {
> +            msg_Err( p_obj, "cannot set tuner frequency (%m)" );
> +            goto open_failed;
> +        }
> +        msg_Dbg( p_obj, "Tuner frequency set" );
> +    }
> +
> +    /* Set the tuner's audio mode */
> +    if( p_sys->i_audio_mode >= 0 )
> +    {
> +        if( p_sys->i_cur_tuner < 0 || (unsigned)p_sys->i_cur_tuner >=
> p_sys->i_tuner )
> +        {
> +            msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
> +            goto open_failed;
> +        }
> +        struct v4l2_tuner tuner;
> +        memset( &tuner, 0, sizeof( tuner ) );
> +        tuner.index = p_sys->i_cur_tuner;
> +        tuner.audmode = p_sys->i_audio_mode;
> +        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_TUNER, &tuner ) < 0 )
> +        {
> +            msg_Err( p_obj, "cannot set tuner audio mode (%m)" );
> +            goto open_failed;
> +        }
> +        msg_Dbg( p_obj, "Tuner audio mode set" );
> +    }
> +
> +    /* Select input */
> +    if( p_sys->i_selected_input >= p_sys->i_input )
> +    {
> +        msg_Warn( p_obj, "invalid input. Using the default one" );
> +        p_sys->i_selected_input = 0;
> +    }
> +
> +    if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_INPUT,
&p_sys->i_selected_input
> ) < 0 )
> +    {
> +        msg_Err( p_obj, "cannot set input (%m)" );
> +        goto open_failed;
> +    }
> +
> +    /* Set audio input */
> +    if( p_sys->i_audio > 0 )
> +    {
> +        if( p_sys->i_selected_audio_input < 0
> +         || (unsigned)p_sys->i_selected_audio_input >= p_sys->i_audio )
> +        {
> +            msg_Warn( p_obj, "invalid audio input. Using the default
one"
> );
> +            p_sys->i_selected_audio_input = 0;
> +        }
> +
> +        if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_AUDIO,
> &p_sys->p_audios[p_sys->i_selected_audio_input] ) < 0 )
> +        {
> +            msg_Err( p_obj, "cannot set audio input (%m)" );
> +            goto open_failed;
> +        }
> +        msg_Dbg( p_obj, "Audio input set to %d",
> p_sys->i_selected_audio_input );
> +    }
> +
> +    ControlList( p_obj, p_sys, p_sys->i_fd,
> +                  var_GetBool( p_obj, "v4l2-controls-reset" ), b_demux
);
> +    SetAvailControlsByString( p_obj, p_sys, p_sys->i_fd );
> +
> +    return VLC_SUCCESS;
> +
> +open_failed:
> +    if( p_sys->i_fd >= 0 ) v4l2_close( p_sys->i_fd );
> +    return VLC_EGENERIC;
> +
> +}
> +
>
+/*****************************************************************************
> + * ProbeDev: probe device for capabilities
>  
*****************************************************************************/
> -static int ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
> +static int ProbeDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
>                                   const char *psz_device )
>  {
>      int i_fd;
> @@ -2737,6 +2843,14 @@ open_failed:
>  
>  }
>  
> +static bool IsRadioDev( demux_sys_t *p_sys )
> +{
> +    if ( p_sys && ( p_sys->dev_cap.capabilities & V4L2_CAP_RADIO ) )
> +        return true;
> +
> +    return false;
> +}
> +
>  static void name2var( unsigned char *name )
>  {
>      for( ; *name; name++ )

-- 
Rémi Denis-Courmont
http://www.remlab.net/



More information about the vlc-devel mailing list