[vlc-commits] audiotrack: handle HW latency

Thomas Guillem git at videolan.org
Wed Apr 15 17:27:07 CEST 2015


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Apr 15 12:04:45 2015 +0200| [985ff5cb03d483d034aa7a2192705f5835b760dc] | committer: Thomas Guillem

audiotrack: handle HW latency

Since Android 4.3 there is a hidden method that retrieve the audio hardware
latency: AudioSystem.getOutputLatency() (that should not be used according to
the android comments).

This latency should not be used when we use AudioTrack.getTimestamp since it
already take into account the hardware latency. So why adding a new method ?
Because AudioTrack.getTimestamp don't work with Bluetooth (it returns false).

This fix lip sync with Bluetooth audio.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=985ff5cb03d483d034aa7a2192705f5835b760dc
---

 modules/audio_output/audiotrack.c |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index c2c06c3..14a6e53 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -83,6 +83,7 @@ struct aout_sys_t {
         mtime_t p_us[SMOOTHPOS_SAMPLE_COUNT];
         mtime_t i_us;
         mtime_t i_last_time;
+        mtime_t i_latency_us;
     } smoothpos;
 
     uint64_t i_samples_written; /* number of samples written since last flush */
@@ -183,6 +184,10 @@ static struct
     } AudioManager;
     struct {
         jclass clazz;
+        jmethodID getOutputLatency;
+    } AudioSystem;
+    struct {
+        jclass clazz;
         jmethodID ctor;
         jfieldID framePosition;
         jfieldID nanoTime;
@@ -297,6 +302,15 @@ InitJNIFields( audio_output_t *p_aout )
                 "nanoTime", "J", true );
     }
 
+    /* AudioSystem class init */
+    GET_CLASS( "android/media/AudioSystem", false );
+    if( clazz )
+    {
+        jfields.AudioSystem.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
+        GET_ID( GetStaticMethodID, AudioSystem.getOutputLatency,
+                "getOutputLatency", "(I)I", false );
+    }
+
     /* AudioFormat class init */
     GET_CLASS( "android/media/AudioFormat", true );
     GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
@@ -507,6 +521,7 @@ AudioTrack_ResetPositions( JNIEnv *env, audio_output_t *p_aout )
     p_sys->smoothpos.i_idx = 0;
     p_sys->smoothpos.i_last_time = 0;
     p_sys->smoothpos.i_us = 0;
+    p_sys->smoothpos.i_latency_us = 0;
 }
 
 /**
@@ -541,9 +556,20 @@ AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
         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;
+
+        if( jfields.AudioSystem.getOutputLatency )
+        {
+            int i_latency_ms = JNI_CALL( CallStaticIntMethod,
+                                         jfields.AudioSystem.clazz,
+                                         jfields.AudioSystem.getOutputLatency,
+                                         jfields.AudioManager.STREAM_MUSIC );
+
+            p_sys->smoothpos.i_latency_us = i_latency_ms > 0 ?
+                                            i_latency_ms * 1000L : 0;
+        }
     }
     if( p_sys->smoothpos.i_us != 0 )
-        return p_sys->smoothpos.i_us + i_now;
+        return p_sys->smoothpos.i_us + i_now - p_sys->smoothpos.i_latency_us;
     else
         return 0;
 }



More information about the vlc-commits mailing list