* [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.