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

Commit d595b7c8 authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: multiple tracks on direct output

Fix problems when multiple tracks exist on a direct output
thread:  when multiple tracks are active, continue to update all
track states but only take into account the last track started
for audio HAL volume and mixer state control.

Bug 8388941

Change-Id: I57e6757286f41651dda99b11a5449e431812431b
parent a9cbef06
Loading
Loading
Loading
Loading
+52 −45
Original line number Diff line number Diff line
@@ -3122,16 +3122,15 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
    Vector< sp<Track> > *tracksToRemove
)
{
    sp<Track> trackToRemove;

    size_t count = mActiveTracks.size();
    mixer_state mixerStatus = MIXER_IDLE;

    // find out which tracks need to be processed
    if (mActiveTracks.size() != 0) {
        sp<Track> t = mActiveTracks[0].promote();
    for (size_t i = 0; i < count; i++) {
        sp<Track> t = mActiveTracks[i].promote();
        // The track died recently
        if (t == 0) {
            return MIXER_IDLE;
            continue;
        }

        Track* const track = t.get();
@@ -3180,7 +3179,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                }
                right = v_clamped/MAX_GAIN;
            }

            // Only consider last track started for volume and mixer state control.
            // This is the last entry in mActiveTracks unless a track underruns.
            // As we only care about the transition phase between two tracks on a
            // direct output, it is not a problem to ignore the underrun case.
            if (i == (count - 1)) {
                if (left != mLeftVolFloat || right != mRightVolFloat) {
                    mLeftVolFloat = left;
                    mRightVolFloat = right;
@@ -3205,10 +3208,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                track->mRetryCount = kMaxTrackRetriesDirect;
                mActiveTrack = t;
                mixerStatus = MIXER_TRACKS_READY;
            }
        } else {
            // clear effect chain input buffer if an active track underruns to avoid sending
            // previous audio buffer again to effects
            if (!mEffectChains.isEmpty()) {
            // clear effect chain input buffer if the last active track started underruns
            // to avoid sending previous audio buffer again to effects
            if (!mEffectChains.isEmpty() && (i == (count -1))) {
                mEffectChains[0]->clearInputBuffer();
            }

@@ -3224,33 +3228,36 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                    if (track->isStopped()) {
                        track->reset();
                    }
                    trackToRemove = track;
                    tracksToRemove->add(track);
                }
            } else {
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                // Only consider last track started for mixer state control
                if (--(track->mRetryCount) <= 0) {
                    ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
                    trackToRemove = track;
                } else {
                    tracksToRemove->add(track);
                } else if (i == (count -1)){
                    mixerStatus = MIXER_TRACKS_ENABLED;
                }
            }
        }
    }

    // FIXME merge this with similar code for removing multiple tracks
    // remove all the tracks that need to be...
    if (CC_UNLIKELY(trackToRemove != 0)) {
        tracksToRemove->add(trackToRemove);
        mActiveTracks.remove(trackToRemove);
    count = tracksToRemove->size();
    if (CC_UNLIKELY(count)) {
        for (size_t i = 0 ; i < count ; i++) {
            const sp<Track>& track = tracksToRemove->itemAt(i);
            mActiveTracks.remove(track);
            if (!mEffectChains.isEmpty()) {
                ALOGV("stopping track on chain %p for session Id: %d", mEffectChains[0].get(),
                    trackToRemove->sessionId());
                      track->sessionId());
                mEffectChains[0]->decActiveTrackCnt();
            }
        if (trackToRemove->isTerminated()) {
            removeTrack_l(trackToRemove);
            if (track->isTerminated()) {
                removeTrack_l(track);
            }
        }
    }