[vlc-devel] [PATCH] audiotrack: add AC3 passthrough support
Thomas Guillem
thomas at gllm.fr
Tue Mar 10 16:01:31 CET 2015
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