[vlc-devel] [PATCH 3/3] audiotrack: smooth out the AudioTrack position

Thomas Guillem thomas at gllm.fr
Tue Apr 14 19:44:53 CEST 2015


It improves delay precision for old devices.
---
 modules/audio_output/audiotrack.c | 80 +++++++++++++++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 7 deletions(-)

diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 8744647..d1821b9 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -37,6 +37,9 @@
 #define MIN_AUDIOTRACK_BUFFER_US INT64_C(250000)  // 250ms
 #define MAX_AUDIOTRACK_BUFFER_US INT64_C(1000000) // 1000ms
 
+#define SMOOTHPOS_SAMPLE_COUNT 10
+#define SMOOTHPOS_INTERVAL_US 30000 // 30ms
+
 static int  Open( vlc_object_t * );
 static void Close( vlc_object_t * );
 static void Stop( audio_output_t * );
@@ -63,6 +66,15 @@ struct aout_sys_t {
         uint32_t i_last;
     } headpos;
 
+    /* Used by AudioTrack_GetSmoothPositionUs */
+    struct {
+        uint32_t i_idx;
+        uint32_t i_count;
+        mtime_t p_us[SMOOTHPOS_SAMPLE_COUNT];
+        mtime_t i_us;
+        mtime_t i_last_time;
+    } smoothpos;
+
     uint64_t i_samples_written; /* number of samples written since last flush */
     uint32_t i_bytes_per_frame; /* byte per frame */
     uint32_t i_max_audiotrack_samples;
@@ -438,6 +450,63 @@ AudioTrack_GetPosition( JNIEnv *env, audio_output_t *p_aout )
         - p_sys->headpos.i_initial;
 }
 
+static void
+AudioTrack_ResetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    VLC_UNUSED( env );
+
+    p_sys->smoothpos.i_count = 0;
+    p_sys->smoothpos.i_idx = 0;
+    p_sys->smoothpos.i_last_time = 0;
+    p_sys->smoothpos.i_us = 0;
+}
+
+/**
+ * Get a smooth AudioTrack position
+ *
+ * This function smooth out the AudioTrack position since it has a very bad
+ * precision (+/- 20ms on old devices).
+ */
+static mtime_t
+AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    uint64_t i_audiotrack_us;
+    mtime_t i_now = mdate();
+
+    /* Fetch an AudioTrack position every SMOOTHPOS_INTERVAL_US (30ms) */
+    if( i_now - p_sys->smoothpos.i_last_time >= SMOOTHPOS_INTERVAL_US )
+    {
+        i_audiotrack_us = FRAMES_TO_US( AudioTrack_GetPosition( env, p_aout ) );
+        if( i_audiotrack_us <= 0 )
+            return 0;
+
+        p_sys->smoothpos.i_last_time = i_now;
+
+        /* Base the position off the current time */
+        p_sys->smoothpos.p_us[p_sys->smoothpos.i_idx] = i_audiotrack_us - i_now;
+        p_sys->smoothpos.i_idx = (p_sys->smoothpos.i_idx + 1)
+                                 % SMOOTHPOS_SAMPLE_COUNT;
+        if( p_sys->smoothpos.i_count < SMOOTHPOS_SAMPLE_COUNT )
+            p_sys->smoothpos.i_count++;
+
+        if( p_sys->smoothpos.i_count >= SMOOTHPOS_SAMPLE_COUNT )
+        {
+            /* Calculate the average position based off the current time */
+            p_sys->smoothpos.i_us = 0;
+            for( uint32_t i = 0; i < p_sys->smoothpos.i_count; ++i )
+                p_sys->smoothpos.i_us += p_sys->smoothpos.p_us[i];
+            p_sys->smoothpos.i_us /= p_sys->smoothpos.i_count;
+            msg_Err( p_aout, "AudioTrack_GetSmoothPositionUs: %lld", p_sys->smoothpos.i_us + i_now);
+        }
+    }
+    if( p_sys->smoothpos.i_us != 0 )
+        return p_sys->smoothpos.i_us + i_now;
+    else
+        return 0;
+}
+
 static mtime_t
 AudioTrack_GetTimestampPositionUs( JNIEnv *env, audio_output_t *p_aout )
 {
@@ -512,6 +581,7 @@ AudioTrack_InitDelay( JNIEnv *env, audio_output_t *p_aout )
     p_sys->i_samples_written = 0;
     p_sys->headpos.i_last = 0;
     p_sys->headpos.i_wrap_count = 0;
+    AudioTrack_ResetSmoothPositionUs(env, p_aout );
 }
 
 static int
@@ -529,13 +599,8 @@ TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
 
     i_audiotrack_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
 
-    if( i_audiotrack_us == 0 )
-    {
-        uint64_t i_audiotrack_pos = AudioTrack_GetPosition( env, p_aout );
-
-        if( p_sys->i_samples_written > i_audiotrack_pos )
-            i_audiotrack_us = FRAMES_TO_US( i_audiotrack_pos );
-    }
+    if( i_audiotrack_us <= 0 )
+        i_audiotrack_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
 
     if( i_audiotrack_us > 0 )
     {
@@ -1223,6 +1288,7 @@ Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
         JNI_AT_CALL_VOID( play );
         CHECK_AT_EXCEPTION( "play" );
         p_sys->i_play_time = mdate();
+        AudioTrack_ResetSmoothPositionUs( env, p_aout );
     }
 }
 
-- 
2.1.3




More information about the vlc-devel mailing list