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

Commit 565b4c8f authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

Merge "audioflinger: Add session effects on spatializer mixer" into sc-v2-dev am: 3de17646

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/16149448

Change-Id: Ic69e2dddad57d729d0406390d2244ce52f7e3f56
parents 71499069 3de17646
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2574,10 +2574,15 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t mo
            //TODO: b/193496180 use spatializer flag at audio HAL when available
            if (flags == (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST
                                                    | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
#ifdef MULTICHANNEL_EFFECT_CHAIN
                thread = new SpatializerThread(this, outputStream, *output,
                                                    mSystemReady, mixerConfig);
                ALOGD("openOutput_l() created virtualizer output: ID %d thread %p",
                ALOGD("openOutput_l() created spatializer output: ID %d thread %p",
                      *output, thread.get());
#else
                ALOGE("openOutput_l() cannot create spatializer thread "
                        "without #define MULTICHANNEL_EFFECT_CHAIN");
#endif
            } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
                thread = new OffloadThread(this, outputStream, *output, mSystemReady);
                ALOGV("openOutput_l() created offload output: ID %d thread %p",
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ public:
    bool isOffload() const override { return false; }
    bool isOffloadOrDirect() const override { return false; }
    bool isOffloadOrMmap() const override { return false; }
    bool isSpatializer() const override { return false; }

    uint32_t  sampleRate() const override { return 0; }
    audio_channel_mask_t inChannelMask(int id __unused) const override {
+158 −113
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@
#include "Configuration.h"
#include <utils/Log.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_dynamicsprocessing.h>
#include <system/audio_effects/effect_hapticgenerator.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_spatializer.h>
#include <system/audio_effects/effect_visualizer.h>
#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
@@ -2231,11 +2233,9 @@ status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
{
    effect_descriptor_t desc = effect->desc();
    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;

    effect->setCallback(mEffectCallback);

    effect_descriptor_t desc = effect->desc();
    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        // Auxiliary effects are inserted at the beginning of mEffects vector as
        // they are processed first and accumulated in chain input buffer
@@ -2263,6 +2263,59 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
        // by insert effects
        effect->setOutBuffer(mInBuffer);
    } else {
        ssize_t idx_insert = getInsertIndex(desc);
        if (idx_insert < 0) {
            return INVALID_OPERATION;
        }

        size_t previousSize = mEffects.size();
        mEffects.insertAt(effect, idx_insert);

        effect->configure();

        // - By default:
        //   All effects read samples from chain input buffer.
        //   The last effect in the chain, writes samples to chain output buffer,
        //   otherwise to chain input buffer
        // - In the OUTPUT_STAGE chain of a spatializer mixer thread:
        //   The spatializer effect (first effect) reads samples from the input buffer
        //   and writes samples to the output buffer.
        //   All other effects read and writes samples to the output buffer
        if (mEffectCallback->isSpatializer()
                && mSessionId == AUDIO_SESSION_OUTPUT_STAGE) {
            effect->setOutBuffer(mOutBuffer);
            if (idx_insert == 0) {
                if (previousSize != 0) {
                    mEffects[1]->configure();
                    mEffects[1]->setInBuffer(mOutBuffer);
                    mEffects[1]->updateAccessMode();      // reconfig if neeeded.
                }
                effect->setInBuffer(mInBuffer);
            } else {
                effect->setInBuffer(mOutBuffer);
            }
        } else {
            effect->setInBuffer(mInBuffer);
            if (idx_insert == previousSize) {
                if (idx_insert != 0) {
                    mEffects[idx_insert-1]->configure();
                    mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
                    mEffects[idx_insert - 1]->updateAccessMode();      // reconfig if neeeded.
                }
                effect->setOutBuffer(mOutBuffer);
            } else {
                effect->setOutBuffer(mInBuffer);
            }
        }
        ALOGV("%s effect %p, added in chain %p at rank %zu",
                __func__, effect.get(), this, idx_insert);
    }
    effect->configure();

    return NO_ERROR;
}

ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
    // Insert effects are inserted at the end of mEffects vector as they are processed
    //  after track and auxiliary effects.
    // Insert effect order as a function of indicated preference:
@@ -2275,12 +2328,20 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
    //  else if EFFECT_FLAG_INSERT_ANY insert after first or before last
    // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
    // already present
    // Spatializer or Downmixer effects are inserted in first position because
    // they adapt the channel count for all other effects in the chain
    if ((memcmp(&desc.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0)
            || (memcmp(&desc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0)) {
        return 0;
    }

    size_t size = mEffects.size();
        size_t idx_insert = size;
    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
    ssize_t idx_insert;
    ssize_t idx_insert_first = -1;
    ssize_t idx_insert_last = -1;

    idx_insert = size;
    for (size_t i = 0; i < size; i++) {
        effect_descriptor_t d = mEffects[i]->desc();
        uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
@@ -2289,9 +2350,9 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
            // check invalid effect chaining combinations
            if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
                iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
                    ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s",
                            desc.name, d.name);
                    return INVALID_OPERATION;
                ALOGW("%s could not insert effect %s: exclusive conflict with %s",
                        __func__, desc.name, d.name);
                return -1;
            }
            // remember position of first insert effect and by default
            // select this as insert position for new effect
@@ -2324,34 +2385,7 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
            idx_insert = idx_insert_first + 1;
        }
    }

        mEffects.insertAt(effect, idx_insert);

        effect->configure();

        // always read samples from chain input buffer
        effect->setInBuffer(mInBuffer);

        // if last effect in the chain, output samples to chain
        // output buffer, otherwise to chain input buffer
        if (idx_insert == size) {
            if (idx_insert != 0) {
                // update channel mask before setting output buffer.
                mEffects[idx_insert - 1]->configure();
                mEffects[idx_insert - 1]->setOutBuffer(mInBuffer); // set output buffer
                mEffects[idx_insert - 1]->updateAccessMode();      // reconfig if neeeded.
            }
            effect->setOutBuffer(mOutBuffer);
        } else {
            effect->setOutBuffer(mInBuffer);
        }

        ALOGV("addEffect_l() effect %p, added in chain %p at rank %zu", effect.get(), this,
                idx_insert);
    }
    effect->configure();

    return NO_ERROR;
    return idx_insert;
}

