Fix dead lock when changing and restoring stream format for digital output,

replaced with lockless code.


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25008 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
ulion 2007-11-10 02:07:34 +00:00
parent 4ab4cd3dcd
commit 894000c434
1 changed files with 14 additions and 31 deletions

View File

@ -44,9 +44,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <pthread.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
@ -857,21 +855,16 @@ static int AudioStreamChangeFormat( AudioStreamID i_stream_id, AudioStreamBasicD
UInt32 i_param_size = 0; UInt32 i_param_size = 0;
int i; int i;
struct timeval now; static volatile int stream_format_changed;
struct timespec timeout; stream_format_changed = 0;
struct { pthread_mutex_t lock; pthread_cond_t cond; } w;
print_format(MSGL_V, "setting stream format:", &change_format); print_format(MSGL_V, "setting stream format:", &change_format);
/* Condition because SetProperty is asynchronious. */
pthread_cond_init(&w.cond, NULL);
pthread_mutex_init(&w.lock, NULL);
pthread_mutex_lock(&w.lock);
/* Install the callback. */ /* Install the callback. */
err = AudioStreamAddPropertyListener(i_stream_id, 0, err = AudioStreamAddPropertyListener(i_stream_id, 0,
kAudioStreamPropertyPhysicalFormat, kAudioStreamPropertyPhysicalFormat,
StreamListener, (void *)&w); StreamListener,
(void *)&stream_format_changed);
if (err != noErr) if (err != noErr)
{ {
ao_msg(MSGT_AO, MSGL_WARN, "AudioStreamAddPropertyListener failed: [%4.4s]\n", (char *)&err); ao_msg(MSGT_AO, MSGL_WARN, "AudioStreamAddPropertyListener failed: [%4.4s]\n", (char *)&err);
@ -889,19 +882,19 @@ static int AudioStreamChangeFormat( AudioStreamID i_stream_id, AudioStreamBasicD
return CONTROL_FALSE; return CONTROL_FALSE;
} }
/* The AudioStreamSetProperty is not only asynchronious (requiring the locks), /* The AudioStreamSetProperty is not only asynchronious,
* it is also not Atomic, in its behaviour. * it is also not Atomic, in its behaviour.
* Therefore we check 5 times before we really give up. * Therefore we check 5 times before we really give up.
* FIXME: failing isn't actually implemented yet. */ * FIXME: failing isn't actually implemented yet. */
for (i = 0; i < 5; ++i) for (i = 0; i < 5; ++i)
{ {
AudioStreamBasicDescription actual_format; AudioStreamBasicDescription actual_format;
int j;
gettimeofday(&now, NULL); for (j = 0; !stream_format_changed && j < 50; ++j)
timeout.tv_sec = now.tv_sec; usec_sleep(10000);
timeout.tv_nsec = (now.tv_usec + 500000) * 1000; if (stream_format_changed)
stream_format_changed = 0;
if (pthread_cond_timedwait(&w.cond, &w.lock, &timeout)) else
ao_msg(MSGT_AO, MSGL_V, "reached timeout\n" ); ao_msg(MSGT_AO, MSGL_V, "reached timeout\n" );
i_param_size = sizeof(AudioStreamBasicDescription); i_param_size = sizeof(AudioStreamBasicDescription);
@ -931,11 +924,6 @@ static int AudioStreamChangeFormat( AudioStreamID i_stream_id, AudioStreamBasicD
return CONTROL_FALSE; return CONTROL_FALSE;
} }
/* Destroy the lock and condition. */
pthread_mutex_unlock(&w.lock);
pthread_mutex_destroy(&w.lock);
pthread_cond_destroy(&w.cond);
return CONTROL_TRUE; return CONTROL_TRUE;
} }
@ -1144,17 +1132,12 @@ static OSStatus StreamListener( AudioStreamID inStream,
AudioDevicePropertyID inPropertyID, AudioDevicePropertyID inPropertyID,
void * inClientData ) void * inClientData )
{ {
struct { pthread_mutex_t lock; pthread_cond_t cond; } * w = inClientData;
switch (inPropertyID) switch (inPropertyID)
{ {
case kAudioStreamPropertyPhysicalFormat: case kAudioStreamPropertyPhysicalFormat:
if (NULL!=w) ao_msg(MSGT_AO, MSGL_V, "got notify kAudioStreamPropertyPhysicalFormat changed.\n");
{ if (inClientData)
pthread_mutex_lock(&w->lock); *(volatile int *)inClientData = 1;
pthread_cond_signal(&w->cond);
pthread_mutex_unlock(&w->lock);
}
default: default:
break; break;
} }