[vlc-devel] [PATCH] audiotrack: add AC3 passthrough support

Thomas Guillem thomas at gllm.fr
Tue Mar 10 18:45:14 CET 2015


Please abort this patch, I'll do an other one better after a little
refactoring.

On Tue, Mar 10, 2015, at 16:01, Thomas Guillem wrote:
> Only activated if libvlc is created with audiotrack-ac3 argument.
> 
> Don't use AC3 passthrough dynamically for now, since we have to first
> rework
> the communication system between android and libvlc.
> ---
>  modules/audio_output/audiotrack.c | 93
>  ++++++++++++++++++++++++++++++++++-----
>  1 file changed, 82 insertions(+), 11 deletions(-)
> 
> diff --git a/modules/audio_output/audiotrack.c
> b/modules/audio_output/audiotrack.c
> index cb8d9bd..d7aee24 100644
> --- a/modules/audio_output/audiotrack.c
> +++ b/modules/audio_output/audiotrack.c
> @@ -66,6 +66,7 @@ struct aout_sys_t {
>      mtime_t i_play_time; /* time when play was called */
>      bool b_audiotrack_exception; /* true if audiotrack throwed an
>      exception */
>      int i_audiotrack_stuck_count;
> +    bool b_is_ac3;
>      uint8_t i_chans_to_reorder; /* do we need channel reordering */
>      uint8_t p_chan_table[AOUT_CHAN_MAX];
>  
> @@ -87,10 +88,17 @@ struct aout_sys_t {
>  // TODO: activate getTimestamp for new android versions
>  //#define AUDIOTRACK_USE_TIMESTAMP
>  
> +#define AC3_TEXT N_("AudioTrack Ac3 passthrough")
> +#define AC3_LONGTEXT N_(\
> +        "Enable AudioTrack Ac3 passthrough via HDMI or SPDIF.")
> +
> +#define CFG_PREFIX "audiotrack-"
> +
>  vlc_module_begin ()
>      set_shortname( "AudioTrack" )
>      set_description( N_( "Android AudioTrack audio output" ) )
>      set_capability( "audio output", 180 )
> +    add_bool( CFG_PREFIX "ac3", false, AC3_TEXT, AC3_LONGTEXT, true )
>      set_category( CAT_AUDIO )
>      set_subcategory( SUBCAT_AUDIO_AOUT )
>      add_sw_gain()
> @@ -172,6 +180,9 @@ static struct
>          jint ENCODING_PCM_16BIT;
>          jint ENCODING_PCM_FLOAT;
>          bool has_ENCODING_PCM_FLOAT;
> +        jint ENCODING_AC3;
> +        jint ENCODING_E_AC3;
> +        bool has_ENCODING_AC3;
>          jint CHANNEL_OUT_MONO;
>          jint CHANNEL_OUT_STEREO;
>          jint CHANNEL_OUT_FRONT_LEFT;
> @@ -325,6 +336,14 @@ InitJNIFields( audio_output_t *p_aout )
>  #else
>      jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
>  #endif
> +    GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
> +    if( field != NULL )
> +    {
> +        GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3",
> false );
> +        jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
> +    } else
> +        jfields.AudioFormat.has_ENCODING_AC3 = false;
> +
>      GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO",
>      true );
>      GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO",
>      true );
>      GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT,
>      "CHANNEL_OUT_FRONT_LEFT", true );
> @@ -404,6 +423,26 @@ frames_to_us( aout_sys_t *p_sys, uint32_t
> i_nb_frames )
>  }
>  #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
>  
> +static inline uint32_t
> +bytes_to_frames( aout_sys_t *p_sys, size_t i_bytes )
> +{
> +    if( p_sys->b_is_ac3 )
> +        return i_bytes * A52_FRAME_NB / p_sys->i_bytes_per_frame;
> +    else
> +        return i_bytes / p_sys->i_bytes_per_frame;
> +}
> +#define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
> +
> +static inline size_t
> +frames_to_bytes( aout_sys_t *p_sys, uint32_t i_frames )
> +{
> +    if( p_sys->b_is_ac3 )
> +        return i_frames * p_sys->i_bytes_per_frame / A52_FRAME_NB;
> +    else
> +        return i_frames * p_sys->i_bytes_per_frame;
> +}
> +#define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
> +
>  static struct thread_cmd *
>  ThreadCmd_New( int id )
>  {
> @@ -503,7 +542,7 @@ JNIThread_TimeGet( JNIEnv *env, audio_output_t
> *p_aout, mtime_t *p_delay )
>      jlong i_frame_pos;
>      uint32_t i_audiotrack_delay = 0;
>  
> -    if( p_sys->i_samples_queued == 0 )
> +    if( p_sys->i_samples_queued == 0 || p_sys->b_is_ac3 )
>          return -1;
>      if( p_sys->p_audioTimestamp )
>      {
> @@ -610,13 +649,14 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>      uint8_t i_chans_to_reorder = 0;
>      uint8_t p_chan_table[AOUT_CHAN_MAX];
>      uint32_t p_chans_out[AOUT_CHAN_MAX];
> +    bool b_is_ac3 = false;
>      jobject p_audiotrack;
>      audio_sample_format_t fmt = p_sys->fmt;
>  
>      /* 4000 <= frequency <= 48000 */
>      fmt.i_rate = VLC_CLIP( fmt.i_rate, 4000, 48000 );
>  
> -    /* We can only accept U8, S16N, FL32 */
> +    /* We can only accept U8, S16N, FL32, and AC3 */
>      switch( fmt.i_format )
>      {
>          case VLC_CODEC_U8:
> @@ -627,6 +667,13 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>              if( !jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
>                  fmt.i_format = VLC_CODEC_S16N;
>              break;
> +        case VLC_CODEC_A52:
> +            if( jfields.AudioFormat.has_ENCODING_AC3
> +                && var_InheritBool( p_aout, CFG_PREFIX "ac3" ) )
> +                fmt.i_format = VLC_CODEC_SPDIFB;
> +            else
> +                fmt.i_format = VLC_CODEC_S16N;
> +            break;
>          default:
>              fmt.i_format = VLC_CODEC_S16N;
>              break;
> @@ -645,6 +692,11 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>              i_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
>              i_format_size = 4;
>              break;
> +        case VLC_CODEC_SPDIFB:
> +            i_format = jfields.AudioFormat.ENCODING_AC3;
> +            i_format_size = 2;
> +            b_is_ac3 = true;
> +            break;
>          default:
>              vlc_assert_unreachable();
>      }
> @@ -682,11 +734,14 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>      }
>      i_nb_channels = aout_FormatNbChannels( &fmt );
>  
> -    memset( p_chans_out, 0, sizeof(p_chans_out) );
> -    AudioTrack_GetChanOrder( i_channel_config, p_chans_out );
> -    i_chans_to_reorder = aout_CheckChannelReorder( NULL, p_chans_out,
> -                                                  
> fmt.i_physical_channels,
> -                                                   p_chan_table );
> +    if( !b_is_ac3 )
> +    {
> +        memset( p_chans_out, 0, sizeof(p_chans_out) );
> +        AudioTrack_GetChanOrder( i_channel_config, p_chans_out );
> +        i_chans_to_reorder = aout_CheckChannelReorder( NULL,
> p_chans_out,
> +                                                      
> fmt.i_physical_channels,
> +                                                       p_chan_table );
> +    }
>  
>      i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize,
>      fmt.i_rate,
>                                                  i_channel_config,
>                                                  i_format );
> @@ -696,6 +751,14 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>          return 1;
>      }
>      i_size = i_min_buffer_size * 4;
> +    if( b_is_ac3 )
> +    {
> +        /* multiple of AOUT_SPDIF_SIZE */
> +        i_size = ( i_min_buffer_size / AOUT_SPDIF_SIZE + 1 ) *
> AOUT_SPDIF_SIZE;
> +    } else
> +    {
> +        i_size = i_min_buffer_size * 4;
> +    }
>  
>      /* create AudioTrack object */
>      p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC,
>      fmt.i_rate,
> @@ -711,8 +774,15 @@ JNIThread_Configure( JNIEnv *env, audio_output_t
> *p_aout )
>      p_sys->i_chans_to_reorder = i_chans_to_reorder;
>      if( i_chans_to_reorder )
>          memcpy( p_sys->p_chan_table, p_chan_table,
>          sizeof(p_sys->p_chan_table) );
> -    p_sys->i_bytes_per_frame = i_nb_channels * i_format_size;
> -    p_sys->i_max_audiotrack_samples = i_size / p_sys->i_bytes_per_frame;
> +    p_sys->b_is_ac3 = b_is_ac3;
> +    if( p_sys->b_is_ac3 )
> +    {
> +        fmt.i_bytes_per_frame = AOUT_SPDIF_SIZE;
> +        fmt.i_frame_length = A52_FRAME_NB;
> +        p_sys->i_bytes_per_frame = fmt.i_bytes_per_frame;
> +    } else
> +        p_sys->i_bytes_per_frame = i_nb_channels * i_format_size;
> +    p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( i_size );
>      p_sys->fmt = fmt;
>  
>      return 0;
> @@ -855,7 +925,7 @@ JNIThread_Write( JNIEnv *env, audio_output_t *p_aout,
> block_t *p_buffer )
>      i_samples = __MIN( p_sys->i_max_audiotrack_samples -
>      i_samples_pending,
>                         p_buffer->i_nb_samples );
>  
> -    i_data = i_samples * p_sys->i_bytes_per_frame;
> +    i_data = FRAMES_TO_BYTES( i_samples );
>  
>      /* check if we need to realloc a ByteArray */
>      if( i_data > p_sys->i_bytearray_size )
> @@ -967,7 +1037,8 @@ JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
>          *p_wait = FRAMES_TO_US( p_sys->i_max_audiotrack_samples / 20 );
>      } else
>      {
> -        uint32_t i_samples = i_ret / p_sys->i_bytes_per_frame;
> +        uint32_t i_samples = BYTES_TO_FRAMES( i_ret );
> +
>          p_sys->i_samples_queued -= i_samples;
>          p_sys->i_samples_written += i_samples;
>  
> -- 
> 2.1.3
> 



More information about the vlc-devel mailing list