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

Commit 69725a47 authored by Glenn Maynard's avatar Glenn Maynard Committed by Steve Kondik
Browse files

Fix FLAC decoder lock contention.

The FLAC decoder is doing everything with the lock held, so the only
time it ever releases the lock when playing is for a few cycles between
each loop.  This prevents other threads from ever acquiring the lock.
This can cause other threads to wait for the lock indefinitely.

Handle decoding like the other decoder classes: do the brief read and
decode with the lock held, then release the lock while making the
blocking call to write data to the audio sink.

Fixes media player ANRs with NORMALIZED_SLEEPER=0, and generally
unresponsive media API calls in any case when this decoder is in use.
parent 26ed7aeb
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ static status_t STATE_OPEN = 2;
FLACPlayer::FLACPlayer() :
    mTotalSamples(-1), mCurrentSample(0), mBytesPerSample(-1),
    mChannels(-1), mSampleRate(-1), mAudioBuffer(NULL),
    mAudioBufferSize(0), mState(STATE_ERROR), mStreamType(AudioSystem::MUSIC),
    mAudioBufferSize(0), mAudioBufferFilled(0),
    mState(STATE_ERROR), mStreamType(AudioSystem::MUSIC),
    mLoop(false), mAndroidLoop(false), mExit(false), mPaused(false),
    mRender(false), mRenderTid(-1)
{
@@ -429,11 +430,7 @@ FLAC__StreamDecoderWriteStatus FLACPlayer::vp_write(const FLAC__StreamDecoder *d
            }
        }
    }

    if (!self->mAudioSink->write(self->mAudioBuffer, frame_size)) {
        LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(self->mDecoder));
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    self->mAudioBufferFilled = frame_size;

    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
@@ -547,6 +544,18 @@ int FLACPlayer::render() {
            sendEvent(MEDIA_ERROR);
            break;
        }

        if (mAudioBufferFilled > 0) {
            /* Be sure to clear mAudioBufferFilled even if there's an error. */
            uint32_t toPlay = mAudioBufferFilled;
            mAudioBufferFilled = 0;

            if (!mAudioSink->write(mAudioBuffer, toPlay)) {
                LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(mDecoder));
                sendEvent(MEDIA_ERROR);
                break;
            }
        }
    }

threadExit:
@@ -555,6 +564,7 @@ threadExit:
        delete [] mAudioBuffer;
        mAudioBuffer = NULL;
        mAudioBufferSize = 0;
        mAudioBufferFilled = 0;
    }

    // tell main thread goodbye
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ private:

    FLAC__int8 *         mAudioBuffer;
    uint32_t             mAudioBufferSize;
    uint32_t             mAudioBufferFilled;

    Mutex                mMutex;
    Condition            mCondition;