From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Eduardo Habkost" <eduardo@habkost.net>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"Akihiko Odaki" <akihiko.odaki@gmail.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Thomas Huth" <huth@tuxfamily.org>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Volker Rümelin" <vr_qemu@t-online.de>,
"Christian Schoenebeck" <qemu_oss@crudebyte.com>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>
Subject: [PULL 17/35] audio: restore mixing-engine playback buffer size
Date: Fri, 4 Mar 2022 15:21:05 +0100 [thread overview]
Message-ID: <20220304142123.956171-18-kraxel@redhat.com> (raw)
In-Reply-To: <20220304142123.956171-1-kraxel@redhat.com>
From: Volker Rümelin <vr_qemu@t-online.de>
Commit ff095e5231 "audio: api for mixeng code free backends"
introduced another FIFO for the audio subsystem with exactly the
same size as the mixing-engine FIFO. Most audio backends use
this generic FIFO. The generic FIFO used together with the
mixing-engine FIFO doubles the audio FIFO size, because that's
just two independent FIFOs connected together in series.
For audio playback this nearly doubles the playback latency.
This patch restores the effective mixing-engine playback buffer
size to a pre v4.2.0 size by only accepting the amount of
samples for the mixing-engine queue which the downstream queue
accepts.
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Message-Id: <20220301191311.26695-10-vr_qemu@t-online.de>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
audio/audio_int.h | 7 ++++-
audio/alsaaudio.c | 1 +
audio/audio.c | 69 +++++++++++++++++++++++++++++++++++------------
audio/coreaudio.c | 3 +++
audio/jackaudio.c | 1 +
audio/noaudio.c | 1 +
audio/ossaudio.c | 12 +++++++++
audio/sdlaudio.c | 3 +++
audio/wavaudio.c | 1 +
9 files changed, 80 insertions(+), 18 deletions(-)
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 71be162271b5..2a6914d2aa65 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -161,10 +161,14 @@ struct audio_pcm_ops {
void (*fini_out)(HWVoiceOut *hw);
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
void (*run_buffer_out)(HWVoiceOut *hw);
+ /*
+ * Get the free output buffer size. This is an upper limit. The size
+ * returned by function get_buffer_out may be smaller.
+ */
+ size_t (*buffer_get_free)(HWVoiceOut *hw);
/*
* get a buffer that after later can be passed to put_buffer_out; optional
* returns the buffer, and writes it's size to size (in bytes)
- * this is unrelated to the above buffer_size_out function
*/
void *(*get_buffer_out)(HWVoiceOut *hw, size_t *size);
/*
@@ -190,6 +194,7 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw);
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
void audio_generic_run_buffer_out(HWVoiceOut *hw);
+size_t audio_generic_buffer_get_free(HWVoiceOut *hw);
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 2b9789e64771..b04716a6cc21 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -916,6 +916,7 @@ static struct audio_pcm_ops alsa_pcm_ops = {
.init_out = alsa_init_out,
.fini_out = alsa_fini_out,
.write = alsa_write,
+ .buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = alsa_enable_out,
diff --git a/audio/audio.c b/audio/audio.c
index c420a8bd1c4a..a88572e71388 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -663,6 +663,12 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
return 0;
}
+static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
+{
+ return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
+ INT_MAX) / hw->info.bytes_per_frame;
+}
+
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
{
size_t clipped = 0;
@@ -687,7 +693,8 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
*/
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
{
- size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
+ size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
+ size_t hw_free;
size_t ret = 0, pos = 0, total = 0;
if (!sw) {
@@ -710,27 +717,28 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
}
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
- samples = size / sw->info.bytes_per_frame;
dead = hwsamples - live;
- swlim = ((int64_t) dead << 32) / sw->ratio;
- swlim = MIN (swlim, samples);
- if (swlim) {
- sw->conv (sw->buf, buf, swlim);
+ hw_free = audio_pcm_hw_get_free(sw->hw);
+ hw_free = hw_free > live ? hw_free - live : 0;
+ samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
+ samples = MIN(samples, size / sw->info.bytes_per_frame);
+ if (samples) {
+ sw->conv(sw->buf, buf, samples);
if (!sw->hw->pcm_ops->volume_out) {
- mixeng_volume (sw->buf, swlim, &sw->vol);
+ mixeng_volume(sw->buf, samples, &sw->vol);
}
}
- while (swlim) {
+ while (samples) {
dead = hwsamples - live;
left = hwsamples - wpos;
blck = MIN (dead, left);
if (!blck) {
break;
}
- isamp = swlim;
+ isamp = samples;
osamp = blck;
st_rate_flow_mix (
sw->rate,
@@ -740,7 +748,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
&osamp
);
ret += isamp;
- swlim -= isamp;
+ samples -= isamp;
pos += isamp;
live += osamp;
wpos = (wpos + osamp) % hwsamples;
@@ -1002,6 +1010,11 @@ static size_t audio_get_avail (SWVoiceIn *sw)
return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
+static size_t audio_sw_bytes_free(SWVoiceOut *sw, size_t free)
+{
+ return (((int64_t)free << 32) / sw->ratio) * sw->info.bytes_per_frame;
+}
+
static size_t audio_get_free(SWVoiceOut *sw)
{
size_t live, dead;
@@ -1021,13 +1034,11 @@ static size_t audio_get_free(SWVoiceOut *sw)
dead = sw->hw->mix_buf->size - live;
#ifdef DEBUG_OUT
- dolog ("%s: get_free live %zu dead %zu ret %" PRId64 "\n",
- SW_NAME (sw),
- live, dead, (((int64_t) dead << 32) / sw->ratio) *
- sw->info.bytes_per_frame);
+ dolog("%s: get_free live %zu dead %zu sw_bytes %zu\n",
+ SW_NAME(sw), live, dead, audio_sw_bytes_free(sw, dead));
#endif
- return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
+ return dead;
}
static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
@@ -1131,12 +1142,21 @@ static void audio_run_out (AudioState *s)
}
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
- size_t played, live, prev_rpos, free;
+ size_t played, live, prev_rpos;
+ size_t hw_free = audio_pcm_hw_get_free(hw);
int nb_live;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
- free = audio_get_free(sw);
+ size_t sw_free = audio_get_free(sw);
+ size_t free;
+
+ if (hw_free > sw->total_hw_samples_mixed) {
+ free = audio_sw_bytes_free(sw,
+ MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
+ } else {
+ free = 0;
+ }
if (free > 0) {
sw->callback.fn(sw->callback.opaque, free);
}
@@ -1398,6 +1418,15 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
hw->pending_emul -= size;
}
+size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
+{
+ if (hw->buf_emul) {
+ return hw->size_emul - hw->pending_emul;
+ } else {
+ return hw->samples * hw->info.bytes_per_frame;
+ }
+}
+
void audio_generic_run_buffer_out(HWVoiceOut *hw)
{
while (hw->pending_emul) {
@@ -1445,6 +1474,12 @@ size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
{
size_t total = 0;
+ if (hw->pcm_ops->buffer_get_free) {
+ size_t free = hw->pcm_ops->buffer_get_free(hw);
+
+ size = MIN(size, free);
+ }
+
while (total < size) {
size_t dst_size = size - total;
size_t copy_size, proc;
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 1fdd1d4b14f6..91ea6ae975e5 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -283,6 +283,7 @@ static int coreaudio_buf_unlock (coreaudioVoiceOut *core, const char *fn_name)
coreaudio_buf_unlock(core, "coreaudio_" #name); \
return ret; \
}
+COREAUDIO_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw))
COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
(hw, size))
COREAUDIO_WRAPPER_FUNC(put_buffer_out, size_t,
@@ -652,6 +653,8 @@ static struct audio_pcm_ops coreaudio_pcm_ops = {
.fini_out = coreaudio_fini_out,
/* wrapper for audio_generic_write */
.write = coreaudio_write,
+ /* wrapper for audio_generic_buffer_get_free */
+ .buffer_get_free = coreaudio_buffer_get_free,
/* wrapper for audio_generic_get_buffer_out */
.get_buffer_out = coreaudio_get_buffer_out,
/* wrapper for audio_generic_put_buffer_out */
diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index 26246c3a8b43..bf757250b597 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -652,6 +652,7 @@ static struct audio_pcm_ops jack_pcm_ops = {
.init_out = qjack_init_out,
.fini_out = qjack_fini_out,
.write = qjack_write,
+ .buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = qjack_enable_out,
diff --git a/audio/noaudio.c b/audio/noaudio.c
index aac87dbc93fb..84a6bfbb1c87 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -118,6 +118,7 @@ static struct audio_pcm_ops no_pcm_ops = {
.init_out = no_init_out,
.fini_out = no_fini_out,
.write = no_write,
+ .buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = no_enable_out,
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 60eff66424b9..1bd680084065 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -389,6 +389,17 @@ static void oss_run_buffer_out(HWVoiceOut *hw)
}
}
+static size_t oss_buffer_get_free(HWVoiceOut *hw)
+{
+ OSSVoiceOut *oss = (OSSVoiceOut *)hw;
+
+ if (oss->mmapped) {
+ return INT_MAX;
+ } else {
+ return audio_generic_buffer_get_free(hw);
+ }
+}
+
static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
@@ -750,6 +761,7 @@ static struct audio_pcm_ops oss_pcm_ops = {
.init_out = oss_init_out,
.fini_out = oss_fini_out,
.write = oss_write,
+ .buffer_get_free = oss_buffer_get_free,
.run_buffer_out = oss_run_buffer_out,
.get_buffer_out = oss_get_buffer_out,
.put_buffer_out = oss_put_buffer_out,
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index d6f3aa1a9ac5..e605c787baf3 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -309,6 +309,7 @@ static void sdl_callback_in(void *opaque, Uint8 *buf, int len)
SDL_UnlockAudioDevice(sdl->devid); \
}
+SDL_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw), Out)
SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
(hw, size), Out)
SDL_WRAPPER_FUNC(put_buffer_out, size_t,
@@ -471,6 +472,8 @@ static struct audio_pcm_ops sdl_pcm_ops = {
.fini_out = sdl_fini_out,
/* wrapper for audio_generic_write */
.write = sdl_write,
+ /* wrapper for audio_generic_buffer_get_free */
+ .buffer_get_free = sdl_buffer_get_free,
/* wrapper for audio_generic_get_buffer_out */
.get_buffer_out = sdl_get_buffer_out,
/* wrapper for audio_generic_put_buffer_out */
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index 20e6853f8586..ac666335c783 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -197,6 +197,7 @@ static struct audio_pcm_ops wav_pcm_ops = {
.init_out = wav_init_out,
.fini_out = wav_fini_out,
.write = wav_write_out,
+ .buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = wav_enable_out,
};
--
2.35.1
next prev parent reply other threads:[~2022-03-04 14:59 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-04 14:20 [PULL 00/35] Kraxel 20220304 patches Gerd Hoffmann
2022-03-04 14:20 ` [PULL 01/35] hw/usb: pacify xhciwmi.exe warning Gerd Hoffmann
2022-03-04 14:20 ` [PULL 02/35] hw/usb/dev-mtp: create directories with a+x mode mask Gerd Hoffmann
2022-03-04 14:20 ` [PULL 03/35] usb/ohci: Move trace point and log ep number to help debugging Gerd Hoffmann
2022-03-04 14:20 ` [PULL 04/35] usb/ohci: Move cancelling async packet to ohci_stop_endpoints() Gerd Hoffmann
2022-03-04 14:20 ` [PULL 05/35] usb/ohci: Move USBPortOps related functions together Gerd Hoffmann
2022-03-04 14:20 ` [PULL 06/35] usb/ohci: Merge ohci_async_cancel_device() into ohci_child_detach() Gerd Hoffmann
2022-03-04 14:20 ` [PULL 07/35] usb/ohci: Don't use packet from OHCIState for isochronous transfers Gerd Hoffmann
2022-03-04 14:20 ` [PULL 08/35] audio: replace open-coded buffer arithmetic Gerd Hoffmann
2022-03-04 14:20 ` [PULL 09/35] audio: move function audio_pcm_hw_clip_out() Gerd Hoffmann
2022-03-04 14:20 ` [PULL 10/35] audio: add function audio_pcm_hw_conv_in() Gerd Hoffmann
2022-03-04 14:20 ` [PULL 11/35] audio: inline function audio_pcm_sw_get_rpos_in() Gerd Hoffmann
2022-03-04 14:21 ` [PULL 12/35] paaudio: increase default latency to 46ms Gerd Hoffmann
2022-03-04 14:21 ` [PULL 13/35] jackaudio: use more jack audio buffers Gerd Hoffmann
2022-03-04 14:21 ` [PULL 14/35] audio: copy playback stream in sequential order Gerd Hoffmann
2022-03-04 14:21 ` [PULL 15/35] audio: add pcm_ops function table for capture backend Gerd Hoffmann
2022-03-04 14:21 ` [PULL 16/35] Revert "audio: fix wavcapture segfault" Gerd Hoffmann
2022-03-04 14:21 ` Gerd Hoffmann [this message]
2022-03-04 14:21 ` [PULL 18/35] paaudio: reduce effective playback buffer size Gerd Hoffmann
2022-03-04 14:21 ` [PULL 19/35] dsoundaudio: " Gerd Hoffmann
2022-03-04 14:21 ` [PULL 20/35] ossaudio: " Gerd Hoffmann
2022-03-04 14:21 ` [PULL 21/35] paaudio: fix samples vs. frames mix-up Gerd Hoffmann
2022-03-04 14:21 ` [PULL 22/35] sdlaudio: " Gerd Hoffmann
2022-03-04 14:21 ` [PULL 23/35] hw/usb/redirect.c: Stop using qemu_oom_check() Gerd Hoffmann
2022-03-04 14:21 ` [PULL 24/35] coreaudio: Notify error in coreaudio_init_out Gerd Hoffmann
2022-03-04 14:21 ` [PULL 25/35] hw/i386: Improve bounds checking in OVMF table parsing Gerd Hoffmann
2022-03-04 14:21 ` [PULL 26/35] hw/i386: Replace magic number with field length calculation Gerd Hoffmann
2022-03-04 14:21 ` [PULL 27/35] docs: Add spec of OVMF GUIDed table for SEV guests Gerd Hoffmann
2022-03-04 14:21 ` [PULL 28/35] ui/console: fix crash when using gl context with non-gl listeners Gerd Hoffmann
2022-03-04 14:21 ` [PULL 29/35] ui/console: fix texture leak when calling surface_gl_create_texture() Gerd Hoffmann
2022-03-04 14:21 ` [PULL 30/35] ui: do not create a surface when resizing a GL scanout Gerd Hoffmann
2022-03-04 14:21 ` [PULL 31/35] ui/clipboard: fix use-after-free regression Gerd Hoffmann
2022-03-04 14:21 ` [PULL 32/35] ui/cocoa: Add Services menu Gerd Hoffmann
2022-03-04 14:21 ` [PULL 33/35] softmmu/qdev-monitor: Add virtio-gpu-gl aliases Gerd Hoffmann
2022-03-04 14:21 ` [PULL 34/35] edid: Fix clock of Detailed Timing Descriptor Gerd Hoffmann
2022-03-04 14:21 ` [PULL 35/35] hw/display/vmware_vga: replace fprintf calls with trace events Gerd Hoffmann
2022-03-05 10:46 ` [PULL 00/35] Kraxel 20220304 patches Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220304142123.956171-18-kraxel@redhat.com \
--to=kraxel@redhat.com \
--cc=akihiko.odaki@gmail.com \
--cc=berrange@redhat.com \
--cc=eduardo@habkost.net \
--cc=f4bug@amsat.org \
--cc=huth@tuxfamily.org \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu_oss@crudebyte.com \
--cc=richard.henderson@linaro.org \
--cc=vr_qemu@t-online.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).