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

Commit 982a1b34 authored by Sidipotu Ashok's avatar Sidipotu Ashok Committed by Steve Kondik
Browse files

audioflinger: Enhance LPA-effect logic to handle rapid config.

-Issue:Rapid Config events cause pops/glitches, raw data
 playback.
-Rootcause1:Raw data leakage to DSP: applyEffectsOn() applies
 effects chunk by chunk in a loop, if effects change during
 this time the loop exits and this results in creation of
 a buffer in which part of it is effects processed and rest
 raw, this causes raw data to leak to DSP.
-RootCause2:Effectsthread directly works on the DSP buffers,
 while DSP is rendering from there, so that effect application
 is instantaneous and for this it gives the DSP buffers as
 output to effects chain, this means that all the effects in
 the chain update the DSP buffers one after the other, this
 can create unpredictable rendering patterns.
 RootCause1 and 2 combined seem to fragment memory with
 parts of it with effects and parts with raw data etc.
-Fix1:Dont update DSP mem unless the effects are applied
 completely on a buffer.
-Fix2:Effectschain will work on a temp scrath buffer
 instead of DSP mem and when effects are applied
 completely on this scrath buffer, memcpy this to DSP mem
 with this DSP mem is updated in one shot.
-Remove repetetive logs which clutter the logcat if
 msgs are enabled in audioflinger.

Change-Id: I9051e7b8531aa5c8cb3dcfafe0be3136a2cf0f9d
CRs-Fixed: 463880
parent b2254761
Loading
Loading
Loading
Loading
+47 −22
Original line number Diff line number Diff line
@@ -695,7 +695,8 @@ void AudioFlinger::deleteEffectSession()

// ToDo: Should we go ahead with this frameCount?
#define DEAFULT_FRAME_COUNT 1200
void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBuffer, int size)
bool AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer,
                            int16_t *outBuffer, int size, bool force)
{
    ALOGV("applyEffectsOn: inBuf %p outBuf %p size %d token %p", inBuffer, outBuffer, size, token);
    // This might be the first buffer to apply effects after effect config change
@@ -703,6 +704,12 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu
    mIsEffectConfigChanged = false;

    volatile size_t numEffects = 0;

#ifdef SRS_PROCESSING
    POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(token, AUDIO_FORMAT_PCM_16_BIT, outBuffer, size,
        mLPASampleRate, mLPANumChannels);
#endif

    if(mLPAEffectChain != NULL) {
        numEffects = mLPAEffectChain->getNumEffects();
    }
@@ -733,16 +740,17 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu
            bool isEffectEnabled = false;
            for(i = 0; i < numEffects; i++) {
                // If effect configuration is changed while applying effects do not process further
                if(mIsEffectConfigChanged) {

                if(mIsEffectConfigChanged && !force) {
                    mLPAEffectChain->unlock();
                    ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing");
                    return;
                    ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing %d",frameCount);
                    return false;
                }
                sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
                if(effect == NULL) {
                    ALOGE("getEffectFromIndex_l(%d) returned NULL ptr", i);
                    mLPAEffectChain->unlock();
                    return;
                    return false;
                }
                if(i == 0) {
                    // For the first set input and output buffers different
@@ -777,16 +785,14 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu
        }
    }

    if (!numEffects) {
    if (!numEffects && !force) {
        ALOGV("applyEffectsOn: There are no effects to be applied");
        if(inBuffer != outBuffer) {
            // No effect applied so just copy input buffer to output buffer
            memcpy(outBuffer, inBuffer, size);
        }
    }
#ifdef SRS_PROCESSING
    POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(token, AUDIO_FORMAT_PCM_16_BIT, outBuffer, size, mLPASampleRate, mLPANumChannels);
#endif
    return true;
}
#endif

@@ -6347,7 +6353,8 @@ AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFl
                                                 int output, AudioSessionDescriptor *outputDesc,
                                                 IDirectTrackClient* client, audio_output_flags_t outflag)
    : BnDirectTrack(), mIsPaused(false), mAudioFlinger(audioFlinger), mOutput(output), mOutputDesc(outputDesc),
      mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag)
      mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag),
      mEffectsThreadScratchBuffer(NULL)
{
#ifdef SRS_PROCESSING
    ALOGD("SRS_Processing - DirectAudioTrack - OutNotify_Init: %p TID %d\n", this, gettid());
@@ -6445,9 +6452,11 @@ ssize_t AudioFlinger::DirectAudioTrack::write(const void *buffer, size_t size) {
        memcpy((char *) buf.localBuf, (char *)buffer, size);
        buf.bytesToWrite = size;
        mEffectsPool.push_back(buf);
        mAudioFlinger->applyEffectsOn(static_cast<void *>(this), (int16_t*)buf.localBuf,(int16_t*)buffer,(int)size);
        mAudioFlinger->applyEffectsOn(static_cast<void *>(this),
            (int16_t*)buf.localBuf, (int16_t*)buffer, (int)size, true);
        mEffectLock.unlock();
    }
    ALOGV("out of Writing to AudioSessionOut");
    return mOutputDesc->stream->write(mOutputDesc->stream, buffer, size);
}

