// ---------------------------------------------------------------------------- static jint android_media_AudioRecord_readInDirectBuffer(JNIEnv *env, jobject thiz, jobject jBuffer, jint sizeInBytes) { AudioRecord *lpRecorder = NULL; //LOGV("Entering android_media_AudioRecord_readInBuffer"); // get the audio recorder from which we'll read new audio samples lpRecorder = (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj); if(lpRecorder==NULL) return 0; // direct buffer and direct access supported? long capacity = env->GetDirectBufferCapacity(jBuffer); if(capacity == -1) { // buffer direct access is not supported LOGE("Buffer direct access is not supported, can't record"); return 0; } //LOGV("capacity = %ld", capacity); jbyte* nativeFromJavaBuf = (jbyte*) env->GetDirectBufferAddress(jBuffer); if(nativeFromJavaBuf==NULL) { LOGE("Buffer direct access is not supported, can't record"); return 0; } // read new data from the recorder return (jint) lpRecorder->read(nativeFromJavaBuf, capacity < sizeInBytes ? capacity : sizeInBytes); }
// ---------------------------------------------------------------------------- static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz, jbyteArray javaAudioData, jint offsetInBytes, jint sizeInBytes) { jbyte* recordBuff = NULL; AudioRecord *lpRecorder = NULL; // get the audio recorder from which we'll read new audio samples lpRecorder = (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj); if (lpRecorder == NULL) { LOGE("Unable to retrieve AudioRecord object, can't record"); return 0; } if (!javaAudioData) { LOGE("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 = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); if (recordBuff == NULL) { LOGE("Error retrieving destination for recorded audio data, can't record"); return 0; } // read the new audio data from the native AudioRecord object ssize_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize(); ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes, sizeInBytes > (jint)recorderBuffSize ? (jint)recorderBuffSize : sizeInBytes ); env->ReleaseByteArrayElements(javaAudioData, recordBuff, 0); return (jint) readSize; }
// ---------------------------------------------------------------------------- static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz, jbyteArray javaAudioData, jint offsetInBytes, jint sizeInBytes) { jbyte* recordBuff = NULL; AudioRecord *lpRecorder = NULL; // get the audio recorder from which we'll read new audio samples lpRecorder = (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj); if (lpRecorder == NULL) { LOGE("Unable to retrieve AudioRecord object, can't record"); return 0; } if (!javaAudioData) { LOGE("Invalid Java array to store recorded audio, can't record"); return 0; } // get the pointer to where we'll record the audio recordBuff = (jbyte *)env->GetPrimitiveArrayCritical(javaAudioData, NULL); if (recordBuff == NULL) { LOGE("Error retrieving destination for recorded audio data, can't record"); return 0; } // read the new audio data from the native AudioRecord object ssize_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize(); ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes, sizeInBytes > (jint)recorderBuffSize ? (jint)recorderBuffSize : sizeInBytes ); env->ReleasePrimitiveArrayCritical(javaAudioData, recordBuff, 0); return (jint) readSize; }
status_t FMA2DPWriter::readerthread() { status_t err = OK; int framecount =((4*mBufferSize)/mAudioChannels)/sizeof(int16_t); //sizeof(int16_t) is frame size for PCM stream int inChannel = (mAudioChannels == 2) ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_IN_MONO; prctl(PR_SET_NAME, (unsigned long)"FMA2DPReaderThread", 0, 0, 0); AudioRecord* record = new AudioRecord( mAudioSource, mSampleRate, mAudioFormat, inChannel, framecount); if(!record){ ALOGE("fatal:Not able to open audiorecord"); return UNKNOWN_ERROR; } status_t res = record->initCheck(); if (res == NO_ERROR) res = record->start(); else{ ALOGE("fatal:record init check failure"); return UNKNOWN_ERROR; } while (!mDone) { mFreeQLock.lock(); if(mFreeQ.empty()){ mFreeQLock.unlock(); ALOGV("FreeQ empty"); sem_wait(&mReaderThreadWakeupsem); ALOGV("FreeQ filled up"); continue; } List<audioBufferstruct>::iterator it = mFreeQ.begin(); audioBufferstruct buff ( it->audioBuffer,it->bufferlen); mFreeQ.erase(it); mFreeQLock.unlock(); buff.bufferlen = record->read(buff.audioBuffer, mBufferSize); ALOGV("read %d bytes", buff.bufferlen); if (buff.bufferlen <= 0){ ALOGE("error in reading from audiorecord..bailing out."); this ->notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, ERROR_MALFORMED); err = INVALID_OPERATION ; break; } mDataQLock.lock(); if(mDataQ.empty()){ ALOGV("waking up reader"); sem_post(&mWriterThreadWakeupsem); } mDataQ.push_back(buff); mDataQLock.unlock(); } record->stop(); delete record; return err; }