diff options
author | Glenn Kasten <gkasten@google.com> | 2013-09-17 22:03:00 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-09-17 22:03:01 +0000 |
commit | 18f861404efc054da0a2ea6c582e293940f63bc8 (patch) | |
tree | e1c4cc80e19505e28e7922dd10f7be0aa2ad4e63 | |
parent | bc910e5c8d05f24531bd6b11379cf41cc73415ed (diff) | |
parent | ce8828a016b082f730152af2204b8ea3610dc1ec (diff) | |
download | frameworks_av-18f861404efc054da0a2ea6c582e293940f63bc8.zip frameworks_av-18f861404efc054da0a2ea6c582e293940f63bc8.tar.gz frameworks_av-18f861404efc054da0a2ea6c582e293940f63bc8.tar.bz2 |
Merge "Fix underruns when fast track denied due to SRC" into klp-dev
-rw-r--r-- | include/private/media/AudioTrackShared.h | 2 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 67 | ||||
-rw-r--r-- | media/libmedia/AudioTrackShared.cpp | 7 |
3 files changed, 37 insertions, 39 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index ad7409d..fe258ad 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -383,8 +383,6 @@ public: protected: size_t mAvailToClient; // estimated frames available to client prior to releaseBuffer() int32_t mFlush; // our copy of cblk->u.mStreaming.mFlush, for streaming output only -private: - bool mDeferWake; // whether another releaseBuffer() is expected soon }; // Proxy used by AudioFlinger for servicing AudioTrack diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 744faee..15249a4 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -815,12 +815,29 @@ status_t AudioTrack::createTrack_l( return NO_INIT; } + // Not all of these values are needed under all conditions, but it is easier to get them all + uint32_t afLatency; - if ((status = AudioSystem::getLatency(output, streamType, &afLatency)) != NO_ERROR) { + status = AudioSystem::getLatency(output, streamType, &afLatency); + if (status != NO_ERROR) { ALOGE("getLatency(%d) failed status %d", output, status); return NO_INIT; } + size_t afFrameCount; + status = AudioSystem::getFrameCount(output, streamType, &afFrameCount); + if (status != NO_ERROR) { + ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status); + return NO_INIT; + } + + uint32_t afSampleRate; + status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate); + if (status != NO_ERROR) { + ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status); + return NO_INIT; + } + // Client decides whether the track is TIMED (see below), but can only express a preference // for FAST. Server will perform additional tests. if ((flags & AUDIO_OUTPUT_FLAG_FAST) && !( @@ -836,6 +853,14 @@ status_t AudioTrack::createTrack_l( } ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); + // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where + // n = 1 fast track; nBuffering is ignored + // n = 2 normal track, no sample rate conversion + // n = 3 normal track, with sample rate conversion + // (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering) + // n > 3 very high latency or very small notification interval; nBuffering is ignored + const uint32_t nBuffering = (sampleRate == afSampleRate) ? 2 : 3; + mNotificationFramesAct = mNotificationFramesReq; if (!audio_is_linear_pcm(format)) { @@ -844,13 +869,6 @@ status_t AudioTrack::createTrack_l( // Same comment as below about ignoring frameCount parameter for set() frameCount = sharedBuffer->size(); } else if (frameCount == 0) { - size_t afFrameCount; - status = AudioSystem::getFrameCount(output, streamType, &afFrameCount); - if (status != NO_ERROR) { - ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, - status); - return NO_INIT; - } frameCount = afFrameCount; } if (mNotificationFramesAct != frameCount) { @@ -880,26 +898,13 @@ status_t AudioTrack::createTrack_l( } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { // FIXME move these calculations and associated checks to server - uint32_t afSampleRate; - status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate); - if (status != NO_ERROR) { - ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, - status); - return NO_INIT; - } - size_t afFrameCount; - status = AudioSystem::getFrameCount(output, streamType, &afFrameCount); - if (status != NO_ERROR) { - ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status); - return NO_INIT; - } // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d", afFrameCount, minBufCount, afSampleRate, afLatency); - if (minBufCount <= 2) { - minBufCount = sampleRate == afSampleRate ? 2 : 3; + if (minBufCount <= nBuffering) { + minBufCount = nBuffering; } size_t minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; @@ -909,18 +914,16 @@ status_t AudioTrack::createTrack_l( if (frameCount == 0) { frameCount = minFrameCount; - } - // Make sure that application is notified with sufficient margin - // before underrun - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { - mNotificationFramesAct = frameCount/2; - } - if (frameCount < minFrameCount) { + } else if (frameCount < minFrameCount) { // not ALOGW because it happens all the time when playing key clicks over A2DP ALOGV("Minimum buffer size corrected from %d to %d", frameCount, minFrameCount); frameCount = minFrameCount; } + // Make sure that application is notified with sufficient margin before underrun + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { + mNotificationFramesAct = frameCount/nBuffering; + } } else { // For fast tracks, the frame count calculations and checks are done by server @@ -1001,8 +1004,8 @@ status_t AudioTrack::createTrack_l( flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); mFlags = flags; if (sharedBuffer == 0) { - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { - mNotificationFramesAct = frameCount/2; + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { + mNotificationFramesAct = frameCount/nBuffering; } } } diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index e7abb40..4fd92b2 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -481,7 +481,7 @@ size_t StaticAudioTrackClientProxy::getBufferPosition() ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), - mAvailToClient(0), mFlush(0), mDeferWake(false) + mAvailToClient(0), mFlush(0) { } @@ -559,9 +559,6 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer) &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL; buffer->mNonContig = availToServer - part1; mUnreleased = part1; - // optimization to avoid waking up the client too early - // FIXME need to test for recording - mDeferWake = part1 < ask && availToServer >= ask; return part1 > 0 ? NO_ERROR : WOULD_BLOCK; } no_init: @@ -607,7 +604,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) minimum = half; } // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time - if (!mIsOut || (!mDeferWake && mAvailToClient + stepCount >= minimum)) { + if (!mIsOut || (mAvailToClient + stepCount >= minimum)) { ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum); int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { |