[MPlayer-cvslog] r38417 - trunk/libao2/ao_coreaudio.c

reimar subversion at mplayerhq.hu
Wed Apr 19 22:42:04 EEST 2023


Author: reimar
Date: Wed Apr 19 22:42:04 2023
New Revision: 38417

Log:
ao_coreaudio.c: Avoid random hangs at end of file.

Calling audio_pause from different threads leads to
deadlocks.
Change how an empty audio buffer is handled to avoid
the need for audio_pause and thus avoid the hangs.
Also remove some duplicated code during uninit (re-use
audio_pause instead) and make audio_pause not do
anything if audio is already paused.

Fixes trac issue #2410

Modified:
   trunk/libao2/ao_coreaudio.c

Modified: trunk/libao2/ao_coreaudio.c
==============================================================================
--- trunk/libao2/ao_coreaudio.c	Sat Apr  8 22:54:00 2023	(r38416)
+++ trunk/libao2/ao_coreaudio.c	Wed Apr 19 22:42:04 2023	(r38417)
@@ -159,13 +159,21 @@ int req=(inNumFrames)*ao->packetSize;
 
 	if(amt>req)
  		amt=req;
+	// clear whole buffer since coreaudio seems to have
+	// issues handling data amounts smaller than it requested
+	if (amt < req)
+		memset(ioData->mBuffers[0].mData + amt, 0, req - amt);
 
 	if(amt)
 		read_buffer((unsigned char *)ioData->mBuffers[0].mData, amt);
-	else audio_pause();
 	ioData->mBuffers[0].mDataByteSize = amt;
 
- 	return noErr;
+	// In theory it might be nicer to call audio_pause if
+	// there is no data, as the code originally did.
+	// However since this runs in a separate thread, this can
+	// trigger a race condition if MPlayer calls AudioOutputUnitStop
+	// for example during uninit, which then causes a hang.
+	return amt ? noErr : kAudioFileEndOfFileError;
 }
 
 static int control(int cmd,void *arg){
@@ -1146,17 +1154,12 @@ static void uninit(int immed)
     usec_sleep((int)timeleft);
   }
 
+  audio_pause();
   if (!ao->b_digital) {
-      AudioOutputUnitStop(ao->theOutputUnit);
       AudioUnitUninitialize(ao->theOutputUnit);
       CloseComponent(ao->theOutputUnit);
   }
   else {
-      /* Stop device. */
-      err = AudioDeviceStop(ao->i_selected_dev, ao->renderCallback);
-      if (err != noErr)
-          ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceStop failed: [%4.4s]\n", (char *)&err);
-
       /* Remove IOProc callback. */
       err = AudioDeviceDestroyIOProcID(ao->i_selected_dev, ao->renderCallback);
       if (err != noErr)
@@ -1207,6 +1210,9 @@ static void audio_pause(void)
 {
     OSErr err=noErr;
 
+    if (ao->paused)
+        return;
+
     /* Stop callback. */
     if (!ao->b_digital)
     {


More information about the MPlayer-cvslog mailing list