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

Commit 091ee7a2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Dup first haptic channel to the second when it is not provided." into...

Merge "Dup first haptic channel to the second when it is not provided." into sc-v2-dev am: 2bcfe35e am: ccb5df31

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

Change-Id: I6cb173028bbf2095949f5a6b35c9ce7777a35f9b
parents 98c24211 ccb5df31
Loading
Loading
Loading
Loading
+15 −58
Original line number Diff line number Diff line
@@ -108,15 +108,11 @@ bool AudioMixer::setChannelMasks(int name,

    if (track->mHapticChannelCount > 0) {
        track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
        track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
        track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
        track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
        track->mAdjustOutChannelCount = track->channelCount;
        track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
    } else {
        track->mAdjustInChannelCount = 0;
        track->mAdjustOutChannelCount = 0;
        track->mAdjustNonDestructiveInChannelCount = 0;
        track->mAdjustNonDestructiveOutChannelCount = 0;
        track->mKeepContractedChannels = false;
    }

@@ -131,8 +127,7 @@ bool AudioMixer::setChannelMasks(int name,
    // do it after downmix since track format may change!
    track->prepareForReformat();

    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
    track->prepareForAdjustChannels();
    track->prepareForAdjustChannels(mFrameCount);

    // Resampler channels may have changed.
    track->recreateResampler(mSampleRate);
@@ -283,48 +278,20 @@ void AudioMixer::Track::unprepareForAdjustChannels()
    }
}

status_t AudioMixer::Track::prepareForAdjustChannels()
status_t AudioMixer::Track::prepareForAdjustChannels(size_t frames)
{
    ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u",
            this, mAdjustInChannelCount, mAdjustOutChannelCount);
    unprepareForAdjustChannels();
    if (mAdjustInChannelCount != mAdjustOutChannelCount) {
        mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
                mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount));
        reconfigureBufferProviders();
    }
    return NO_ERROR;
}

void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
{
    ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
        reconfigureBufferProviders();
    }
}

status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames)
{
    ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, "
          "outChannelCount: %u, keepContractedChannels: %d",
            this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount,
            mKeepContractedChannels);
    unprepareForAdjustChannelsNonDestructive();
    if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) {
        uint8_t* buffer = mKeepContractedChannels
                ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
                        mMixerChannelCount, mMixerFormat)
                : NULL;
        mContractChannelsNonDestructiveBufferProvider.reset(
                new AdjustChannelsBufferProvider(
                        mFormat,
                        mAdjustNonDestructiveInChannelCount,
                        mAdjustNonDestructiveOutChannelCount,
                        frames,
                : nullptr;
        mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
                mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, frames,
                mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
                        buffer));
                buffer, mMixerHapticChannelCount));
        reconfigureBufferProviders();
    }
    return NO_ERROR;
@@ -332,9 +299,9 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames

void AudioMixer::Track::clearContractedBuffer()
{
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
    if (mAdjustChannelsBufferProvider.get() != nullptr) {
        static_cast<AdjustChannelsBufferProvider*>(
                mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
                mAdjustChannelsBufferProvider.get())->clearContractedFrames();
    }
}

@@ -346,10 +313,6 @@ void AudioMixer::Track::reconfigureBufferProviders()
        mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mAdjustChannelsBufferProvider.get();
    }
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
    }
    if (mReformatBufferProvider.get() != nullptr) {
        mReformatBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mReformatBufferProvider.get();
@@ -395,7 +358,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
                track->mainBuffer = valueBuf;
                ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
                if (track->mKeepContractedChannels) {
                    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
                    track->prepareForAdjustChannels(mFrameCount);
                }
                invalidate();
            }
@@ -423,7 +386,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
                track->mMixerFormat = format;
                ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
                if (track->mKeepContractedChannels) {
                    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
                    track->prepareForAdjustChannels(mFrameCount);
                }
            }
            } break;
@@ -442,8 +405,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
            if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
                track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
                track->mKeepContractedChannels = hapticPlaybackEnabled;
                track->prepareForAdjustChannelsNonDestructive(mFrameCount);
                track->prepareForAdjustChannels();
                track->prepareForAdjustChannels(mFrameCount);
            }
            } break;
        case HAPTIC_INTENSITY: {
@@ -536,8 +498,6 @@ void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider
        track->mDownmixerBufferProvider->reset();
    } else if (track->mReformatBufferProvider.get() != nullptr) {
        track->mReformatBufferProvider->reset();
    } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        track->mContractChannelsNonDestructiveBufferProvider->reset();
    } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
        track->mAdjustChannelsBufferProvider->reset();
    }
