summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_sdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_sdl.c')
-rw-r--r--audio/out/ao_sdl.c180
1 files changed, 15 insertions, 165 deletions
diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c
index 662eeca484..1b229d2090 100644
--- a/audio/out/ao_sdl.c
+++ b/audio/out/ao_sdl.c
@@ -24,58 +24,34 @@
#include "talloc.h"
#include "ao.h"
#include "internal.h"
+#include "common/common.h"
#include "common/msg.h"
#include "options/m_option.h"
#include "osdep/timer.h"
-#include <libavutil/fifo.h>
-#include <libavutil/common.h>
#include <SDL.h>
-// hack because SDL can't be asked about the current delay
-#define ESTIMATE_DELAY
-
struct priv
{
- AVFifoBuffer *buffer;
- SDL_mutex *buffer_mutex;
- SDL_cond *underrun_cond;
- bool unpause;
bool paused;
-#ifdef ESTIMATE_DELAY
- int64_t callback_time0;
- int64_t callback_time1;
-#endif
+
float buflen;
- float bufcnt;
};
static void audio_callback(void *userdata, Uint8 *stream, int len)
{
struct ao *ao = userdata;
- struct priv *priv = ao->priv;
- SDL_LockMutex(priv->buffer_mutex);
+ void *data[1] = {stream};
-#ifdef ESTIMATE_DELAY
- priv->callback_time1 = priv->callback_time0;
- priv->callback_time0 = mp_time_us();
-#endif
+ if (len % ao->sstride)
+ MP_ERR(ao, "SDL audio callback not sample aligned");
- while (len > 0 && !priv->paused) {
- int got = av_fifo_size(priv->buffer);
- if (got > len)
- got = len;
- if (got > 0) {
- av_fifo_generic_read(priv->buffer, stream, got, NULL);
- len -= got;
- stream += got;
- }
- if (len > 0)
- SDL_CondWait(priv->underrun_cond, priv->buffer_mutex);
- }
+ // Time this buffer will take, plus assume 1 period (1 callback invocation)
+ // fixed latency.
+ double delay = 2 * len / (double)ao->bps;
- SDL_UnlockMutex(priv->buffer_mutex);
+ ao_read_data(ao, data, len / ao->sstride, mp_time_us() + 1000000LL * delay);
}
static void uninit(struct ao *ao)
@@ -84,34 +60,13 @@ static void uninit(struct ao *ao)
if (!priv)
return;
- // abort the callback
- priv->paused = 1;
-
if (SDL_WasInit(SDL_INIT_AUDIO)) {
- if (priv->buffer_mutex)
- SDL_LockMutex(priv->buffer_mutex);
- if (priv->underrun_cond)
- SDL_CondSignal(priv->underrun_cond);
- if (priv->buffer_mutex)
- SDL_UnlockMutex(priv->buffer_mutex);
-
// make sure the callback exits
SDL_LockAudio();
// close audio device
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
-
- // get rid of the mutex
- if (priv->underrun_cond)
- SDL_DestroyCond(priv->underrun_cond);
- if (priv->buffer_mutex)
- SDL_DestroyMutex(priv->buffer_mutex);
- if (priv->buffer)
- av_fifo_free(priv->buffer);
-
- talloc_free(ao->priv);
- ao->priv = NULL;
}
static unsigned int ceil_power_of_two(unsigned int x)
@@ -172,7 +127,7 @@ static int init(struct ao *ao)
}
desired.freq = ao->samplerate;
desired.channels = ao->channels.num;
- desired.samples = FFMIN(32768, ceil_power_of_two(ao->samplerate *
+ desired.samples = MPMIN(32768, ceil_power_of_two(ao->samplerate *
priv->buflen));
desired.callback = audio_callback;
desired.userdata = ao;
@@ -227,125 +182,26 @@ static int init(struct ao *ao)
}
ao->samplerate = obtained.freq;
- priv->buffer = av_fifo_alloc(obtained.size * priv->bufcnt);
- priv->buffer_mutex = SDL_CreateMutex();
- if (!priv->buffer_mutex) {
- MP_ERR(ao, "SDL_CreateMutex failed\n");
- uninit(ao);
- return -1;
- }
- priv->underrun_cond = SDL_CreateCond();
- if (!priv->underrun_cond) {
- MP_ERR(ao, "SDL_CreateCond failed\n");
- uninit(ao);
- return -1;
- }
- priv->unpause = 1;
priv->paused = 1;
- priv->callback_time0 = priv->callback_time1 = mp_time_us();
return 1;
}
-static void reset(struct ao *ao)
-{
- struct priv *priv = ao->priv;
- SDL_LockMutex(priv->buffer_mutex);
- av_fifo_reset(priv->buffer);
- SDL_UnlockMutex(priv->buffer_mutex);
-}
-
-static int get_space(struct ao *ao)
-{
- struct priv *priv = ao->priv;
- SDL_LockMutex(priv->buffer_mutex);
- int space = av_fifo_space(priv->buffer);
- SDL_UnlockMutex(priv->buffer_mutex);
- return space / ao->sstride;
-}
-
static void pause(struct ao *ao)
{
struct priv *priv = ao->priv;
- SDL_PauseAudio(SDL_TRUE);
- priv->unpause = 0;
+ if (!priv->paused)
+ SDL_PauseAudio(SDL_TRUE);
priv->paused = 1;
- SDL_CondSignal(priv->underrun_cond);
-}
-
-static void do_resume(struct ao *ao)
-{
- struct priv *priv = ao->priv;
- priv->paused = 0;
- SDL_PauseAudio(SDL_FALSE);
}
static void resume(struct ao *ao)
{
struct priv *priv = ao->priv;
- SDL_LockMutex(priv->buffer_mutex);
- int free = av_fifo_space(priv->buffer);
- SDL_UnlockMutex(priv->buffer_mutex);
- if (free)
- priv->unpause = 1;
- else
- do_resume(ao);
-}
-
-static int play(struct ao *ao, void **data, int samples, int flags)
-{
- struct priv *priv = ao->priv;
- int len = samples * ao->sstride;
- SDL_LockMutex(priv->buffer_mutex);
- int free = av_fifo_space(priv->buffer);
- if (len > free) len = free;
- av_fifo_generic_write(priv->buffer, data[0], len, NULL);
- SDL_CondSignal(priv->underrun_cond);
- SDL_UnlockMutex(priv->buffer_mutex);
- if (priv->unpause) {
- priv->unpause = 0;
- do_resume(ao);
- }
- return len / ao->sstride;
-}
-
-static float get_delay(struct ao *ao)
-{
- struct priv *priv = ao->priv;
- SDL_LockMutex(priv->buffer_mutex);
- int sz = av_fifo_size(priv->buffer);
-#ifdef ESTIMATE_DELAY
- int64_t callback_time0 = priv->callback_time0;
- int64_t callback_time1 = priv->callback_time1;
-#endif
- SDL_UnlockMutex(priv->buffer_mutex);
-
- // delay component: our FIFO's length
- float delay = sz / (float) ao->bps;
-
-#ifdef ESTIMATE_DELAY
- // delay component: outstanding audio living in SDL
-
- int64_t current_time = mp_time_us();
-
- // interval between callbacks
- int64_t callback_interval = callback_time0 - callback_time1;
- int64_t elapsed_interval = current_time - callback_time0;
- if (elapsed_interval > callback_interval)
- elapsed_interval = callback_interval;
-
- // delay subcomponent: remaining audio from the currently played buffer
- int64_t buffer_interval = callback_interval - elapsed_interval;
-
- // delay subcomponent: remaining audio from the next played buffer, as
- // provided by the callback
- buffer_interval += callback_interval;
-
- delay += buffer_interval / 1000000.0;
-#endif
-
- return delay;
+ if (priv->paused)
+ SDL_PauseAudio(SDL_FALSE);
+ priv->paused = 0;
}
#define OPT_BASE_STRUCT struct priv
@@ -355,20 +211,14 @@ const struct ao_driver audio_out_sdl = {
.name = "sdl",
.init = init,
.uninit = uninit,
- .get_space = get_space,
- .play = play,
- .get_delay = get_delay,
.pause = pause,
.resume = resume,
- .reset = reset,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.buflen = 0, // use SDL default
- .bufcnt = 2,
},
.options = (const struct m_option[]) {
OPT_FLOAT("buflen", buflen, 0),
- OPT_FLOAT("bufcnt", bufcnt, 0),
{0}
},
};