summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2014-09-23 12:36:39 +0200
committerJohns <johns98@gmx.net>2014-09-23 12:36:39 +0200
commita3c0052c4b87b44679d8264c89d085fcda721a2e (patch)
tree7796cbee9deaf9cd63eae02ba614e84e0ede2943
parent8b7402a397bf460e25a75add8059aa2eb83709ee (diff)
downloadvdr-plugin-softhddevice-a3c0052c4b87b44679d8264c89d085fcda721a2e.tar.gz
vdr-plugin-softhddevice-a3c0052c4b87b44679d8264c89d085fcda721a2e.tar.bz2
Fix audio thread close race condition.
-rw-r--r--ChangeLog1
-rw-r--r--audio.c29
2 files changed, 24 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index fef7942..23650d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
User johns
Date:
+ Fix audio thread close race condition.
Support ffmpeg new AVFrame API in the audio codec.
Config for automatic AES parameters.
Use GCC built-in functions for atomic operations.
diff --git a/audio.c b/audio.c
index 6ca3df1..a9da207 100644
--- a/audio.c
+++ b/audio.c
@@ -149,6 +149,7 @@ static int AudioBufferTime = 336; ///< audio buffer time in ms
static pthread_t AudioThread; ///< audio play thread
static pthread_mutex_t AudioMutex; ///< audio condition mutex
static pthread_cond_t AudioStartCond; ///< condition variable
+static char AudioThreadStop; ///< stop audio thread
#else
static const int AudioThread; ///< dummy audio thread
#endif
@@ -942,7 +943,6 @@ static int AlsaThread(void)
return -1;
}
for (;;) {
- pthread_testcancel();
if (AudioPaused) {
return 1;
}
@@ -1216,7 +1216,8 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
snd_pcm_t *handle;
handle = AlsaPCMHandle;
- // FIXME: need lock
+ // no lock needed, thread exit in main loop only
+ //Debug(3, "audio: %s [\n", __FUNCTION__);
AlsaPCMHandle = NULL; // other threads should check handle
snd_pcm_close(handle);
if (AudioAlsaCloseOpenDelay) {
@@ -1227,6 +1228,7 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
return -1;
}
AlsaPCMHandle = handle;
+ //Debug(3, "audio: %s ]\n", __FUNCTION__);
}
for (;;) {
@@ -1548,7 +1550,6 @@ static int OssThread(void)
for (;;) {
struct pollfd fds[1];
- pthread_testcancel();
if (AudioPaused) {
return 1;
}
@@ -2050,6 +2051,12 @@ static void *AudioPlayHandlerThread(void *dummy)
{
Debug(3, "audio: play thread started\n");
for (;;) {
+ // check if we should stop the thread
+ if (AudioThreadStop) {
+ Debug(3, "audio: play thread stopped\n");
+ return PTHREAD_CANCELED;
+ }
+
Debug(3, "audio: wait on start condition\n");
pthread_mutex_lock(&AudioMutex);
AudioRunning = 0;
@@ -2072,6 +2079,11 @@ static void *AudioPlayHandlerThread(void *dummy)
int err;
int i;
+ // check if we should stop the thread
+ if (AudioThreadStop) {
+ Debug(3, "audio: play thread stopped\n");
+ return PTHREAD_CANCELED;
+ }
// look if there is a flush command in the queue
flush = 0;
filled = atomic_read(&AudioRingFilled);
@@ -2156,6 +2168,7 @@ static void *AudioPlayHandlerThread(void *dummy)
*/
static void AudioInitThread(void)
{
+ AudioThreadStop = 0;
pthread_mutex_init(&AudioMutex, NULL);
pthread_cond_init(&AudioStartCond, NULL);
pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL);
@@ -2169,10 +2182,12 @@ static void AudioExitThread(void)
{
void *retval;
+ Debug(3, "audio: %s\n", __FUNCTION__);
+
if (AudioThread) {
- if (pthread_cancel(AudioThread)) {
- Error(_("audio: can't queue cancel play thread\n"));
- }
+ AudioThreadStop = 1;
+ AudioRunning = 1; // wakeup thread, if needed
+ pthread_cond_signal(&AudioStartCond);
if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("audio: can't cancel play thread\n"));
}
@@ -2994,6 +3009,8 @@ void AudioExit(void)
{
const AudioModule *module;
+ Debug(3, "audio: %s\n", __FUNCTION__);
+
#ifdef USE_AUDIO_THREAD
if (AudioUsedModule->Thread) { // supports threads
AudioExitThread();