[vlc-devel] [PATCH] OSS Audio for screen capture.

Antoine Cellerier dionoea at videolan.org
Thu Apr 3 22:34:02 CEST 2008


On Thu, Apr 03, 2008, Tony Biondo wrote:
>    OSS Audio support for the screen capture module.
>    Mostly based on the audio capture from the v4l module.
> 
>    First time I'm trying to submit a patch to a big project, be nice :)

Thanks for the patch. This audio vs video access support is something
that I've been wanting to address. We should split it in different
modules, and then use blackmagic (also known as --input-slave) to use 2
inputs simultaneously. So we would end up having something like:

video:
 * v4l
 * v4l2
audio:
 * oss
 * alsa
 * ...

The advantages would be to simplify the current v4l modules, make the
code readable, etc. We could add needed code to use the audio modules
seemlessly when using v4l and v4l2 to keep it simple from the user's
point of view.

Do any of the other devs have comments about that?

(Or we could at least put the audio code in a source file shared by
several plugins)

> From 0551f78b1d420284971f8f919856214b082bbe27 Mon Sep 17 00:00:00 2001
> From: Tony Biondo <tonyb at tonybox.net>
> Date: Thu, 3 Apr 2008 15:05:57 -0400
> Subject: [PATCH] OSS Audio for screen capture.
> 
> ---
>  configure.ac                   |    3 +
>  modules/access/screen/screen.c |  190 ++++++++++++++++++++++++++++++++++++----
>  modules/access/screen/screen.h |   13 +++
>  3 files changed, 189 insertions(+), 17 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index f53dd11..9550f41 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2603,6 +2603,9 @@ if test "${enable_screen}" != "no"; then
>        VLC_ADD_LIBS([screen],[${X_LIBS} ${X_PRE_LIBS} -lX11])
>        VLC_ADD_CPPFLAGS([screen],[${X_CFLAGS}])
>      ])
> +    AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h, [
> +      VLC_ADD_CPPFLAGS([screen],[-DHAVE_OSS])
> +    ])
>      CPPFLAGS="${CPPFLAGS_save}"
>    fi
>  fi
> diff --git a/modules/access/screen/screen.c b/modules/access/screen/screen.c
> index 42a4c40..e6f20ce 100644
> --- a/modules/access/screen/screen.c
> +++ b/modules/access/screen/screen.c
> @@ -49,14 +49,21 @@
>      "Optimize the capture by fragmenting the screen in chunks " \
>      "of predefined height (16 might be a good value, and 0 means disabled)." )
>  #endif
> +#ifdef HAVE_OSS
> +#define ADEV_TEXT N_("Audio device name")
> +#define ADEV_LONGTEXT N_( \
> +    "Name of the audio device to use. " \
> +    "If you don't specify anything, no audio device will be used.")
> +#endif
>  
>  static int  Open ( vlc_object_t * );
>  static void Close( vlc_object_t * );
>  
> +
>  #ifdef WIN32
>  #   define SCREEN_FPS 1
>  #else
> -#   define SCREEN_FPS 5
> +#   define SCREEN_FPS 30
>  #endif
>  
>  vlc_module_begin();
> @@ -73,6 +80,9 @@ vlc_module_begin();
>      add_integer( "screen-fragment-size", 0, NULL, FRAGS_TEXT,
>          FRAGS_LONGTEXT, VLC_TRUE );
>  #endif
> +#ifdef HAVE_OSS
> +    add_string( "screen-adev", 0, 0, ADEV_TEXT, ADEV_LONGTEXT, VLC_FALSE );
> +#endif
>  
>      set_capability( "access_demux", 0 );
>      add_shortcut( "screen" );
> @@ -84,6 +94,10 @@ vlc_module_end();
>   *****************************************************************************/
>  static int Control( demux_t *, int, va_list );
>  static int Demux  ( demux_t * );
> +#ifdef HAVE_OSS
> +static int OpenAudioDev( demux_t *p_demux, char *psz_device );
> +static block_t *GrabAudio( demux_t *p_demux );
> +#endif
>  
>  /*****************************************************************************
>   * DemuxOpen:
> @@ -102,8 +116,8 @@ static int Open( vlc_object_t *p_this )
>  
>      /* Update default_pts to a suitable value for screen access */
>      var_Create( p_demux, "screen-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
> -
>      var_Create( p_demux, "screen-fps", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
> +
>      var_Get( p_demux, "screen-fps", &val );
>      p_sys->f_fps = val.f_float;
>      p_sys->i_incr = 1000000 / val.f_float;
> @@ -121,6 +135,43 @@ static int Open( vlc_object_t *p_this )
>  
>      p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
>  
> +#ifdef HAVE_OSS
> +    p_sys->i_sample_rate=44100;
> +    if( !p_sys->psz_adev || !*p_sys->psz_adev )
> +    {
> +         free( p_sys->psz_adev );
> +         p_sys->psz_adev = var_CreateGetString( p_demux, "screen-adev" );
> +    }
> +    if(p_sys->psz_adev[0]) 
> +    {
> +       msg_Dbg( p_demux, "Using audio device '%s'", p_sys->psz_adev);
> +       p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_adev);
> +    } else {
> +       msg_WarDbgn( p_demux, "Disabling audio capture.");
> +       p_sys->fd_audio = -1; /* Do not use any audio device if there is none selected. */
> +    }
> +
> +    if( p_sys->fd_audio >= 0 )
> +    {
> +        es_format_t fmt;
> +        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
> +
> +        fmt.audio.i_channels = p_sys->b_stereo ? 2 : 1;
> +        fmt.audio.i_rate = p_sys->i_sample_rate;
> +        fmt.audio.i_bitspersample = 16; /* FIXME ? */
> +        fmt.audio.i_blockalign = fmt.audio.i_channels *
> +            fmt.audio.i_bitspersample / 8;
> +        fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
> +            fmt.audio.i_bitspersample;
> +
> +        msg_Dbg( p_demux, "new audio es %d channels %dHz",
> +                 fmt.audio.i_channels, fmt.audio.i_rate );
> +
> +        p_sys->p_es_audio = es_out_Add( p_demux->out, &fmt );
> +    }
> +#endif
> +
> +
>      return VLC_SUCCESS;
>  }
>  
> @@ -131,6 +182,7 @@ 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->fd_audio >= 0 ) close( p_sys->fd_audio );
>  
>      screen_CloseCapture( p_demux );
>      free( p_sys );
> @@ -143,25 +195,30 @@ static int Demux( demux_t *p_demux )
>  {
>      demux_sys_t *p_sys = p_demux->p_sys;
>      block_t *p_block;
> +    es_out_id_t  *p_es = p_sys->p_es_audio;
>  
> -    if( !p_sys->i_next_date ) p_sys->i_next_date = mdate();
>  
> -    /* Frame skipping if necessary */
> -    while( mdate() >= p_sys->i_next_date + p_sys->i_incr )
> -        p_sys->i_next_date += p_sys->i_incr;
> -
> -    mwait( p_sys->i_next_date );
> -    p_block = screen_Capture( p_demux );
> -    if( !p_block )
> +#ifdef HAVE_OSS
> +    if( p_sys->fd_audio < 0 || !( p_block = GrabAudio( p_demux ) ) )
>      {
> -        p_sys->i_next_date += p_sys->i_incr;
> -        return 1;
> -    }
> -
> -    p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
> -
> +#endif
> +        if( !p_sys->i_next_date ) p_sys->i_next_date = mdate();
> +        p_es = p_sys->es;
> +        while( mdate() >= p_sys->i_next_date + p_sys->i_incr )
> +          p_sys->i_next_date += p_sys->i_incr;
> +        mwait( p_sys->i_next_date );
> +        p_block = screen_Capture( p_demux );
> +        if( !p_block )
> +        {
> +           p_sys->i_next_date += p_sys->i_incr;
> +           return 1;
> +        }
> +        p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
> +#ifdef HAVE_OSS
> +    } 
> +#endif
>      es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
> -    es_out_Send( p_demux->out, p_sys->es, p_block );
> +    es_out_Send( p_demux->out, p_es, p_block );
>  
>      p_sys->i_next_date += p_sys->i_incr;
>  
> @@ -197,3 +254,102 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
>              return VLC_EGENERIC;
>      }
>  }
> +
> +
> +#ifdef HAVE_OSS
> +/*****************************************************************************
> + * OpenAudioDev:
> + *****************************************************************************/
> +static int OpenAudioDev( demux_t *p_demux, char *psz_device )
> +{
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +    int i_fd, i_format;
> +
> +    if( (i_fd = open( psz_device, O_RDONLY | O_NONBLOCK )) < 0 )
> +    {
> +        msg_Err( p_demux, "cannot open audio device (%m)" );
> +        goto adev_fail;
> +    }
> +
> +    i_format = AFMT_S16_LE;
> +    if( ioctl( i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
> +        || i_format != AFMT_S16_LE )
> +    {
> +        msg_Err( p_demux, "cannot set audio format (16b little endian) "
> +                 "(%m)" );
> +        goto adev_fail;
> +    }
> +
> +    if( ioctl( i_fd, SNDCTL_DSP_STEREO,
> +               &p_sys->b_stereo ) < 0 )
> +    {
> +        msg_Err( p_demux, "cannot set audio channels count (%m)" );
> +        goto adev_fail;
> +    }
> +
> +    if( ioctl( i_fd, SNDCTL_DSP_SPEED,
> +               &p_sys->i_sample_rate ) < 0 )
> +    {
> +        msg_Err( p_demux, "cannot set audio sample rate (%m)" );
> +        goto adev_fail;
> +    }
> +
> +    msg_Dbg( p_demux, "opened adev=`%s' %s %dHz",
> +             psz_device, p_sys->b_stereo ? "stereo" : "mono",
> +             p_sys->i_sample_rate );
> +
> +    p_sys->i_audio_max_frame_size = 6 * 1024;
> +
> +    return i_fd;
> +
> + adev_fail:
> +
> +    if( i_fd >= 0 ) close( i_fd );
> +    return -1;
> +}
> +
> +/*****************************************************************************
> + * GrabAudio: grab audio
> + *****************************************************************************/
> +static block_t *GrabAudio( demux_t *p_demux )
> +{
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +    struct audio_buf_info buf_info;
> +    int i_read, i_correct;
> +    block_t *p_block;
> +
> +    /* if( p_sys->p_block_audio ) p_block = p_sys->p_block_audio; */
> +    p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );
> +
> +    if( !p_block )
> +    {
> +        msg_Warn( p_demux, "cannot get block" );
> +        return 0;
> +    }
> +
> +    p_sys->p_block_audio = p_block;
> +
> +    i_read = read( p_sys->fd_audio, p_block->p_buffer,
> +                   p_sys->i_audio_max_frame_size );
> +
> +    if( i_read <= 0 ) return 0;
> +
> +    p_block->i_buffer = i_read;
> +    p_sys->p_block_audio = 0;
> +
> +    /* Correct the date because of kernel buffering */
> +    i_correct = i_read;
> +    if( ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )
> +    {
> +        i_correct += buf_info.bytes;
> +    }
> +
> +    p_block->i_pts = p_block->i_dts =
> +        mdate() - I64C(1000000) * (mtime_t)i_correct /
> +        2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;
> +
> +    return p_block;
> +}
> +
> +#endif
> +
> diff --git a/modules/access/screen/screen.h b/modules/access/screen/screen.h
> index 56a5d85..6853ee5 100644
> --- a/modules/access/screen/screen.h
> +++ b/modules/access/screen/screen.h
> @@ -24,6 +24,11 @@
>  #include <vlc_input.h>
>  #include <vlc_access.h>
>  #include <vlc_demux.h>
> +#ifdef HAVE_OSS
> +#	include <sys/soundcard.h>
> +#	include <fcntl.h>
> +#endif
> +
>  
>  typedef struct screen_data_t screen_data_t;
>  
> @@ -37,6 +42,14 @@ struct demux_sys_t
>      int i_incr;
>  
>      screen_data_t *p_data;
> +    vlc_fourcc_t i_acodec_raw;
> +    int          i_sample_rate;
> +    vlc_bool_t   b_stereo;
> +    int          i_audio_max_frame_size;
> +    block_t      *p_block_audio;
> +    es_out_id_t  *p_es_audio;
> +    int  fd_audio;
> +    char *psz_adev;
>  };
>  
>  int      screen_InitCapture ( demux_t * );
> -- 
> 1.5.4.1
> 

> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> http://mailman.videolan.org/listinfo/vlc-devel

-- 
Antoine Cellerier
dionoea



More information about the vlc-devel mailing list