Pārlūkot izejas kodu

audio: Fix device refcounting vs ProvidesOwnCallbackThread backends.

Ryan C. Gordon 1 gadu atpakaļ
vecāks
revīzija
b733adb503

+ 4 - 4
src/audio/SDL_audio.c

@@ -352,7 +352,7 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device)
 }
 
 // Don't hold the device lock when calling this, as we may destroy the device!
-static void UnrefPhysicalAudioDevice(SDL_AudioDevice *device)
+void UnrefPhysicalAudioDevice(SDL_AudioDevice *device)
 {
     if (SDL_AtomicDecRef(&device->refcount)) {
         // take it out of the device list.
@@ -365,7 +365,7 @@ static void UnrefPhysicalAudioDevice(SDL_AudioDevice *device)
     }
 }
 
-static void RefPhysicalAudioDevice(SDL_AudioDevice *device)
+void RefPhysicalAudioDevice(SDL_AudioDevice *device)
 {
     SDL_AtomicIncRef(&device->refcount);
 }
@@ -861,6 +861,7 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size)
 void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device)
 {
     SDL_assert(!device->iscapture);
+    RefPhysicalAudioDevice(device);  // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately).
     current_audio.impl.ThreadInit(device);
 }
 
@@ -1010,6 +1011,7 @@ static int SDLCALL OutputAudioThread(void *devicep)  // thread entry point
 void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device)
 {
     SDL_assert(device->iscapture);
+    RefPhysicalAudioDevice(device);  // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately).
     current_audio.impl.ThreadInit(device);
 }
 
@@ -1495,8 +1497,6 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
         }
     }
 
-    RefPhysicalAudioDevice(device);  // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately).
-
     return 0;
 }
 

+ 3 - 0
src/audio/SDL_sysaudio.h

@@ -106,6 +106,9 @@ extern void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device);
 // Backends can call this to get a standardized name for a thread to power a specific audio device.
 extern char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen);
 
+// Backends can call these to change a device's refcount.
+extern void RefPhysicalAudioDevice(SDL_AudioDevice *device);
+extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device);
 
 // These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread.
 extern void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device);

+ 2 - 0
src/audio/emscripten/SDL_emscriptenaudio.c

@@ -181,6 +181,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
         return SDL_OutOfMemory();
     }
 
+    RefPhysicalAudioDevice(device);  // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
+
     // limit to native freq
     device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });
 

+ 2 - 0
src/audio/haiku/SDL_haikuaudio.cc

@@ -112,6 +112,8 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device)
     }
     SDL_zerop(device->hidden);
 
+    RefPhysicalAudioDevice(device);  // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
+
     // Parse the audio format and fill the Be raw audio format
     media_raw_audio_format format;
     SDL_zero(format);

+ 2 - 0
src/audio/jack/SDL_jackaudio.c

@@ -300,6 +300,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
         return SDL_OutOfMemory();
     }
 
+    RefPhysicalAudioDevice(device);  // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
+
     client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL);
     device->hidden->client = client;
     if (client == NULL) {