//----------------------------------------------------------------------------- static void audioRecorder_callback(int event, void* user, void *info) { //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info); CAudioRecorder *ar = (CAudioRecorder *)user; if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) { // it is not safe to enter the callback (the track is about to go away) return; } void * callbackPContext = NULL; switch(event) { case android::AudioRecord::EVENT_MORE_DATA: { slBufferQueueCallback callback = NULL; android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info; // push data to the buffer queue interface_lock_exclusive(&ar->mBufferQueue); if (ar->mBufferQueue.mState.count != 0) { assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear); BufferHeader *oldFront = ar->mBufferQueue.mFront; BufferHeader *newFront = &oldFront[1]; // FIXME handle 8bit based on buffer format short *pDest = (short*)((char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed); if (ar->mBufferQueue.mSizeConsumed + pBuff->size < oldFront->mSize) { // can't consume the whole or rest of the buffer in one shot ar->mBufferQueue.mSizeConsumed += pBuff->size; // leave pBuff->size untouched // consume data // FIXME can we avoid holding the lock during the copy? memcpy (pDest, pBuff->i16, pBuff->size); #ifdef MONITOR_RECORDING if (NULL != gMonitorFp) { fwrite(pBuff->i16, pBuff->size, 1, gMonitorFp); } #endif } else { // finish pushing the buffer or push the buffer in one shot pBuff->size = oldFront->mSize - ar->mBufferQueue.mSizeConsumed; ar->mBufferQueue.mSizeConsumed = 0; if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) { newFront = ar->mBufferQueue.mArray; } ar->mBufferQueue.mFront = newFront; ar->mBufferQueue.mState.count--; ar->mBufferQueue.mState.playIndex++; // consume data // FIXME can we avoid holding the lock during the copy? memcpy (pDest, pBuff->i16, pBuff->size); #ifdef MONITOR_RECORDING if (NULL != gMonitorFp) { fwrite(pBuff->i16, pBuff->size, 1, gMonitorFp); } #endif // data has been copied to the buffer, and the buffer queue state has been updated // we will notify the client if applicable callback = ar->mBufferQueue.mCallback; // save callback data callbackPContext = ar->mBufferQueue.mContext; } } else { // no destination to push the data pBuff->size = 0; } interface_unlock_exclusive(&ar->mBufferQueue); // notify client if (NULL != callback) { (*callback)(&ar->mBufferQueue.mItf, callbackPContext); } } break; case android::AudioRecord::EVENT_OVERRUN: audioRecorder_handleOverrun_lockRecord(ar); break; case android::AudioRecord::EVENT_MARKER: audioRecorder_handleMarker_lockRecord(ar); break; case android::AudioRecord::EVENT_NEW_POS: audioRecorder_handleNewPos_lockRecord(ar); break; } ar->mCallbackProtector->exitCb(); }
//----------------------------------------------------------------------------- static void audioRecorder_callback(int event, void* user, void *info) { //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info); CAudioRecorder *ar = (CAudioRecorder *)user; if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) { // it is not safe to enter the callback (the track is about to go away) return; } void * callbackPContext = NULL; switch (event) { case android::AudioRecord::EVENT_MORE_DATA: { slBufferQueueCallback callback = NULL; android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info; // push data to the buffer queue interface_lock_exclusive(&ar->mBufferQueue); if (ar->mBufferQueue.mState.count != 0) { assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear); BufferHeader *oldFront = ar->mBufferQueue.mFront; BufferHeader *newFront = &oldFront[1]; size_t availSink = oldFront->mSize - ar->mBufferQueue.mSizeConsumed; size_t availSource = pBuff->size; size_t bytesToCopy = availSink < availSource ? availSink : availSource; void *pDest = (char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed; memcpy(pDest, pBuff->raw, bytesToCopy); if (bytesToCopy < availSink) { // can't consume the whole or rest of the buffer in one shot ar->mBufferQueue.mSizeConsumed += availSource; // pBuff->size is already equal to bytesToCopy in this case } else { // finish pushing the buffer or push the buffer in one shot pBuff->size = bytesToCopy; ar->mBufferQueue.mSizeConsumed = 0; if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) { newFront = ar->mBufferQueue.mArray; } ar->mBufferQueue.mFront = newFront; ar->mBufferQueue.mState.count--; ar->mBufferQueue.mState.playIndex++; // data has been copied to the buffer, and the buffer queue state has been updated // we will notify the client if applicable callback = ar->mBufferQueue.mCallback; // save callback data callbackPContext = ar->mBufferQueue.mContext; } } else { // empty queue // no destination to push the data pBuff->size = 0; } interface_unlock_exclusive(&ar->mBufferQueue); // notify client if (NULL != callback) { (*callback)(&ar->mBufferQueue.mItf, callbackPContext); } } break; case android::AudioRecord::EVENT_OVERRUN: audioRecorder_handleOverrun_lockRecord(ar); break; case android::AudioRecord::EVENT_MARKER: audioRecorder_handleMarker_lockRecord(ar); break; case android::AudioRecord::EVENT_NEW_POS: audioRecorder_handleNewPos_lockRecord(ar); break; case android::AudioRecord::EVENT_NEW_IAUDIORECORD: // ignore for now break; default: SL_LOGE("Encountered unknown AudioRecord event %d for CAudioRecord %p", event, ar); break; } ar->mCallbackProtector->exitCb(); }