summaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-09-24 17:22:17 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-09-24 17:22:17 +0100
commit1bd5556f6686365e76f7ff67fe67260c449e8345 (patch)
treec302198da685f9aedb1ed6a6a2208d290e63fcd1 /audio
parentf7f1d916b22306c35ab9c090aab5233a91b4b7f9 (diff)
parent5e626fa7364bc2d7db5f6c8e59150dee1689b98a (diff)
Merge remote-tracking branch 'remotes/kraxel/tags/audio-20200923-pull-request' into staging
audio: various buffering fixes. audio: build spiceaudio as module. # gpg: Signature made Wed 23 Sep 2020 10:09:46 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/audio-20200923-pull-request: audio: build spiceaudio as module audio: remove qemu_spice_audio_init() audio: run downstream playback queue unconditionally audio: align audio_generic_write with audio_pcm_hw_run_out audio: remove unnecessary calls to put_buffer_in audio: align audio_generic_read with audio_pcm_hw_run_in audio/spiceaudio: always rate limit playback stream audio/audio: fix video playback slowdown with spiceaudio audio: handle buf == NULL in put_buffer_out() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'audio')
-rw-r--r--audio/audio.c80
-rw-r--r--audio/meson.build4
-rw-r--r--audio/spiceaudio.c26
3 files changed, 80 insertions, 30 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 1a68cfaafb..46578e4a58 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -34,6 +34,7 @@
#include "qemu/module.h"
#include "sysemu/replay.h"
#include "sysemu/runstate.h"
+#include "ui/qemu-spice.h"
#include "trace.h"
#define AUDIO_CAP "audio"
@@ -1089,14 +1090,18 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
size_t clipped = 0;
while (live) {
- size_t size, decr, proc;
+ size_t size = live * hw->info.bytes_per_frame;
+ size_t decr, proc;
void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
- if (!buf || size == 0) {
+
+ if (size == 0) {
break;
}
decr = MIN(size / hw->info.bytes_per_frame, live);
- audio_pcm_hw_clip_out(hw, buf, decr);
+ if (buf) {
+ audio_pcm_hw_clip_out(hw, buf, decr);
+ }
proc = hw->pcm_ops->put_buffer_out(hw, buf,
decr * hw->info.bytes_per_frame) /
hw->info.bytes_per_frame;
@@ -1182,6 +1187,9 @@ static void audio_run_out (AudioState *s)
}
}
}
+ if (hw->pcm_ops->run_buffer_out) {
+ hw->pcm_ops->run_buffer_out(hw);
+ }
continue;
}
@@ -1257,7 +1265,6 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
assert(size % hw->info.bytes_per_frame == 0);
if (size == 0) {
- hw->pcm_ops->put_buffer_in(hw, buf, size);
break;
}
@@ -1481,22 +1488,54 @@ 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)
{
- size_t dst_size, copy_size;
- void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
- copy_size = MIN(size, dst_size);
+ size_t total = 0;
+
+ while (total < size) {
+ size_t dst_size = size - total;
+ size_t copy_size, proc;
+ void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
+
+ if (dst_size == 0) {
+ break;
+ }
+
+ copy_size = MIN(size - total, dst_size);
+ if (dst) {
+ memcpy(dst, (char *)buf + total, copy_size);
+ }
+ proc = hw->pcm_ops->put_buffer_out(hw, dst, copy_size);
+ total += proc;
+
+ if (proc == 0 || proc < copy_size) {
+ break;
+ }
+ }
- memcpy(dst, buf, copy_size);
- return hw->pcm_ops->put_buffer_out(hw, dst, copy_size);
+ if (hw->pcm_ops->run_buffer_out) {
+ hw->pcm_ops->run_buffer_out(hw);
+ }
+
+ return total;
}
size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
{
- void *src = hw->pcm_ops->get_buffer_in(hw, &size);
+ size_t total = 0;
- memcpy(buf, src, size);
- hw->pcm_ops->put_buffer_in(hw, src, size);
+ while (total < size) {
+ size_t src_size = size - total;
+ void *src = hw->pcm_ops->get_buffer_in(hw, &src_size);
- return size;
+ if (src_size == 0) {
+ break;
+ }
+
+ memcpy((char *)buf + total, src, src_size);
+ hw->pcm_ops->put_buffer_in(hw, src, src_size);
+ total += src_size;
+ }
+
+ return total;
}
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
@@ -1658,6 +1697,21 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
/* silence gcc warning about uninitialized variable */
AudiodevListHead head = QSIMPLEQ_HEAD_INITIALIZER(head);
+ if (using_spice) {
+ /*
+ * When using spice allow the spice audio driver being picked
+ * as default.
+ *
+ * Temporary hack. Using audio devices without explicit
+ * audiodev= property is already deprecated. Same goes for
+ * the -soundhw switch. Once this support gets finally
+ * removed we can also drop the concept of a default audio
+ * backend and this can go away.
+ */
+ driver = audio_driver_lookup("spice");
+ driver->can_be_default = 1;
+ }
+
if (dev) {
/* -audiodev option */
legacy_config = false;
diff --git a/audio/meson.build b/audio/meson.build
index 15c06ba045..18a831129e 100644
--- a/audio/meson.build
+++ b/audio/meson.build
@@ -7,7 +7,6 @@ softmmu_ss.add(files(
'wavcapture.c',
))
-softmmu_ss.add(when: [spice, 'CONFIG_SPICE'], if_true: files('spiceaudio.c'))
softmmu_ss.add(when: [coreaudio, 'CONFIG_AUDIO_COREAUDIO'], if_true: files('coreaudio.c'))
softmmu_ss.add(when: [dsound, 'CONFIG_AUDIO_DSOUND'], if_true: files('dsoundaudio.c'))
softmmu_ss.add(when: ['CONFIG_AUDIO_WIN_INT'], if_true: files('audio_win_int.c'))
@@ -18,7 +17,8 @@ foreach m : [
['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'],
['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'],
['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'],
- ['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c']
+ ['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'],
+ ['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c']
]
if config_host.has_key(m[0])
module_ss = ss.source_set()
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index b6b5da4812..ed6dff1dcc 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -130,12 +130,11 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
}
if (out->frame) {
- *size = audio_rate_get_bytes(
- &hw->info, &out->rate,
- (out->fsize - out->fpos) * hw->info.bytes_per_frame);
- } else {
- audio_rate_start(&out->rate);
+ *size = MIN((out->fsize - out->fpos) << 2, *size);
}
+
+ *size = audio_rate_get_bytes(&hw->info, &out->rate, *size);
+
return out->frame + out->fpos;
}
@@ -143,12 +142,14 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size)
{
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
- assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
- out->fpos += size >> 2;
+ if (buf) {
+ assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
+ out->fpos += size >> 2;
- if (out->fpos == out->fsize) { /* buffer full */
- spice_server_playback_put_samples(&out->sin, out->frame);
- out->frame = NULL;
+ if (out->fpos == out->fsize) { /* buffer full */
+ spice_server_playback_put_samples(&out->sin, out->frame);
+ out->frame = NULL;
+ }
}
return size;
@@ -310,11 +311,6 @@ static struct audio_driver spice_audio_driver = {
.voice_size_in = sizeof (SpiceVoiceIn),
};
-void qemu_spice_audio_init (void)
-{
- spice_audio_driver.can_be_default = 1;
-}
-
static void register_audio_spice(void)
{
audio_driver_register(&spice_audio_driver);