Skip to content

Commit

Permalink
Android: Fix deadlock in AudioTrack processing
Browse files Browse the repository at this point in the history
When exiting during a pause, there was an infinite wait for the
output thread to end if there was data buffered. Now fixed.

Refs #13446
  • Loading branch information
bennettpeter committed May 19, 2019
1 parent f3c9089 commit af05a71
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
Expand Up @@ -26,6 +26,7 @@ public class AudioOutputAudioTrack
int latencyCount;
boolean isSettled;
boolean isBufferInFlux;
boolean isOutputThreadStarted;

public AudioOutputAudioTrack(int encoding, int sampleRate, int bufferSize, int channels)
{
Expand Down Expand Up @@ -94,36 +95,34 @@ public int write(byte[] audioData, int sizeInBytes)
int written = 0;
int ret = 0;
int i;
if (player != null)
while (buf.hasRemaining())
{
while (buf.hasRemaining())
synchronized(syncBuffer)
{
// get out if we should not be here
if (player == null || !isOutputThreadStarted)
break;
ret = player.write(buf, buf.remaining(), AudioTrack.WRITE_NON_BLOCKING);
if (ret < 0)
{
break;
}
written += ret;
synchronized(syncBuffer)
{
bytesWritten += ret;
lastwritetime = System.nanoTime();
// Note that only after this method returns is this data
// removed from the caller's buffer.
// bufferedBytes may be negative because actually some
// data still in the "Audio circular buffer" may have
// already played.
bufferedBytes = buf.remaining() - sizeInBytes;
}
try
{
Thread.sleep(10);
}
catch (InterruptedException ex) {}
bytesWritten += ret;
lastwritetime = System.nanoTime();
// Note that only after this method returns is this data
// removed from the caller's buffer.
// bufferedBytes may be negative because actually some
// data still in the "Audio circular buffer" may have
// already played.
bufferedBytes = buf.remaining() - sizeInBytes;
}
try
{
Thread.sleep(10);
}
catch (InterruptedException ex) {}
}
else
written = AudioTrack.ERROR;
synchronized(syncBuffer)
{
// After we return to caller, the data will be removed from
Expand Down Expand Up @@ -216,9 +215,21 @@ public void pause (boolean doPause)

public void release ()
{
if (player != null)
if (player == null)
return;

synchronized(syncBuffer)
{
pause(true);
player.flush();
player.release();
player = null;
player = null;
}
}

public void setOutputThread (boolean isStarted)
{
isOutputThreadStarted = isStarted;
}

}
25 changes: 24 additions & 1 deletion mythtv/libs/libmyth/audio/audiooutputaudiotrack.cpp
Expand Up @@ -56,7 +56,6 @@ AudioOutputAudioTrack::AudioOutputAudioTrack(const AudioSettings &settings) :
AudioOutputAudioTrack::~AudioOutputAudioTrack()
{
KillAudio();
CloseDevice();
}

bool AudioOutputAudioTrack::OpenDevice()
Expand Down Expand Up @@ -295,3 +294,27 @@ void AudioOutputAudioTrack::SetSourceBitrate(int rate)
}
}
}

bool AudioOutputAudioTrack::StartOutputThread(void)
{
QAndroidJniEnvironment env;
if (m_audioTrack)
{
m_audioTrack->callMethod<void>("setOutputThread","(Z)V",true);
ANDROID_EXCEPTION_CLEAR
}

return AudioOutputBase::StartOutputThread();
}

void AudioOutputAudioTrack::StopOutputThread(void)
{
QAndroidJniEnvironment env;
if (m_audioTrack)
{
m_audioTrack->callMethod<void>("setOutputThread","(Z)V",false);
ANDROID_EXCEPTION_CLEAR
}

AudioOutputBase::StopOutputThread();
}
2 changes: 2 additions & 0 deletions mythtv/libs/libmyth/audio/audiooutputaudiotrack.h
Expand Up @@ -35,6 +35,8 @@ class AudioOutputAudioTrack : public AudioOutputBase
int GetBufferedOnSoundcard(void) const override; // AudioOutputBase
AudioOutputSettings* GetOutputSettings(bool digital) override; // AudioOutputBase
void SetSourceBitrate(int rate) override; // AudioOutputBase
bool StartOutputThread(void) override; // AudioOutputBase
void StopOutputThread(void) override; // AudioOutputBase
QAndroidJniObject *m_audioTrack {nullptr};
int m_bitsPer10Frames {0};
};
Expand Down

0 comments on commit af05a71

Please sign in to comment.