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

Commit 40715983 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix secondary output under&over run"

parents 40143b19 01c7d9ee
Loading
Loading
Loading
Loading
+29 −2
Original line number Original line Diff line number Diff line
@@ -813,7 +813,33 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
                    continue;
                    continue;
                }
                }


                size_t frameCount = std::lcm(thread->frameCount(), secondaryThread->frameCount());
                size_t sourceFrameCount = thread->frameCount() * output.sampleRate
                                          / thread->sampleRate();
                size_t sinkFrameCount = secondaryThread->frameCount() * output.sampleRate
                                          / secondaryThread->sampleRate();
                // If the secondary output has just been opened, the first secondaryThread write
                // will not block as it will fill the empty startup buffer of the HAL,
                // so a second sink buffer needs to be ready for the immediate next blocking write.
                // Additionally, have a margin of one main thread buffer as the scheduling jitter
                // can reorder the writes (eg if thread A&B have the same write intervale,
                // the scheduler could schedule AB...BA)
                size_t frameCountToBeReady = 2 * sinkFrameCount + sourceFrameCount;
                // Total secondary output buffer must be at least as the read frames plus
                // the margin of a few buffers on both sides in case the
                // threads scheduling has some jitter.
                // That value should not impact latency as the secondary track is started before
                // its buffer is full, see frameCountToBeReady.
                size_t frameCount = frameCountToBeReady + 2 * (sourceFrameCount + sinkFrameCount);
                // The frameCount should also not be smaller than the secondary thread min frame
                // count
                size_t minFrameCount = AudioSystem::calculateMinFrameCount(
                            [&] { Mutex::Autolock _l(secondaryThread->mLock);
                                  return secondaryThread->latency_l(); }(),
                            secondaryThread->mNormalFrameCount,
                            secondaryThread->mSampleRate,
                            output.sampleRate,
                            input.speed);
                frameCount = std::max(frameCount, minFrameCount);


                using namespace std::chrono_literals;
                using namespace std::chrono_literals;
                auto inChannelMask = audio_channel_mask_out_to_in(input.config.channel_mask);
                auto inChannelMask = audio_channel_mask_out_to_in(input.config.channel_mask);
@@ -846,7 +872,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
                                                               patchRecord->buffer(),
                                                               patchRecord->buffer(),
                                                               patchRecord->bufferSize(),
                                                               patchRecord->bufferSize(),
                                                               outputFlags,
                                                               outputFlags,
                                                               0ns /* timeout */);
                                                               0ns /* timeout */,
                                                               frameCountToBeReady);
                status = patchTrack->initCheck();
                status = patchTrack->initCheck();
                if (status != NO_ERROR) {
                if (status != NO_ERROR) {
                    ALOGE("Secondary output patchTrack init failed: %d", status);
                    ALOGE("Secondary output patchTrack init failed: %d", status);
+11 −3
Original line number Original line Diff line number Diff line
@@ -74,7 +74,10 @@ public:
                                uid_t uid,
                                uid_t uid,
                                audio_output_flags_t flags,
                                audio_output_flags_t flags,
                                track_type type,
                                track_type type,
                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                /** default behaviour is to start when there are as many frames
                                  * ready as possible (aka. Buffer is full). */
                                size_t frameCountToBeReady = SIZE_MAX);
    virtual             ~Track();
    virtual             ~Track();
    virtual status_t    initCheck() const;
    virtual status_t    initCheck() const;


@@ -263,6 +266,8 @@ protected:
    };
    };
    sp<AudioVibrationController> mAudioVibrationController;
    sp<AudioVibrationController> mAudioVibrationController;
    sp<os::ExternalVibration>    mExternalVibration;
    sp<os::ExternalVibration>    mExternalVibration;
    /** How many frames should be in the buffer before the track is considered ready */
    const size_t        mFrameCountToBeReady;


private:
private:
    void                interceptBuffer(const AudioBufferProvider::Buffer& buffer);
    void                interceptBuffer(const AudioBufferProvider::Buffer& buffer);
@@ -382,7 +387,11 @@ public:
                                   void *buffer,
                                   void *buffer,
                                   size_t bufferSize,
                                   size_t bufferSize,
                                   audio_output_flags_t flags,
                                   audio_output_flags_t flags,
                                   const Timeout& timeout = {});
                                   const Timeout& timeout = {},
                                   size_t frameCountToBeReady = 1 /** Default behaviour is to start
                                                                    *  as soon as possible to have
                                                                    *  the lowest possible latency
                                                                    *  even if it might glitch. */);
    virtual             ~PatchTrack();
    virtual             ~PatchTrack();


            size_t      framesReady() const override;
            size_t      framesReady() const override;
