Commit b83d1386 authored by Thomas Guillem's avatar Thomas Guillem

audiotrack: add AudioTrack_Reset

Refactor AudioTrack creation, and add a function that destroy and recreate an
AudioTrack object using the previous arguments.
parent 9cd3560b
...@@ -61,6 +61,13 @@ struct aout_sys_t { ...@@ -61,6 +61,13 @@ struct aout_sys_t {
jobject p_bytebuffer; /* ByteBuffer ref (for WriteV21) */ jobject p_bytebuffer; /* ByteBuffer ref (for WriteV21) */
audio_sample_format_t fmt; /* fmt setup by Start */ audio_sample_format_t fmt; /* fmt setup by Start */
struct {
unsigned int i_rate;
int i_channel_config;
int i_format;
int i_size;
} audiotrack_args;
/* Used by AudioTrack_GetPosition / AudioTrack_getPlaybackHeadPosition */ /* Used by AudioTrack_GetPosition / AudioTrack_getPlaybackHeadPosition */
struct { struct {
uint64_t i_initial; uint64_t i_initial;
...@@ -726,20 +733,70 @@ AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] ) ...@@ -726,20 +733,70 @@ AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] )
#undef HAS_CHAN #undef HAS_CHAN
} }
/**
* Create an Android AudioTrack.
* returns -1 on error, 0 on success.
*/
static int
AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
int i_channel_config, int i_format, int i_size )
{
aout_sys_t *p_sys = p_aout->sys;
jobject p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC,
i_rate, i_channel_config, i_format,
i_size, jfields.AudioTrack.MODE_STREAM );
if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
{
msg_Warn( p_aout, "AudioTrack Init failed" ) ;
return -1;
}
if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
!= jfields.AudioTrack.STATE_INITIALIZED )
{
JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
(*env)->DeleteLocalRef( env, p_audiotrack );
msg_Err( p_aout, "AudioTrack getState failed" );
return -1;
}
p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
(*env)->DeleteLocalRef( env, p_audiotrack );
if( !p_sys->p_audiotrack )
return -1;
return 0;
}
/**
* Destroy and recreate an Android AudioTrack using the same arguments.
* returns -1 on error, 0 on success.
*/
static int
AudioTrack_Reset( JNIEnv *env, audio_output_t *p_aout )
{
aout_sys_t *p_sys = p_aout->sys;
JNI_AT_CALL_VOID( release );
(*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
return AudioTrack_New( env, p_aout, p_sys->audiotrack_args.i_rate,
p_sys->audiotrack_args.i_channel_config,
p_sys->audiotrack_args.i_format,
p_sys->audiotrack_args.i_size );
}
/** /**
* Configure and create an Android AudioTrack. * Configure and create an Android AudioTrack.
* returns NULL on configuration error * returns -1 on configuration error, 0 on success.
*/ */
static jobject static int
AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, AudioTrack_Create( JNIEnv *env, audio_output_t *p_aout,
unsigned int i_rate, unsigned int i_rate,
vlc_fourcc_t i_vlc_format, vlc_fourcc_t i_vlc_format,
uint16_t i_physical_channels, uint16_t i_physical_channels,
int i_bytes_per_frame, int i_bytes_per_frame )
int *p_audiotrack_size )
{ {
aout_sys_t *p_sys = p_aout->sys;
int i_size, i_min_buffer_size, i_channel_config, i_format; int i_size, i_min_buffer_size, i_channel_config, i_format;
jobject p_audiotrack;
switch( i_vlc_format ) switch( i_vlc_format )
{ {
...@@ -785,7 +842,7 @@ AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, ...@@ -785,7 +842,7 @@ AudioTrack_New( JNIEnv *env, audio_output_t *p_aout,
if( i_min_buffer_size <= 0 ) if( i_min_buffer_size <= 0 )
{ {
msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ; msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
return NULL; return -1;
} }
if( i_vlc_format == VLC_CODEC_SPDIFB ) if( i_vlc_format == VLC_CODEC_SPDIFB )
i_size = ( i_min_buffer_size / AOUT_SPDIF_SIZE + 1 ) * AOUT_SPDIF_SIZE; i_size = ( i_min_buffer_size / AOUT_SPDIF_SIZE + 1 ) * AOUT_SPDIF_SIZE;
...@@ -805,25 +862,16 @@ AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, ...@@ -805,25 +862,16 @@ AudioTrack_New( JNIEnv *env, audio_output_t *p_aout,
} }
/* create AudioTrack object */ /* create AudioTrack object */
p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate, if( AudioTrack_New( env, p_aout, i_rate, i_channel_config,
i_channel_config, i_format, i_size, i_format , i_size ) != 0 )
jfields.AudioTrack.MODE_STREAM ); return -1;
if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
{
msg_Warn( p_aout, "AudioTrack Init failed" ) ;
return NULL;
}
if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
!= jfields.AudioTrack.STATE_INITIALIZED )
{
JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
(*env)->DeleteLocalRef( env, p_audiotrack );
msg_Err( p_aout, "AudioTrack getState failed" );
return NULL;
}
*p_audiotrack_size = i_size;
return p_audiotrack; p_sys->audiotrack_args.i_rate = i_rate;
p_sys->audiotrack_args.i_channel_config = i_channel_config;
p_sys->audiotrack_args.i_format = i_format;
p_sys->audiotrack_args.i_size = i_size;
return 0;
} }
static int static int
...@@ -831,9 +879,8 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -831,9 +879,8 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
JNIEnv *env; JNIEnv *env;
jobject p_audiotrack = NULL; int i_nb_channels, i_max_channels, i_bytes_per_frame, i_native_rate = 0,
int i_nb_channels, i_max_channels, i_audiotrack_size, i_bytes_per_frame, i_ret;
i_native_rate = 0;
unsigned int i_rate; unsigned int i_rate;
bool b_spdif; bool b_spdif;
...@@ -916,15 +963,13 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -916,15 +963,13 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
: (unsigned int) i_native_rate; : (unsigned int) i_native_rate;
/* Try to create an AudioTrack with the most advanced channel and /* Try to create an AudioTrack with the most advanced channel and
* format configuration. If AudioTrack_New fails, try again with a less * format configuration. If AudioTrack_Create fails, try again with a
* advanced format (PCM S16N). If it fails again, try again with Stereo * less advanced format (PCM S16N). If it fails again, try again with
* channels. */ * Stereo channels. */
p_audiotrack = AudioTrack_New( env, p_aout, i_rate, i_ret = AudioTrack_Create( env, p_aout, i_rate, p_sys->fmt.i_format,
p_sys->fmt.i_format, p_sys->fmt.i_physical_channels,
p_sys->fmt.i_physical_channels, i_bytes_per_frame );
i_bytes_per_frame, if( i_ret != 0 )
&i_audiotrack_size );
if( !p_audiotrack )
{ {
if( p_sys->fmt.i_format == VLC_CODEC_SPDIFB ) if( p_sys->fmt.i_format == VLC_CODEC_SPDIFB )
{ {
...@@ -950,14 +995,9 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -950,14 +995,9 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
else else
break; break;
} }
} while( !p_audiotrack ); } while( i_ret != 0 );
if( !p_audiotrack ) if( i_ret != 0 )
return VLC_EGENERIC;
p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
(*env)->DeleteLocalRef( env, p_audiotrack );
if( !p_sys->p_audiotrack )
return VLC_EGENERIC; return VLC_EGENERIC;
p_sys->fmt.i_rate = i_rate; p_sys->fmt.i_rate = i_rate;
...@@ -980,7 +1020,7 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -980,7 +1020,7 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
p_sys->p_chan_table ); p_sys->p_chan_table );
p_sys->i_bytes_per_frame = i_bytes_per_frame; p_sys->i_bytes_per_frame = i_bytes_per_frame;
} }
p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( i_audiotrack_size ); p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( p_sys->audiotrack_args.i_size );
#ifdef AUDIOTRACK_HW_LATENCY #ifdef AUDIOTRACK_HW_LATENCY
if( jfields.AudioTimestamp.clazz ) if( jfields.AudioTimestamp.clazz )
...@@ -1282,8 +1322,7 @@ AudioTrack_Play( JNIEnv *env, audio_output_t *p_aout, ...@@ -1282,8 +1322,7 @@ AudioTrack_Play( JNIEnv *env, audio_output_t *p_aout,
{ {
msg_Warn( p_aout, "ERROR_DEAD_OBJECT: " msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
"try recreating AudioTrack" ); "try recreating AudioTrack" );
Stop( p_aout ); i_ret = AudioTrack_Reset( env, p_aout );
i_ret = Start( p_aout, &p_sys->fmt );
} else } else
{ {
const char *str; const char *str;
......
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