[vlc-devel] [PATCH 1/2] audiotrack: fix too unstable delay
Thomas Guillem
thomas at gllm.fr
Wed Feb 25 19:29:08 CET 2015
It was impossible to calculate a stable delay from 2 different threads.
Calculate audiotrack delay and the Queue delay from JNIThread. All JNIThread
commands are now executed in locked state.
---
modules/audio_output/audiotrack.c | 85 +++++++++++++++++++++++++--------------
1 file changed, 54 insertions(+), 31 deletions(-)
diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 7b2646f..e1e0b8b 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -72,7 +72,6 @@ struct aout_sys_t {
bool b_thread_run; /* is thread alive */
THREAD_CMD_QUEUE thread_cmd_queue; /* thread cmd queue */
uint32_t i_samples_queued; /* number of samples queued */
- uint32_t i_audiotrack_delay; /* audiotrack delay in samples */
};
/* Soft volume helper */
@@ -99,6 +98,7 @@ struct thread_cmd
CMD_STOP,
CMD_PLAY,
CMD_PAUSE,
+ CMD_TIME_GET,
CMD_FLUSH,
CMD_DONE,
} id;
@@ -122,6 +122,10 @@ struct thread_cmd
int i_ret;
audio_sample_format_t *p_fmt;
} start;
+ struct {
+ int i_ret;
+ mtime_t i_delay;
+ } time_get;
} out;
void ( *pf_destroy )( struct thread_cmd * );
};
@@ -403,7 +407,7 @@ ThreadCmd_FlushQueue( aout_sys_t *p_sys )
}
static void
-JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
+JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout )
{
aout_sys_t *p_sys = p_aout->sys;
@@ -424,11 +428,11 @@ JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
} while( p_sys->i_pos_initial != i_last_pos );
}
p_sys->i_samples_written = 0;
- *p_delay = 0;
+ p_sys->i_samples_queued = 0;
}
-static void
-JNIThread_SetDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
+static int
+JNIThread_TimeGet( JNIEnv *env, audio_output_t *p_aout, mtime_t *p_delay )
{
aout_sys_t *p_sys = p_aout->sys;
bool b_frame_delay_set = false;
@@ -487,11 +491,18 @@ JNIThread_SetDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
uint32_t i_head_pos = JNI_AT_CALL_INT( getPlaybackHeadPosition );
i_frame_pos = i_head_pos - p_sys->i_pos_initial;
- b_frame_delay_set = true;
+ if (i_frame_pos > 0)
+ b_frame_delay_set = true;
}
if( b_frame_delay_set && p_sys->i_samples_written > i_frame_pos )
- *p_delay = p_sys->i_samples_written - i_frame_pos;
+ {
+ uint32_t i_audiotrack_delay = p_sys->i_samples_written - i_frame_pos;
+
+ *p_delay = FRAMES_TO_US( p_sys->i_samples_queued + i_audiotrack_delay );
+ return 0;
+ } else
+ return -1;
}
static int
@@ -691,6 +702,7 @@ JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
i_offset += i_ret;
}
+ p_sys->i_samples_queued -= p_buffer->i_nb_samples;
p_sys->i_samples_written += p_buffer->i_nb_samples;
return VLC_SUCCESS;
}
@@ -756,7 +768,6 @@ JNIThread( void *data )
aout_sys_t *p_sys = p_aout->sys;
bool b_error = false;
bool b_paused = false;
- uint32_t i_audiotrack_delay = 0;
JNIEnv* env;
jni_attach_thread( &env, THREAD_NAME );
@@ -782,16 +793,20 @@ JNIThread( void *data )
vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
continue;
}
-
- TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
-
if( p_cmd->id == CMD_PLAY )
{
- p_sys->i_samples_queued -= p_cmd->in.play.p_buffer->i_nb_samples;
- vlc_cond_signal( &p_sys->cond );
+ /* Yield the current thread. Give room for others commands.
+ * Especially TimeGet that is called very often */
+ mtime_t i_wait =
+ FRAMES_TO_US( p_cmd->in.play.p_buffer->i_nb_samples ) / 2
+ vlc_cond_timedwait( &p_sys->cond, &p_sys->mutex, mdate() + i_wait );
+ p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue );
+ if( p_cmd == NULL )
+ break;
}
- vlc_mutex_unlock( &p_sys->mutex );
+ TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
+
/* process a command */
switch( p_cmd->id )
{
@@ -804,14 +819,14 @@ JNIThread( void *data )
p_sys->fmt = *p_cmd->in.start.p_fmt;
p_cmd->out.start.i_ret =
JNIThread_Start( env, p_aout );
- JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
+ JNIThread_InitDelay( env, p_aout );
p_cmd->out.start.p_fmt = &p_sys->fmt;
b_paused = false;
break;
case CMD_STOP:
assert( p_sys->p_audiotrack );
JNIThread_Stop( env, p_aout );
- JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
+ JNIThread_InitDelay( env, p_aout );
b_paused = false;
b_error = false;
break;
@@ -821,7 +836,6 @@ JNIThread( void *data )
break;
b_error = JNIThread_Play( env, p_aout,
p_cmd->in.play.p_buffer ) != VLC_SUCCESS;
- JNIThread_SetDelay( env, p_aout, &i_audiotrack_delay );
break;
case CMD_PAUSE:
assert( p_sys->p_audiotrack );
@@ -832,13 +846,21 @@ JNIThread( void *data )
p_cmd->in.pause.i_date );
b_paused = p_cmd->in.pause.b_pause;
break;
+ case CMD_TIME_GET:
+ assert( p_sys->p_audiotrack );
+ if( b_error )
+ break;
+ p_cmd->out.time_get.i_ret =
+ JNIThread_TimeGet( env, p_aout,
+ &p_cmd->out.time_get.i_delay );
+ break;
case CMD_FLUSH:
assert( p_sys->p_audiotrack );
if( b_error )
break;
JNIThread_Flush( env, p_aout,
p_cmd->in.flush.b_wait );
- JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
+ JNIThread_InitDelay( env, p_aout );
break;
default:
vlc_assert_unreachable();
@@ -846,10 +868,6 @@ JNIThread( void *data )
if( p_sys->b_audiotrack_exception )
b_error = true;
- vlc_mutex_lock( &p_sys->mutex );
-
- p_sys->i_audiotrack_delay = i_audiotrack_delay;
-
p_cmd->id = CMD_DONE;
if( p_cmd->pf_destroy )
p_cmd->pf_destroy( p_cmd );
@@ -909,7 +927,6 @@ Stop( audio_output_t *p_aout )
vlc_mutex_lock( &p_sys->mutex );
- p_sys->i_samples_queued = 0;
ThreadCmd_FlushQueue( p_sys );
p_cmd = ThreadCmd_New( CMD_STOP );
@@ -993,7 +1010,6 @@ Flush( audio_output_t *p_aout, bool b_wait )
vlc_mutex_lock( &p_sys->mutex );
- p_sys->i_samples_queued = 0;
ThreadCmd_FlushQueue( p_sys );
p_cmd = ThreadCmd_New( CMD_FLUSH );
@@ -1015,16 +1031,23 @@ static int
TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
{
aout_sys_t *p_sys = p_aout->sys;
- int i_ret;
+ struct thread_cmd *p_cmd;
+ int i_ret = -1;
vlc_mutex_lock( &p_sys->mutex );
- if( p_sys->i_samples_queued != 0 )
+
+ p_cmd = ThreadCmd_New( CMD_TIME_GET );
+ if( p_cmd)
{
- *p_delay = FRAMES_TO_US( p_sys->i_samples_queued +
- p_sys->i_audiotrack_delay );
- i_ret = 0;
- } else
- i_ret = -1;
+ ThreadCmd_InsertHead( p_sys, p_cmd );
+ ThreadCmd_Wait( p_sys, p_cmd );
+
+ i_ret = p_cmd->out.time_get.i_ret;
+ *p_delay = p_cmd->out.time_get.i_delay;
+
+ free( p_cmd );
+ }
+
vlc_mutex_unlock( &p_sys->mutex );
return i_ret;
--
2.1.3
More information about the vlc-devel
mailing list