@@ -581,9 +541,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track)
    t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
    t->mMixerHapticChannelCount = 0;
    t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
    t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
    t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
    t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
    t->mAdjustOutChannelCount = t->channelCount;
    t->mKeepContractedChannels = false;
    // Check the downmixing (or upmixing) requirements.
    status_t status = t->prepareForDownmix();
@@ -594,8 +552,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track)
    // prepareForDownmix() may change mDownmixRequiresFormat
    ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
    t->prepareForReformat();
    t->prepareForAdjustChannelsNonDestructive(mFrameCount);
    t->prepareForAdjustChannels();
    t->prepareForAdjustChannels(mFrameCount);
    return OK;
}

+45 −23
Original line number Diff line number Diff line
@@ -653,7 +653,8 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames

AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
        audio_format_t format, size_t inChannelCount, size_t outChannelCount,
        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer,
        size_t contractedOutChannelCount) :
        CopyBufferProvider(
                audio_bytes_per_frame(inChannelCount, format),
                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
@@ -663,15 +664,22 @@ AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
        mOutChannelCount(outChannelCount),
        mSampleSizeInBytes(audio_bytes_per_sample(format)),
        mFrameCount(frameCount),
        mContractedChannelCount(inChannelCount - outChannelCount),
        mContractedFormat(contractedFormat),
        mContractedFormat(inChannelCount > outChannelCount
                ? contractedFormat : AUDIO_FORMAT_INVALID),
        mContractedInChannelCount(inChannelCount > outChannelCount
                ? inChannelCount - outChannelCount : 0),
        mContractedOutChannelCount(contractedOutChannelCount),
        mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)),
        mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes),
        mContractedBuffer(contractedBuffer),
        mContractedWrittenFrames(0)
{
    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
            inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)",
          this, format, inChannelCount, outChannelCount, frameCount, contractedFormat,
          contractedBuffer, contractedOutChannelCount);
    if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
        mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
        mContractedOutputFrameSize =
                audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat);
    }
}

@@ -690,7 +698,6 @@ status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer

void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    if (mInChannelCount > mOutChannelCount) {
    // For case multi to mono, adjust_channels has special logic that will mix first two input
    // channels into a single output channel. In that case, use adjust_channels_non_destructive
    // to keep only one channel data even when contracting to mono.
@@ -699,16 +706,31 @@ void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t
    if (mContractedFormat != AUDIO_FORMAT_INVALID
        && mContractedBuffer != nullptr) {
        const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
        uint8_t* oriBuf = (uint8_t*) dst + contractedIdx;
        uint8_t* buf = (uint8_t*) mContractedBuffer
                + mContractedWrittenFrames * mContractedOutputFrameSize;
        if (mContractedInChannelCount > mContractedOutChannelCount) {
            // Adjust the channels first as the contracted buffer may not have enough
            // space for the data.
            // Use adjust_channels_non_destructive to avoid mix first two channels into one single
            // output channel when it is multi to mono.
            adjust_channels_non_destructive(
                    oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount,
                    mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes);
            memcpy_by_audio_format(
                    (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
                    mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
                    mContractedChannelCount * frames);
            mContractedWrittenFrames += frames;
        }
                    buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames);
        } else {
        // Prefer expanding data from the end of each audio frame.
        adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
            // Copy the data first as the dst buffer may not have enough space for extra channel.
            memcpy_by_audio_format(
                buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames);
            // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels
            // will be duplicated with the original single input channel and all the other channels
            // will be 0-filled.
            adjust_channels(
                    buf, mContractedInChannelCount, buf, mContractedOutChannelCount,
                    mContractedSampleSizeInBytes, mContractedInputFrameSize * frames);
        }
        mContractedWrittenFrames += frames;
    }
}

