AudioTrack: fix getPlaybackHeadPosition and write

this fixes audio sync in exoplayer
This commit is contained in:
Mis012
2024-04-28 23:39:04 +02:00
parent 639a786056
commit a99dfd80cc
3 changed files with 39 additions and 9 deletions

View File

@@ -217,7 +217,7 @@ JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1play(JNIEnv *env, j
/*--↑*/ /*--↑*/
} }
JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write(JNIEnv *env, jobject this, jbyteArray audioData, jint offsetInBytes, jint frames_to_write) JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write(JNIEnv *env, jobject this, jbyteArray audio_data, jint offset_in_bytes, jint frames_to_write)
{ {
int ret; int ret;
@@ -225,9 +225,9 @@ JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write(JNIEnv *env,
snd_pcm_sframes_t frames_written; snd_pcm_sframes_t frames_written;
jbyte *buffer = _GET_BYTE_ARRAY_ELEMENTS(audioData); jbyte *buffer = _GET_BYTE_ARRAY_ELEMENTS(audio_data);
ret = frames_written = snd_pcm_writei(pcm_handle, buffer, frames_to_write); ret = frames_written = snd_pcm_writei(pcm_handle, buffer + offset_in_bytes, frames_to_write);
if (ret < 0) { if (ret < 0) {
if (ret == -EPIPE) { if (ret == -EPIPE) {
printf("XRUN.\n"); printf("XRUN.\n");
@@ -239,7 +239,7 @@ JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write(JNIEnv *env,
// printf("::::> tried to write %d frames, actually wrote %d frames.\n", frames_to_write, frames_written); // printf("::::> tried to write %d frames, actually wrote %d frames.\n", frames_to_write, frames_written);
_RELEASE_BYTE_ARRAY_ELEMENTS(audioData, buffer); _RELEASE_BYTE_ARRAY_ELEMENTS(audio_data, buffer);
return frames_written; return frames_written;
} }
@@ -254,3 +254,12 @@ JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1release(JNIEnv *env
snd_pcm_t *pcm_handle = _PTR(_GET_LONG_FIELD(this, "pcm_handle")); snd_pcm_t *pcm_handle = _PTR(_GET_LONG_FIELD(this, "pcm_handle"));
snd_pcm_close(pcm_handle); snd_pcm_close(pcm_handle);
} }
JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1getPlaybackHeadPosition(JNIEnv *env, jobject this)
{
snd_pcm_t *pcm_handle = _PTR(_GET_LONG_FIELD(this, "pcm_handle"));
snd_pcm_sframes_t delay;
snd_pcm_delay(pcm_handle, &delay);
return delay;
}

View File

@@ -7,6 +7,8 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#undef android_media_AudioTrack_ERROR_BAD_VALUE
#define android_media_AudioTrack_ERROR_BAD_VALUE -2L
#undef android_media_AudioTrack_PLAYSTATE_STOPPED #undef android_media_AudioTrack_PLAYSTATE_STOPPED
#define android_media_AudioTrack_PLAYSTATE_STOPPED 1L #define android_media_AudioTrack_PLAYSTATE_STOPPED 1L
#undef android_media_AudioTrack_PLAYSTATE_PAUSED #undef android_media_AudioTrack_PLAYSTATE_PAUSED
@@ -29,6 +31,14 @@ JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1constructor
JNIEXPORT jint JNICALL Java_android_media_AudioTrack_getMinBufferSize JNIEXPORT jint JNICALL Java_android_media_AudioTrack_getMinBufferSize
(JNIEnv *, jclass, jint, jint, jint); (JNIEnv *, jclass, jint, jint, jint);
/*
* Class: android_media_AudioTrack
* Method: native_getPlaybackHeadPosition
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1getPlaybackHeadPosition
(JNIEnv *, jobject);
/* /*
* Class: android_media_AudioTrack * Class: android_media_AudioTrack
* Method: native_play * Method: native_play

View File

@@ -6,6 +6,8 @@ public class AudioTrack {
void onPeriodicNotification(AudioTrack track); void onPeriodicNotification(AudioTrack track);
} }
public static final int ERROR_BAD_VALUE = -2; // basically EINVAL
public static final int PLAYSTATE_STOPPED = 1; public static final int PLAYSTATE_STOPPED = 1;
public static final int PLAYSTATE_PAUSED = 2; public static final int PLAYSTATE_PAUSED = 2;
public static final int PLAYSTATE_PLAYING = 3; public static final int PLAYSTATE_PLAYING = 3;
@@ -67,7 +69,7 @@ public class AudioTrack {
} }
public int setPositionNotificationPeriod(int periodInFrames) { public int setPositionNotificationPeriod(int periodInFrames) {
System.out.println("\n\n\nsetPositionNotificationPeriod(" + periodInFrames + "); called\n\n\n\n"); System.out.println("\n\nAudioTrack.nsetPositionNotificationPeriod(" + periodInFrames + "); called\n\n\n\n");
return 0; // SUCCESS return 0; // SUCCESS
} }
@@ -82,16 +84,16 @@ public class AudioTrack {
} }
public void stop() { public void stop() {
System.out.println("calling stop(), how did this not get reported before DIDREEEEEEEEEEEEEEEEEEEEEEEEE\n"); System.out.println("STUB: AudioTrack.stop()\n");
playbackState = PLAYSTATE_STOPPED; playbackState = PLAYSTATE_STOPPED;
} }
public void flush() { public void flush() {
System.out.println("calling flush(), how did this not get reported before DIDREEEEEEEEEEEEEEEEEEEEEEEEE\n"); System.out.println("STUB: AudioTrack.flush()\n");
} }
public void release() { public void release() {
System.out.println("calling release(), how did this not get reported before DIDREEEEEEEEEEEEEEEEEEEEEEEEE\n"); System.out.println("calling AudioTrack.release()\n");
native_release(); native_release();
} }
@@ -100,6 +102,14 @@ public class AudioTrack {
} }
public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) { public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) {
/* sanity check the parameters before calling native_write */
if ((audioData == null)
|| (offsetInBytes < 0) || (sizeInBytes < 0)
|| (offsetInBytes + sizeInBytes < 0)
|| (offsetInBytes + sizeInBytes > audioData.length)) {
return ERROR_BAD_VALUE;
}
int framesToWrite = sizeInBytes / channels / 2; // 2 means PCM16 int framesToWrite = sizeInBytes / channels / 2; // 2 means PCM16
int ret = native_write(audioData, offsetInBytes, framesToWrite); int ret = native_write(audioData, offsetInBytes, framesToWrite);
if (ret > 0) { if (ret > 0) {
@@ -131,9 +141,10 @@ public class AudioTrack {
} }
public int getPlaybackHeadPosition() { public int getPlaybackHeadPosition() {
return playbackHeadPosition; return playbackHeadPosition - native_getPlaybackHeadPosition();
} }
private native int native_getPlaybackHeadPosition();
public native void native_play(); public native void native_play();
public native void native_pause(); public native void native_pause();
private native int native_write(byte[] audioData, int offsetInBytes, int sizeInBytes); private native int native_write(byte[] audioData, int offsetInBytes, int sizeInBytes);