// ----------------------------------------------------------------------------
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 void android_media_AudioRecord_release(JNIEnv *env,  jobject thiz) {

    // serialize access. Ugly, but functional.
    Mutex::Autolock lock(&sLock);
    AudioRecord *lpRecorder = 
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetIntField(
        thiz, javaAudioRecordFields.nativeCallbackCookie);

    // reset the native resources in the Java object so any attempt to access
    // them after a call to release fails.
    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);

    // delete the AudioRecord object
    if (lpRecorder) {
        LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
        lpRecorder->stop();
        delete lpRecorder;
    }
    
    // delete the callback information
    if (lpCookie) {
        LOGV("deleting lpCookie: %x\n", (int)lpCookie);
        env->DeleteGlobalRef(lpCookie->audioRecord_class);
        env->DeleteGlobalRef(lpCookie->audioRecord_ref);
        delete lpCookie;
    }
}
Esempio n. 3
0
// ----------------------------------------------------------------------------
static void
android_media_AudioRecord_start(JNIEnv *env, jobject thiz)
{
    AudioRecord *lpRecorder = 
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    if (lpRecorder == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }
    
    lpRecorder->start();
}
// ----------------------------------------------------------------------------
static int
android_media_AudioRecord_start(JNIEnv *env, jobject thiz)
{
    AudioRecord *lpRecorder = 
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    if (lpRecorder == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return AUDIORECORD_ERROR;
    }
    
    return android_media_translateRecorderErrorCode(lpRecorder->start());
}
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_get_pos_update_period(JNIEnv *env,  jobject thiz) {
    
    AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
                thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    uint32_t period = 0;
                
    if (lpRecorder) {
        lpRecorder->getPositionUpdatePeriod(&period);
        return (jint)period;
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioRecord pointer for getPositionUpdatePeriod()");
        return AUDIORECORD_ERROR;
    }
}
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_set_pos_update_period(JNIEnv *env,  jobject thiz,
        jint period) {
            
    AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
                thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
                
    if (lpRecorder) {
        return 
            android_media_translateRecorderErrorCode( lpRecorder->setPositionUpdatePeriod(period) );   
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioRecord pointer for setPositionUpdatePeriod()");
        return AUDIORECORD_ERROR;
    }            
}
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_get_marker_pos(JNIEnv *env,  jobject thiz) {
    
    AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
                thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    uint32_t markerPos = 0;
                
    if (lpRecorder) {
        lpRecorder->getMarkerPosition(&markerPos);
        return (jint)markerPos;
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioRecord pointer for getMarkerPosition()");
        return AUDIORECORD_ERROR;
    }
}
Esempio n. 8
0
// ----------------------------------------------------------------------------
static void android_media_AudioRecord_finalize(JNIEnv *env,  jobject thiz) {
    
    // delete the AudioRecord object
    AudioRecord *lpRecorder = 
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);

    if (lpRecorder) {
        //LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
        lpRecorder->stop();
        delete lpRecorder;
    }
    
    // delete the callback information
    audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetIntField(
        thiz, javaAudioRecordFields.nativeCallbackCookie);
    if (lpCookie) {
        LOGV("deleting lpCookie: %x\n", (int)lpCookie);
        delete lpCookie;
    }

}
// ----------------------------------------------------------------------------
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;
}
Esempio n. 10
0
// ----------------------------------------------------------------------------
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;
}
// ----------------------------------------------------------------------------
static int
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jint source, jint sampleRateInHertz, jint channels,
        jint audioFormat, jint buffSizeInBytes, jintArray jSession)
{
    //LOGV(">> Entering android_media_AudioRecord_setup");
    //LOGV("sampleRate=%d, audioFormat=%d, channels=%x, buffSizeInBytes=%d",
    //     sampleRateInHertz, audioFormat, channels,     buffSizeInBytes);

    if (!audio_is_input_channel(channels)) {
        LOGE("Error creating AudioRecord: channel count is not 1 or 2.");
        return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
    }
    uint32_t nbChannels = popcount(channels);

    // compare the format against the Java constants
    if ((audioFormat != javaAudioRecordFields.PCM16) 
        && (audioFormat != javaAudioRecordFields.PCM8)) {
        LOGE("Error creating AudioRecord: unsupported audio format.");
        return AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
    }

    int bytesPerSample = audioFormat==javaAudioRecordFields.PCM16 ? 2 : 1;
    int format = audioFormat==javaAudioRecordFields.PCM16 ? 
            AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT;

    if (buffSizeInBytes == 0) {
         LOGE("Error creating AudioRecord: frameCount is 0.");
        return AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
    }
    int frameSize = nbChannels * bytesPerSample;
    size_t frameCount = buffSizeInBytes / frameSize;
    
    if (source >= AUDIO_SOURCE_CNT) {
        LOGE("Error creating AudioRecord: unknown source.");
        return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE;
    }

    if (jSession == NULL) {
        LOGE("Error creating AudioRecord: invalid session ID pointer");
        return AUDIORECORD_ERROR;
    }

    jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
    if (nSession == NULL) {
        LOGE("Error creating AudioRecord: Error retrieving session id pointer");
        return AUDIORECORD_ERROR;
    }
    int sessionId = nSession[0];
    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    nSession = NULL;

    audiorecord_callback_cookie *lpCallbackData = NULL;
    AudioRecord* lpRecorder = NULL;

    // create an uninitialized AudioRecord object
    lpRecorder = new AudioRecord();
        if(lpRecorder == NULL) {
        LOGE("Error creating AudioRecord instance.");
        return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
    }
    
    // create the callback information:
    // this data will be passed with every AudioRecord callback
    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        LOGE("Can't find %s when setting up callback.", kClassPathName);
        goto native_track_failure;
    }
    lpCallbackData = new audiorecord_callback_cookie;
    lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
    // we use a weak reference so the AudioRecord object can be garbage collected.
    lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
    
    lpRecorder->set(source,
        sampleRateInHertz,
        format,        // word length, PCM
        channels,
        frameCount,
        0,             // flags
        recorderCallback,// callback_t
        lpCallbackData,// void* user
        0,             // notificationFrames,
        true,          // threadCanCallJava)
        sessionId);

    if(lpRecorder->initCheck() != NO_ERROR) {
        LOGE("Error creating AudioRecord instance: initialization check failed.");
        goto native_init_failure;
    }

    nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
    if (nSession == NULL) {
        LOGE("Error creating AudioRecord: Error retrieving session id pointer");
        goto native_init_failure;
    }
    // read the audio session ID back from AudioTrack in case a new session was created during set()
    nSession[0] = lpRecorder->getSessionId();
    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    nSession = NULL;

    // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field 
    // of the Java object
    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (int)lpRecorder);
    
    // save our newly created callback information in the "nativeCallbackCookie" field
    // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize()
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, (int)lpCallbackData);
    
    return AUDIORECORD_SUCCESS;
    
    // failure:
