diff options
author | Ricardo Garcia <rago@google.com> | 2015-04-02 14:58:29 -0700 |
---|---|---|
committer | Ricardo Garcia <rago@google.com> | 2015-04-02 15:04:24 -0700 |
commit | e1b0d76f5597f735509e48e732e3efa26ea9fe0b (patch) | |
tree | 7108e4c96aa47b7cb72466cd8097bf234bf28e49 /LoopbackApp/app/src/main/jni | |
parent | 6c27b1100b1db706d824c78f8ad1311f08ef23f2 (diff) | |
download | drrickorang-e1b0d76f5597f735509e48e732e3efa26ea9fe0b.tar.gz |
Bugfixing for older Android versions
Fixing some race conditions that became problematic on older android versions.
Instrumented JNI code with debug/log messages.
Reduced memory footprint of JNI test by directly using the actual buffer of interest.
Diffstat (limited to 'LoopbackApp/app/src/main/jni')
-rw-r--r-- | LoopbackApp/app/src/main/jni/jni_sles.c | 24 | ||||
-rw-r--r-- | LoopbackApp/app/src/main/jni/jni_sles.h | 2 | ||||
-rw-r--r-- | LoopbackApp/app/src/main/jni/sles.cpp | 72 | ||||
-rw-r--r-- | LoopbackApp/app/src/main/jni/sles.h | 3 |
4 files changed, 94 insertions, 7 deletions
diff --git a/LoopbackApp/app/src/main/jni/jni_sles.c b/LoopbackApp/app/src/main/jni/jni_sles.c index 02e69dc..9d12a1c 100644 --- a/LoopbackApp/app/src/main/jni/jni_sles.c +++ b/LoopbackApp/app/src/main/jni/jni_sles.c @@ -24,21 +24,35 @@ JNIEXPORT jlong JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesInit (JNIEnv *env __unused, jobject obj __unused, jint samplingRate, jint frameCount) { - sles_data * pSles; - slesInit(&pSles, samplingRate, frameCount); + sles_data * pSles = NULL; + + if( slesInit(&pSles, samplingRate, frameCount) != SLES_FAIL ) { + + return (long)pSles; + } // FIXME This should be stored as a (long) field in the object, // so that incorrect Java code could not synthesize a bad sles pointer. - return (long)pSles; + return 0; } JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesProcessNext -(JNIEnv *env __unused, jobject obj __unused, jlong sles, jdoubleArray samplesArray) { +(JNIEnv *env __unused, jobject obj __unused, jlong sles, jdoubleArray samplesArray, jlong offset) { sles_data * pSles= (sles_data*) sles; long maxSamples = (*env)->GetArrayLength(env, samplesArray); double *pSamples = (*env)->GetDoubleArrayElements(env, samplesArray,0); - int samplesRead = slesProcessNext(pSles, pSamples, maxSamples); + long availableSamples = maxSamples-offset; + double *pCurrentSample = pSamples+offset; + + + + //int samplesRead = slesProcessNext(pSles, pSamples, maxSamples); + + SLES_PRINTF("jni slesProcessNext pSles:%p, currentSample %p, availableSamples %d ", pSles, pCurrentSample, availableSamples); + + + int samplesRead = slesProcessNext(pSles, pCurrentSample, availableSamples); return samplesRead; } diff --git a/LoopbackApp/app/src/main/jni/jni_sles.h b/LoopbackApp/app/src/main/jni/jni_sles.h index 56e7bb6..8be992a 100644 --- a/LoopbackApp/app/src/main/jni/jni_sles.h +++ b/LoopbackApp/app/src/main/jni/jni_sles.h @@ -29,7 +29,7 @@ JNIEXPORT jlong JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesInit (JNIEnv *, jobject, jint, jint ); JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesProcessNext - (JNIEnv *, jobject , jlong, jdoubleArray ); + (JNIEnv *, jobject , jlong, jdoubleArray, jlong ); JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesDestroy (JNIEnv *, jobject , jlong ); diff --git a/LoopbackApp/app/src/main/jni/sles.cpp b/LoopbackApp/app/src/main/jni/sles.cpp index 0290099..06efe44 100644 --- a/LoopbackApp/app/src/main/jni/sles.cpp +++ b/LoopbackApp/app/src/main/jni/sles.cpp @@ -40,10 +40,15 @@ int slesInit(sles_data ** ppSles, int samplingRate, int frameCount) { int status = SLES_FAIL; if (ppSles != NULL) { sles_data * pSles = (sles_data*)malloc( sizeof (sles_data)); + + SLES_PRINTF("malloc %d bytes at %p",sizeof(sles_data), pSles); + //__android_log_print(ANDROID_LOG_INFO, "sles_jni", "malloc %d bytes at %p",sizeof(sles_data), pSles);//Or ANDROID_LOG_INFO, ... *ppSles = pSles; if (pSles != NULL) { + SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",samplingRate, frameCount); status = slesCreateServer(pSles, samplingRate, frameCount); + SLES_PRINTF("slesCreateServer =%d",status); } } return status; @@ -70,9 +75,11 @@ static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void if (pSles != NULL) { + SLresult result; pthread_mutex_lock(&(pSles->mutex)); + //ee SLES_PRINTF("<R"); // We should only be called when a recording buffer is done assert(pSles->rxFront <= pSles->rxBufCount); @@ -118,6 +125,7 @@ static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void + //ee SLES_PRINTF("r>"); pthread_mutex_unlock(&(pSles->mutex)); } //pSles not null @@ -132,6 +140,7 @@ static void playerCallback(SLBufferQueueItf caller __unused, void *context) { SLresult result; pthread_mutex_lock(&(pSles->mutex)); + //ee SLES_PRINTF("<P"); // Get the buffer that just finished playing assert(pSles->txFront <= pSles->txBufCount); @@ -182,7 +191,7 @@ static void playerCallback(SLBufferQueueItf caller __unused, void *context) { pSles->txRear = txRearNext; - + //ee SLES_PRINTF("p>"); pthread_mutex_unlock(&(pSles->mutex)); } //pSles not null @@ -363,6 +372,8 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount) { if (SL_RESULT_CONTENT_UNSUPPORTED == result) { fprintf(stderr, "Could not create audio player (result %x), check sample rate\n", result); + SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n", + result); goto cleanup; } ASSERT_EQ(SL_RESULT_SUCCESS, result); @@ -429,6 +440,9 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount) { fprintf(stderr, "Could not create audio recorder (result %x), " "check sample rate and channel count\n", result); status = SLES_FAIL; + + SLES_PRINTF("ERROR: Could not create audio recorder (result %x), " + "check sample rate and channel count\n", result); goto cleanup; } } @@ -479,6 +493,8 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount) { status = SLES_SUCCESS; cleanup: + SLES_PRINTF("Finished initialization with status: %d", status); + int xx =1; } @@ -488,6 +504,8 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount) { int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples) { //int status = SLES_FAIL; + SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p, maxSamples = %d", pSles, pSamples, maxSamples); + int samplesRead = 0; int currentSample = 0; @@ -537,32 +555,84 @@ int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples) { result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue, &recorderBQState); ASSERT_EQ(SL_RESULT_SUCCESS, result); + + SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples= %d", pSles, samplesRead, maxSamples); } return samplesRead; } int slesDestroyServer(sles_data *pSles) { int status = SLES_FAIL; + SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles); + if (pSles != NULL) { + + + + if (NULL != pSles->playerObject) { + + SLES_PRINTF("stopping player..."); + SLPlayItf playerPlay; + SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY, + &playerPlay); + + ASSERT_EQ(SL_RESULT_SUCCESS, result); + + //stop player and recorder if they exist + result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED); + ASSERT_EQ(SL_RESULT_SUCCESS, result); + } + + if (NULL != pSles->recorderObject) { + + + SLES_PRINTF("stopping recorder..."); + SLRecordItf recorderRecord; + SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD, + &recorderRecord); + ASSERT_EQ(SL_RESULT_SUCCESS, result); + + + result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); + ASSERT_EQ(SL_RESULT_SUCCESS, result); + } + + usleep(1000); + + audio_utils_fifo_deinit(&(pSles->fifo)); delete[] pSles->fifoBuffer; + SLES_PRINTF("slesDestroyServer 2"); + // if (sndfile != NULL) { audio_utils_fifo_deinit(&(pSles->fifo2)); delete[] pSles->fifo2Buffer; + + SLES_PRINTF("slesDestroyServer 3"); + // sf_close(sndfile); // } if (NULL != pSles->playerObject) { (*(pSles->playerObject))->Destroy(pSles->playerObject); } + + SLES_PRINTF("slesDestroyServer 4"); + if (NULL != pSles->recorderObject) { (*(pSles->recorderObject))->Destroy(pSles->recorderObject); } + + SLES_PRINTF("slesDestroyServer 5"); + (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject); + SLES_PRINTF("slesDestroyServer 6"); (*(pSles->engineObject))->Destroy(pSles->engineObject); + SLES_PRINTF("slesDestroyServer 7"); } + SLES_PRINTF("End slesDestroyServer: status = %d", status); return status; } diff --git a/LoopbackApp/app/src/main/jni/sles.h b/LoopbackApp/app/src/main/jni/sles.h index 5e41b15..15f6f2e 100644 --- a/LoopbackApp/app/src/main/jni/sles.h +++ b/LoopbackApp/app/src/main/jni/sles.h @@ -17,11 +17,14 @@ #include <SLES/OpenSLES.h> #include <SLES/OpenSLES_Android.h> #include <pthread.h> +#include <android/log.h> #ifndef _Included_org_drrickorang_loopback_sles #define _Included_org_drrickorang_loopback_sles //struct audio_utils_fifo; +#define SLES_PRINTF(...) __android_log_print(ANDROID_LOG_INFO, "sles_jni", __VA_ARGS__); + #ifdef __cplusplus extern "C" { |