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

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

Merge changes I52ec5b02,I376656e3,I3f005583,Icba4e33d

* changes:
  Use PassthruPatchRecord for DIRECT to DIRECT connections
  Add PassthruPatchRecord for low latency software patches
  Abstract access to HAL stream via Source in RecordThread
  Move PlaybackThread::Track::writeFrames to PatchRecord
parents fb1fb155 9515fc85
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -547,6 +547,16 @@ private:
        bool        mute;
    };

    // Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
    struct Source
    {
        virtual ~Source() = default;
        // The following methods have the same signatures as in StreamHalInterface.
        virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
        virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
        virtual status_t standby() = 0;
    };

    // --- PlaybackThread ---
#ifdef FLOAT_EFFECT_CHAIN
#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
@@ -749,7 +759,7 @@ using effect_buffer_t = int16_t;
    // For emphasis, we could also make all pointers to them be "const *",
    // but that would clutter the code unnecessarily.

    struct AudioStreamIn {
    struct AudioStreamIn : public Source {
        AudioHwDevice* const audioHwDev;
        sp<StreamInHalInterface> stream;
        audio_input_flags_t flags;
@@ -758,6 +768,13 @@ using effect_buffer_t = int16_t;

        AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
            audioHwDev(dev), stream(in), flags(flags) {}
        status_t read(void *buffer, size_t bytes, size_t *read) override {
            return stream->read(buffer, bytes, read);
        }
        status_t getCapturePosition(int64_t *frames, int64_t *time) override {
            return stream->getCapturePosition(frames, time);
        }
        status_t standby() override { return stream->standby(); }
    };

    struct TeePatch {
+26 −14
Original line number Diff line number Diff line
@@ -483,19 +483,6 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel)
        // Fast mode is not available in this case.
        inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST);
    }
    sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord(
                                             mRecord.thread().get(),
                                             sampleRate,
                                             inChannelMask,
                                             format,
                                             frameCount,
                                             NULL,
                                             (size_t)0 /* bufferSize */,
                                             inputFlags);
    status = mRecord.checkTrack(tempRecordTrack.get());
    if (status != NO_ERROR) {
        return status;
    }

    audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ?
            mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE;
@@ -512,9 +499,34 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel)
        outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST);
    }

    sp<RecordThread::PatchRecord> tempRecordTrack;
    if ((inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
        tempRecordTrack = new RecordThread::PassthruPatchRecord(
                                                 mRecord.thread().get(),
                                                 sampleRate,
                                                 inChannelMask,
                                                 format,
                                                 frameCount,
                                                 inputFlags);
    } else {
        tempRecordTrack = new RecordThread::PatchRecord(
                                                 mRecord.thread().get(),
                                                 sampleRate,
                                                 inChannelMask,
                                                 format,
                                                 frameCount,
                                                 nullptr,
                                                 (size_t)0 /* bufferSize */,
                                                 inputFlags);
    }
    status = mRecord.checkTrack(tempRecordTrack.get());
    if (status != NO_ERROR) {
        return status;
    }

    // create a special playback track to render to playback thread.
    // this track is given the same buffer as the PatchRecord buffer
    sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack(
    sp<PlaybackThread::PatchTrack> tempPatchTrack = new PlaybackThread::PatchTrack(
                                           mPlayback.thread().get(),
                                           streamType,
                                           sampleRate,
+2 −2
Original line number Diff line number Diff line
@@ -266,8 +266,6 @@ protected:

private:
    void                interceptBuffer(const AudioBufferProvider::Buffer& buffer);
    /** Write the source data in the buffer provider. @return written frame count. */
    size_t              writeFrames(AudioBufferProvider* dest, const void* src, size_t frameCount);
    template <class F>
    void                forEachTeePatchTrack(F f) {
        for (auto& tp : mTeePatches) { f(tp.patchTrack); }
@@ -387,6 +385,8 @@ public:
                                   const Timeout& timeout = {});
    virtual             ~PatchTrack();

            size_t      framesReady() const override;

    virtual status_t    start(AudioSystem::sync_event_t event =
                                    AudioSystem::SYNC_EVENT_NONE,
                             audio_session_t triggerSession = AUDIO_SESSION_NONE);
+69 −0
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ public:
                const Timeout& timeout = {});
    virtual             ~PatchRecord();

    virtual Source* getSource() { return nullptr; }

    // AudioBufferProvider interface
    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
    virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -175,4 +177,71 @@ public:
    virtual status_t    obtainBuffer(Proxy::Buffer *buffer,
                                     const struct timespec *timeOut = NULL);
    virtual void        releaseBuffer(Proxy::Buffer *buffer);

    size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) {
        return writeFrames(this, src, frameCount, frameSize);
    }

protected:
    /** Write the source data into the buffer provider. @return written frame count. */
    static size_t writeFrames(AudioBufferProvider* dest, const void* src,
            size_t frameCount, size_t frameSize);

};  // end of PatchRecord