+5 −16
Original line number Diff line number Diff line
@@ -80,7 +80,6 @@ private:
            mPostDownmixReformatBufferProvider.reset(nullptr);
            mDownmixerBufferProvider.reset(nullptr);
            mReformatBufferProvider.reset(nullptr);
            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
            mAdjustChannelsBufferProvider.reset(nullptr);
        }

@@ -95,10 +94,8 @@ private:
        void        unprepareForDownmix();
        status_t    prepareForReformat();
        void        unprepareForReformat();
        status_t    prepareForAdjustChannels();
        status_t    prepareForAdjustChannels(size_t frames);
        void        unprepareForAdjustChannels();
        status_t    prepareForAdjustChannelsNonDestructive(size_t frames);
        void        unprepareForAdjustChannelsNonDestructive();
        void        clearContractedBuffer();
        bool        setPlaybackRate(const AudioPlaybackRate &playbackRate);
        void        reconfigureBufferProviders();
@@ -114,24 +111,18 @@ private:
         * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
         *    channel format to another. Expanded channels are filled with zeros and put at the end
         *    of each audio frame. Contracted channels are copied to the end of the buffer.
         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
         *    data. Contracted channels could be written to given buffer.
         * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
         * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to
         *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
         *    requires reformat. For example, it may convert floating point input to
         *    PCM_16_bit if that's required by the downmixer.
         * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
         * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
         *    the number of channels required by the mixer sink.
         * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
         * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
         *    the downmixer requirements to the mixer engine input requirements.
         * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
         * 6) mTimestretchBufferProvider: Adds timestretching for playback rate
         */
        AudioBufferProvider* mInputBufferProvider;    // externally provided buffer provider.
        // TODO: combine mAdjustChannelsBufferProvider and
        // mContractChannelsNonDestructiveBufferProvider
        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
@@ -153,8 +144,6 @@ private:
        uint32_t             mMixerHapticChannelCount;
        uint32_t             mAdjustInChannelCount;
        uint32_t             mAdjustOutChannelCount;
        uint32_t             mAdjustNonDestructiveInChannelCount;
        uint32_t             mAdjustNonDestructiveOutChannelCount;
        bool                 mKeepContractedChannels;
    };

+17 −9
Original line number Diff line number Diff line
@@ -241,17 +241,22 @@ private:
// Extra expanded channels are filled with zeros and put at the end of each audio frame.
// Contracted channels are copied to the end of the output buffer(storage should be
// allocated appropriately).
// Contracted channels could be written to output buffer.
// Contracted channels could be written to output buffer and got adjusted. When the contracted
// channels are adjusted in the contracted buffer, the input channel count will be calculated
// as `inChannelCount - outChannelCount`. The output channel count is provided by caller, which
// is `contractedOutChannelCount`. Currently, adjusting contracted channels is used for audio
// coupled haptic playback. If the device supports two haptic channels while apps only provide
// single haptic channel, the second haptic channel will be duplicated with the first haptic
// channel's data. If the device supports single haptic channels while apps provide two haptic
// channels, the second channel will be contracted.
class AdjustChannelsBufferProvider : public CopyBufferProvider {
public:
    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
            size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
                    format, inChannelCount, outChannelCount,
                    frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
    // Contracted data is converted to contractedFormat and put into contractedBuffer.
    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
            size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
            void* contractedBuffer);
            size_t outChannelCount, size_t frameCount,
            audio_format_t contractedFormat = AUDIO_FORMAT_INVALID,
            void* contractedBuffer = nullptr,
            size_t contractedOutChannelCount = 0);
    //Overrides
    status_t getNextBuffer(Buffer* pBuffer) override;
    void copyFrames(void *dst, const void *src, size_t frames) override;
@@ -265,11 +270,14 @@ protected:
    const size_t         mOutChannelCount;
    const size_t         mSampleSizeInBytes;
    const size_t         mFrameCount;
    const size_t         mContractedChannelCount;
    const audio_format_t mContractedFormat;
    const size_t         mContractedInChannelCount;
    const size_t         mContractedOutChannelCount;
    const size_t         mContractedSampleSizeInBytes;
    const size_t         mContractedInputFrameSize; // contracted input frame size
    void                *mContractedBuffer;
    size_t               mContractedWrittenFrames;
    size_t               mContractedFrameSize;
    size_t               mContractedOutputFrameSize; // contracted output frame size
};
// ----------------------------------------------------------------------------
} // namespace android