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

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

Merge "AudioFlinger: Incorporate downstream patch latency into timestamps"

parents 6d7c0f62 2dbffc2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ public:


        // Must be called under AudioFlinger::mLock
        // Must be called under AudioFlinger::mLock
        status_t getLatencyMs_l(double *latencyMs) const;
        status_t getLatencyMs_l(double *latencyMs) const;
        audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
        audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
        audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
        audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
        audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
      private:
      private:
+54 −0
Original line number Original line Diff line number Diff line
@@ -3220,6 +3220,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
    if (mType == OFFLOAD || mType == DIRECT) {
    if (mType == OFFLOAD || mType == DIRECT) {
        mTimestampVerifier.setDiscontinuityMode(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
        mTimestampVerifier.setDiscontinuityMode(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
    }
    }
    audio_utils::Statistics<double> downstreamLatencyStatMs(0.999 /* alpha */);
    audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;


    while (!exitPending())
    while (!exitPending())
    {
    {
@@ -3231,6 +3233,46 @@ bool AudioFlinger::PlaybackThread::threadLoop()


        Vector< sp<EffectChain> > effectChains;
        Vector< sp<EffectChain> > effectChains;


        // If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
        //
        // Note: we access outDevice() outside of mLock.
        if (isMsdDevice() && (outDevice() & AUDIO_DEVICE_OUT_BUS) != 0) {
            // Here, we try for the AF lock, but do not block on it as the latency
            // is more informational.
            if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
                std::vector<PatchPanel::SoftwarePatch> swPatches;
                double latencyMs;
                status_t status = INVALID_OPERATION;
                audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
                if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
                        && swPatches.size() > 0) {
                        status = swPatches[0].getLatencyMs_l(&latencyMs);
                        downstreamPatchHandle = swPatches[0].getPatchHandle();
                }
                if (downstreamPatchHandle != lastDownstreamPatchHandle) {
                    downstreamLatencyStatMs.reset();
                    lastDownstreamPatchHandle = downstreamPatchHandle;
                }
                if (status == OK) {
                    // verify downstream latency (we assume a max reasonable
                    // latency of 1 second).
                    if (latencyMs >= 0. && latencyMs <= 1000.) {
                        ALOGV("new downstream latency %lf ms", latencyMs);
                        downstreamLatencyStatMs.add(latencyMs);
                    } else {
                        ALOGD("out of range downstream latency %lf ms", latencyMs);
                    }
                }
                mAudioFlinger->mLock.unlock();
            }
        } else {
            if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
                // our device is no longer AUDIO_DEVICE_OUT_BUS, reset patch handle and stats.
                downstreamLatencyStatMs.reset();
                lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
            }
        }

        { // scope for mLock
        { // scope for mLock


            Mutex::Autolock _l(mLock);
            Mutex::Autolock _l(mLock);
@@ -3273,6 +3315,18 @@ bool AudioFlinger::PlaybackThread::threadLoop()
                    ALOGV("TS_AFTER: %d %lld %lld", id(),
                    ALOGV("TS_AFTER: %d %lld %lld", id(),
                            (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
                            (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
                            (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
                            (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);

                    // Note: Downstream latency only added if timestamp correction enabled.
                    if (downstreamLatencyStatMs.getN() > 0) { // we have latency info.
                        const int64_t newPosition =
                                timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
                                - int64_t(downstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
                        // prevent retrograde
                        timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = max(
                                newPosition,
                                (mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
                                        - mSuspendedFrames));
                    }
                }
                }


                // We always fetch the timestamp here because often the downstream
                // We always fetch the timestamp here because often the downstream