class PassthruPatchRecord : public PatchRecord, public Source {
public:
    PassthruPatchRecord(RecordThread *recordThread,
                        uint32_t sampleRate,
                        audio_channel_mask_t channelMask,
                        audio_format_t format,
                        size_t frameCount,
                        audio_input_flags_t flags);

    Source* getSource() override { return static_cast<Source*>(this); }

    // Source interface
    status_t read(void *buffer, size_t bytes, size_t *read) override;
    status_t getCapturePosition(int64_t *frames, int64_t *time) override;
    status_t standby() override;

    // AudioBufferProvider interface
    // This interface is used by RecordThread to pass the data obtained
    // from HAL or other source to the client. PassthruPatchRecord receives
    // the data in 'obtainBuffer' so these calls are stubbed out.
    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
    void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;

    // PatchProxyBufferProvider interface
    // This interface is used from DirectOutputThread to acquire data from HAL.
    bool producesBufferOnDemand() const override { return true; }
    status_t obtainBuffer(Proxy::Buffer *buffer, const struct timespec *timeOut = nullptr) override;
    void releaseBuffer(Proxy::Buffer *buffer) override;

private:
    // This is to use with PatchRecord::writeFrames
    struct PatchRecordAudioBufferProvider : public AudioBufferProvider {
        explicit PatchRecordAudioBufferProvider(PassthruPatchRecord& passthru) :
                mPassthru(passthru) {}
        status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override {
            return mPassthru.PatchRecord::getNextBuffer(buffer);
        }
        void releaseBuffer(AudioBufferProvider::Buffer* buffer) override {
            return mPassthru.PatchRecord::releaseBuffer(buffer);
        }
    private:
        PassthruPatchRecord& mPassthru;
    };

    sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);

    PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
    std::unique_ptr<void, decltype(free)*> mSinkBuffer;  // frame size aligned continuous buffer
    std::unique_ptr<void, decltype(free)*> mStubBuffer;  // buffer used for AudioBufferProvider
    size_t mUnconsumedFrames = 0;
    std::mutex mReadLock;
    std::condition_variable mReadCV;
    size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
    status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
    int64_t mLastReadFrames = 0;  // accessed on RecordThread only
};
+10 −3
Original line number Diff line number Diff line
@@ -6679,6 +6679,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
                                         ) :
    ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
    mInput(input),
    mSource(mInput),
    mActiveTracks(&this->mLocalLog),
    mRsmpInBuffer(NULL),
    // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
@@ -7131,7 +7132,7 @@ reacquire_wakelock:
        } else {
            ATRACE_BEGIN("read");
            size_t bytesRead;
            status_t result = mInput->stream->read(
            status_t result = mSource->read(
                    (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
            ATRACE_END();
            if (result < 0) {
@@ -7153,7 +7154,7 @@ reacquire_wakelock:
            int64_t position, time;
            if (mStandby) {
                mTimestampVerifier.discontinuity();
            } else if (mInput->stream->getCapturePosition(&position, &time) == NO_ERROR
            } else if (mSource->getCapturePosition(&position, &time) == NO_ERROR
                    && time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {

                mTimestampVerifier.add(position, time, mSampleRate);
@@ -7434,7 +7435,7 @@ void AudioFlinger::RecordThread::inputStandBy()
            sq->end(false /*didModify*/);
        }
    }
    status_t result = mInput->stream->standby();
    status_t result = mSource->standby();
    ALOGE_IF(result != OK, "Error when putting input stream into standby: %d", result);

    // If going into standby, flush the pipe source.
@@ -8420,11 +8421,17 @@ void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
{
    Mutex::Autolock _l(mLock);
    mTracks.add(record);
    if (record->getSource()) {
        mSource = record->getSource();
    }
}

void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
{
    Mutex::Autolock _l(mLock);
    if (mSource == record->getSource()) {
        mSource = mInput;
    }
    destroyTrack_l(record);
}

Loading