All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2
@ 2017-01-31  8:46 Thomas Huth
  2017-02-01 13:25 ` Gerd Hoffmann
  0 siblings, 1 reply; 4+ messages in thread
From: Thomas Huth @ 2017-01-31  8:46 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel

When compiling with SDL2, the semaphore trick used in sdlaudio.c
does not work - QEMU locks up completely in this case. To avoid
the hang and get at least some audio playback up and running (it's
a little bit crackling, but better than nothing), we can use the
SDL locking functions SDL_LockAudio() and SDL_UnlockAudio() to sync
with the sound playback thread instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 audio/sdlaudio.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index db69fe1..e8d91d2 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -38,10 +38,14 @@
 #define AUDIO_CAP "sdl"
 #include "audio_int.h"
 
+#define USE_SEMAPHORE (SDL_MAJOR_VERSION < 2)
+
 typedef struct SDLVoiceOut {
     HWVoiceOut hw;
     int live;
+#if USE_SEMAPHORE
     int rpos;
+#endif
     int decr;
 } SDLVoiceOut;
 
@@ -53,8 +57,10 @@ static struct {
 
 static struct SDLAudioState {
     int exit;
+#if USE_SEMAPHORE
     SDL_mutex *mutex;
     SDL_sem *sem;
+#endif
     int initialized;
     bool driver_created;
 } glob_sdl;
@@ -73,31 +79,45 @@ static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
 
 static int sdl_lock (SDLAudioState *s, const char *forfn)
 {
+#if USE_SEMAPHORE
     if (SDL_LockMutex (s->mutex)) {
         sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
         return -1;
     }
+#else
+    SDL_LockAudio();
+#endif
+
     return 0;
 }
 
 static int sdl_unlock (SDLAudioState *s, const char *forfn)
 {
+#if USE_SEMAPHORE
     if (SDL_UnlockMutex (s->mutex)) {
         sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
         return -1;
     }
+#else
+    SDL_UnlockAudio();
+#endif
+
     return 0;
 }
 
 static int sdl_post (SDLAudioState *s, const char *forfn)
 {
+#if USE_SEMAPHORE
     if (SDL_SemPost (s->sem)) {
         sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
         return -1;
     }
+#endif
+
     return 0;
 }
 
+#if USE_SEMAPHORE
 static int sdl_wait (SDLAudioState *s, const char *forfn)
 {
     if (SDL_SemWait (s->sem)) {
@@ -106,6 +126,7 @@ static int sdl_wait (SDLAudioState *s, const char *forfn)
     }
     return 0;
 }
+#endif
 
 static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
 {
@@ -246,6 +267,7 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
         int to_mix, decr;
 
         /* dolog ("in callback samples=%d\n", samples); */
+#if USE_SEMAPHORE
         sdl_wait (s, "sdl_callback");
         if (s->exit) {
             return;
@@ -264,6 +286,11 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
         if (!sdl->live) {
             goto again;
         }
+#else
+        if (s->exit || !sdl->live) {
+            break;
+        }
+#endif
 
         /* dolog ("in callback live=%d\n", live); */
         to_mix = audio_MIN (samples, sdl->live);
@@ -274,7 +301,11 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
 
             /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
             hw->clip (buf, src, chunk);
+#if USE_SEMAPHORE
             sdl->rpos = (sdl->rpos + chunk) % hw->samples;
+#else
+            hw->rpos = (hw->rpos + chunk) % hw->samples;
+#endif
             to_mix -= chunk;
             buf += chunk << hw->info.shift;
         }
@@ -282,12 +313,21 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
         sdl->live -= decr;
         sdl->decr += decr;
 
+#if USE_SEMAPHORE
     again:
         if (sdl_unlock (s, "sdl_callback")) {
             return;
         }
+#endif
     }
     /* dolog ("done len=%d\n", len); */
+
+#if (SDL_MAJOR_VERSION >= 2)
+    /* SDL2 does not clear the remaining buffer for us, so do it on our own */
+    if (samples) {
+        memset(buf, 0, samples << hw->info.shift);
+    }
+#endif
 }
 
 static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
@@ -315,8 +355,12 @@ static int sdl_run_out (HWVoiceOut *hw, int live)
     decr = audio_MIN (sdl->decr, live);
     sdl->decr -= decr;
 
+#if USE_SEMAPHORE
     sdl->live = live - decr;
     hw->rpos = sdl->rpos;
+#else
+    sdl->live = live;
+#endif
 
     if (sdl->live > 0) {
         sdl_unlock_and_post (s, "sdl_run_out");
@@ -405,6 +449,7 @@ static void *sdl_audio_init (void)
         return NULL;
     }
 
+#if USE_SEMAPHORE
     s->mutex = SDL_CreateMutex ();
     if (!s->mutex) {
         sdl_logerr ("Failed to create SDL mutex\n");
@@ -419,6 +464,7 @@ static void *sdl_audio_init (void)
         SDL_QuitSubSystem (SDL_INIT_AUDIO);
         return NULL;
     }
+#endif
 
     s->driver_created = true;
     return s;
@@ -428,8 +474,10 @@ static void sdl_audio_fini (void *opaque)
 {
     SDLAudioState *s = opaque;
     sdl_close (s);
+#if USE_SEMAPHORE
     SDL_DestroySemaphore (s->sem);
     SDL_DestroyMutex (s->mutex);
+#endif
     SDL_QuitSubSystem (SDL_INIT_AUDIO);
     s->driver_created = false;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2
  2017-01-31  8:46 [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2 Thomas Huth
@ 2017-02-01 13:25 ` Gerd Hoffmann
  2017-02-01 15:30   ` Thomas Huth
  0 siblings, 1 reply; 4+ messages in thread
From: Gerd Hoffmann @ 2017-02-01 13:25 UTC (permalink / raw)
  To: Thomas Huth; +Cc: qemu-devel

On Di, 2017-01-31 at 09:46 +0100, Thomas Huth wrote:
> When compiling with SDL2, the semaphore trick used in sdlaudio.c
> does not work - QEMU locks up completely in this case. To avoid
> the hang and get at least some audio playback up and running (it's
> a little bit crackling, but better than nothing), we can use the
> SDL locking functions SDL_LockAudio() and SDL_UnlockAudio() to sync
> with the sound playback thread instead.

Does SDL_LockAudio work with sdl1 too?
So we can possibly avoid having all those #ifdefs?

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2
  2017-02-01 13:25 ` Gerd Hoffmann
