Loading services/audioflinger/Threads.cpp +28 −6 Original line number Original line Diff line number Diff line Loading @@ -124,12 +124,26 @@ using media::permission::Identity; // 50 * ~20msecs = 1 second // 50 * ~20msecs = 1 second static const int8_t kMaxTrackRetries = 50; static const int8_t kMaxTrackRetries = 50; static const int8_t kMaxTrackStartupRetries = 50; static const int8_t kMaxTrackStartupRetries = 50; // allow less retry attempts on direct output thread. // allow less retry attempts on direct output thread. // direct outputs can be a scarce resource in audio hardware and should // direct outputs can be a scarce resource in audio hardware and should // be released as quickly as possible. // be released as quickly as possible. static const int8_t kMaxTrackRetriesDirect = 2; // Notes: // 1) The retry duration kMaxTrackRetriesDirectMs may be increased // in case the data write is bursty for the AudioTrack. The application // should endeavor to write at least once every kMaxTrackRetriesDirectMs // to prevent an underrun situation. If the data is bursty, then // the application can also throttle the data sent to be even. // 2) For compressed audio data, any data present in the AudioTrack buffer // will be sent and reset the retry count. This delivers data as // it arrives, with approximately kDirectMinSleepTimeUs = 10ms checking interval. // 3) For linear PCM or proportional PCM, we wait one period for a period's worth // of data to be available, then any remaining data is delivered. // This is required to ensure the last bit of data is delivered before underrun. // // Sleep time per cycle is kDirectMinSleepTimeUs for compressed tracks // or the size of the HAL period for proportional / linear PCM tracks. static const int32_t kMaxTrackRetriesDirectMs = 200; // don't warn about blocked writes or record buffer overflows more often than this // don't warn about blocked writes or record buffer overflows more often than this static const nsecs_t kWarningThrottleNs = seconds(5); static const nsecs_t kWarningThrottleNs = seconds(5); Loading Loading @@ -5931,11 +5945,19 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // Allow draining the buffer in case the client // Allow draining the buffer in case the client // app does not call stop() and relies on underrun to stop: // app does not call stop() and relies on underrun to stop: // hence the test on (track->mRetryCount > 1). // hence the test on (track->mRetryCount > 1). // If retryCount<=1 then track is about to underrun and be removed. // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed, // so we accept any nonzero amount of data delivered by the AudioTrack (which will // reset the retry counter). // Do not use a high threshold for compressed audio. // Do not use a high threshold for compressed audio. // target retry count that we will use is based on the time we wait for retries. const int32_t targetRetryCount = kMaxTrackRetriesDirectMs * 1000 / mActiveSleepTimeUs; // the retry threshold is when we accept any size for PCM data. This is slightly // smaller than the retry count so we can push small bits of data without a glitch. const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1; uint32_t minFrames; uint32_t minFrames; if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing() if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing() && (track->mRetryCount > 1) && audio_has_proportional_frames(mFormat)) { && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) { minFrames = mNormalFrameCount; minFrames = mNormalFrameCount; } else { } else { minFrames = 1; minFrames = 1; Loading Loading @@ -5979,7 +6001,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep mPreviousTrack = track; mPreviousTrack = track; // reset retry count // reset retry count track->mRetryCount = kMaxTrackRetriesDirect; track->mRetryCount = targetRetryCount; mActiveTrack = t; mActiveTrack = t; mixerStatus = MIXER_TRACKS_READY; mixerStatus = MIXER_TRACKS_READY; if (mHwPaused) { if (mHwPaused) { Loading Loading
services/audioflinger/Threads.cpp +28 −6 Original line number Original line Diff line number Diff line Loading @@ -124,12 +124,26 @@ using media::permission::Identity; // 50 * ~20msecs = 1 second // 50 * ~20msecs = 1 second static const int8_t kMaxTrackRetries = 50; static const int8_t kMaxTrackRetries = 50; static const int8_t kMaxTrackStartupRetries = 50; static const int8_t kMaxTrackStartupRetries = 50; // allow less retry attempts on direct output thread. // allow less retry attempts on direct output thread. // direct outputs can be a scarce resource in audio hardware and should // direct outputs can be a scarce resource in audio hardware and should // be released as quickly as possible. // be released as quickly as possible. static const int8_t kMaxTrackRetriesDirect = 2; // Notes: // 1) The retry duration kMaxTrackRetriesDirectMs may be increased // in case the data write is bursty for the AudioTrack. The application // should endeavor to write at least once every kMaxTrackRetriesDirectMs // to prevent an underrun situation. If the data is bursty, then // the application can also throttle the data sent to be even. // 2) For compressed audio data, any data present in the AudioTrack buffer // will be sent and reset the retry count. This delivers data as // it arrives, with approximately kDirectMinSleepTimeUs = 10ms checking interval. // 3) For linear PCM or proportional PCM, we wait one period for a period's worth // of data to be available, then any remaining data is delivered. // This is required to ensure the last bit of data is delivered before underrun. // // Sleep time per cycle is kDirectMinSleepTimeUs for compressed tracks // or the size of the HAL period for proportional / linear PCM tracks. static const int32_t kMaxTrackRetriesDirectMs = 200; // don't warn about blocked writes or record buffer overflows more often than this // don't warn about blocked writes or record buffer overflows more often than this static const nsecs_t kWarningThrottleNs = seconds(5); static const nsecs_t kWarningThrottleNs = seconds(5); Loading Loading @@ -5931,11 +5945,19 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // Allow draining the buffer in case the client // Allow draining the buffer in case the client // app does not call stop() and relies on underrun to stop: // app does not call stop() and relies on underrun to stop: // hence the test on (track->mRetryCount > 1). // hence the test on (track->mRetryCount > 1). // If retryCount<=1 then track is about to underrun and be removed. // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed, // so we accept any nonzero amount of data delivered by the AudioTrack (which will // reset the retry counter). // Do not use a high threshold for compressed audio. // Do not use a high threshold for compressed audio. // target retry count that we will use is based on the time we wait for retries. const int32_t targetRetryCount = kMaxTrackRetriesDirectMs * 1000 / mActiveSleepTimeUs; // the retry threshold is when we accept any size for PCM data. This is slightly // smaller than the retry count so we can push small bits of data without a glitch. const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1; uint32_t minFrames; uint32_t minFrames; if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing() if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing() && (track->mRetryCount > 1) && audio_has_proportional_frames(mFormat)) { && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) { minFrames = mNormalFrameCount; minFrames = mNormalFrameCount; } else { } else { minFrames = 1; minFrames = 1; Loading Loading @@ -5979,7 +6001,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep mPreviousTrack = track; mPreviousTrack = track; // reset retry count // reset retry count track->mRetryCount = kMaxTrackRetriesDirect; track->mRetryCount = targetRetryCount; mActiveTrack = t; mActiveTrack = t; mixerStatus = MIXER_TRACKS_READY; mixerStatus = MIXER_TRACKS_READY; if (mHwPaused) { if (mHwPaused) { Loading