summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAGonauta <lagonauta@gmail.com>2018-04-01 10:26:45 -0300
committerJan Ekström <jeebjp@gmail.com>2018-04-15 00:57:01 +0300
commit614ad62f891f8dc0156ae57631fb9195e56df026 (patch)
tree7e0b8d022a882d6433c8521a62f3436acd80d3d7
parent567df04012121a1d8e2a145deff11354fefd4876 (diff)
downloadmpv-614ad62f891f8dc0156ae57631fb9195e56df026.tar.bz2
mpv-614ad62f891f8dc0156ae57631fb9195e56df026.tar.xz
ao/openal: Add option to set buffering characteristics
One can now set the number of buffers and the buffer size. This can reduce the CPU usage and the total latency stays mostly the same. As there are sync mechanisms the A/V sync continue intact and working. It also modifies 6.1 channel order, as per OpenAL spec and add AOPLAY_FINAL_CHUNK support
-rw-r--r--DOCS/man/ao.rst8
-rw-r--r--audio/out/ao_openal.c85
2 files changed, 70 insertions, 23 deletions
diff --git a/DOCS/man/ao.rst b/DOCS/man/ao.rst
index 5beca55384..3fc1ba9734 100644
--- a/DOCS/man/ao.rst
+++ b/DOCS/man/ao.rst
@@ -112,6 +112,14 @@ Available audio output drivers are:
``openal``
Experimental OpenAL audio output driver
+ ``--openal-num-buffers=<2-128>``
+ Specify the number of audio buffers to use. Lower values are better for
+ lower CPU usage. Default: 4.
+
+ ``--openal-num-samples=<256-32768>``
+ Specify the number of complete samples to use for each buffer. Higher
+ values are better for lower CPU usage. Default: 8192.
+
``--openal-direct-channels=<yes|no>``
Enable OpenAL Soft's direct channel extension when available to avoid
tinting the sound with ambisonics or HRTF.
diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c
index 4d82a09ddb..9381d2a906 100644
--- a/audio/out/ao_openal.c
+++ b/audio/out/ao_openal.c
@@ -57,9 +57,10 @@
#include "options/m_option.h"
#define MAX_CHANS MP_NUM_CHANNELS
-#define NUM_BUF 128
-#define CHUNK_SAMPLES 256
-static ALuint buffers[NUM_BUF];
+#define MAX_BUF 128
+#define MAX_SAMPLES 32768
+static ALuint buffers[MAX_BUF];
+static ALuint buffer_size[MAX_BUF];
static ALuint source;
static int cur_buf;
@@ -69,7 +70,8 @@ static struct ao *ao_data;
struct priv {
ALenum al_format;
- int chunk_size;
+ int num_buffers;
+ int num_samples;
int direct_channels;
};
@@ -171,10 +173,11 @@ static ALenum get_supported_layout(int format, int channels)
// close audio device
static void uninit(struct ao *ao)
{
+ struct priv *p = ao->priv;
alSourceStop(source);
alSourcei(source, AL_BUFFER, 0);
- alDeleteBuffers(NUM_BUF, buffers);
+ alDeleteBuffers(p->num_buffers, buffers);
alDeleteSources(1, &source);
ALCcontext *ctx = alcGetCurrentContext();
@@ -217,7 +220,11 @@ static int init(struct ao *ao)
cur_buf = 0;
unqueue_buf = 0;
- alGenBuffers(NUM_BUF, buffers);
+ for (int i = 0; i < p->num_buffers; ++i) {
+ buffer_size[i] = 0;
+ }
+
+ alGenBuffers(p->num_buffers, buffers);
alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq);
if (alcGetError(dev) == ALC_NO_ERROR && freq)
@@ -259,7 +266,7 @@ static int init(struct ao *ao)
MP_CHMAP4(FL, FR, BL, BR), // 4.0
{0}, // 5.0
MP_CHMAP6(FL, FR, FC, LFE, BL, BR), // 5.1
- MP_CHMAP7(FL, FR, FC, LFE, BC, SL, SR), // 6.1
+ MP_CHMAP7(FL, FR, FC, LFE, SL, SR, BC), // 6.1
MP_CHMAP8(FL, FR, FC, LFE, BL, BR, SL, SR), // 7.1
};
ao->channels = possible_layouts[num_channels];
@@ -272,8 +279,7 @@ static int init(struct ao *ao)
goto err_out;
}
- p->chunk_size = CHUNK_SAMPLES * af_fmt_to_bytes(ao->format);
- ao->period_size = CHUNK_SAMPLES;
+ ao->period_size = p->num_samples;
return 0;
err_out:
@@ -291,10 +297,11 @@ static void drain(struct ao *ao)
}
}
-static void unqueue_buffers(void)
+static void unqueue_buffers(struct ao *ao)
{
+ struct priv *q = ao->priv;
ALint p;
- int till_wrap = NUM_BUF - unqueue_buf;
+ int till_wrap = q->num_buffers - unqueue_buf;
alGetSourcei(source, AL_BUFFERS_PROCESSED, &p);
if (p >= till_wrap) {
alSourceUnqueueBuffers(source, till_wrap, &buffers[unqueue_buf]);
@@ -313,7 +320,7 @@ static void unqueue_buffers(void)
static void reset(struct ao *ao)
{
alSourceStop(source);
- unqueue_buffers();
+ unqueue_buffers(ao);
}
/**
@@ -334,13 +341,14 @@ static void audio_resume(struct ao *ao)
static int get_space(struct ao *ao)
{
+ struct priv *p = ao->priv;
ALint queued;
- unqueue_buffers();
+ unqueue_buffers(ao);
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
- queued = NUM_BUF - queued - 3;
+ queued = p->num_buffers - queued;
if (queued < 0)
return 0;
- return queued * CHUNK_SAMPLES;
+ return p->num_samples * queued;
}
/**
@@ -349,25 +357,44 @@ static int get_space(struct ao *ao)
static int play(struct ao *ao, void **data, int samples, int flags)
{
struct priv *p = ao->priv;
- ALint state;
- int num = samples / CHUNK_SAMPLES;
+
+ int buffered_samples = 0;
+ int num = 0;
+ if (flags & AOPLAY_FINAL_CHUNK) {
+ num = 1;
+ buffered_samples = samples;
+ } else {
+ num = samples / p->num_samples;
+ buffered_samples = num * p->num_samples;
+ }
+
for (int i = 0; i < num; i++) {
char *d = *data;
- d += i * p->chunk_size * ao->channels.num;
- alBufferData(buffers[cur_buf], p->al_format, d, p->chunk_size * ao->channels.num, ao->samplerate);
+ if (flags & AOPLAY_FINAL_CHUNK) {
+ buffer_size[cur_buf] = samples;
+ } else {
+ buffer_size[cur_buf] = p->num_samples;
+ }
+ d += i * buffer_size[cur_buf] * ao->sstride;
+ alBufferData(buffers[cur_buf], p->al_format, d,
+ buffer_size[cur_buf] * ao->sstride, ao->samplerate);
alSourceQueueBuffers(source, 1, &buffers[cur_buf]);
- cur_buf = (cur_buf + 1) % NUM_BUF;
+ cur_buf = (cur_buf + 1) % p->num_buffers;
}
+
+ ALint state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
if (state != AL_PLAYING) // checked here in case of an underrun
alSourcePlay(source);
- return num * CHUNK_SAMPLES;
+
+ return buffered_samples;
}
static double get_delay(struct ao *ao)
{
+ struct priv *p = ao->priv;
ALint queued;
- unqueue_buffers();
+ unqueue_buffers(ao);
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
double soft_source_latency = 0;
@@ -384,7 +411,12 @@ static double get_delay(struct ao *ao)
soft_source_latency = -offset;
}
- return (queued * CHUNK_SAMPLES / (double)ao->samplerate) + soft_source_latency;
+ int queued_samples = 0;
+ for (int i = 0, index = cur_buf; i < queued; ++i) {
+ queued_samples += buffer_size[index];
+ index = (index + 1) % p->num_buffers;
+ }
+ return (queued_samples / (double)ao->samplerate) + soft_source_latency;
}
#define OPT_BASE_STRUCT struct priv
@@ -403,7 +435,14 @@ const struct ao_driver audio_out_openal = {
.reset = reset,
.drain = drain,
.priv_size = sizeof(struct priv),
+ .priv_defaults = &(const struct priv) {
+ .num_buffers = 4,
+ .num_samples = 8192,
+ .direct_channels = 0,
+ },
.options = (const struct m_option[]) {
+ OPT_INTRANGE("num-buffers", num_buffers, 0, 2, MAX_BUF),
+ OPT_INTRANGE("num-samples", num_samples, 0, 256, MAX_SAMPLES),
OPT_FLAG("direct-channels", direct_channels, 0),
{0}
},