diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index 2a4838ead5abe..c82874544d388 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -32,6 +32,8 @@ API changes :: + --- mpv 0.41.0 --- + 2.6 - add mpv_set_audio_callback() --- mpv 0.40.0 --- 2.5 - Deprecate MPV_RENDER_PARAM_AMBIENT_LIGHT. no replacement. --- mpv 0.39.0 --- diff --git a/audio/out/ao.c b/audio/out/ao.c index ee76b702ea580..0eb427f832e02 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -51,6 +51,7 @@ extern const struct ao_driver audio_out_opensles; extern const struct ao_driver audio_out_null; extern const struct ao_driver audio_out_alsa; extern const struct ao_driver audio_out_wasapi; +extern const struct ao_driver audio_out_libmpv; extern const struct ao_driver audio_out_pcm; extern const struct ao_driver audio_out_lavc; extern const struct ao_driver audio_out_sdl; @@ -104,6 +105,7 @@ static const struct ao_driver * const audio_out_drivers[] = { #if HAVE_COREAUDIO &audio_out_coreaudio_exclusive, #endif + &audio_out_libmpv, &audio_out_pcm, &audio_out_lavc, }; diff --git a/audio/out/ao_libmpv.c b/audio/out/ao_libmpv.c new file mode 100644 index 0000000000000..6fc88986a4090 --- /dev/null +++ b/audio/out/ao_libmpv.c @@ -0,0 +1,107 @@ +/* + * libmpv audio output driver + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include "ao.h" +#include "audio/format.h" +#include "ao_libmpv.h" +#include "internal.h" +#include "common/msg.h" + +struct priv { + void (*write_cb)(void *userdata, const void *data, int bytes); + void *userdata; +}; + +void ao_libmpv_set_cb(struct ao *ao, void (*cb)(void *userdata, const void *data, int bytes), void *userdata) +{ + struct priv *p = ao->priv; + p->write_cb = cb; + p->userdata = userdata; +} + +static int init(struct ao *ao) +{ + ao->format = af_fmt_from_planar(ao->format); + + struct mp_chmap_sel sel = {0}; + mp_chmap_sel_add_waveext(&sel); + if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) + return -1; + + ao->bps = ao->channels.num * (int64_t)ao->samplerate * af_fmt_to_bytes(ao->format); + + MP_INFO(ao, "libmpv: Samplerate: %d Hz Channels: %d Format: %s\n", + ao->samplerate, ao->channels.num, af_fmt_to_str(ao->format)); + + ao->untimed = true; + ao->device_buffer = 1 << 16; + + return 0; +} + +static void uninit(struct ao *ao) +{ +} + +static bool audio_write(struct ao *ao, void **data, int samples) +{ + struct priv *priv = ao->priv; + const int len = samples * ao->sstride; + + if (priv->write_cb) + priv->write_cb(priv->userdata, data[0], len); + + return true; +} + +static void get_state(struct ao *ao, struct mp_pcm_state *state) +{ + state->free_samples = ao->device_buffer; + state->queued_samples = 0; + state->delay = 0; +} + +static bool set_pause(struct ao *ao, bool paused) +{ + return true; // signal support so common code doesn't write silence +} + +static void start(struct ao *ao) +{ + // we use data immediately +} + +static void reset(struct ao *ao) +{ +} + +#define OPT_BASE_STRUCT struct priv + +const struct ao_driver audio_out_libmpv = { + .description = "libmpv audio output with a callback", + .name = "libmpv", + .init = init, + .uninit = uninit, + .get_state = get_state, + .set_pause = set_pause, + .write = audio_write, + .start = start, + .reset = reset, + .priv_size = sizeof(struct priv), +}; diff --git a/audio/out/ao_libmpv.h b/audio/out/ao_libmpv.h new file mode 100644 index 0000000000000..2adb446c61081 --- /dev/null +++ b/audio/out/ao_libmpv.h @@ -0,0 +1,24 @@ +/* + * libmpv audio output driver + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#pragma once + +#include "ao.h" + +void ao_libmpv_set_cb(struct ao *ao, void (*cb)(void *userdata, const void *data, int bytes), void *userdata); diff --git a/include/mpv/client.h b/include/mpv/client.h index 85cff63bd5d20..8261dde61816e 100644 --- a/include/mpv/client.h +++ b/include/mpv/client.h @@ -248,7 +248,7 @@ extern "C" { * relational operators (<, >, <=, >=). */ #define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL) -#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(2, 5) +#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(2, 6) /** * The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before @@ -1768,6 +1768,18 @@ MPV_EXPORT void mpv_wakeup(mpv_handle *ctx); */ MPV_EXPORT void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d); + /** + * Set a custom function that should be called on new audio data. + * Raw PCM is passed in as an argument to the callback, the format should be set before init using appropriate options. + * + * This can only be used with ao_libmpv and must be called before the ao is initialized (so before playback starts). + * Only one audio callback can be set per instance. + * + * @param cb function that should be called on audio data + * @param d arbitrary userdata passed to cb + */ +MPV_EXPORT void mpv_set_audio_callback(mpv_handle *ctx, void (*cb)(void *d, const void *data, int bytes), void *d); + /** * Block until all asynchronous requests are done. This affects functions like * mpv_command_async(), which return immediately and return their result as diff --git a/meson.build b/meson.build index 94ee12feee4f1..45b293522c42b 100644 --- a/meson.build +++ b/meson.build @@ -72,6 +72,7 @@ sources = files( 'audio/out/ao.c', 'audio/out/ao_lavc.c', 'audio/out/ao_null.c', + 'audio/out/ao_libmpv.c', 'audio/out/ao_pcm.c', 'audio/out/buffer.c', diff --git a/player/audio.c b/player/audio.c index b3e975dd2eda3..38870f10f9588 100644 --- a/player/audio.c +++ b/player/audio.c @@ -21,6 +21,8 @@ #include #include #include +#include