Loading services/audioflinger/PlaybackTracks.h +14 −1 Original line number Diff line number Diff line Loading @@ -244,7 +244,7 @@ public: AudioSystem::SYNC_EVENT_NONE, audio_session_t triggerSession = AUDIO_SESSION_NONE); virtual void stop(); bool write(void* data, uint32_t frames); ssize_t write(void* data, uint32_t frames); bool bufferQueueEmpty() const { return mBufferQueue.size() == 0; } bool isActive() const { return mActive; } const wp<ThreadBase>& thread() const { return mThread; } Loading @@ -252,6 +252,18 @@ public: void copyMetadataTo(MetadataInserter& backInserter) const override; /** Set the metadatas of the upstream tracks. Thread safe. */ void setMetadatas(const SourceMetadatas& metadatas); /** returns client timestamp to the upstream duplicating thread. */ ExtendedTimestamp getClientProxyTimestamp() const { // server - kernel difference is not true latency when drained // i.e. mServerProxy->isDrained(). ExtendedTimestamp timestamp; (void) mClientProxy->getTimestamp(×tamp); // On success, the timestamp LOCATION_SERVER and LOCATION_KERNEL // entries will be properly filled. If getTimestamp() // is unsuccessful, then a default initialized timestamp // (with mTimeNs[] filled with -1's) is returned. return timestamp; } private: status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, Loading @@ -268,6 +280,7 @@ private: bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() sp<AudioTrackClientProxy> mClientProxy; /** Attributes of the source tracks. * * This member must be accessed with mTrackMetadatasMutex taken. Loading services/audioflinger/Threads.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -3203,12 +3203,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() // 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. ExtendedTimestamp timestamp; // use private copy to fetch if (threadloop_getHalTimestamp_l(×tamp) == OK) { // We always fetch the timestamp here because often the downstream // sink will block while writing. ExtendedTimestamp timestamp; // use private copy to fetch (void) mNormalSink->getTimestamp(timestamp); // We keep track of the last valid kernel position in case we are in underrun // and the normal mixer period is the same as the fast mixer period, or there Loading Loading @@ -6096,7 +6094,22 @@ void AudioFlinger::DuplicatingThread::threadLoop_sleepTime() ssize_t AudioFlinger::DuplicatingThread::threadLoop_write() { for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->write(mSinkBuffer, writeFrames); const ssize_t actualWritten = outputTracks[i]->write(mSinkBuffer, writeFrames); // Consider the first OutputTrack for timestamp and frame counting. // The threadLoop() generally assumes writing a full sink buffer size at a time. // Here, we correct for writeFrames of 0 (a stop) or underruns because // we always claim success. if (i == 0) { const ssize_t correction = mSinkBufferSize / mFrameSize - actualWritten; ALOGD_IF(correction != 0 && writeFrames != 0, "%s: writeFrames:%u actualWritten:%zd correction:%zd mFramesWritten:%lld", __func__, writeFrames, actualWritten, correction, (long long)mFramesWritten); mFramesWritten -= correction; } // TODO: Report correction for the other output tracks and show in the dump. } mStandby = false; return (ssize_t)mSinkBufferSize; Loading services/audioflinger/Threads.h +30 −0 Original line number Diff line number Diff line Loading @@ -434,6 +434,12 @@ protected: virtual void setMasterMono_l(bool mono __unused) { } virtual bool requireMonoBlend() { return false; } // called within the threadLoop to obtain timestamp from the HAL. virtual status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp __unused) const { return INVALID_OPERATION; } friend class AudioFlinger; // for mEffectChains const type_t mType; Loading Loading @@ -1150,6 +1156,14 @@ public: return mFastMixerDumpState.mTracks[fastIndex].mUnderruns; } status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp) const override { if (mNormalSink.get() != nullptr) { return mNormalSink->getTimestamp(*timestamp); } return INVALID_OPERATION; } protected: virtual void setMasterMono_l(bool mono) { mMasterMono.store(mono); Loading Loading @@ -1314,6 +1328,22 @@ private: SortedVector < sp<OutputTrack> > mOutputTracks; public: virtual bool hasFastMixer() const { return false; } status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp) const override { if (mOutputTracks.size() > 0) { // forward the first OutputTrack's kernel information for timestamp. const ExtendedTimestamp trackTimestamp = mOutputTracks[0]->getClientProxyTimestamp(); if (trackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) { timestamp->mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = trackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]; timestamp->mPosition[ExtendedTimestamp::LOCATION_KERNEL] = trackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]; return OK; // discard server timestamp - that's ignored. } } return INVALID_OPERATION; } }; // record thread Loading services/audioflinger/Tracks.cpp +7 −3 Original line number Diff line number Diff line Loading @@ -435,7 +435,8 @@ AudioFlinger::PlaybackThread::Track::Track( } mName = TRACK_NAME_PENDING; mServerLatencySupported = thread->type() == ThreadBase::MIXER; mServerLatencySupported = thread->type() == ThreadBase::MIXER || thread->type() == ThreadBase::DUPLICATING; #ifdef TEE_SINK mTee.setId(std::string("_") + std::to_string(mThreadIoHandle) + "_" + std::to_string(mId) + Loading Loading @@ -1354,7 +1355,7 @@ void AudioFlinger::PlaybackThread::OutputTrack::stop() mActive = false; } bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames) ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames) { Buffer *pInBuffer; Buffer inBuffer; Loading Loading @@ -1443,9 +1444,12 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame mBufferQueue.add(pInBuffer); ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %zu", this, mThread.unsafe_get(), mBufferQueue.size()); // audio data is consumed (stored locally); set frameCount to 0. inBuffer.frameCount = 0; } else { ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this); // TODO: return error for this. } } } Loading @@ -1456,7 +1460,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame stop(); } return outputBufferFull; return frames - inBuffer.frameCount; // number of frames consumed. } void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const Loading Loading
services/audioflinger/PlaybackTracks.h +14 −1 Original line number Diff line number Diff line Loading @@ -244,7 +244,7 @@ public: AudioSystem::SYNC_EVENT_NONE, audio_session_t triggerSession = AUDIO_SESSION_NONE); virtual void stop(); bool write(void* data, uint32_t frames); ssize_t write(void* data, uint32_t frames); bool bufferQueueEmpty() const { return mBufferQueue.size() == 0; } bool isActive() const { return mActive; } const wp<ThreadBase>& thread() const { return mThread; } Loading @@ -252,6 +252,18 @@ public: void copyMetadataTo(MetadataInserter& backInserter) const override; /** Set the metadatas of the upstream tracks. Thread safe. */ void setMetadatas(const SourceMetadatas& metadatas); /** returns client timestamp to the upstream duplicating thread. */ ExtendedTimestamp getClientProxyTimestamp() const { // server - kernel difference is not true latency when drained // i.e. mServerProxy->isDrained(). ExtendedTimestamp timestamp; (void) mClientProxy->getTimestamp(×tamp); // On success, the timestamp LOCATION_SERVER and LOCATION_KERNEL // entries will be properly filled. If getTimestamp() // is unsuccessful, then a default initialized timestamp // (with mTimeNs[] filled with -1's) is returned. return timestamp; } private: status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, Loading @@ -268,6 +280,7 @@ private: bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() sp<AudioTrackClientProxy> mClientProxy; /** Attributes of the source tracks. * * This member must be accessed with mTrackMetadatasMutex taken. Loading
services/audioflinger/Threads.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -3203,12 +3203,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() // 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. ExtendedTimestamp timestamp; // use private copy to fetch if (threadloop_getHalTimestamp_l(×tamp) == OK) { // We always fetch the timestamp here because often the downstream // sink will block while writing. ExtendedTimestamp timestamp; // use private copy to fetch (void) mNormalSink->getTimestamp(timestamp); // We keep track of the last valid kernel position in case we are in underrun // and the normal mixer period is the same as the fast mixer period, or there Loading Loading @@ -6096,7 +6094,22 @@ void AudioFlinger::DuplicatingThread::threadLoop_sleepTime() ssize_t AudioFlinger::DuplicatingThread::threadLoop_write() { for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->write(mSinkBuffer, writeFrames); const ssize_t actualWritten = outputTracks[i]->write(mSinkBuffer, writeFrames); // Consider the first OutputTrack for timestamp and frame counting. // The threadLoop() generally assumes writing a full sink buffer size at a time. // Here, we correct for writeFrames of 0 (a stop) or underruns because // we always claim success. if (i == 0) { const ssize_t correction = mSinkBufferSize / mFrameSize - actualWritten; ALOGD_IF(correction != 0 && writeFrames != 0, "%s: writeFrames:%u actualWritten:%zd correction:%zd mFramesWritten:%lld", __func__, writeFrames, actualWritten, correction, (long long)mFramesWritten); mFramesWritten -= correction; } // TODO: Report correction for the other output tracks and show in the dump. } mStandby = false; return (ssize_t)mSinkBufferSize; Loading
services/audioflinger/Threads.h +30 −0 Original line number Diff line number Diff line Loading @@ -434,6 +434,12 @@ protected: virtual void setMasterMono_l(bool mono __unused) { } virtual bool requireMonoBlend() { return false; } // called within the threadLoop to obtain timestamp from the HAL. virtual status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp __unused) const { return INVALID_OPERATION; } friend class AudioFlinger; // for mEffectChains const type_t mType; Loading Loading @@ -1150,6 +1156,14 @@ public: return mFastMixerDumpState.mTracks[fastIndex].mUnderruns; } status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp) const override { if (mNormalSink.get() != nullptr) { return mNormalSink->getTimestamp(*timestamp); } return INVALID_OPERATION; } protected: virtual void setMasterMono_l(bool mono) { mMasterMono.store(mono); Loading Loading @@ -1314,6 +1328,22 @@ private: SortedVector < sp<OutputTrack> > mOutputTracks; public: virtual bool hasFastMixer() const { return false; } status_t threadloop_getHalTimestamp_l( ExtendedTimestamp *timestamp) const override { if (mOutputTracks.size() > 0) { // forward the first OutputTrack's kernel information for timestamp. const ExtendedTimestamp trackTimestamp = mOutputTracks[0]->getClientProxyTimestamp(); if (trackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) { timestamp->mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = trackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]; timestamp->mPosition[ExtendedTimestamp::LOCATION_KERNEL] = trackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]; return OK; // discard server timestamp - that's ignored. } } return INVALID_OPERATION; } }; // record thread Loading
services/audioflinger/Tracks.cpp +7 −3 Original line number Diff line number Diff line Loading @@ -435,7 +435,8 @@ AudioFlinger::PlaybackThread::Track::Track( } mName = TRACK_NAME_PENDING; mServerLatencySupported = thread->type() == ThreadBase::MIXER; mServerLatencySupported = thread->type() == ThreadBase::MIXER || thread->type() == ThreadBase::DUPLICATING; #ifdef TEE_SINK mTee.setId(std::string("_") + std::to_string(mThreadIoHandle) + "_" + std::to_string(mId) + Loading Loading @@ -1354,7 +1355,7 @@ void AudioFlinger::PlaybackThread::OutputTrack::stop() mActive = false; } bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames) ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames) { Buffer *pInBuffer; Buffer inBuffer; Loading Loading @@ -1443,9 +1444,12 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame mBufferQueue.add(pInBuffer); ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %zu", this, mThread.unsafe_get(), mBufferQueue.size()); // audio data is consumed (stored locally); set frameCount to 0. inBuffer.frameCount = 0; } else { ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this); // TODO: return error for this. } } } Loading @@ -1456,7 +1460,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame stop(); } return outputBufferFull; return frames - inBuffer.frameCount; // number of frames consumed. } void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const Loading