Loading media/libmediaplayerservice/MediaPlayerService.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -2150,7 +2150,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // // The underrun event is sent once per track underrun; the condition is reset // when more data is sent to the AudioTrack. ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)"); ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); break; default: Loading services/audioflinger/AudioFlinger.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -1847,8 +1847,7 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_ PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady, config->offload_info.bit_rate); thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) Loading services/audioflinger/Threads.cpp +58 −102 Original line number Diff line number Diff line Loading @@ -110,12 +110,7 @@ static const int8_t kMaxTrackStartupRetries = 50; // direct outputs can be a scarce resource in audio hardware and should // be released as quickly as possible. static const int8_t kMaxTrackRetriesDirect = 2; // retry count before removing active track in case of underrun on offloaded thread: // we need to make sure that AudioTrack client has enough time to send large buffers //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is handled // for offloaded tracks static const int8_t kMaxTrackRetriesOffload = 10; static const int8_t kMaxTrackStartupRetriesOffload = 100; // don't warn about blocked writes or record buffer overflows more often than this Loading Loading @@ -148,10 +143,6 @@ static const nsecs_t kOffloadStandbyDelayNs = seconds(1); // Direct output thread minimum sleep time in idle or active(underrun) state static const nsecs_t kDirectMinSleepTimeUs = 10000; // Offloaded output bit rate in bits per second when unknown. // Used for sleep time calculation, so use a high default bitrate to be conservative on sleep time. static const uint32_t kOffloadDefaultBitRateBps = 1500000; // Whether to use fast mixer static const enum { Loading Loading @@ -1567,8 +1558,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady, uint32_t bitRate) bool systemReady) : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady), mNormalFrameCount(0), mSinkBuffer(NULL), mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision), Loading Loading @@ -1631,13 +1621,6 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream); mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream); } if (audio_has_proportional_frames(mFormat)) { mBufferDurationUs = (uint32_t)((mNormalFrameCount * 1000000LL) / mSampleRate); } else { bitRate = bitRate != 0 ? bitRate : kOffloadDefaultBitRateBps; mBufferDurationUs = (uint32_t)((mBufferSize * 8 * 1000000LL) / bitRate); } } AudioFlinger::PlaybackThread::~PlaybackThread() Loading Loading @@ -2049,12 +2032,18 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) // set retry count for buffer fill if (track->isOffloaded()) { if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackStartupRetriesOffload; } track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED; } else { track->mRetryCount = kMaxTrackStartupRetries; track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING; } track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING; track->mResetDone = false; track->mPresentationCompleteFrames = 0; mActiveTracks.add(track); Loading Loading @@ -3181,32 +3170,9 @@ bool AudioFlinger::PlaybackThread::threadLoop() } else { ATRACE_BEGIN("sleep"); if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) { Mutex::Autolock _l(mLock); if (!mSignalPending && !exitPending()) { // If more than one buffer has been written to the audio HAL since exiting // standby or last flush, do not sleep more than one buffer duration // since last write and not less than kDirectMinSleepTimeUs. // Wake up if a command is received uint32_t timeoutUs = mSleepTimeUs; if (mBytesWritten >= (int64_t) mBufferSize) { nsecs_t now = systemTime(); uint32_t deltaUs = (uint32_t)((now - mLastWriteTime) / 1000); if (timeoutUs + deltaUs > mBufferDurationUs) { if (mBufferDurationUs > deltaUs) { timeoutUs = mBufferDurationUs - deltaUs; if (timeoutUs < kDirectMinSleepTimeUs) { timeoutUs = kDirectMinSleepTimeUs; } } else { timeoutUs = kDirectMinSleepTimeUs; } } } mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)timeoutUs)); } } else { usleep(mSleepTimeUs); if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) { mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs)); } ATRACE_END(); } Loading Loading @@ -4592,17 +4558,16 @@ void AudioFlinger::MixerThread::cacheParameters_l() // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady, uint32_t bitRate) : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady, bitRate) AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady) // mLeftVolFloat, mRightVolFloat { } AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, bool systemReady, uint32_t bitRate) : PlaybackThread(audioFlinger, output, id, device, type, systemReady, bitRate) ThreadBase::type_t type, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat { } Loading Loading @@ -4908,14 +4873,7 @@ void AudioFlinger::DirectOutputThread::threadLoop_sleepTime() } if (mSleepTimeUs == 0) { if (mMixerStatus == MIXER_TRACKS_ENABLED) { // For compressed offload, use faster sleep time when underruning until more than an // entire buffer was written to the audio HAL if (!audio_has_proportional_frames(mFormat) && (mType == OFFLOAD) && (mBytesWritten < (int64_t) mBufferSize)) { mSleepTimeUs = kDirectMinSleepTimeUs; } else { mSleepTimeUs = mActiveSleepTimeUs; } } else { mSleepTimeUs = mIdleSleepTimeUs; } Loading Loading @@ -5187,9 +5145,8 @@ void AudioFlinger::AsyncCallbackThread::resetDraining() // ---------------------------------------------------------------------------- AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady, uint32_t bitRate) : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady, bitRate), AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady) : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady), mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true) { //FIXME: mStandby should be set to true by ThreadBase constructor Loading Loading @@ -5273,7 +5230,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } tracksToRemove->add(track); } else if (track->isFlushPending()) { if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackRetriesOffload; } track->flushAck(); if (last) { mFlushPending = true; Loading Loading @@ -5334,13 +5295,18 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } mPreviousTrack = track; // reset retry count if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackRetriesOffload; } mActiveTrack = t; mixerStatus = MIXER_TRACKS_READY; } } else { ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer); if (track->isStopping_1()) { if (--(track->mRetryCount) <= 0) { // Hardware buffer can hold a large amount of audio so we must // wait for all current track's data to drain before we say // that the track is stopped. Loading @@ -5348,8 +5314,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // Only start draining when all data in mixbuffer // has been written ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2"); track->mState = TrackBase::STOPPING_2; // so presentation completes after drain // do not drain if no data was ever sent to HAL (mStandby == true) track->mState = TrackBase::STOPPING_2; // so presentation completes after // drain do not drain if no data was ever sent to HAL (mStandby == true) if (last && !mStandby) { // do not modify drain sequence if we are already draining. This happens // when resuming from pause after drain. Loading @@ -5367,6 +5333,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } } } } else if (last) { ALOGV("stopping1 underrun retries left %d", track->mRetryCount); mixerStatus = MIXER_TRACKS_ENABLED; } } else if (track->isStopping_2()) { // Drain has completed or we are in standby, signal presentation complete if (!(mDrainSequence & 1) || !last || mStandby) { Loading Loading @@ -5456,20 +5426,6 @@ void AudioFlinger::OffloadThread::flushHw_l() } } uint32_t AudioFlinger::OffloadThread::activeSleepTimeUs() const { uint32_t time; if (audio_has_proportional_frames(mFormat)) { time = PlaybackThread::activeSleepTimeUs(); } else { // sleep time is half the duration of an audio HAL buffer. // Note: This can be problematic in case of underrun with variable bit rate and // current rate is much less than initial rate. time = (uint32_t)max(kDirectMinSleepTimeUs, mBufferDurationUs / 2); } return time; } void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType) { Mutex::Autolock _l(mLock); Loading services/audioflinger/Threads.h +12 −11 Original line number Diff line number Diff line Loading @@ -486,9 +486,16 @@ public: // suspend by audio policy manager is orthogonal to mixer state }; // retry count before removing active track in case of underrun on offloaded thread: // we need to make sure that AudioTrack client has enough time to send large buffers //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is // handled for offloaded tracks static const int8_t kMaxTrackRetriesOffload = 20; static const int8_t kMaxTrackStartupRetriesOffload = 100; static const int8_t kMaxTrackStopRetriesOffload = 2; PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady, uint32_t bitRate = 0); audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady); virtual ~PlaybackThread(); void dump(int fd, const Vector<String16>& args); Loading Loading @@ -843,8 +850,6 @@ protected: bool mHwSupportsPause; bool mHwPaused; bool mFlushPending; uint32_t mBufferDurationUs; // estimated duration of an audio HAL buffer // based on initial bit rate (offload only) }; class MixerThread : public PlaybackThread { Loading Loading @@ -935,8 +940,7 @@ class DirectOutputThread : public PlaybackThread { public: DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady, uint32_t bitRate = 0); audio_io_handle_t id, audio_devices_t device, bool systemReady); virtual ~DirectOutputThread(); // Thread virtuals Loading Loading @@ -969,7 +973,7 @@ protected: DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, bool systemReady, uint32_t bitRate = 0); bool systemReady); void processVolume_l(Track *track, bool lastTrack); // prepareTracks_l() tells threadLoop_mix() the name of the single active track Loading @@ -985,8 +989,7 @@ class OffloadThread : public DirectOutputThread { public: OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady, uint32_t bitRate); audio_io_handle_t id, uint32_t device, bool systemReady); virtual ~OffloadThread() {}; virtual void flushHw_l(); Loading @@ -995,8 +998,6 @@ protected: virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); virtual void threadLoop_exit(); virtual uint32_t activeSleepTimeUs() const; virtual bool waitingAsyncCallback(); virtual bool waitingAsyncCallback_l(); virtual void invalidateTracks(audio_stream_type_t streamType); Loading services/audioflinger/Tracks.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -373,7 +373,7 @@ AudioFlinger::PlaybackThread::Track::Track( // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(), sharedBuffer->size()); if (mCblk == NULL) { Loading Loading @@ -728,6 +728,9 @@ void AudioFlinger::PlaybackThread::Track::stop() // For an offloaded track this starts a drain and state will // move to STOPPING_2 when drain completes and then STOPPED mState = STOPPING_1; if (isOffloaded()) { mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload; } } playbackThread->broadcast_l(); ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, Loading Loading
media/libmediaplayerservice/MediaPlayerService.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -2150,7 +2150,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // // The underrun event is sent once per track underrun; the condition is reset // when more data is sent to the AudioTrack. ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)"); ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); break; default: Loading
services/audioflinger/AudioFlinger.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -1847,8 +1847,7 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_ PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady, config->offload_info.bit_rate); thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) Loading
services/audioflinger/Threads.cpp +58 −102 Original line number Diff line number Diff line Loading @@ -110,12 +110,7 @@ static const int8_t kMaxTrackStartupRetries = 50; // direct outputs can be a scarce resource in audio hardware and should // be released as quickly as possible. static const int8_t kMaxTrackRetriesDirect = 2; // retry count before removing active track in case of underrun on offloaded thread: // we need to make sure that AudioTrack client has enough time to send large buffers //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is handled // for offloaded tracks static const int8_t kMaxTrackRetriesOffload = 10; static const int8_t kMaxTrackStartupRetriesOffload = 100; // don't warn about blocked writes or record buffer overflows more often than this Loading Loading @@ -148,10 +143,6 @@ static const nsecs_t kOffloadStandbyDelayNs = seconds(1); // Direct output thread minimum sleep time in idle or active(underrun) state static const nsecs_t kDirectMinSleepTimeUs = 10000; // Offloaded output bit rate in bits per second when unknown. // Used for sleep time calculation, so use a high default bitrate to be conservative on sleep time. static const uint32_t kOffloadDefaultBitRateBps = 1500000; // Whether to use fast mixer static const enum { Loading Loading @@ -1567,8 +1558,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady, uint32_t bitRate) bool systemReady) : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady), mNormalFrameCount(0), mSinkBuffer(NULL), mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision), Loading Loading @@ -1631,13 +1621,6 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream); mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream); } if (audio_has_proportional_frames(mFormat)) { mBufferDurationUs = (uint32_t)((mNormalFrameCount * 1000000LL) / mSampleRate); } else { bitRate = bitRate != 0 ? bitRate : kOffloadDefaultBitRateBps; mBufferDurationUs = (uint32_t)((mBufferSize * 8 * 1000000LL) / bitRate); } } AudioFlinger::PlaybackThread::~PlaybackThread() Loading Loading @@ -2049,12 +2032,18 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) // set retry count for buffer fill if (track->isOffloaded()) { if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackStartupRetriesOffload; } track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED; } else { track->mRetryCount = kMaxTrackStartupRetries; track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING; } track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING; track->mResetDone = false; track->mPresentationCompleteFrames = 0; mActiveTracks.add(track); Loading Loading @@ -3181,32 +3170,9 @@ bool AudioFlinger::PlaybackThread::threadLoop() } else { ATRACE_BEGIN("sleep"); if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) { Mutex::Autolock _l(mLock); if (!mSignalPending && !exitPending()) { // If more than one buffer has been written to the audio HAL since exiting // standby or last flush, do not sleep more than one buffer duration // since last write and not less than kDirectMinSleepTimeUs. // Wake up if a command is received uint32_t timeoutUs = mSleepTimeUs; if (mBytesWritten >= (int64_t) mBufferSize) { nsecs_t now = systemTime(); uint32_t deltaUs = (uint32_t)((now - mLastWriteTime) / 1000); if (timeoutUs + deltaUs > mBufferDurationUs) { if (mBufferDurationUs > deltaUs) { timeoutUs = mBufferDurationUs - deltaUs; if (timeoutUs < kDirectMinSleepTimeUs) { timeoutUs = kDirectMinSleepTimeUs; } } else { timeoutUs = kDirectMinSleepTimeUs; } } } mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)timeoutUs)); } } else { usleep(mSleepTimeUs); if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) { mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs)); } ATRACE_END(); } Loading Loading @@ -4592,17 +4558,16 @@ void AudioFlinger::MixerThread::cacheParameters_l() // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady, uint32_t bitRate) : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady, bitRate) AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady) // mLeftVolFloat, mRightVolFloat { } AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, bool systemReady, uint32_t bitRate) : PlaybackThread(audioFlinger, output, id, device, type, systemReady, bitRate) ThreadBase::type_t type, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat { } Loading Loading @@ -4908,14 +4873,7 @@ void AudioFlinger::DirectOutputThread::threadLoop_sleepTime() } if (mSleepTimeUs == 0) { if (mMixerStatus == MIXER_TRACKS_ENABLED) { // For compressed offload, use faster sleep time when underruning until more than an // entire buffer was written to the audio HAL if (!audio_has_proportional_frames(mFormat) && (mType == OFFLOAD) && (mBytesWritten < (int64_t) mBufferSize)) { mSleepTimeUs = kDirectMinSleepTimeUs; } else { mSleepTimeUs = mActiveSleepTimeUs; } } else { mSleepTimeUs = mIdleSleepTimeUs; } Loading Loading @@ -5187,9 +5145,8 @@ void AudioFlinger::AsyncCallbackThread::resetDraining() // ---------------------------------------------------------------------------- AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady, uint32_t bitRate) : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady, bitRate), AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady) : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady), mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true) { //FIXME: mStandby should be set to true by ThreadBase constructor Loading Loading @@ -5273,7 +5230,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } tracksToRemove->add(track); } else if (track->isFlushPending()) { if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackRetriesOffload; } track->flushAck(); if (last) { mFlushPending = true; Loading Loading @@ -5334,13 +5295,18 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } mPreviousTrack = track; // reset retry count if (track->isStopping_1()) { track->mRetryCount = kMaxTrackStopRetriesOffload; } else { track->mRetryCount = kMaxTrackRetriesOffload; } mActiveTrack = t; mixerStatus = MIXER_TRACKS_READY; } } else { ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer); if (track->isStopping_1()) { if (--(track->mRetryCount) <= 0) { // Hardware buffer can hold a large amount of audio so we must // wait for all current track's data to drain before we say // that the track is stopped. Loading @@ -5348,8 +5314,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // Only start draining when all data in mixbuffer // has been written ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2"); track->mState = TrackBase::STOPPING_2; // so presentation completes after drain // do not drain if no data was ever sent to HAL (mStandby == true) track->mState = TrackBase::STOPPING_2; // so presentation completes after // drain do not drain if no data was ever sent to HAL (mStandby == true) if (last && !mStandby) { // do not modify drain sequence if we are already draining. This happens // when resuming from pause after drain. Loading @@ -5367,6 +5333,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } } } } else if (last) { ALOGV("stopping1 underrun retries left %d", track->mRetryCount); mixerStatus = MIXER_TRACKS_ENABLED; } } else if (track->isStopping_2()) { // Drain has completed or we are in standby, signal presentation complete if (!(mDrainSequence & 1) || !last || mStandby) { Loading Loading @@ -5456,20 +5426,6 @@ void AudioFlinger::OffloadThread::flushHw_l() } } uint32_t AudioFlinger::OffloadThread::activeSleepTimeUs() const { uint32_t time; if (audio_has_proportional_frames(mFormat)) { time = PlaybackThread::activeSleepTimeUs(); } else { // sleep time is half the duration of an audio HAL buffer. // Note: This can be problematic in case of underrun with variable bit rate and // current rate is much less than initial rate. time = (uint32_t)max(kDirectMinSleepTimeUs, mBufferDurationUs / 2); } return time; } void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType) { Mutex::Autolock _l(mLock); Loading
services/audioflinger/Threads.h +12 −11 Original line number Diff line number Diff line Loading @@ -486,9 +486,16 @@ public: // suspend by audio policy manager is orthogonal to mixer state }; // retry count before removing active track in case of underrun on offloaded thread: // we need to make sure that AudioTrack client has enough time to send large buffers //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is // handled for offloaded tracks static const int8_t kMaxTrackRetriesOffload = 20; static const int8_t kMaxTrackStartupRetriesOffload = 100; static const int8_t kMaxTrackStopRetriesOffload = 2; PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady, uint32_t bitRate = 0); audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady); virtual ~PlaybackThread(); void dump(int fd, const Vector<String16>& args); Loading Loading @@ -843,8 +850,6 @@ protected: bool mHwSupportsPause; bool mHwPaused; bool mFlushPending; uint32_t mBufferDurationUs; // estimated duration of an audio HAL buffer // based on initial bit rate (offload only) }; class MixerThread : public PlaybackThread { Loading Loading @@ -935,8 +940,7 @@ class DirectOutputThread : public PlaybackThread { public: DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady, uint32_t bitRate = 0); audio_io_handle_t id, audio_devices_t device, bool systemReady); virtual ~DirectOutputThread(); // Thread virtuals Loading Loading @@ -969,7 +973,7 @@ protected: DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, bool systemReady, uint32_t bitRate = 0); bool systemReady); void processVolume_l(Track *track, bool lastTrack); // prepareTracks_l() tells threadLoop_mix() the name of the single active track Loading @@ -985,8 +989,7 @@ class OffloadThread : public DirectOutputThread { public: OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady, uint32_t bitRate); audio_io_handle_t id, uint32_t device, bool systemReady); virtual ~OffloadThread() {}; virtual void flushHw_l(); Loading @@ -995,8 +998,6 @@ protected: virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); virtual void threadLoop_exit(); virtual uint32_t activeSleepTimeUs() const; virtual bool waitingAsyncCallback(); virtual bool waitingAsyncCallback_l(); virtual void invalidateTracks(audio_stream_type_t streamType); Loading
services/audioflinger/Tracks.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -373,7 +373,7 @@ AudioFlinger::PlaybackThread::Track::Track( // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(), sharedBuffer->size()); if (mCblk == NULL) { Loading Loading @@ -728,6 +728,9 @@ void AudioFlinger::PlaybackThread::Track::stop() // For an offloaded track this starts a drain and state will // move to STOPPING_2 when drain completes and then STOPPED mState = STOPPING_1; if (isOffloaded()) { mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload; } } playbackThread->broadcast_l(); ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName, Loading