Loading include/media/ToneGenerator.h +1 −0 Original line number Diff line number Diff line Loading @@ -248,6 +248,7 @@ private: // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, // no crash will occur but tone sequence will show a glitch. unsigned int mMaxSmp; // Maximum number of audio samples played (maximun tone duration) int mDurationMs; // Maximum tone duration in ms unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] unsigned short mCurCount; // Current sequence repeat count Loading libs/audioflinger/AudioFlinger.cpp +69 −54 Original line number Diff line number Diff line Loading @@ -62,8 +62,6 @@ static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n"; static const char* kHardwareLockedString = "Hardware lock is taken\n"; //static const nsecs_t kStandbyTimeInNsecs = seconds(3); static const unsigned long kBufferRecoveryInUsecs = 2000; static const unsigned long kMaxBufferRecoveryInUsecs = 20000; static const float MAX_GAIN = 4096.0f; // retry counts for buffer fill timeout Loading Loading @@ -1070,10 +1068,10 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) // in both cases "unstop" the track if (track->isPaused()) { track->mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d)", track->name()); LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this); } else { track->mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d)", track->name()); LOGV("? => ACTIVE (%d) on thread %p", track->name(), this); } // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; Loading Loading @@ -1175,7 +1173,8 @@ AudioFlinger::MixerThread::~MixerThread() bool AudioFlinger::MixerThread::threadLoop() { unsigned long sleepTime = 0; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; Loading @@ -1200,6 +1199,7 @@ bool AudioFlinger::MixerThread::threadLoop() // FIXME: Relaxed timing because of a certain device that can't meet latency // Should be reduced to 2x after the vendor fixes the driver issue maxPeriod = seconds(mFrameCount) / mSampleRate * 3; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -1235,7 +1235,6 @@ bool AudioFlinger::MixerThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading @@ -1249,28 +1248,23 @@ bool AudioFlinger::MixerThread::threadLoop() sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { // If no tracks are ready, sleep once for the duration of an output // buffer size, then write 0s to the output if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0) { memset (curBuf, 0, mixBufferSize); sleepTime = 0; } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; LOGV("mOutput->write() thread %p frames %d", this, mFrameCount); int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); if (bytesWritten > 0) mBytesWritten += bytesWritten; mNumWrites++; Loading Loading @@ -1393,7 +1387,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> // No buffers for this track. Give it a few chances to // fill a buffer, then remove it from active list. if (--(track->mRetryCount) <= 0) { LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name()); LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this); tracksToRemove->add(track); } // For tracks using static shared memory buffer, make sure that we have Loading Loading @@ -1583,6 +1577,16 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16> return NO_ERROR; } uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs() { uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000; // Add some margin with regard to scheduling precision if (time > 10000) { time -= 10000; } return time; } // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) : PlaybackThread(audioFlinger, output), Loading @@ -1598,7 +1602,8 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() bool AudioFlinger::DirectOutputThread::threadLoop() { unsigned long sleepTime = 0; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); Loading @@ -1615,6 +1620,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } // put audio hardware into standby after short delay Loading Loading @@ -1648,7 +1654,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading Loading @@ -1761,23 +1766,16 @@ bool AudioFlinger::DirectOutputThread::threadLoop() sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs && AudioSystem::isLinearPCM(mFormat)) { if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) { memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { Loading Loading @@ -1861,6 +1859,21 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() return reconfig; } uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs() { uint32_t time; if (AudioSystem::isLinearPCM(mFormat)) { time = ((mFrameCount * 1000) / mSampleRate) * 1000; // Add some margin with regard to scheduling precision if (time > 10000) { time -= 10000; } } else { time = 10000; } return time; } // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) Loading @@ -1877,13 +1890,15 @@ AudioFlinger::DuplicatingThread::~DuplicatingThread() bool AudioFlinger::DuplicatingThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount*mFrameSize; SortedVector< sp<OutputTrack> > outputTracks; uint32_t writeFrames = 0; while (!exitPending()) { Loading @@ -1896,6 +1911,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -1935,7 +1951,6 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = kBufferRecoveryInUsecs; continue; } } Loading @@ -1947,29 +1962,30 @@ bool AudioFlinger::DuplicatingThread::threadLoop() // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; writeFrames = mFrameCount; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { memset (curBuf, 0, mixBufferSize); if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0) { // flush remaining overflow buffers in output tracks for (size_t i = 0; i < outputTracks.size(); i++) { if (outputTracks[i]->isActive()) { sleepTime = 0; writeFrames = 0; break; } } } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { standbyTime = systemTime() + kStandbyTimeInNsecs; for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->write(curBuf, mFrameCount); outputTracks[i]->write(curBuf, writeFrames); } mStandby = false; mBytesWritten += mixBufferSize; Loading Loading @@ -2026,7 +2042,6 @@ void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread) LOGV("removeOutputTrack(): unkonwn thread: %p", thread); } // ---------------------------------------------------------------------------- // TrackBase constructor must be called with AudioFlinger::mLock held Loading Loading @@ -2300,7 +2315,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider: getNextBuffer_exit: buffer->raw = 0; buffer->frameCount = 0; LOGV("getNextBuffer() no more data"); LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get()); return NOT_ENOUGH_DATA; } Loading Loading @@ -2341,7 +2356,7 @@ void AudioFlinger::PlaybackThread::Track::stop() if (playbackThread->mActiveTracks.indexOf(this) < 0) { reset(); } LOGV("(> STOPPED) => STOPPED (%d)", mName); LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); } } } Loading @@ -2354,7 +2369,7 @@ void AudioFlinger::PlaybackThread::Track::pause() Mutex::Autolock _l(thread->mLock); if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); } } } Loading Loading @@ -2566,7 +2581,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t waitTimeLeftMs = mWaitTimeMs; if (!mActive) { if (!mActive && frames != 0) { start(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Loading Loading @@ -2608,7 +2623,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr break; } uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime); // LOGV("OutputTrack::write() waitTimeMs %d waitTimeLeftMs %d", waitTimeMs, waitTimeLeftMs) LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs); if (waitTimeLeftMs >= waitTimeMs) { waitTimeLeftMs -= waitTimeMs; } else { Loading Loading @@ -2663,7 +2678,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr pInBuffer->i16 = pInBuffer->mBuffer; memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); mBufferQueue.add(pInBuffer); } else { } else if (mActive) { stop(); } } Loading libs/audioflinger/AudioFlinger.h +12 −5 Original line number Diff line number Diff line Loading @@ -524,6 +524,10 @@ private: bool mMasterMute; SortedVector< wp<Track> > mActiveTracks; virtual int getTrackName_l() = 0; virtual void deleteTrackName_l(int name) = 0; virtual uint32_t getMaxBufferRecoveryInUsecs() = 0; private: friend class AudioFlinger; Loading @@ -539,8 +543,7 @@ private: status_t addTrack_l(const sp<Track>& track); void destroyTrack_l(const sp<Track>& track); virtual int getTrackName_l() = 0; virtual void deleteTrackName_l(int name) = 0; void readOutputParameters(); virtual status_t dumpInternals(int fd, const Vector<String16>& args); Loading Loading @@ -571,13 +574,14 @@ private: int streamType); void putTracks(SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual bool checkForNewParameters_l(); virtual status_t dumpInternals(int fd, const Vector<String16>& args); protected: size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual uint32_t getMaxBufferRecoveryInUsecs(); AudioMixer* mAudioMixer; }; Loading @@ -591,9 +595,12 @@ private: // Thread virtuals virtual bool threadLoop(); virtual bool checkForNewParameters_l(); protected: virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual bool checkForNewParameters_l(); virtual uint32_t getMaxBufferRecoveryInUsecs(); private: float mLeftVolume; Loading media/libmedia/ToneGenerator.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -879,6 +879,7 @@ ToneGenerator::~ToneGenerator() { //////////////////////////////////////////////////////////////////////////////// bool ToneGenerator::startTone(int toneType, int durationMs) { bool lResult = false; status_t lStatus; if ((toneType < 0) || (toneType >= NUM_TONES)) return lResult; Loading @@ -898,15 +899,16 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { toneType = getToneForRegion(toneType); mpNewToneDesc = &sToneDescriptors[toneType]; if (durationMs == -1) { mMaxSmp = TONEGEN_INF; } else { if (durationMs > (int)(TONEGEN_INF / mSamplingRate)) { mMaxSmp = (durationMs / 1000) * mSamplingRate; } else { mMaxSmp = (durationMs * mSamplingRate) / 1000; mDurationMs = durationMs; if (mState == TONE_STOPPED) { LOGV("Start waiting for previous tone to stop"); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus != NO_ERROR) { LOGE("--- start wait for stop timed out, status %d", lStatus); mState = TONE_IDLE; return lResult; } LOGV("startTone, duration limited to %d ms", durationMs); } if (mState == TONE_INIT) { Loading @@ -919,7 +921,7 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { mLock.lock(); if (mState == TONE_STARTING) { LOGV("Wait for start callback"); status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus != NO_ERROR) { LOGE("--- Immediate start timed out, status %d", lStatus); mState = TONE_IDLE; Loading @@ -931,9 +933,8 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { } } else { LOGV("Delayed start\n"); mState = TONE_RESTARTING; status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus == NO_ERROR) { if (mState != TONE_IDLE) { lResult = true; Loading Loading @@ -1316,6 +1317,17 @@ bool ToneGenerator::prepareWave() { mpToneDesc = mpNewToneDesc; if (mDurationMs == -1) { mMaxSmp = TONEGEN_INF; } else { if (mDurationMs > (int)(TONEGEN_INF / mSamplingRate)) { mMaxSmp = (mDurationMs / 1000) * mSamplingRate; } else { mMaxSmp = (mDurationMs * mSamplingRate) / 1000; } LOGV("prepareWave, duration limited to %d ms", mDurationMs); } while (mpToneDesc->segments[segmentIdx].duration) { // Get total number of sine waves: needed to adapt sine wave gain. unsigned int lNumWaves = numWaves(segmentIdx); Loading Loading
include/media/ToneGenerator.h +1 −0 Original line number Diff line number Diff line Loading @@ -248,6 +248,7 @@ private: // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, // no crash will occur but tone sequence will show a glitch. unsigned int mMaxSmp; // Maximum number of audio samples played (maximun tone duration) int mDurationMs; // Maximum tone duration in ms unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] unsigned short mCurCount; // Current sequence repeat count Loading
libs/audioflinger/AudioFlinger.cpp +69 −54 Original line number Diff line number Diff line Loading @@ -62,8 +62,6 @@ static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n"; static const char* kHardwareLockedString = "Hardware lock is taken\n"; //static const nsecs_t kStandbyTimeInNsecs = seconds(3); static const unsigned long kBufferRecoveryInUsecs = 2000; static const unsigned long kMaxBufferRecoveryInUsecs = 20000; static const float MAX_GAIN = 4096.0f; // retry counts for buffer fill timeout Loading Loading @@ -1070,10 +1068,10 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) // in both cases "unstop" the track if (track->isPaused()) { track->mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d)", track->name()); LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this); } else { track->mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d)", track->name()); LOGV("? => ACTIVE (%d) on thread %p", track->name(), this); } // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; Loading Loading @@ -1175,7 +1173,8 @@ AudioFlinger::MixerThread::~MixerThread() bool AudioFlinger::MixerThread::threadLoop() { unsigned long sleepTime = 0; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; Loading @@ -1200,6 +1199,7 @@ bool AudioFlinger::MixerThread::threadLoop() // FIXME: Relaxed timing because of a certain device that can't meet latency // Should be reduced to 2x after the vendor fixes the driver issue maxPeriod = seconds(mFrameCount) / mSampleRate * 3; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -1235,7 +1235,6 @@ bool AudioFlinger::MixerThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading @@ -1249,28 +1248,23 @@ bool AudioFlinger::MixerThread::threadLoop() sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { // If no tracks are ready, sleep once for the duration of an output // buffer size, then write 0s to the output if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0) { memset (curBuf, 0, mixBufferSize); sleepTime = 0; } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; LOGV("mOutput->write() thread %p frames %d", this, mFrameCount); int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); if (bytesWritten > 0) mBytesWritten += bytesWritten; mNumWrites++; Loading Loading @@ -1393,7 +1387,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> // No buffers for this track. Give it a few chances to // fill a buffer, then remove it from active list. if (--(track->mRetryCount) <= 0) { LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name()); LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this); tracksToRemove->add(track); } // For tracks using static shared memory buffer, make sure that we have Loading Loading @@ -1583,6 +1577,16 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16> return NO_ERROR; } uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs() { uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000; // Add some margin with regard to scheduling precision if (time > 10000) { time -= 10000; } return time; } // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) : PlaybackThread(audioFlinger, output), Loading @@ -1598,7 +1602,8 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() bool AudioFlinger::DirectOutputThread::threadLoop() { unsigned long sleepTime = 0; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); Loading @@ -1615,6 +1620,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } // put audio hardware into standby after short delay Loading Loading @@ -1648,7 +1654,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading Loading @@ -1761,23 +1766,16 @@ bool AudioFlinger::DirectOutputThread::threadLoop() sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs && AudioSystem::isLinearPCM(mFormat)) { if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) { memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { Loading Loading @@ -1861,6 +1859,21 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() return reconfig; } uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs() { uint32_t time; if (AudioSystem::isLinearPCM(mFormat)) { time = ((mFrameCount * 1000) / mSampleRate) * 1000; // Add some margin with regard to scheduling precision if (time > 10000) { time -= 10000; } } else { time = 10000; } return time; } // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) Loading @@ -1877,13 +1890,15 @@ AudioFlinger::DuplicatingThread::~DuplicatingThread() bool AudioFlinger::DuplicatingThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; uint32_t sleepTime = 0; uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount*mFrameSize; SortedVector< sp<OutputTrack> > outputTracks; uint32_t writeFrames = 0; while (!exitPending()) { Loading @@ -1896,6 +1911,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -1935,7 +1951,6 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = kBufferRecoveryInUsecs; continue; } } Loading @@ -1947,29 +1962,30 @@ bool AudioFlinger::DuplicatingThread::threadLoop() // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; writeFrames = mFrameCount; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime > kMaxBufferRecoveryInUsecs) { sleepTime = kMaxBufferRecoveryInUsecs; } // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { memset (curBuf, 0, mixBufferSize); if (sleepTime == 0) { sleepTime = maxBufferRecoveryInUsecs; } else if (mBytesWritten != 0) { // flush remaining overflow buffers in output tracks for (size_t i = 0; i < outputTracks.size(); i++) { if (outputTracks[i]->isActive()) { sleepTime = 0; writeFrames = 0; break; } } } } if (mSuspended) { sleepTime = kMaxBufferRecoveryInUsecs; sleepTime = maxBufferRecoveryInUsecs; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { standbyTime = systemTime() + kStandbyTimeInNsecs; for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->write(curBuf, mFrameCount); outputTracks[i]->write(curBuf, writeFrames); } mStandby = false; mBytesWritten += mixBufferSize; Loading Loading @@ -2026,7 +2042,6 @@ void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread) LOGV("removeOutputTrack(): unkonwn thread: %p", thread); } // ---------------------------------------------------------------------------- // TrackBase constructor must be called with AudioFlinger::mLock held Loading Loading @@ -2300,7 +2315,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider: getNextBuffer_exit: buffer->raw = 0; buffer->frameCount = 0; LOGV("getNextBuffer() no more data"); LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get()); return NOT_ENOUGH_DATA; } Loading Loading @@ -2341,7 +2356,7 @@ void AudioFlinger::PlaybackThread::Track::stop() if (playbackThread->mActiveTracks.indexOf(this) < 0) { reset(); } LOGV("(> STOPPED) => STOPPED (%d)", mName); LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); } } } Loading @@ -2354,7 +2369,7 @@ void AudioFlinger::PlaybackThread::Track::pause() Mutex::Autolock _l(thread->mLock); if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); } } } Loading Loading @@ -2566,7 +2581,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t waitTimeLeftMs = mWaitTimeMs; if (!mActive) { if (!mActive && frames != 0) { start(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Loading Loading @@ -2608,7 +2623,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr break; } uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime); // LOGV("OutputTrack::write() waitTimeMs %d waitTimeLeftMs %d", waitTimeMs, waitTimeLeftMs) LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs); if (waitTimeLeftMs >= waitTimeMs) { waitTimeLeftMs -= waitTimeMs; } else { Loading Loading @@ -2663,7 +2678,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr pInBuffer->i16 = pInBuffer->mBuffer; memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); mBufferQueue.add(pInBuffer); } else { } else if (mActive) { stop(); } } Loading
libs/audioflinger/AudioFlinger.h +12 −5 Original line number Diff line number Diff line Loading @@ -524,6 +524,10 @@ private: bool mMasterMute; SortedVector< wp<Track> > mActiveTracks; virtual int getTrackName_l() = 0; virtual void deleteTrackName_l(int name) = 0; virtual uint32_t getMaxBufferRecoveryInUsecs() = 0; private: friend class AudioFlinger; Loading @@ -539,8 +543,7 @@ private: status_t addTrack_l(const sp<Track>& track); void destroyTrack_l(const sp<Track>& track); virtual int getTrackName_l() = 0; virtual void deleteTrackName_l(int name) = 0; void readOutputParameters(); virtual status_t dumpInternals(int fd, const Vector<String16>& args); Loading Loading @@ -571,13 +574,14 @@ private: int streamType); void putTracks(SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual bool checkForNewParameters_l(); virtual status_t dumpInternals(int fd, const Vector<String16>& args); protected: size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual uint32_t getMaxBufferRecoveryInUsecs(); AudioMixer* mAudioMixer; }; Loading @@ -591,9 +595,12 @@ private: // Thread virtuals virtual bool threadLoop(); virtual bool checkForNewParameters_l(); protected: virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual bool checkForNewParameters_l(); virtual uint32_t getMaxBufferRecoveryInUsecs(); private: float mLeftVolume; Loading
media/libmedia/ToneGenerator.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -879,6 +879,7 @@ ToneGenerator::~ToneGenerator() { //////////////////////////////////////////////////////////////////////////////// bool ToneGenerator::startTone(int toneType, int durationMs) { bool lResult = false; status_t lStatus; if ((toneType < 0) || (toneType >= NUM_TONES)) return lResult; Loading @@ -898,15 +899,16 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { toneType = getToneForRegion(toneType); mpNewToneDesc = &sToneDescriptors[toneType]; if (durationMs == -1) { mMaxSmp = TONEGEN_INF; } else { if (durationMs > (int)(TONEGEN_INF / mSamplingRate)) { mMaxSmp = (durationMs / 1000) * mSamplingRate; } else { mMaxSmp = (durationMs * mSamplingRate) / 1000; mDurationMs = durationMs; if (mState == TONE_STOPPED) { LOGV("Start waiting for previous tone to stop"); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus != NO_ERROR) { LOGE("--- start wait for stop timed out, status %d", lStatus); mState = TONE_IDLE; return lResult; } LOGV("startTone, duration limited to %d ms", durationMs); } if (mState == TONE_INIT) { Loading @@ -919,7 +921,7 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { mLock.lock(); if (mState == TONE_STARTING) { LOGV("Wait for start callback"); status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus != NO_ERROR) { LOGE("--- Immediate start timed out, status %d", lStatus); mState = TONE_IDLE; Loading @@ -931,9 +933,8 @@ bool ToneGenerator::startTone(int toneType, int durationMs) { } } else { LOGV("Delayed start\n"); mState = TONE_RESTARTING; status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); if (lStatus == NO_ERROR) { if (mState != TONE_IDLE) { lResult = true; Loading Loading @@ -1316,6 +1317,17 @@ bool ToneGenerator::prepareWave() { mpToneDesc = mpNewToneDesc; if (mDurationMs == -1) { mMaxSmp = TONEGEN_INF; } else { if (mDurationMs > (int)(TONEGEN_INF / mSamplingRate)) { mMaxSmp = (mDurationMs / 1000) * mSamplingRate; } else { mMaxSmp = (mDurationMs * mSamplingRate) / 1000; } LOGV("prepareWave, duration limited to %d ms", mDurationMs); } while (mpToneDesc->segments[segmentIdx].duration) { // Get total number of sine waves: needed to adapt sine wave gain. unsigned int lNumWaves = numWaves(segmentIdx); Loading