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

Commit 5dcce8b1 authored by Haynes Mathew George's avatar Haynes Mathew George Committed by Steve Kondik
Browse files

AudioTrack: Handle track invalidate on wait for stream done

If a track invalidate is called while waiting for a stream done,
AudioCallback handler is notified with event EVENT_STREAM_END.
This might cause substantial data loss for offload playback. Try to
recreate the track if needed.

Change-Id: Ie663c85e92588ddfd8d633f4bf5024f9fa4f5c2e
parent cb542dbf
Loading
Loading
Loading
Loading
+39 −31
Original line number Diff line number Diff line
@@ -1716,6 +1716,38 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)

    mLock.unlock();

    // perform callbacks while unlocked
    if (newUnderrun) {
        mCbf(EVENT_UNDERRUN, mUserData, NULL);
    }
    // FIXME we will miss loops if loop cycle was signaled several times since last call
    //       to processAudioBuffer()
    if (flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) {
        mCbf(EVENT_LOOP_END, mUserData, NULL);
    }
    if (flags & CBLK_BUFFER_END) {
        mCbf(EVENT_BUFFER_END, mUserData, NULL);
    }
    if (markerReached) {
        mCbf(EVENT_MARKER, mUserData, &markerPosition);
    }
    while (newPosCount > 0) {
        size_t temp = newPosition;
        mCbf(EVENT_NEW_POS, mUserData, &temp);
        newPosition += updatePeriod;
        newPosCount--;
    }

    if (mObservedSequence != sequence) {
        mObservedSequence = sequence;
        mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL);
        // for offloaded tracks, just wait for the upper layers to recreate the track
        if (isOffloaded()) {
            return NS_INACTIVE;
        }
    }


    if (waitStreamEnd) {
        AutoMutex lock(mLock);

@@ -1733,6 +1765,13 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
        case NO_ERROR:
        case DEAD_OBJECT:
        case TIMED_OUT:
            if (isOffloaded()) {
                if (mCblk->mFlags & CBLK_INVALID) {
                    // will trigger EVENT_NEW_IAUDIOTRACK in next iteration
                    return 0;
                }
            }

            mLock.unlock();
            mCbf(EVENT_STREAM_END, mUserData, NULL);
            mLock.lock();
@@ -1748,37 +1787,6 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
        }
    }

    // perform callbacks while unlocked
    if (newUnderrun) {
        mCbf(EVENT_UNDERRUN, mUserData, NULL);
    }
    // FIXME we will miss loops if loop cycle was signaled several times since last call
    //       to processAudioBuffer()
    if (flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) {
        mCbf(EVENT_LOOP_END, mUserData, NULL);
    }
    if (flags & CBLK_BUFFER_END) {
        mCbf(EVENT_BUFFER_END, mUserData, NULL);
    }
    if (markerReached) {
        mCbf(EVENT_MARKER, mUserData, &markerPosition);
    }
    while (newPosCount > 0) {
        size_t temp = newPosition;
        mCbf(EVENT_NEW_POS, mUserData, &temp);
        newPosition += updatePeriod;
        newPosCount--;
    }

    if (mObservedSequence != sequence) {
        mObservedSequence = sequence;
        mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL);
        // for offloaded tracks, just wait for the upper layers to recreate the track
        if (isOffloaded()) {
            return NS_INACTIVE;
        }
    }

    // if inactive, then don't run me again until re-started
    if (!active) {
        return NS_INACTIVE;