summaryrefslogtreecommitdiffstats
path: root/audio/out/internal.h
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-03-09 00:04:37 +0100
committerwm4 <wm4@nowhere>2014-03-09 01:27:41 +0100
commita477481aabaa16f1ed15af456125160bc8face5a (patch)
treec99949f3e13e7c7ba498c56edcbcfa433e487cd3 /audio/out/internal.h
parent5ffd6a9e9b7a0d894d7513ad20c24c2727426ecd (diff)
downloadmpv-a477481aabaa16f1ed15af456125160bc8face5a.tar.bz2
mpv-a477481aabaa16f1ed15af456125160bc8face5a.tar.xz
audio/out: feed AOs from a separate thread
This has 2 goals: - Ensure that AOs have always enough data, even if the device buffers are very small. - Reduce complexity in some AOs, which do their own buffering. One disadvantage is that performance is slightly reduced due to more copying. Implementation-wise, we don't change ao.c much, and instead "redirect" the driver's callback to an API wrapper in push.c. Additionally, we add code for dealing with AOs that have a pull API. These AOs usually do their own buffering (jack, coreaudio, portaudio), and adding a thread is basically a waste. The code in pull.c manages a ringbuffer, and allows callback-based AOs to read data directly.
Diffstat (limited to 'audio/out/internal.h')
-rw-r--r--audio/out/internal.h59
1 files changed, 56 insertions, 3 deletions
diff --git a/audio/out/internal.h b/audio/out/internal.h
index e996f8afeb..98de7e08b3 100644
--- a/audio/out/internal.h
+++ b/audio/out/internal.h
@@ -19,25 +19,74 @@
#ifndef MP_AO_INTERNAL_H_
#define MP_AO_INTERNAL_H_
+#include <stdbool.h>
+
+#include "audio/chmap.h"
+#include "audio/chmap_sel.h"
+
/* global data used by ao.c and ao drivers */
struct ao {
int samplerate;
struct mp_chmap channels;
int format; // one of AF_FORMAT_...
- int bps; // bytes per second
+ int bps; // bytes per second (per plane)
int sstride; // size of a sample on each plane
// (format_size*num_channels/num_planes)
+ int num_planes;
bool probing; // if true, don't fail loudly on init
bool untimed; // don't assume realtime playback
bool no_persistent_volume; // the AO does the equivalent of af_volume
bool per_application_mixer; // like above, but volume persists (per app)
+ int device_buffer; // device buffer in samples (guessed by
+ // common init code if not set by driver)
+ const struct ao_driver *api; // entrypoints to the wrapper (push.c/pull.c)
const struct ao_driver *driver;
void *priv;
struct encode_lavc_context *encode_lavc_ctx;
struct input_ctx *input_ctx;
struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix
+
+ int buffer;
+ void *api_priv;
};
+extern const struct ao_driver ao_api_push;
+extern const struct ao_driver ao_api_pull;
+
+
+/* Note:
+ *
+ * In general, there are two types of audio drivers:
+ * a) push based (the user queues data that should be played)
+ * b) pull callback based (the audio API calls a callback to get audio)
+ *
+ * The ao.c code can handle both. It basically implements two audio paths
+ * and provides a uniform API for them. If ao_driver->play is NULL, it assumes
+ * that the driver uses a callback based audio API, otherwise push based.
+ *
+ * Requirements:
+ * a) Most functions (except ->control) must be provided. ->play is called to
+ * queue audio. ao.c creates a thread to regularly refill audio device
+ * buffers with ->play, but all driver functions are always called under
+ * an exclusive lock.
+ * Mandatory:
+ * init
+ * uninit
+ * reset
+ * get_space
+ * play
+ * get_delay
+ * pause
+ * resume
+ * b) ->play must be NULL. The driver can start the audio API in init(). The
+ * audio API in turn will start a thread and call a callback provided by the
+ * driver. That callback calls ao_read_data() to get audio data. Most
+ * functions are optional and will be emulated if missing (e.g. pausing
+ * is emulated as silence). ->get_delay and ->get_space are never called.
+ * Mandatory:
+ * init
+ * uninit
+ */
struct ao_driver {
// If true, use with encoding only.
bool encode;
@@ -49,7 +98,7 @@ struct ao_driver {
// device doesn't accept these parameters, you can attempt to negotiate
// fallback parameters, and set the ao format fields accordingly.
int (*init)(struct ao *ao);
- // See ao_control() etc. in ao.c
+ // Optional. See ao_control() etc. in ao.c
int (*control)(struct ao *ao, enum aocontrol cmd, void *arg);
void (*uninit)(struct ao *ao, bool cut_audio);
void (*reset)(struct ao*ao);
@@ -65,8 +114,12 @@ struct ao_driver {
const struct m_option *options;
};
-// These functions can be called by AOs. They don't lock the AO.
+// These functions can be called by AOs.
+
int ao_play_silence(struct ao *ao, int samples);
+void ao_wait_drain(struct ao *ao);
+int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us);
+
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);
bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,