Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8f5443c authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "AudioFlinger: Add latency information for duplicating threads"

parents 7e19897b 1c86ebe1
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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; }
@@ -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(&timestamp);
                            // 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,
@@ -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.
+18 −5
Original line number Diff line number Diff line
@@ -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(&timestamp) == 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
@@ -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;
+30 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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
+7 −3
Original line number Diff line number Diff line
@@ -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) +
@@ -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;
@@ -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.
            }
        }
    }
@@ -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