@@ -6521,6 +6530,10 @@ void AudioFlinger::DirectAudioTrack::allocateBufPool() {

        ALOGV("The MEM that is allocated buffer is %x, size %d",(unsigned int)dsp_buf,nSize);
    }

    mEffectsThreadScratchBuffer = malloc(nSize);
    ALOGV("effectsThreadScratchBuffer = %x",mEffectsThreadScratchBuffer);

    free(buf);
}

@@ -6539,6 +6552,9 @@ void AudioFlinger::DirectAudioTrack::deallocateBufPool() {
        ALOGV("Removing from bufpool");
        mBufPool.erase(it);
    }

    free(mEffectsThreadScratchBuffer);
    mEffectsThreadScratchBuffer = NULL;
}

status_t AudioFlinger::DirectAudioTrack::onTransact(
@@ -6569,13 +6585,22 @@ void AudioFlinger::DirectAudioTrack::EffectsThreadEntry() {
            if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
                for ( List<BufferInfo>::iterator it = mEffectsPool.begin();
                      it != mEffectsPool.end(); it++) {
                    ALOGV("Apply effects on the buffer dspbuf %p, mEffectsPool.size() %d",
                             it->dspBuf,mEffectsPool.size());
                    mAudioFlinger->applyEffectsOn(static_cast<void *>(this),
                    ALOGV("ete: calling applyEffectsOn buff %x",it->localBuf);
                    bool isEffectsApplied = mAudioFlinger->applyEffectsOn(
                                    static_cast<void *>(this),
                                    (int16_t *)it->localBuf,
                                                  (int16_t *)it->dspBuf,
                                                  it->bytesToWrite);
                                    (int16_t *)mEffectsThreadScratchBuffer,
                                    it->bytesToWrite,
                                    false);
                    if (isEffectsApplied == true){
                        ALOGV("ete:dsp updated for local buf %x",it->localBuf);
                        memcpy(it->dspBuf, mEffectsThreadScratchBuffer, it->bytesToWrite);
                    }
                    else
                        ALOGV("ete:dsp updated for local buf %x SKIPPED",it->localBuf);

                    if (mEffectConfigChanged) {
                        ALOGE("ete:effects changed, abort effects application");
                        break;
                    }
            }
@@ -9530,7 +9555,7 @@ status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, in
        } else {
            channels = AUDIO_CHANNEL_OUT_STEREO;
        }
        ALOGV("%s: LPA ON - channels %d", __func__, channels);
//        ALOGV("%s: LPA ON - channels %d", __func__, channels);
    } else {
        if (thread->channelCount() == 1) {
            channels = AUDIO_CHANNEL_OUT_MONO;
@@ -9588,8 +9613,8 @@ status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, in
        mConfig.inputCfg.buffer.frameCount = thread->frameCount();
    mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;

    ALOGV("configure() %p thread %p buffer %p framecount %d",
            this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
//    ALOGV("configure() %p thread %p buffer %p framecount %d",
//            this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);

    status_t cmdStatus;
    uint32_t size = sizeof(int);
@@ -10278,7 +10303,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
        (cmdCode == EFFECT_CMD_SET_VOLUME) || (cmdCode == EFFECT_CMD_SET_AUDIO_MODE)) ) {
        // Notify Direct track for the change in Effect module
        // TODO: check if it is required to send mLPAHandle
        ALOGV("Notifying Direct Track for the change in effect config");
        ALOGV("Notifying Direct Track for the change in effect config %d", cmdCode);
        mClient->audioFlinger()->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
    }
#endif
+4 −2
Original line number Diff line number Diff line
@@ -245,10 +245,11 @@ public:
                                uint32_t flags);

#ifdef QCOM_HARDWARE
    void applyEffectsOn(void *token,
    bool applyEffectsOn(void *token,
                        int16_t *buffer1,
                        int16_t *buffer2,
                        int size);
                        int size,
                        bool force);
#endif

    // end of IAudioFlinger interface
@@ -1485,6 +1486,7 @@ private:
        };
        List<BufferInfo> mBufPool;
        List<BufferInfo> mEffectsPool;
        void *mEffectsThreadScratchBuffer;

        void allocateBufPool();
        void deallocateBufPool();