From 58101e218cb014322798fe18e4ef5f08395f9a30 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Wed, 26 Jun 2013 12:43:36 +0100 Subject: [PATCH] Expose latency methods through AudioManager and AudioTrack. There's a longer term plan to fix audio/video sync, but this gets the Java level to parity with the native level, and allows applications in Java to achieve sync in the same way as the native media player. APIs are left as hidden for now. Bug: 9587132 Change-Id: Iaf70baac1ffb50ef48e03355163158568fbd0fe9 --- core/jni/android_media_AudioSystem.cpp | 12 ++++++++++++ core/jni/android_media_AudioTrack.cpp | 14 ++++++++++++++ media/java/android/media/AudioManager.java | 11 +++++++++++ media/java/android/media/AudioSystem.java | 1 + media/java/android/media/AudioTrack.java | 14 ++++++++++++++ 5 files changed, 52 insertions(+) diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 0827f7ca40c7a..67c2cfdc9bb3c 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -271,6 +271,17 @@ android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz) return (jint) AudioSystem::getPrimaryOutputFrameCount(); } +static jint +android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream) +{ + uint32_t afLatency; + if (AudioSystem::getOutputLatency(&afLatency, static_cast (stream)) + != NO_ERROR) { + afLatency = -1; + } + return (jint) afLatency; +} + // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { @@ -296,6 +307,7 @@ static JNINativeMethod gMethods[] = { {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate}, {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount}, + {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency}, }; int register_android_media_AudioSystem(JNIEnv *env) diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index e2d34c9054a0d..3ff9dda1de7bb 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -727,6 +727,19 @@ static jint android_media_AudioTrack_get_position(JNIEnv *env, jobject thiz) { } +// ---------------------------------------------------------------------------- +static jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) { + sp lpTrack = getAudioTrack(env, thiz); + + if (lpTrack == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioTrack pointer for latency()"); + return AUDIOTRACK_ERROR; + } + return (jint)lpTrack->latency(); +} + + // ---------------------------------------------------------------------------- static jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz, jint loopStart, jint loopEnd, jint loopCount) { @@ -854,6 +867,7 @@ static JNINativeMethod gMethods[] = { "()I", (void *)android_media_AudioTrack_get_pos_update_period}, {"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position}, {"native_get_position", "()I", (void *)android_media_AudioTrack_get_position}, + {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency}, {"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop}, {"native_reload_static", "()I", (void *)android_media_AudioTrack_reload}, {"native_get_output_sample_rate", diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 8295c5f5cdd14..93ab40138d594 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2553,4 +2553,15 @@ public class AudioManager { } } + /** + * Returns the estimated latency for the given stream type in milliseconds. + * + * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need + * a better solution. + * @hide + */ + public int getOutputLatency(int streamType) { + return AudioSystem.getOutputLatency(streamType); + } + } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 4a33743ae0dda..d42bfd4442eb7 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -401,5 +401,6 @@ public class AudioSystem // helpers for android.media.AudioManager.getProperty(), see description there for meaning public static native int getPrimaryOutputSamplingRate(); public static native int getPrimaryOutputFrameCount(); + public static native int getOutputLatency(int stream); } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 399eb7bdb3a89..9768a78f7c79e 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -627,6 +627,18 @@ public class AudioTrack return native_get_position(); } + /** + * Returns this track's estimated latency in milliseconds. This includes the latency due + * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver. + * + * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need + * a better solution. + * @hide + */ + public int getLatency() { + return native_get_latency(); + } + /** * Returns the hardware output sample rate */ @@ -1256,6 +1268,8 @@ public class AudioTrack private native final int native_set_position(int position); private native final int native_get_position(); + private native final int native_get_latency(); + private native final int native_set_loop(int start, int end, int loopCount); static private native final int native_get_output_sample_rate(int streamType);