[vlc-commits] audiotrack: use AudioTrack.getLatency()
Thomas Guillem
git at videolan.org
Tue Dec 1 12:16:11 CET 2020
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Nov 23 14:21:15 2020 +0100| [560221d6621c9354ae25e2a00e62f19f6a76d454] | committer: Thomas Guillem
audiotrack: use AudioTrack.getLatency()
Instead of AudioSystem.getOutputLatency().
That way, we are sure the get the latency of the current output device.
Note: both methods are hidden and should not be used in favor or
AudioTrack.getTimestamp(). Unfortunately, getTimestamp() returns a valid
timestamp too late (after few seconds) or doesn't work with some phones.
Therefore, the usage of the hidden API is still needed as a backup plan.
cf. https://github.com/google/ExoPlayer/issues/5763
The android team allow the usage of this hidden API, waiting for a new
method in next Android versions.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=560221d6621c9354ae25e2a00e62f19f6a76d454
---
modules/audio_output/audiotrack.c | 60 ++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 8237af217f..a371104730 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -118,7 +118,6 @@ typedef struct
vlc_tick_t p_us[SMOOTHPOS_SAMPLE_COUNT];
vlc_tick_t i_us;
vlc_tick_t i_last_time;
- vlc_tick_t i_latency_us;
} smoothpos;
uint32_t i_max_audiotrack_samples;
@@ -211,6 +210,7 @@ static struct
jmethodID writeShortV23;
jmethodID writeBufferV21;
jmethodID writeFloat;
+ jmethodID getLatency;
jmethodID getPlaybackHeadPosition;
jmethodID getTimestamp;
jmethodID getMinBufferSize;
@@ -274,10 +274,6 @@ static struct
bool has_ERROR_DEAD_OBJECT;
jint STREAM_MUSIC;
} AudioManager;
- struct {
- jclass clazz;
- jmethodID getOutputLatency;
- } AudioSystem;
struct {
jclass clazz;
jmethodID ctor;
@@ -364,6 +360,10 @@ InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
} else
GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
+#ifdef AUDIOTRACK_HW_LATENCY
+ GET_ID( GetMethodID, AudioTrack.getLatency, "getLatency", "()I", false );
+#endif
+
GET_ID( GetMethodID, AudioTrack.getTimestamp,
"getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
@@ -431,17 +431,6 @@ InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
"nanoTime", "J", true );
}
-#ifdef AUDIOTRACK_HW_LATENCY
- /* 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 );
- }
-#endif
-
/* AudioFormat class init */
GET_CLASS( "android/media/AudioFormat", true );
GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
@@ -639,7 +628,6 @@ 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;
}
/**
@@ -655,6 +643,29 @@ AudioTrack_Reset( JNIEnv *env, audio_output_t *p_aout )
p_sys->i_samples_written = 0;
}
+static vlc_tick_t
+AudioTrack_GetLatencyUs( JNIEnv *env, audio_output_t *p_aout )
+{
+ aout_sys_t *p_sys = p_aout->sys;
+
+ if( jfields.AudioTrack.getLatency )
+ {
+ int i_latency_ms = JNI_AT_CALL_INT( getLatency );
+
+ /* getLatency() includes the latency due to AudioTrack buffer size,
+ * AudioMixer (if any) and audio hardware driver. We only need the
+ * audio hardware latency */
+ if( i_latency_ms > 0 )
+ {
+ vlc_tick_t i_latency_us = VLC_TICK_FROM_MS( i_latency_ms )
+ - FRAMES_TO_US( p_sys->i_max_audiotrack_samples );
+ return i_latency_us >= 0 ? i_latency_us : 0;
+ }
+ }
+
+ return 0;
+}
+
/**
* Get a smooth AudioTrack position
*
@@ -688,19 +699,9 @@ AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
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 - p_sys->smoothpos.i_latency_us;
+ return p_sys->smoothpos.i_us + i_now - AudioTrack_GetLatencyUs( env, p_aout );
else
return 0;
}
@@ -789,9 +790,10 @@ TimeGet( audio_output_t *p_aout, vlc_tick_t *restrict p_delay )
{
vlc_tick_t i_ts_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
vlc_tick_t i_smooth_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
+ vlc_tick_t i_latency_us = AudioTrack_GetLatencyUs( env, p_aout );
msg_Err( p_aout, "TimeGet: TimeStamp: %"PRId64", Smooth: %"PRId64" (latency: %"PRId64")",
- i_ts_us, i_smooth_us, p_sys->smoothpos.i_latency_us );
+ i_ts_us, i_smooth_us, i_latency_us );
}
#endif
More information about the vlc-commits
mailing list