// removeEffect_l() must be called with ThreadBase::mLock held
@@ -2935,27 +2969,26 @@ bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
}

bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
        return false;
    }
    return t->type() == ThreadBase::OFFLOAD;
    return mThreadType == ThreadBase::OFFLOAD;
}

bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
        return false;
    }
    return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::DIRECT;
    return mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT;
}

bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
    switch (mThreadType) {
    case ThreadBase::OFFLOAD:
    case ThreadBase::MMAP_PLAYBACK:
    case ThreadBase::MMAP_CAPTURE:
        return true;
    default:
        return false;
    }
    return t->isOffloadOrMmap();
}

bool AudioFlinger::EffectChain::EffectCallback::isSpatializer() const {
    return mThreadType == ThreadBase::SPATIALIZER;
}

uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
@@ -2976,46 +3009,58 @@ audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::inChannelMask(in
        return AUDIO_CHANNEL_NONE;
    }

    if (c->sessionId() != AUDIO_SESSION_OUTPUT_STAGE
            || c->isFirstEffect(id)) {
    if (mThreadType == ThreadBase::SPATIALIZER) {
        if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
            if (c->isFirstEffect(id)) {
                return t->mixerChannelMask();
            } else {
                return t->channelMask();
            }
        } else if (!audio_is_global_session(c->sessionId())) {
            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
                return t->mixerChannelMask();
            } else {
                return t->channelMask();
            }
        } else {
            return t->channelMask();
        }
    } else {
        return t->channelMask();
    }
}

uint32_t AudioFlinger::EffectChain::EffectCallback::inChannelCount(int id) const {
    return audio_channel_count_from_out_mask(inChannelMask(id));
}

audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::outChannelMask() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
        return 0;
        return AUDIO_CHANNEL_NONE;
    }
    sp<EffectChain> c = chain().promote();
    if (c == nullptr) {
        return 0;
        return AUDIO_CHANNEL_NONE;
    }

    if (c->sessionId() != AUDIO_SESSION_OUTPUT_STAGE
            || c->isFirstEffect(id)) {
        return audio_channel_count_from_out_mask(t->mixerChannelMask());
    if (mThreadType == ThreadBase::SPATIALIZER) {
        if (!audio_is_global_session(c->sessionId())) {
            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
                return t->mixerChannelMask();
            } else {
        return t->channelCount();
    }
                return t->channelMask();
            }

audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::outChannelMask() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
        return AUDIO_CHANNEL_NONE;
        } else {
            return t->channelMask();
        }
    } else {
        return t->channelMask();
    }
}

uint32_t AudioFlinger::EffectChain::EffectCallback::outChannelCount() const {
    sp<ThreadBase> t = thread().promote();
    if (t == nullptr) {
        return 0;
    }
    return t->channelCount();
    return audio_channel_count_from_out_mask(outChannelMask());
}

audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
+8 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ public:
    virtual bool isOffload() const = 0;
    virtual bool isOffloadOrDirect() const = 0;
    virtual bool isOffloadOrMmap() const = 0;
    virtual bool isSpatializer() const = 0;
    virtual uint32_t sampleRate() const = 0;
    virtual audio_channel_mask_t inChannelMask(int id) const = 0;
    virtual uint32_t inChannelCount(int id) const = 0;
@@ -576,6 +577,7 @@ private:
        bool isOffload() const override;
        bool isOffloadOrDirect() const override;
        bool isOffloadOrMmap() const override;
        bool isSpatializer() const override;

        uint32_t sampleRate() const override;
        audio_channel_mask_t inChannelMask(int id) const override;
@@ -608,14 +610,16 @@ private:

        wp<ThreadBase> thread() const { return mThread.load(); }

        void setThread(const wp<ThreadBase>& thread) {
        void setThread(const sp<ThreadBase>& thread) {
            mThread = thread;
            mThreadType = thread->type();
        }

    private:
        const wp<EffectChain> mChain;
        mediautils::atomic_wp<ThreadBase> mThread;
        AudioFlinger &mAudioFlinger;  // implementation detail: outer instance always exists.
        ThreadBase::type_t mThreadType;
    };

    friend class AudioFlinger;  // for mThread, mEffects
@@ -652,6 +656,8 @@ private:

    void setVolumeForOutput_l(uint32_t left, uint32_t right);

    ssize_t getInsertIndex(const effect_descriptor_t& desc);

    mutable  Mutex mLock;        // mutex protecting effect list
             Vector< sp<EffectModule> > mEffects; // list of effect modules
             audio_session_t mSessionId; // audio session ID
@@ -732,6 +738,7 @@ private:
        bool isOffload() const override { return false; }
        bool isOffloadOrDirect() const override { return false; }
        bool isOffloadOrMmap() const override { return false; }
        bool isSpatializer() const override { return false; }

        uint32_t sampleRate() const override;
        audio_channel_mask_t inChannelMask(int id) const override;
+0 −3
Original line number Diff line number Diff line
@@ -196,9 +196,6 @@ public:
    audio_output_flags_t getOutputFlags() const { return mFlags; }
    float getSpeed() const { return mSpeed; }

    bool canBeSpatialized() const { return (mAttr.flags
            & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) == 0; }

protected:
    // for numerous
    friend class PlaybackThread;
Loading