@@ -402,5 +411,4 @@ public:


private:
private:
            void restartIfDisabled();
            void restartIfDisabled();

};  // end of PatchTrack
};  // end of PatchTrack
+15 −7
Original line number Original line Diff line number Diff line
@@ -508,7 +508,8 @@ AudioFlinger::PlaybackThread::Track::Track(
            uid_t uid,
            uid_t uid,
            audio_output_flags_t flags,
            audio_output_flags_t flags,
            track_type type,
            track_type type,
            audio_port_handle_t portId)
            audio_port_handle_t portId,
            size_t frameCountToBeReady)
    :   TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
    :   TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
                  // TODO: Using unsecurePointer() has some associated security pitfalls
                  // TODO: Using unsecurePointer() has some associated security pitfalls
                  //       (see declaration for details).
                  //       (see declaration for details).
@@ -531,6 +532,7 @@ AudioFlinger::PlaybackThread::Track::Track(
    mVolumeHandler(new media::VolumeHandler(sampleRate)),
    mVolumeHandler(new media::VolumeHandler(sampleRate)),
    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
    // mSinkTimestamp
    // mSinkTimestamp
    mFrameCountToBeReady(frameCountToBeReady),
    mFastIndex(-1),
    mFastIndex(-1),
    mCachedVolume(1.0),
    mCachedVolume(1.0),
    /* The track might not play immediately after being active, similarly as if its volume was 0.
    /* The track might not play immediately after being active, similarly as if its volume was 0.
@@ -833,7 +835,7 @@ void AudioFlinger::PlaybackThread::Track::interceptBuffer(
    auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
    auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
    using namespace std::chrono_literals;
    using namespace std::chrono_literals;
    // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
    // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
    ALOGD_IF(spent > 200us, "%s: took %lldus to intercept %zu tracks", __func__,
    ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
             spent.count(), mTeePatches.size());
             spent.count(), mTeePatches.size());
}
}


@@ -886,8 +888,12 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
        return true;
        return true;
    }
    }


    if (framesReady() >= mServerProxy->getBufferSizeInFrames() ||
    size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
            (mCblk->mFlags & CBLK_FORCEREADY)) {
    size_t framesToBeReady = std::min(mFrameCountToBeReady, bufferSizeInFrames);

    if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
        ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
              __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
        mFillingUpStatus = FS_FILLED;
        mFillingUpStatus = FS_FILLED;
        android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
        android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
        return true;
        return true;
@@ -1389,6 +1395,7 @@ void AudioFlinger::PlaybackThread::Track::invalidate()


void AudioFlinger::PlaybackThread::Track::disable()
void AudioFlinger::PlaybackThread::Track::disable()
{
{
    // TODO(b/142394888): the filling status should also be reset to filling
    signalClientFlag(CBLK_DISABLED);
    signalClientFlag(CBLK_DISABLED);
}
}


@@ -1766,12 +1773,14 @@ AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThr
                                                     void *buffer,
                                                     void *buffer,
                                                     size_t bufferSize,
                                                     size_t bufferSize,
                                                     audio_output_flags_t flags,
                                                     audio_output_flags_t flags,
                                                     const Timeout& timeout)
                                                     const Timeout& timeout,
                                                     size_t frameCountToBeReady)
    :   Track(playbackThread, NULL, streamType,
    :   Track(playbackThread, NULL, streamType,
              audio_attributes_t{} /* currently unused for patch track */,
              audio_attributes_t{} /* currently unused for patch track */,
              sampleRate, format, channelMask, frameCount,
              sampleRate, format, channelMask, frameCount,
              buffer, bufferSize, nullptr /* sharedBuffer */,
              buffer, bufferSize, nullptr /* sharedBuffer */,
              AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH),
              AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH,
              AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
        PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
        PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
                       *playbackThread, timeout)
                       *playbackThread, timeout)
{
{
@@ -1864,7 +1873,6 @@ void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buff
{
{
    mProxy->releaseBuffer(buffer);
    mProxy->releaseBuffer(buffer);
    restartIfDisabled();
    restartIfDisabled();
    android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
}
}


void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()