diff options
-rw-r--r-- | include/media/AudioRecord.h | 1 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 53 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 3 | ||||
-rwxr-xr-x | services/audioflinger/Threads.cpp | 66 |
4 files changed, 43 insertions, 80 deletions
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index f9c7efd..4edc1bf 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -461,6 +461,7 @@ private: // for notification APIs uint32_t mNotificationFramesReq; // requested number of frames between each // notification callback + // as specified in constructor or set() uint32_t mNotificationFramesAct; // actual number of frames between each // notification callback bool mRefreshRemaining; // processAudioBuffer() should refresh diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index c474a25..80c8c5e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -211,7 +211,7 @@ status_t AudioRecord::set( mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; - mNotificationFramesAct = 0; + // mNotificationFramesAct is initialized in openRecord_l if (sessionId == AUDIO_SESSION_ALLOCATE) { mSessionId = AudioSystem::newAudioSessionId(); @@ -444,42 +444,6 @@ status_t AudioRecord::openRecord_l(size_t epoch) } } - // FIXME Assume double buffering, because we don't know the true HAL sample rate - const uint32_t nBuffering = 2; - - mNotificationFramesAct = mNotificationFramesReq; - size_t frameCount = mReqFrameCount; - - if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) { - // validate framecount - // If fast track was not requested, this preserves - // the old behavior of validating on client side. - // FIXME Eventually the validation should be done on server side - // regardless of whether it's a fast or normal track. It's debatable - // whether to account for the input latency to provision buffers appropriately. - size_t minFrameCount; - status = AudioRecord::getMinFrameCount(&minFrameCount, - mSampleRate, mFormat, mChannelMask); - if (status != NO_ERROR) { - ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; " - "status %d", - mSampleRate, mFormat, mChannelMask, status); - return status; - } - - if (frameCount == 0) { - frameCount = minFrameCount; - } else if (frameCount < minFrameCount) { - ALOGE("frameCount %zu < minFrameCount %zu", frameCount, minFrameCount); - return BAD_VALUE; - } - - // Make sure that application is notified with sufficient margin before overrun - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { - mNotificationFramesAct = frameCount/2; - } - } - audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags); if (input == AUDIO_IO_HANDLE_NONE) { @@ -492,12 +456,13 @@ status_t AudioRecord::openRecord_l(size_t epoch) // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, // we must release it ourselves if anything goes wrong. + size_t frameCount = mReqFrameCount; size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also int originalSessionId = mSessionId; // The notification frame count is the period between callbacks, as suggested by the server. - size_t notificationFrames; + size_t notificationFrames = mNotificationFramesReq; sp<IMemory> iMem; // for cblk sp<IMemory> bufferMem; @@ -576,14 +541,14 @@ status_t AudioRecord::openRecord_l(size_t epoch) // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); } - // Theoretically double-buffering is not required for fast tracks, - // due to tighter scheduling. But in practice, to accomodate kernels with - // scheduling jitter, and apps with computation jitter, we use double-buffering. - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { - mNotificationFramesAct = frameCount/nBuffering; - } } + // Make sure that application is notified with sufficient margin before overrun + if (notificationFrames == 0 || notificationFrames > frameCount) { + ALOGW("Received notificationFrames %zu for frameCount %zu", notificationFrames, frameCount); + } + mNotificationFramesAct = notificationFrames; + // We retain a copy of the I/O handle, but don't own the reference mInput = input; mRefreshRemaining = true; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 7795fdb..bd7ea46 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -197,6 +197,7 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + data.writeInt64(notificationFrames != NULL ? *notificationFrames : 0); cblk.clear(); buffers.clear(); status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply); @@ -966,7 +967,7 @@ status_t BnAudioFlinger::onTransact( track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); - size_t notificationFrames = 0; + size_t notificationFrames = data.readInt64(); sp<IMemory> cblk; sp<IMemory> buffers; status_t status; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index e17aa98..0f555c0 100755 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -5458,21 +5458,14 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe // client expresses a preference for FAST, but we get the final say if (*flags & IAudioFlinger::TRACK_FAST) { if ( - // use case: callback handler and frame count is default or at least as large as HAL - ( - (tid != -1) && - ((frameCount == 0) /*|| - // FIXME must be equal to pipe depth, so don't allow it to be specified by client - // FIXME not necessarily true, should be native frame count for native SR! - (frameCount >= mFrameCount)*/) - ) && + // use case: callback handler + (tid != -1) && + // frame count is not specified, or is exactly the pipe depth + ((frameCount == 0) || (frameCount == mPipeFramesP2)) && // PCM data audio_is_linear_pcm(format) && // native format (format == mFormat) && - // mono or stereo - ( (channelMask == AUDIO_CHANNEL_IN_MONO) || - (channelMask == AUDIO_CHANNEL_IN_STEREO) ) && // native channel mask (channelMask == mChannelMask) && // native hardware sample rate @@ -5482,40 +5475,43 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe // there are sufficient fast track slots available mFastTrackAvail ) { - // if frameCount not specified, then it defaults to pipe frame count - if (frameCount == 0) { - frameCount = mPipeFramesP2; - } - ALOGV("AUDIO_INPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d", + ALOGV("AUDIO_INPUT_FLAG_FAST accepted: frameCount=%u mFrameCount=%u", frameCount, mFrameCount); } else { - ALOGV("AUDIO_INPUT_FLAG_FAST denied: frameCount=%d " - "mFrameCount=%d format=%d isLinear=%d channelMask=%#x sampleRate=%u mSampleRate=%u " + ALOGV("AUDIO_INPUT_FLAG_FAST denied: frameCount=%u mFrameCount=%u mPipeFramesP2=%u " + "format=%#x isLinear=%d channelMask=%#x sampleRate=%u mSampleRate=%u " "hasFastCapture=%d tid=%d mFastTrackAvail=%d", - frameCount, mFrameCount, format, - audio_is_linear_pcm(format), - channelMask, sampleRate, mSampleRate, hasFastCapture(), tid, mFastTrackAvail); + frameCount, mFrameCount, mPipeFramesP2, + format, audio_is_linear_pcm(format), channelMask, sampleRate, mSampleRate, + hasFastCapture(), tid, mFastTrackAvail); *flags &= ~IAudioFlinger::TRACK_FAST; - // FIXME It's not clear that we need to enforce this any more, since we have a pipe. - // For compatibility with AudioRecord calculation, buffer depth is forced - // to be at least 2 x the record thread frame count and cover audio hardware latency. - // This is probably too conservative, but legacy application code may depend on it. - // If you change this calculation, also review the start threshold which is related. - // FIXME It's not clear how input latency actually matters. Perhaps this should be 0. - uint32_t latencyMs = 50; // FIXME mInput->stream->get_latency(mInput->stream); - size_t mNormalFrameCount = 2048; // FIXME - uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); - if (minBufCount < 2) { - minBufCount = 2; + } + } + + // compute track buffer size in frames, and suggest the notification frame count + if (*flags & IAudioFlinger::TRACK_FAST) { + // fast track: frame count is exactly the pipe depth + frameCount = mPipeFramesP2; + // ignore requested notificationFrames, and always notify exactly once every HAL buffer + *notificationFrames = mFrameCount; + } else { + // not fast track: frame count is at least 2 HAL buffers and at least 20 ms + size_t minFrameCount = ((int64_t) mFrameCount * 2 * sampleRate + mSampleRate - 1) / + mSampleRate; + if (frameCount < minFrameCount) { + frameCount = minFrameCount; } - size_t minFrameCount = mNormalFrameCount * minBufCount; + minFrameCount = (sampleRate * 20 / 1000 + 1) & ~1; if (frameCount < minFrameCount) { frameCount = minFrameCount; } - } + // notification is forced to be at least double-buffering + size_t maxNotification = frameCount / 2; + if (*notificationFrames == 0 || *notificationFrames > maxNotification) { + *notificationFrames = maxNotification; + } } *pFrameCount = frameCount; - *notificationFrames = 0; // FIXME implement lStatus = initCheck(); if (lStatus != NO_ERROR) { |