native_init_failure:
    env->DeleteGlobalRef(lpCallbackData->audioRecord_class);
    env->DeleteGlobalRef(lpCallbackData->audioRecord_ref);
    delete lpCallbackData;

native_track_failure:
    delete lpRecorder;

    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);
    
    return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
}
Esempio n. 12
0
// ----------------------------------------------------------------------------
static int
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jint source, jint sampleRateInHertz, jint nbChannels, 
        jint audioFormat, jint buffSizeInBytes)
{
    //LOGV(">> Entering android_media_AudioRecord_setup");
    //LOGV("sampleRate=%d, audioFormat=%d, nbChannels=%d, buffSizeInBytes=%d",
    //     sampleRateInHertz, audioFormat, nbChannels,     buffSizeInBytes);

    if ((nbChannels == 0) || (nbChannels > 2)) {
        LOGE("Error creating AudioRecord: channel count is not 1 or 2.");
        return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT;
    }

    // compare the format against the Java constants
    if ((audioFormat != javaAudioRecordFields.PCM16) 
        && (audioFormat != javaAudioRecordFields.PCM8)) {
        LOGE("Error creating AudioRecord: unsupported audio format.");
        return AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
    }

    int bytesPerSample = audioFormat==javaAudioRecordFields.PCM16 ? 2 : 1;
    int format = audioFormat==javaAudioRecordFields.PCM16 ? 
            AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT;

    if (buffSizeInBytes == 0) {
         LOGE("Error creating AudioRecord: frameCount is 0.");
        return AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
    }
    int frameSize = nbChannels * bytesPerSample;
    size_t frameCount = buffSizeInBytes / frameSize;
    
    // compare the source against the Java constants
    AudioRecord::stream_type arSource;
    if (source == javaAudioRecordFields.SOURCE_DEFAULT) {
        arSource = AudioRecord::DEFAULT_INPUT;
    } else if (source == javaAudioRecordFields.SOURCE_MIC) {
        arSource = AudioRecord::MIC_INPUT;
    } else {
        LOGE("Error creating AudioRecord: unknown source.");
        return AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE;
    }
     
    audiorecord_callback_cookie *lpCallbackData = NULL;
    AudioRecord* lpRecorder = NULL;

    // create an uninitialized AudioRecord object
    lpRecorder = new AudioRecord();
        if(lpRecorder == NULL) {
        LOGE("Error creating AudioRecord instance.");
        return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
    }
    
    // create the callback information:
    // this data will be passed with every AudioRecord callback
    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        LOGE("Can't find %s when setting up callback.", kClassPathName);
        goto native_track_failure;
    }
    lpCallbackData = new audiorecord_callback_cookie;
    lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
    // we use a weak reference so the AudioRecord object can be garbage collected.
    lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
    
    lpRecorder->set(arSource,
        sampleRateInHertz,
        format,        // word length, PCM
        nbChannels,
        frameCount,
        0,             // flags
        recorderCallback,// callback_t
        lpCallbackData,// void* user
        0,             // notificationFrames,
        true);         // threadCanCallJava)

    if(lpRecorder->initCheck() != NO_ERROR) {
        LOGE("Error creating AudioRecord instance: initialization check failed.");
        goto native_init_failure;
    }

    // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field 
    // of the Java object
    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (int)lpRecorder);
    
    // save our newly created callback information in the "nativeCallbackCookie" field
    // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize()
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, (int)lpCallbackData);
    
    return AUDIORECORD_SUCCESS;
    
    // failure:
native_init_failure:
    delete lpCallbackData;
    
native_track_failure:
    delete lpRecorder;

    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);
    
    return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
}
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;
}