diff options
author | Eric Laurent <elaurent@google.com> | 2014-05-01 23:49:51 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-01 23:49:51 +0000 |
commit | 27e12e72926a552bb5f7d9dc57e9ad562fe4f3b0 (patch) | |
tree | 1a9b62d80e7c9bd68d05074c97403668e22cfddc | |
parent | b94d412848653ae532e589c2a7479b0d0149d341 (diff) | |
parent | 3d4c64191a181aac0922abbd56f4046d6b7ec31c (diff) | |
download | frameworks_base-27e12e72926a552bb5f7d9dc57e9ad562fe4f3b0.zip frameworks_base-27e12e72926a552bb5f7d9dc57e9ad562fe4f3b0.tar.gz frameworks_base-27e12e72926a552bb5f7d9dc57e9ad562fe4f3b0.tar.bz2 |
Merge "fix AudioTrack and AudioRecord JNI"
-rw-r--r-- | core/jni/android_media_AudioRecord.cpp | 45 | ||||
-rw-r--r-- | core/jni/android_media_AudioTrack.cpp | 41 |
2 files changed, 74 insertions, 12 deletions
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index d8faaf3..09bdc61 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -393,13 +393,46 @@ static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thi jshortArray javaAudioData, jint offsetInShorts, jint sizeInShorts) { - jint read = android_media_AudioRecord_readInByteArray(env, thiz, - (jbyteArray) javaAudioData, - offsetInShorts*2, sizeInShorts*2); - if (read > 0) { - read /= 2; + jshort* recordBuff = NULL; + // get the audio recorder from which we'll read new audio samples + sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); + if (lpRecorder == NULL) { + ALOGE("Unable to retrieve AudioRecord object, can't record"); + return 0; } - return read; + + if (!javaAudioData) { + ALOGE("Invalid Java array to store recorded audio, can't record"); + return 0; + } + + // get the pointer to where we'll record the audio + // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such + // a way that it becomes much more efficient. When doing so, we will have to prevent the + // AudioSystem callback to be called while in critical section (in case of media server + // process crash for instance) + recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); + + if (recordBuff == NULL) { + ALOGE("Error retrieving destination for recorded audio data, can't record"); + return 0; + } + + // read the new audio data from the native AudioRecord object + const size_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize(); + const size_t sizeInBytes = sizeInShorts * sizeof(short); + ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts * sizeof(short), + sizeInBytes > recorderBuffSize ? + recorderBuffSize : sizeInBytes); + + env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0); + + if (readSize < 0) { + readSize = AUDIORECORD_ERROR_INVALID_OPERATION; + } else { + readSize /= sizeof(short); + } + return (jint) readSize; } // ---------------------------------------------------------------------------- diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 162d0c4..da752752 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -637,14 +637,43 @@ static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz, jshortArray javaAudioData, jint offsetInShorts, jint sizeInShorts, jint javaAudioFormat) { - jint written = android_media_AudioTrack_write_byte(env, thiz, - (jbyteArray) javaAudioData, - offsetInShorts*2, sizeInShorts*2, - javaAudioFormat, - JNI_TRUE /*blocking write, legacy behavior*/); + + //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called", + // offsetInShorts, sizeInShorts); + sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); + if (lpTrack == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioTrack pointer for write()"); + return 0; + } + + // get the pointer for the audio data from the java array + // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such + // a way that it becomes much more efficient. When doing so, we will have to prevent the + // AudioSystem callback to be called while in critical section (in case of media server + // process crash for instance) + jshort* cAudioData = NULL; + if (javaAudioData) { + cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); + if (cAudioData == NULL) { + ALOGE("Error retrieving source of audio data to play, can't play"); + return 0; // out of memory or no data to load + } + } else { + ALOGE("NULL java array of audio data to play, can't play"); + return 0; + } + jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, + offsetInShorts * sizeof(short), sizeInShorts * sizeof(short), + true /*blocking write, legacy behavior*/); + env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0); + if (written > 0) { - written /= 2; + written /= sizeof(short); } + //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d", + // (int)written, (int)(sizeInShorts), (int)offsetInShorts); + return written; } |