Loading media/libmedia/AudioTrack.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2390,6 +2390,9 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } else { timestamp.mPosition = (uint32_t)(ets.mPosition[location] - frames); } } else if (location == ExtendedTimestamp::LOCATION_KERNEL) { ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER, "getTimestamp() location moved from server to kernel"); } mPreviousLocation = location; } else { Loading services/audioflinger/Threads.cpp +50 −19 Original line number Diff line number Diff line Loading @@ -1576,7 +1576,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mActiveTracksGeneration(0), // mStreamTypes[] initialized in constructor body mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), mMixerStatus(MIXER_IDLE), mMixerStatusIgnoringFastTracks(MIXER_IDLE), mStandbyDelayNs(AudioFlinger::mStandbyTimeInNsecs), Loading Loading @@ -2537,8 +2537,6 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l() // shared by MIXER and DIRECT, overridden by DUPLICATING ssize_t AudioFlinger::PlaybackThread::threadLoop_write() { // FIXME rewrite to reduce number of system calls mLastWriteTime = systemTime(); mInWrite = true; ssize_t bytesWritten; const size_t offset = mCurrentWriteLength - mBytesRemaining; Loading Loading @@ -2834,6 +2832,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() Vector< sp<Track> > tracksToRemove; mStandbyTimeNs = systemTime(); nsecs_t lastWriteFinished = -1; // time last server write completed int64_t lastFramesWritten = -1; // track changes in timestamp server frames written // MIXER nsecs_t lastWarning = 0; Loading Loading @@ -2884,10 +2884,11 @@ bool AudioFlinger::PlaybackThread::threadLoop() // Gather the framesReleased counters for all active tracks, // and associate with the sink frames written out. We need // this to convert the sink timestamp to the track timestamp. bool kernelLocationUpdate = false; if (mNormalSink != 0) { // Note: The DuplicatingThread may not have a mNormalSink. // We always fetch the timestamp here because often the downstream // sink will block whie writing. // sink will block while writing. ExtendedTimestamp timestamp; // use private copy to fetch (void) mNormalSink->getTimestamp(timestamp); Loading @@ -2904,6 +2905,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER]; mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER]; } if (timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) { kernelLocationUpdate = true; } else { ALOGV("getTimestamp error - no valid kernel position"); } Loading @@ -2917,8 +2922,24 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mFramesWritten for non-offloaded tracks are contiguous // even after standby() is called. This is useful for the track frame // to sink frame mapping. bool serverLocationUpdate = false; if (mFramesWritten != lastFramesWritten) { serverLocationUpdate = true; lastFramesWritten = mFramesWritten; } // Only update timestamps if there is a meaningful change. // Either the kernel timestamp must be valid or we have written something. if (kernelLocationUpdate || serverLocationUpdate) { if (serverLocationUpdate) { // use the time before we called the HAL write - it is a bit more accurate // to when the server last read data than the current time here. // // If we haven't written anything, mLastWriteTime will be -1 // and we use systemTime(). mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten; mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime(); mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1 ? systemTime() : mLastWriteTime; } const size_t size = mActiveTracks.size(); for (size_t i = 0; i < size; ++i) { sp<Track> t = mActiveTracks[i].promote(); Loading @@ -2929,6 +2950,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp); } } } saveOutputTracks(); if (mSignalPending) { Loading Loading @@ -3104,8 +3126,17 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mSleepTimeUs == 0 means we must write to audio hardware if (mSleepTimeUs == 0) { ssize_t ret = 0; // We save lastWriteFinished here, as previousLastWriteFinished, // for throttling. On thread start, previousLastWriteFinished will be // set to -1, which properly results in no throttling after the first write. nsecs_t previousLastWriteFinished = lastWriteFinished; nsecs_t delta = 0; if (mBytesRemaining) { // FIXME rewrite to reduce number of system calls mLastWriteTime = systemTime(); // also used for dumpsys ret = threadLoop_write(); lastWriteFinished = systemTime(); delta = lastWriteFinished - mLastWriteTime; if (ret < 0) { mBytesRemaining = 0; } else { Loading @@ -3119,15 +3150,13 @@ bool AudioFlinger::PlaybackThread::threadLoop() } if (mType == MIXER && !mStandby) { // write blocked detection nsecs_t now = systemTime(); nsecs_t delta = now - mLastWriteTime; if (delta > maxPeriod) { mNumDelayedWrites++; if ((now - lastWarning) > kWarningThrottleNs) { if ((lastWriteFinished - lastWarning) > kWarningThrottleNs) { ATRACE_NAME("underrun"); ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p", (unsigned long long) ns2ms(delta), mNumDelayedWrites, this); lastWarning = now; lastWarning = lastWriteFinished; } } Loading @@ -3147,7 +3176,9 @@ bool AudioFlinger::PlaybackThread::threadLoop() // (2) minimum buffer sized tracks (even if the track is full, // the app won't fill fast enough to handle the sudden draw). const int32_t deltaMs = delta / 1000000; // it's OK if deltaMs is an overestimate. const int32_t deltaMs = (lastWriteFinished - previousLastWriteFinished) / 1000000; const int32_t throttleMs = mHalfBufferMs - deltaMs; if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) { usleep(throttleMs * 1000); Loading Loading
media/libmedia/AudioTrack.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2390,6 +2390,9 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } else { timestamp.mPosition = (uint32_t)(ets.mPosition[location] - frames); } } else if (location == ExtendedTimestamp::LOCATION_KERNEL) { ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER, "getTimestamp() location moved from server to kernel"); } mPreviousLocation = location; } else { Loading
services/audioflinger/Threads.cpp +50 −19 Original line number Diff line number Diff line Loading @@ -1576,7 +1576,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mActiveTracksGeneration(0), // mStreamTypes[] initialized in constructor body mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), mMixerStatus(MIXER_IDLE), mMixerStatusIgnoringFastTracks(MIXER_IDLE), mStandbyDelayNs(AudioFlinger::mStandbyTimeInNsecs), Loading Loading @@ -2537,8 +2537,6 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l() // shared by MIXER and DIRECT, overridden by DUPLICATING ssize_t AudioFlinger::PlaybackThread::threadLoop_write() { // FIXME rewrite to reduce number of system calls mLastWriteTime = systemTime(); mInWrite = true; ssize_t bytesWritten; const size_t offset = mCurrentWriteLength - mBytesRemaining; Loading Loading @@ -2834,6 +2832,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() Vector< sp<Track> > tracksToRemove; mStandbyTimeNs = systemTime(); nsecs_t lastWriteFinished = -1; // time last server write completed int64_t lastFramesWritten = -1; // track changes in timestamp server frames written // MIXER nsecs_t lastWarning = 0; Loading Loading @@ -2884,10 +2884,11 @@ bool AudioFlinger::PlaybackThread::threadLoop() // Gather the framesReleased counters for all active tracks, // and associate with the sink frames written out. We need // this to convert the sink timestamp to the track timestamp. bool kernelLocationUpdate = false; if (mNormalSink != 0) { // Note: The DuplicatingThread may not have a mNormalSink. // We always fetch the timestamp here because often the downstream // sink will block whie writing. // sink will block while writing. ExtendedTimestamp timestamp; // use private copy to fetch (void) mNormalSink->getTimestamp(timestamp); Loading @@ -2904,6 +2905,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER]; mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER]; } if (timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) { kernelLocationUpdate = true; } else { ALOGV("getTimestamp error - no valid kernel position"); } Loading @@ -2917,8 +2922,24 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mFramesWritten for non-offloaded tracks are contiguous // even after standby() is called. This is useful for the track frame // to sink frame mapping. bool serverLocationUpdate = false; if (mFramesWritten != lastFramesWritten) { serverLocationUpdate = true; lastFramesWritten = mFramesWritten; } // Only update timestamps if there is a meaningful change. // Either the kernel timestamp must be valid or we have written something. if (kernelLocationUpdate || serverLocationUpdate) { if (serverLocationUpdate) { // use the time before we called the HAL write - it is a bit more accurate // to when the server last read data than the current time here. // // If we haven't written anything, mLastWriteTime will be -1 // and we use systemTime(). mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten; mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime(); mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1 ? systemTime() : mLastWriteTime; } const size_t size = mActiveTracks.size(); for (size_t i = 0; i < size; ++i) { sp<Track> t = mActiveTracks[i].promote(); Loading @@ -2929,6 +2950,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp); } } } saveOutputTracks(); if (mSignalPending) { Loading Loading @@ -3104,8 +3126,17 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mSleepTimeUs == 0 means we must write to audio hardware if (mSleepTimeUs == 0) { ssize_t ret = 0; // We save lastWriteFinished here, as previousLastWriteFinished, // for throttling. On thread start, previousLastWriteFinished will be // set to -1, which properly results in no throttling after the first write. nsecs_t previousLastWriteFinished = lastWriteFinished; nsecs_t delta = 0; if (mBytesRemaining) { // FIXME rewrite to reduce number of system calls mLastWriteTime = systemTime(); // also used for dumpsys ret = threadLoop_write(); lastWriteFinished = systemTime(); delta = lastWriteFinished - mLastWriteTime; if (ret < 0) { mBytesRemaining = 0; } else { Loading @@ -3119,15 +3150,13 @@ bool AudioFlinger::PlaybackThread::threadLoop() } if (mType == MIXER && !mStandby) { // write blocked detection nsecs_t now = systemTime(); nsecs_t delta = now - mLastWriteTime; if (delta > maxPeriod) { mNumDelayedWrites++; if ((now - lastWarning) > kWarningThrottleNs) { if ((lastWriteFinished - lastWarning) > kWarningThrottleNs) { ATRACE_NAME("underrun"); ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p", (unsigned long long) ns2ms(delta), mNumDelayedWrites, this); lastWarning = now; lastWarning = lastWriteFinished; } } Loading @@ -3147,7 +3176,9 @@ bool AudioFlinger::PlaybackThread::threadLoop() // (2) minimum buffer sized tracks (even if the track is full, // the app won't fill fast enough to handle the sudden draw). const int32_t deltaMs = delta / 1000000; // it's OK if deltaMs is an overestimate. const int32_t deltaMs = (lastWriteFinished - previousLastWriteFinished) / 1000000; const int32_t throttleMs = mHalfBufferMs - deltaMs; if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) { usleep(throttleMs * 1000); Loading