Commit 1acd7199 authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf

audiotrack: JNIThread is created/joined in Open/Close

Fix Start called after a Stop (When audio track changes).

- JNIThread won't kill itself anymore: In case of error, it will wait for the
  Stop cmd.
- Handle AudioTrack exceptions: don't call audiotrack methods if an exception
  occurred.
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent b7439752
...@@ -61,6 +61,7 @@ struct aout_sys_t { ...@@ -61,6 +61,7 @@ struct aout_sys_t {
uint32_t i_pos_initial; /* initial position set by getPlaybackHeadPosition */ uint32_t i_pos_initial; /* initial position set by getPlaybackHeadPosition */
uint32_t i_samples_written; /* number of samples written since last flush */ uint32_t i_samples_written; /* number of samples written since last flush */
mtime_t i_play_time; /* time when play was called */ mtime_t i_play_time; /* time when play was called */
bool b_audiotrack_exception; /* true if audiotrack throwed an exception */
/* JNIThread control */ /* JNIThread control */
vlc_mutex_t mutex; vlc_mutex_t mutex;
...@@ -314,19 +315,21 @@ end: ...@@ -314,19 +315,21 @@ end:
} }
static inline bool static inline bool
check_exception( JNIEnv *env, bool *p_error, audio_output_t *p_aout, check_exception( JNIEnv *env, audio_output_t *p_aout,
const char *method ) const char *method )
{ {
if( (*env)->ExceptionOccurred( env ) ) if( (*env)->ExceptionOccurred( env ) )
{ {
aout_sys_t *p_sys = p_aout->sys;
p_sys->b_audiotrack_exception = true;
(*env)->ExceptionClear( env ); (*env)->ExceptionClear( env );
*p_error = true;
msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method ); msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
return true; return true;
} else } else
return false; return false;
} }
#define CHECK_EXCEPTION( method ) check_exception( env, p_error, p_aout, method ) #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, method )
#define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ ) #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
...@@ -378,7 +381,7 @@ ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd ) ...@@ -378,7 +381,7 @@ ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
static bool static bool
ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd ) ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
{ {
while( p_cmd->id != CMD_DONE && p_sys->b_thread_run ) while( p_cmd->id != CMD_DONE )
vlc_cond_wait( &p_sys->cond, &p_sys->mutex ); vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
return p_cmd->id == CMD_DONE; return p_cmd->id == CMD_DONE;
...@@ -404,7 +407,10 @@ JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay ) ...@@ -404,7 +407,10 @@ JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition ); if( p_sys->p_audiotrack )
p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
else
p_sys->i_pos_initial = 0;
/* HACK: On some broken devices, head position is still moving after a /* HACK: On some broken devices, head position is still moving after a
* flush or a stop. So, wait for the head position to be stabilized. */ * flush or a stop. So, wait for the head position to be stabilized. */
...@@ -489,7 +495,7 @@ JNIThread_SetDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay ) ...@@ -489,7 +495,7 @@ JNIThread_SetDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
} }
static int static int
JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) JNIThread_Start( JNIEnv *env, audio_output_t *p_aout )
{ {
struct aout_sys_t *p_sys = p_aout->sys; struct aout_sys_t *p_sys = p_aout->sys;
int i_size, i_min_buffer_size, i_channel_config, i_rate, i_format, int i_size, i_min_buffer_size, i_channel_config, i_rate, i_format,
...@@ -558,7 +564,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) ...@@ -558,7 +564,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate, p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
i_channel_config, i_format, i_size, i_channel_config, i_format, i_size,
jfields.AudioTrack.MODE_STREAM ); jfields.AudioTrack.MODE_STREAM );
if( CHECK_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack ) if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
return VLC_EGENERIC; return VLC_EGENERIC;
p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack ); p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
(*env)->DeleteLocalRef( env, p_audiotrack ); (*env)->DeleteLocalRef( env, p_audiotrack );
...@@ -571,7 +577,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) ...@@ -571,7 +577,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
jobject p_audioTimestamp = JNI_CALL( NewObject, jobject p_audioTimestamp = JNI_CALL( NewObject,
jfields.AudioTimestamp.clazz, jfields.AudioTimestamp.clazz,
jfields.AudioTimestamp.ctor ); jfields.AudioTimestamp.ctor );
if( CHECK_EXCEPTION( "AudioTimestamp<init>" ) || !p_audioTimestamp ) if( !p_audioTimestamp )
goto error; goto error;
p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp ); p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp );
(*env)->DeleteLocalRef( env, p_audioTimestamp ); (*env)->DeleteLocalRef( env, p_audioTimestamp );
...@@ -582,7 +588,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) ...@@ -582,7 +588,7 @@ JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
p_sys->fmt.i_rate = i_rate; p_sys->fmt.i_rate = i_rate;
JNI_AT_CALL_VOID( play ); JNI_AT_CALL_VOID( play );
CHECK_EXCEPTION( "play" ); CHECK_AT_EXCEPTION( "play" );
p_sys->i_play_time = mdate(); p_sys->i_play_time = mdate();
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -597,14 +603,17 @@ error: ...@@ -597,14 +603,17 @@ error:
} }
static void static void
JNIThread_Stop( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) JNIThread_Stop( JNIEnv *env, audio_output_t *p_aout )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
JNI_AT_CALL_VOID( stop ); if( !p_sys->b_audiotrack_exception )
CHECK_EXCEPTION( "stop" ); {
JNI_AT_CALL_VOID( stop );
JNI_AT_CALL_VOID( release ); if( !CHECK_AT_EXCEPTION( "stop" ) )
JNI_AT_CALL_VOID( release );
}
p_sys->b_audiotrack_exception = false;
(*env)->DeleteGlobalRef( env, p_sys->p_audiotrack ); (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
p_sys->p_audiotrack = NULL; p_sys->p_audiotrack = NULL;
...@@ -615,8 +624,8 @@ JNIThread_Stop( JNIEnv *env, bool *p_error, audio_output_t *p_aout ) ...@@ -615,8 +624,8 @@ JNIThread_Stop( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
} }
} }
static void static int
JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout, JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
block_t *p_buffer ) block_t *p_buffer )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
...@@ -642,10 +651,7 @@ JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout, ...@@ -642,10 +651,7 @@ JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
p_sys->i_bytearray_size = p_buffer->i_buffer; p_sys->i_bytearray_size = p_buffer->i_buffer;
} }
if( !p_sys->p_bytearray ) if( !p_sys->p_bytearray )
{ return VLC_EGENERIC;
*p_error = true;
return;
}
/* copy p_buffer in to ByteArray */ /* copy p_buffer in to ByteArray */
(*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0, (*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0,
...@@ -665,8 +671,8 @@ JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout, ...@@ -665,8 +671,8 @@ JNIThread_Play( JNIEnv *env, bool *p_error, 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" );
JNIThread_Stop( env, p_error, p_aout ); JNIThread_Stop( env, p_aout );
i_ret = JNIThread_Start( env, p_error, p_aout ); i_ret = JNIThread_Start( env, p_aout );
if( i_ret == VLC_SUCCESS ) if( i_ret == VLC_SUCCESS )
continue; continue;
} else } else
...@@ -680,17 +686,17 @@ JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout, ...@@ -680,17 +686,17 @@ JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
str = "ERROR"; str = "ERROR";
msg_Err( p_aout, "Write failed: %s", str ); msg_Err( p_aout, "Write failed: %s", str );
} }
*p_error = true; return VLC_EGENERIC;
break;
} }
i_offset += i_ret; i_offset += i_ret;
} }
p_sys->i_samples_written += p_buffer->i_nb_samples; p_sys->i_samples_written += p_buffer->i_nb_samples;
return VLC_SUCCESS;
} }
static void static void
JNIThread_Pause( JNIEnv *env, bool *p_error, audio_output_t *p_aout, JNIThread_Pause( JNIEnv *env, audio_output_t *p_aout,
bool b_pause, mtime_t i_date ) bool b_pause, mtime_t i_date )
{ {
VLC_UNUSED( i_date ); VLC_UNUSED( i_date );
...@@ -700,17 +706,17 @@ JNIThread_Pause( JNIEnv *env, bool *p_error, audio_output_t *p_aout, ...@@ -700,17 +706,17 @@ JNIThread_Pause( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
if( b_pause ) if( b_pause )
{ {
JNI_AT_CALL_VOID( pause ); JNI_AT_CALL_VOID( pause );
CHECK_EXCEPTION( "pause" ); CHECK_AT_EXCEPTION( "pause" );
} else } else
{ {
JNI_AT_CALL_VOID( play ); JNI_AT_CALL_VOID( play );
CHECK_EXCEPTION( "play" ); CHECK_AT_EXCEPTION( "play" );
p_sys->i_play_time = mdate(); p_sys->i_play_time = mdate();
} }
} }
static void static void
JNIThread_Flush( JNIEnv *env, bool *p_error, audio_output_t *p_aout, JNIThread_Flush( JNIEnv *env, audio_output_t *p_aout,
bool b_wait ) bool b_wait )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
...@@ -729,17 +735,17 @@ JNIThread_Flush( JNIEnv *env, bool *p_error, audio_output_t *p_aout, ...@@ -729,17 +735,17 @@ JNIThread_Flush( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
if( b_wait ) if( b_wait )
{ {
JNI_AT_CALL_VOID( stop ); JNI_AT_CALL_VOID( stop );
if( CHECK_EXCEPTION( "stop" ) ) if( CHECK_AT_EXCEPTION( "stop" ) )
return; return;
} else } else
{ {
JNI_AT_CALL_VOID( pause ); JNI_AT_CALL_VOID( pause );
if( CHECK_EXCEPTION( "pause" ) ) if( CHECK_AT_EXCEPTION( "pause" ) )
return; return;
JNI_AT_CALL_VOID( flush ); JNI_AT_CALL_VOID( flush );
} }
JNI_AT_CALL_VOID( play ); JNI_AT_CALL_VOID( play );
CHECK_EXCEPTION( "play" ); CHECK_AT_EXCEPTION( "play" );
p_sys->i_play_time = mdate(); p_sys->i_play_time = mdate();
} }
...@@ -790,36 +796,55 @@ JNIThread( void *data ) ...@@ -790,36 +796,55 @@ JNIThread( void *data )
switch( p_cmd->id ) switch( p_cmd->id )
{ {
case CMD_START: case CMD_START:
assert( !p_sys->p_audiotrack );
if( b_error ) {
p_cmd->out.start.i_ret = -1;
break;
}
p_sys->fmt = *p_cmd->in.start.p_fmt; p_sys->fmt = *p_cmd->in.start.p_fmt;
p_cmd->out.start.i_ret = p_cmd->out.start.i_ret =
JNIThread_Start( env, &b_error, p_aout ); JNIThread_Start( env, p_aout );
JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay ); JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
p_cmd->out.start.p_fmt = &p_sys->fmt; p_cmd->out.start.p_fmt = &p_sys->fmt;
b_paused = false; b_paused = false;
break; break;
case CMD_STOP: case CMD_STOP:
JNIThread_Stop( env, &b_error, p_aout ); assert( p_sys->p_audiotrack );
JNIThread_Stop( env, p_aout );
JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
b_paused = false; b_paused = false;
b_error = false;
break; break;
case CMD_PLAY: case CMD_PLAY:
JNIThread_Play( env, &b_error, p_aout, assert( p_sys->p_audiotrack );
p_cmd->in.play.p_buffer ); if( b_error )
break;
b_error = JNIThread_Play( env, p_aout,
p_cmd->in.play.p_buffer ) != VLC_SUCCESS;
JNIThread_SetDelay( env, p_aout, &i_audiotrack_delay ); JNIThread_SetDelay( env, p_aout, &i_audiotrack_delay );
break; break;
case CMD_PAUSE: case CMD_PAUSE:
JNIThread_Pause( env, &b_error, p_aout, assert( p_sys->p_audiotrack );
if( b_error )
break;
JNIThread_Pause( env, p_aout,
p_cmd->in.pause.b_pause, p_cmd->in.pause.b_pause,
p_cmd->in.pause.i_date ); p_cmd->in.pause.i_date );
b_paused = p_cmd->in.pause.b_pause; b_paused = p_cmd->in.pause.b_pause;
break; break;
case CMD_FLUSH: case CMD_FLUSH:
JNIThread_Flush( env, &b_error, p_aout, assert( p_sys->p_audiotrack );
if( b_error )
break;
JNIThread_Flush( env, p_aout,
p_cmd->in.flush.b_wait ); p_cmd->in.flush.b_wait );
JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay ); JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
break; break;
default: default:
vlc_assert_unreachable(); vlc_assert_unreachable();
} }
if( p_sys->b_audiotrack_exception )
b_error = true;
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
...@@ -829,9 +854,6 @@ JNIThread( void *data ) ...@@ -829,9 +854,6 @@ JNIThread( void *data )
if( p_cmd->pf_destroy ) if( p_cmd->pf_destroy )
p_cmd->pf_destroy( p_cmd ); p_cmd->pf_destroy( p_cmd );
if( b_error )
p_sys->b_thread_run = false;
/* signal that command is processed */ /* signal that command is processed */
vlc_cond_signal( &p_sys->cond ); vlc_cond_signal( &p_sys->cond );
} }
...@@ -842,8 +864,6 @@ end: ...@@ -842,8 +864,6 @@ end:
(*env)->DeleteGlobalRef( env, p_sys->p_bytearray ); (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
jni_detach_thread(); jni_detach_thread();
} }
p_sys->b_thread_run = false;
vlc_cond_signal( &p_sys->cond );
vlc_mutex_unlock( &p_sys->mutex ); vlc_mutex_unlock( &p_sys->mutex );
return NULL; return NULL;
} }
...@@ -857,18 +877,6 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -857,18 +877,6 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
assert( !p_sys->b_thread_run );
/* create JNIThread */
p_sys->b_thread_run = true;
if( vlc_clone( &p_sys->thread,
JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
{
msg_Err( p_aout, "JNIThread creation failed" );
vlc_mutex_unlock( &p_sys->mutex );
return VLC_EGENERIC;
}
p_cmd = ThreadCmd_New( CMD_START ); p_cmd = ThreadCmd_New( CMD_START );
if( p_cmd ) if( p_cmd )
{ {
...@@ -884,6 +892,7 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt ) ...@@ -884,6 +892,7 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
} }
free( p_cmd ); free( p_cmd );
} }
vlc_mutex_unlock( &p_sys->mutex ); vlc_mutex_unlock( &p_sys->mutex );
if( i_ret == VLC_SUCCESS ) if( i_ret == VLC_SUCCESS )
...@@ -896,32 +905,24 @@ static void ...@@ -896,32 +905,24 @@ static void
Stop( audio_output_t *p_aout ) Stop( audio_output_t *p_aout )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
struct thread_cmd *p_cmd;
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
if( p_sys->b_thread_run ) p_sys->i_samples_queued = 0;
{ ThreadCmd_FlushQueue( p_sys );
struct thread_cmd *p_cmd;
p_sys->i_samples_queued = 0;
ThreadCmd_FlushQueue( p_sys );
p_cmd = ThreadCmd_New( CMD_STOP ); p_cmd = ThreadCmd_New( CMD_STOP );
if( p_cmd ) if( p_cmd )
{ {
/* ask the thread to process the Stop command */ /* ask the thread to process the Stop command */
ThreadCmd_InsertHead( p_sys, p_cmd ); ThreadCmd_InsertHead( p_sys, p_cmd );
ThreadCmd_Wait( p_sys, p_cmd ); ThreadCmd_Wait( p_sys, p_cmd );
free( p_cmd ); free( p_cmd );
}
/* kill the thread */
p_sys->b_thread_run = false;
vlc_cond_signal( &p_sys->cond );
} }
vlc_mutex_unlock( &p_sys->mutex );
vlc_join( p_sys->thread, NULL ); vlc_mutex_unlock( &p_sys->mutex );
} }
static void static void
...@@ -935,32 +936,28 @@ static void ...@@ -935,32 +936,28 @@ static void
Play( audio_output_t *p_aout, block_t *p_buffer ) Play( audio_output_t *p_aout, block_t *p_buffer )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
struct thread_cmd *p_cmd;
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
if( p_sys->b_thread_run ) while( p_sys->i_samples_queued != 0
{ && FRAMES_TO_US( p_sys->i_samples_queued +
struct thread_cmd *p_cmd; p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
while( p_sys->i_samples_queued != 0 && p_sys->b_thread_run
&& FRAMES_TO_US( p_sys->i_samples_queued +
p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
p_cmd = ThreadCmd_New( CMD_PLAY ); p_cmd = ThreadCmd_New( CMD_PLAY );
if( p_cmd )
{
/* ask the thread to process the Play command */
p_cmd->in.play.p_buffer = p_buffer;
p_cmd->pf_destroy = PlayCmd_Destroy;
if( p_cmd ) ThreadCmd_InsertTail( p_sys, p_cmd );
{
/* ask the thread to process the Play command */
p_cmd->in.play.p_buffer = p_buffer;
p_cmd->pf_destroy = PlayCmd_Destroy;
ThreadCmd_InsertTail( p_sys, p_cmd ); p_sys->i_samples_queued += p_buffer->i_nb_samples;
} else
block_Release( p_cmd->in.play.p_buffer );
p_sys->i_samples_queued += p_buffer->i_nb_samples;
} else
block_Release( p_cmd->in.play.p_buffer );
}
vlc_mutex_unlock( &p_sys->mutex ); vlc_mutex_unlock( &p_sys->mutex );
} }
...@@ -968,25 +965,23 @@ static void ...@@ -968,25 +965,23 @@ static void
Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date ) Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
struct thread_cmd *p_cmd;
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
if( p_sys->b_thread_run ) p_cmd = ThreadCmd_New( CMD_PAUSE );
if( p_cmd )
{ {
struct thread_cmd *p_cmd = ThreadCmd_New( CMD_PAUSE ); /* ask the thread to process the Pause command */
p_cmd->in.pause.b_pause = b_pause;
if( p_cmd ) p_cmd->in.pause.i_date = i_date;
{
/* ask the thread to process the Pause command */
p_cmd->in.pause.b_pause = b_pause;
p_cmd->in.pause.i_date = i_date;
ThreadCmd_InsertHead( p_sys, p_cmd ); ThreadCmd_InsertHead( p_sys, p_cmd );
ThreadCmd_Wait( p_sys, p_cmd ); ThreadCmd_Wait( p_sys, p_cmd );
free( p_cmd ); free( p_cmd );
}
} }
vlc_mutex_unlock( &p_sys->mutex ); vlc_mutex_unlock( &p_sys->mutex );
} }
...@@ -994,28 +989,25 @@ static void ...@@ -994,28 +989,25 @@ static void
Flush( audio_output_t *p_aout, bool b_wait ) Flush( audio_output_t *p_aout, bool b_wait )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
struct thread_cmd *p_cmd;
vlc_mutex_lock( &p_sys->mutex ); vlc_mutex_lock( &p_sys->mutex );
if( p_sys->b_thread_run ) p_sys->i_samples_queued = 0;
{ ThreadCmd_FlushQueue( p_sys );
struct thread_cmd *p_cmd;
p_sys->i_samples_queued = 0; p_cmd = ThreadCmd_New( CMD_FLUSH );
ThreadCmd_FlushQueue( p_sys ); if( p_cmd)
{
p_cmd = ThreadCmd_New( CMD_FLUSH ); /* ask the thread to process the Flush command */
if( p_cmd) p_cmd->in.flush.b_wait = b_wait;
{
/* ask the thread to process the Flush command */
p_cmd->in.flush.b_wait = b_wait;
ThreadCmd_InsertHead( p_sys, p_cmd ); ThreadCmd_InsertHead( p_sys, p_cmd );
ThreadCmd_Wait( p_sys, p_cmd ); ThreadCmd_Wait( p_sys, p_cmd );
free( p_cmd ); free( p_cmd );
}
} }
vlc_mutex_unlock( &p_sys->mutex ); vlc_mutex_unlock( &p_sys->mutex );
} }
...@@ -1057,6 +1049,17 @@ Open( vlc_object_t *obj ) ...@@ -1057,6 +1049,17 @@ Open( vlc_object_t *obj )
vlc_cond_init( &p_sys->cond ); vlc_cond_init( &p_sys->cond );
TAILQ_INIT( &p_sys->thread_cmd_queue ); TAILQ_INIT( &p_sys->thread_cmd_queue );
/* create JNIThread */
p_sys->b_thread_run = true;
if( vlc_clone( &p_sys->thread,
JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
{
msg_Err( p_aout, "JNIThread creation failed" );
p_sys->b_thread_run = false;
Close( obj );
return VLC_EGENERIC;
}
p_aout->sys = p_sys; p_aout->sys = p_sys;
p_aout->start = Start; p_aout->start = Start;
p_aout->stop = Stop; p_aout->stop = Stop;
...@@ -1076,6 +1079,17 @@ Close( vlc_object_t *obj ) ...@@ -1076,6 +1079,17 @@ Close( vlc_object_t *obj )
audio_output_t *p_aout = (audio_output_t *) obj; audio_output_t *p_aout = (audio_output_t *) obj;
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
/* kill the thread */
vlc_mutex_lock( &p_sys->mutex );
if( p_sys->b_thread_run )
{
p_sys->b_thread_run = false;
vlc_cond_signal( &p_sys->cond );
vlc_mutex_unlock( &p_sys->mutex );
vlc_join( p_sys->thread, NULL );
} else
vlc_mutex_unlock( &p_sys->mutex );
vlc_mutex_destroy( &p_sys->mutex ); vlc_mutex_destroy( &p_sys->mutex );
vlc_cond_destroy( &p_sys->cond ); vlc_cond_destroy( &p_sys->cond );
......
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