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

Commit cf1bbf3a authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "Enable FastTrack timestamps" into nyc-dev

parents 56d65dc0 6ae5843c
Loading
Loading
Loading
Loading
+15 −1
Original line number Original line Diff line number Diff line
@@ -79,7 +79,7 @@ struct ExtendedTimestamp {


    // Returns the best timestamp as judged from the closest-to-hw stage in the
    // Returns the best timestamp as judged from the closest-to-hw stage in the
    // pipeline with a valid timestamp.
    // pipeline with a valid timestamp.
    int getBestTimestamp(int64_t *position, int64_t *time, int timebase) {
    status_t getBestTimestamp(int64_t *position, int64_t *time, int timebase) const {
        if (position == nullptr || time == nullptr
        if (position == nullptr || time == nullptr
                || timebase < 0 || timebase >= TIMEBASE_MAX) {
                || timebase < 0 || timebase >= TIMEBASE_MAX) {
            return BAD_VALUE;
            return BAD_VALUE;
@@ -97,6 +97,20 @@ struct ExtendedTimestamp {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }


    status_t getBestTimestamp(AudioTimestamp *timestamp) const {
        if (timestamp == nullptr) {
            return BAD_VALUE;
        }
        int64_t position, time;
        if (getBestTimestamp(&position, &time, TIMEBASE_MONOTONIC) == OK) {
            timestamp->mPosition = position;
            timestamp->mTime.tv_sec = time / 1000000000;
            timestamp->mTime.tv_nsec = time - timestamp->mTime.tv_sec * 1000000000LL;
            return OK;
        }
        return INVALID_OPERATION;
    }

    // convert fields to a printable string
    // convert fields to a printable string
    std::string toString() {
    std::string toString() {
        std::stringstream ss;
        std::stringstream ss;
+34 −37
Original line number Original line Diff line number Diff line
@@ -315,6 +315,19 @@ public:
    // See documentation for AudioTrack.setBufferSizeInFrames()
    // See documentation for AudioTrack.setBufferSizeInFrames()
    size_t      setBufferSizeInFrames(size_t requestedSize);
    size_t      setBufferSizeInFrames(size_t requestedSize);


    status_t    getTimestamp(ExtendedTimestamp *timestamp) {
        if (timestamp == nullptr) {
            return BAD_VALUE;
        }
        (void) mTimestampObserver.poll(mTimestamp);
        *timestamp = mTimestamp;
        return OK;
    }

    void        clearTimestamp() {
        mTimestamp.clear();
    }

protected:
protected:
    // This is set by AudioTrack.setBufferSizeInFrames().
    // This is set by AudioTrack.setBufferSizeInFrames().
    // A write will not fill the buffer above this limit.
    // A write will not fill the buffer above this limit.
@@ -322,6 +335,12 @@ protected:


private:
private:
    Modulo<uint32_t> mEpoch;
    Modulo<uint32_t> mEpoch;

    // The shared buffer contents referred to by the timestamp observer
    // is initialized when the server proxy created.  A local zero timestamp
    // is initialized by the client constructor.
    ExtendedTimestampQueue::Observer mTimestampObserver;
    ExtendedTimestamp mTimestamp; // initialized by constructor
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -333,7 +352,9 @@ public:
            size_t frameSize, bool clientInServer = false)
            size_t frameSize, bool clientInServer = false)
        : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
        : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
          clientInServer),
          clientInServer),
          mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { }
          mPlaybackRateMutator(&cblk->mPlaybackRateQueue) {
    }

    virtual ~AudioTrackClientProxy() { }
    virtual ~AudioTrackClientProxy() { }


    // No barriers on the following operations, so the ordering of loads/stores
    // No barriers on the following operations, so the ordering of loads/stores
@@ -431,23 +452,9 @@ public:
    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
            size_t frameSize)
            size_t frameSize)
        : ClientProxy(cblk, buffers, frameCount, frameSize,
        : ClientProxy(cblk, buffers, frameCount, frameSize,
            false /*isOut*/, false /*clientInServer*/)
            false /*isOut*/, false /*clientInServer*/) { }
        , mTimestampObserver(&cblk->mExtendedTimestampQueue) { }
    ~AudioRecordClientProxy() { }
    ~AudioRecordClientProxy() { }


    status_t    getTimestamp(ExtendedTimestamp *timestamp) {
        if (timestamp == nullptr) {
            return BAD_VALUE;
        }
        (void) mTimestampObserver.poll(mTimestamp);
        *timestamp = mTimestamp;
        return OK;
    }

    void        clearTimestamp() {
        mTimestamp.clear();
    }

    // Advances the client read pointer to the server write head pointer
    // Advances the client read pointer to the server write head pointer
    // effectively flushing the client read buffer. The effect is
    // effectively flushing the client read buffer. The effect is
    // instantaneous. Returns the number of frames flushed.
    // instantaneous. Returns the number of frames flushed.
@@ -457,13 +464,6 @@ public:
        android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront);
        android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront);
        return (Modulo<int32_t>(rear) - front).unsignedValue();
        return (Modulo<int32_t>(rear) - front).unsignedValue();
    }
    }

private:
    // The shared buffer contents referred to by the timestamp observer
    // is initialized when the server proxy created.  A local zero timestamp
    // is initialized by the client constructor.
    ExtendedTimestampQueue::Observer mTimestampObserver;
    ExtendedTimestamp mTimestamp; // initialized by constructor
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -509,10 +509,20 @@ public:
    //  buffer->mRaw is NULL.
    //  buffer->mRaw is NULL.
    virtual void        releaseBuffer(Buffer* buffer);
    virtual void        releaseBuffer(Buffer* buffer);


    // Return the total number of frames that AudioFlinger has obtained and released
    virtual int64_t     framesReleased() const { return mReleased; }

    // Expose timestamp to client proxy. Should only be called by a single thread.
    virtual void        setTimestamp(const ExtendedTimestamp &timestamp) {
        mTimestampMutator.push(timestamp);
    }

