summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-05-01 23:49:51 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-05-01 23:49:51 +0000
commit27e12e72926a552bb5f7d9dc57e9ad562fe4f3b0 (patch)
tree1a9b62d80e7c9bd68d05074c97403668e22cfddc
parentb94d412848653ae532e589c2a7479b0d0149d341 (diff)
parent3d4c64191a181aac0922abbd56f4046d6b7ec31c (diff)
downloadframeworks_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.cpp45
-rw-r--r--core/jni/android_media_AudioTrack.cpp41
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;
}