@ 2017-02-01 15:30   ` Thomas Huth
  2017-02-16 15:14     ` Gerd Hoffmann
  0 siblings, 1 reply; 4+ messages in thread
From: Thomas Huth @ 2017-02-01 15:30 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On 01.02.2017 14:25, Gerd Hoffmann wrote:
> On Di, 2017-01-31 at 09:46 +0100, Thomas Huth wrote:
>> When compiling with SDL2, the semaphore trick used in sdlaudio.c
>> does not work - QEMU locks up completely in this case. To avoid
>> the hang and get at least some audio playback up and running (it's
>> a little bit crackling, but better than nothing), we can use the
>> SDL locking functions SDL_LockAudio() and SDL_UnlockAudio() to sync
>> with the sound playback thread instead.
> 
> Does SDL_LockAudio work with sdl1 too?
> So we can possibly avoid having all those #ifdefs?

It somehow works, too, but sound quality is - at least for me - much
worse here than with the semaphore code. Maybe it can be fixed, too, but
I am really not familiar enough with the QEMU internal audio API to
figure out how to fix this (e.g. I don't understand why the run_out
function is called way more often than the callback function, but its
"live" parameter never reaches the full buffer size).
So maybe we can start with the #ifdefs for now and remove them once
somebody figured out how to improve sound quality for SDL1, too? (or
once we remove support for SDL1 from QEMU completely ... or do we want
to carry that with us forever?).

 Thomas

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2
  2017-02-01 15:30   ` Thomas Huth
@ 2017-02-16 15:14     ` Gerd Hoffmann
  0 siblings, 0 replies; 4+ messages in thread
From: Gerd Hoffmann @ 2017-02-16 15:14 UTC (permalink / raw)
  To: Thomas Huth; +Cc: qemu-devel

On Mi, 2017-02-01 at 16:30 +0100, Thomas Huth wrote:
> On 01.02.2017 14:25, Gerd Hoffmann wrote:
> > On Di, 2017-01-31 at 09:46 +0100, Thomas Huth wrote:
> >> When compiling with SDL2, the semaphore trick used in sdlaudio.c
> >> does not work - QEMU locks up completely in this case. To avoid
> >> the hang and get at least some audio playback up and running (it's
> >> a little bit crackling, but better than nothing), we can use the
> >> SDL locking functions SDL_LockAudio() and SDL_UnlockAudio() to sync
> >> with the sound playback thread instead.
> > 
> > Does SDL_LockAudio work with sdl1 too?
> > So we can possibly avoid having all those #ifdefs?
> 
> It somehow works, too, but sound quality is - at least for me - much
> worse here than with the semaphore code. Maybe it can be fixed, too, but
> I am really not familiar enough with the QEMU internal audio API to
> figure out how to fix this (e.g. I don't understand why the run_out
> function is called way more often than the callback function, but its
> "live" parameter never reaches the full buffer size).
> So maybe we can start with the #ifdefs for now and remove them once
> somebody figured out how to improve sound quality for SDL1, too? (or
> once we remove support for SDL1 from QEMU completely ... or do we want
> to carry that with us forever?).

Ok, picked as-is for now.  It's better than nothing, and I'm too busy
with other stuff atm to have a closer look myself.

thanks,
  Gerd

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-02-16 15:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-31  8:46 [Qemu-devel] [RFC PATCH] audio/sdlaudio: Allow audio playback with SDL2 Thomas Huth
2017-02-01 13:25 ` Gerd Hoffmann
2017-02-01 15:30   ` Thomas Huth
2017-02-16 15:14     ` Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.