mirror of
https://github.com/mpv-player/mpv
synced 2025-02-27 02:40:53 +00:00
ao_opensles: rework the heuristic of buffer/enqueue size setting
ao->device_buffer will only affect the enqueue size if the latter is not specified. In other word, its intended purpose will solely be setting/guarding the soft buffer size. This guarantees that the soft buffer size will be consistent no matter a specific enqueue size is set or not. (In the past it would drop to the default of the generic audio-buffer option.) opensles-frames-per-buffer has been renamed to opensles-frames-per -enqueue, as it was never purposed to set the soft buffer size. It will only make sure the size is never smaller than itself, just as before. opensles-buffer-size-in-ms is introduced to allow easy tuning of the relative (i.e. in time) soft buffer size (and enqueue size, unless the aforementioned option is set). As "device buffer" never really made sense in this AO, this option OVERRIDES audio-buffer whenever its value (including the default) is larger than 0. Setting opensl-buffer-size-in-ms to 1 allows you to equate the soft buffer size to the absolute enqueue size set with opensl-frames-per -enqueue conveniently (unless it is less than 1ms). When both are set to 0, audio-buffer will be the ultimate fallback. If audio-buffer is also 0, the AO errors out.
This commit is contained in:
parent
8baad91e7b
commit
e1bd5288b7
@ -35,12 +35,13 @@ struct priv {
|
||||
SLBufferQueueItf buffer_queue;
|
||||
SLEngineItf engine;
|
||||
SLPlayItf play;
|
||||
char *buf;
|
||||
size_t buffer_size;
|
||||
void *buf;
|
||||
int bytes_per_enqueue;
|
||||
pthread_mutex_t buffer_lock;
|
||||
double audio_latency;
|
||||
|
||||
int cfg_frames_per_buffer;
|
||||
int frames_per_enqueue;
|
||||
int buffer_size_in_ms;
|
||||
};
|
||||
|
||||
#define DESTROY(thing) \
|
||||
@ -65,7 +66,6 @@ static void uninit(struct ao *ao)
|
||||
|
||||
free(p->buf);
|
||||
p->buf = NULL;
|
||||
p->buffer_size = 0;
|
||||
}
|
||||
|
||||
#undef DESTROY
|
||||
@ -75,26 +75,22 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
|
||||
struct ao *ao = context;
|
||||
struct priv *p = ao->priv;
|
||||
SLresult res;
|
||||
void *data[1];
|
||||
double delay;
|
||||
|
||||
pthread_mutex_lock(&p->buffer_lock);
|
||||
|
||||
data[0] = p->buf;
|
||||
delay = 2 * p->buffer_size / (double)ao->bps;
|
||||
delay = 2 * p->frames_per_enqueue / (double)ao->samplerate;
|
||||
delay += p->audio_latency;
|
||||
ao_read_data(ao, data, p->buffer_size / ao->sstride,
|
||||
ao_read_data(ao, &p->buf, p->frames_per_enqueue,
|
||||
mp_time_us() + 1000000LL * delay);
|
||||
|
||||
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->buffer_size);
|
||||
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->bytes_per_enqueue);
|
||||
if (res != SL_RESULT_SUCCESS)
|
||||
MP_ERR(ao, "Failed to Enqueue: %d\n", res);
|
||||
|
||||
pthread_mutex_unlock(&p->buffer_lock);
|
||||
}
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE_MS 250
|
||||
|
||||
#define CHK(stmt) \
|
||||
{ \
|
||||
SLresult res = stmt; \
|
||||
@ -143,17 +139,35 @@ static int init(struct ao *ao)
|
||||
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
||||
pcm.sampleRate = ao->samplerate * 1000;
|
||||
|
||||
if (p->cfg_frames_per_buffer)
|
||||
ao->device_buffer = p->cfg_frames_per_buffer;
|
||||
else
|
||||
ao->device_buffer = ao->samplerate * DEFAULT_BUFFER_SIZE_MS / 1000;
|
||||
p->buffer_size = ao->device_buffer * ao->channels.num *
|
||||
if (p->buffer_size_in_ms) {
|
||||
ao->device_buffer = ao->samplerate * p->buffer_size_in_ms / 1000;
|
||||
// As the purpose of buffer_size_in_ms is to request a specific
|
||||
// soft buffer size:
|
||||
ao->def_buffer = 0;
|
||||
}
|
||||
|
||||
// But it does not make sense if it is smaller than the enqueue size:
|
||||
if (p->frames_per_enqueue) {
|
||||
ao->device_buffer = MPMAX(ao->device_buffer, p->frames_per_enqueue);
|
||||
} else {
|
||||
if (ao->device_buffer) {
|
||||
p->frames_per_enqueue = ao->device_buffer;
|
||||
} else if (ao->def_buffer) {
|
||||
p->frames_per_enqueue = ao->def_buffer * ao->samplerate;
|
||||
} else {
|
||||
MP_ERR(ao, "Enqueue size is not set and can neither be derived\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
p->bytes_per_enqueue = p->frames_per_enqueue * ao->channels.num *
|
||||
af_fmt_to_bytes(ao->format);
|
||||
p->buf = calloc(1, p->buffer_size);
|
||||
p->buf = calloc(1, p->bytes_per_enqueue);
|
||||
if (!p->buf) {
|
||||
MP_ERR(ao, "Failed to allocate device buffer\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
int r = pthread_mutex_init(&p->buffer_lock, NULL);
|
||||
if (r) {
|
||||
MP_ERR(ao, "Failed to initialize the mutex: %d\n", r);
|
||||
@ -236,8 +250,12 @@ const struct ao_driver audio_out_opensles = {
|
||||
.resume = resume,
|
||||
|
||||
.priv_size = sizeof(struct priv),
|
||||
.priv_defaults = &(const struct priv) {
|
||||
.buffer_size_in_ms = 250,
|
||||
},
|
||||
.options = (const struct m_option[]) {
|
||||
OPT_INTRANGE("frames-per-buffer", cfg_frames_per_buffer, 0, 1, 96000),
|
||||
OPT_INTRANGE("frames-per-enqueue", frames_per_enqueue, 0, 1, 96000),
|
||||
OPT_INTRANGE("buffer-size-in-ms", buffer_size_in_ms, 0, 0, 500),
|
||||
{0}
|
||||
},
|
||||
.options_prefix = "opensles",
|
||||
|
Loading…
Reference in New Issue
Block a user