protected:
protected:
    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
    int64_t     mReleased;      // our copy of cblk->mServer, at 64 bit resolution
    int64_t     mReleased;      // our copy of cblk->mServer, at 64 bit resolution

    ExtendedTimestampQueue::Mutator mTimestampMutator;
};
};


// Proxy used by AudioFlinger for servicing AudioTrack
// Proxy used by AudioFlinger for servicing AudioTrack
@@ -556,9 +566,6 @@ public:
    // and thus which resulted in an underrun.
    // and thus which resulted in an underrun.
    virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
    virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }


    // Return the total number of frames that AudioFlinger has obtained and released
    virtual size_t      framesReleased() const { return mReleased; }

    // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
    // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
    AudioPlaybackRate getPlaybackRate();
    AudioPlaybackRate getPlaybackRate();


@@ -611,20 +618,10 @@ class AudioRecordServerProxy : public ServerProxy {
public:
public:
    AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
            size_t frameSize, bool clientInServer)
            size_t frameSize, bool clientInServer)
        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer)
        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
        , mTimestampMutator(&cblk->mExtendedTimestampQueue) { }


    // Return the total number of frames that AudioFlinger has obtained and released
    virtual int64_t     framesReleased() const { return mReleased; }

    // Expose timestamp to client proxy. Should only be called by a single thread.
    virtual void        setExtendedTimestamp(const ExtendedTimestamp &timestamp) {
                            mTimestampMutator.push(timestamp);
                        }
protected:
protected:
    virtual ~AudioRecordServerProxy() { }
    virtual ~AudioRecordServerProxy() { }

    ExtendedTimestampQueue::Mutator       mTimestampMutator;
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
+19 −7
Original line number Original line Diff line number Diff line
@@ -528,12 +528,14 @@ status_t AudioTrack::start()
        mTimestampStartupGlitchReported = false;
        mTimestampStartupGlitchReported = false;
        mRetrogradeMotionReported = false;
        mRetrogradeMotionReported = false;


        // If previousState == STATE_STOPPED, we reactivate markers (mMarkerPosition != 0)
        // If previousState == STATE_STOPPED, we clear the timestamp so that it
        // needs a new server push. We also reactivate markers (mMarkerPosition != 0)
        // as the position is reset to 0. This is legacy behavior. This is not done
        // as the position is reset to 0. This is legacy behavior. This is not done
        // in stop() to avoid a race condition where the last marker event is issued twice.
        // in stop() to avoid a race condition where the last marker event is issued twice.
        // Note: the if is technically unnecessary because previousState == STATE_FLUSHED
        // Note: the if is technically unnecessary because previousState == STATE_FLUSHED
        // is only for streaming tracks, and mMarkerReached is already set to false.
        // is only for streaming tracks, and mMarkerReached is already set to false.
        if (previousState == STATE_STOPPED) {
        if (previousState == STATE_STOPPED) {
            mProxy->clearTimestamp(); // need new server push for valid timestamp
            mMarkerReached = false;
            mMarkerReached = false;
        }
        }


@@ -2169,11 +2171,6 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
    // Set false here to cover all the error return cases.
    // Set false here to cover all the error return cases.
    mPreviousTimestampValid = false;
    mPreviousTimestampValid = false;


    // FIXME not implemented for fast tracks; should use proxy and SSQ
    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
        return INVALID_OPERATION;
    }

    switch (mState) {
    switch (mState) {
    case STATE_ACTIVE:
    case STATE_ACTIVE:
    case STATE_PAUSED:
    case STATE_PAUSED:
@@ -2203,7 +2200,22 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)


    // The presented frame count must always lag behind the consumed frame count.
    // The presented frame count must always lag behind the consumed frame count.
    // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
    // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
    status_t status = mAudioTrack->getTimestamp(timestamp);

    status_t status;
    if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
        // use Binder to get timestamp
        status = mAudioTrack->getTimestamp(timestamp);
    } else {
        // read timestamp from shared memory
        ExtendedTimestamp ets;
        status = mProxy->getTimestamp(&ets);
        if (status == OK) {
            status = ets.getBestTimestamp(&timestamp);
        }
        if (status == INVALID_OPERATION) {
            status = WOULD_BLOCK;
        }
    }
    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
        ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
        ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
        return status;
        return status;
+2 −0
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCo
    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer)
    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer)
    , mBufferSizeInFrames(frameCount)
    , mBufferSizeInFrames(frameCount)
    , mEpoch(0)
    , mEpoch(0)
    , mTimestampObserver(&cblk->mExtendedTimestampQueue)
{
{
}
}


@@ -598,6 +599,7 @@ ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCo
        size_t frameSize, bool isOut, bool clientInServer)
        size_t frameSize, bool isOut, bool clientInServer)
    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
      mAvailToClient(0), mFlush(0), mReleased(0)
      mAvailToClient(0), mFlush(0), mReleased(0)
    , mTimestampMutator(&cblk->mExtendedTimestampQueue)
{
{
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -89,6 +89,7 @@ protected:
    // ExtendedAudioBufferProvider interface
    // ExtendedAudioBufferProvider interface
    virtual size_t framesReady() const;
    virtual size_t framesReady() const;
    virtual size_t framesReleased() const;
    virtual size_t framesReleased() const;
    virtual void onTimestamp(const AudioTimestamp &timestamp);


    bool isPausing() const { return mState == PAUSING; }
    bool isPausing() const { return mState == PAUSING; }
    bool isPaused() const { return mState == PAUSED; }
    bool isPaused() const { return mState == PAUSED; }
Loading