Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/kraxel/tags/kraxel-20220304-pul…
Browse files Browse the repository at this point in the history
…l-request' into staging

usb: fixes for ohci, xhci, mtp and redirect
audio: latency fixes
ui: opengl and cocoa fixes
firmware: ovmf tabel aprser fixes

# gpg: Signature made Fri 04 Mar 2022 14:18:47 GMT
# gpg:                using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# 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/kraxel-20220304-pull-request: (35 commits)
  hw/display/vmware_vga: replace fprintf calls with trace events
  edid: Fix clock of Detailed Timing Descriptor
  softmmu/qdev-monitor: Add virtio-gpu-gl aliases
  ui/cocoa: Add Services menu
  ui/clipboard: fix use-after-free regression
  ui: do not create a surface when resizing a GL scanout
  ui/console: fix texture leak when calling surface_gl_create_texture()
  ui/console: fix crash when using gl context with non-gl listeners
  docs: Add spec of OVMF GUIDed table for SEV guests
  hw/i386: Replace magic number with field length calculation
  hw/i386: Improve bounds checking in OVMF table parsing
  coreaudio: Notify error in coreaudio_init_out
  hw/usb/redirect.c: Stop using qemu_oom_check()
  sdlaudio: fix samples vs. frames mix-up
  paaudio: fix samples vs. frames mix-up
  ossaudio: reduce effective playback buffer size
  dsoundaudio: reduce effective playback buffer size
  paaudio: reduce effective playback buffer size
  audio: restore mixing-engine playback buffer size
  Revert "audio: fix wavcapture segfault"
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 4, 2022
2 parents 3d1fbc5 + 02218ae commit 5c84638
Show file tree
Hide file tree
Showing 27 changed files with 600 additions and 364 deletions.
1 change: 1 addition & 0 deletions audio/alsaaudio.c
Expand Up @@ -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,

Expand Down
194 changes: 107 additions & 87 deletions audio/audio.c
Expand Up @@ -548,65 +548,45 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
return live;
}

static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
{
size_t clipped = 0;
size_t pos = hw->mix_buf->pos;

while (len) {
st_sample *src = hw->mix_buf->samples + pos;
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
size_t conv = 0;
STSampleBuffer *conv_buf = hw->conv_buf;

hw->clip(dst, src, samples_to_clip);
while (samples) {
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);

pos = (pos + samples_to_clip) % hw->mix_buf->size;
len -= samples_to_clip;
clipped += samples_to_clip;
hw->conv(conv_buf->samples + conv_buf->pos, src, proc);
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
samples -= proc;
conv += proc;
}

return conv;
}

/*
* Soft voice (capture)
*/
static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw)
{
HWVoiceIn *hw = sw->hw;
ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired;
ssize_t rpos;

if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) {
dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0;
}

rpos = hw->conv_buf->pos - live;
if (rpos >= 0) {
return rpos;
} else {
return hw->conv_buf->size + rpos;
}
}

static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
{
HWVoiceIn *hw = sw->hw;
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
struct st_sample *src, *dst = sw->buf;

rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size;

live = hw->total_samples_captured - sw->total_hw_samples_acquired;
if (!live) {
return 0;
}
if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0;
}

rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);

samples = size / sw->info.bytes_per_frame;
if (!live) {
return 0;
}

swlim = (live * sw->ratio) >> 32;
swlim = MIN (swlim, samples);
Expand All @@ -632,7 +612,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
total += isamp;
}

if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
if (!hw->pcm_ops->volume_in) {
mixeng_volume (sw->buf, ret, &sw->vol);
}

Expand Down Expand Up @@ -683,12 +663,38 @@ 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;
size_t pos = hw->mix_buf->pos;

while (len) {
st_sample *src = hw->mix_buf->samples + pos;
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);

hw->clip(dst, src, samples_to_clip);

pos = (pos + samples_to_clip) % hw->mix_buf->size;
len -= samples_to_clip;
clipped += samples_to_clip;
}
}

/*
* Soft voice (playback)
*/
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) {
Expand All @@ -711,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 && !sw->hw->pcm_ops->volume_out) {
mixeng_volume (sw->buf, swlim, &sw->vol);
if (!sw->hw->pcm_ops->volume_out) {
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,
Expand All @@ -741,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;
Expand Down Expand Up @@ -1003,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;
Expand All @@ -1022,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,
Expand Down Expand Up @@ -1132,9 +1142,27 @@ 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) {
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);
}
}
}

live = audio_pcm_hw_get_live_out (hw, &nb_live);
if (!nb_live) {
live = 0;
Expand Down Expand Up @@ -1163,14 +1191,6 @@ static void audio_run_out (AudioState *s)
}

if (!live) {
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
free = audio_get_free (sw);
if (free > 0) {
sw->callback.fn (sw->callback.opaque, free);
}
}
}
if (hw->pcm_ops->run_buffer_out) {
hw->pcm_ops->run_buffer_out(hw);
}
Expand Down Expand Up @@ -1211,21 +1231,13 @@ static void audio_run_out (AudioState *s)
if (!sw->total_hw_samples_mixed) {
sw->empty = 1;
}

if (sw->active) {
free = audio_get_free (sw);
if (free > 0) {
sw->callback.fn (sw->callback.opaque, free);
}
}
}
}
}

static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
{
size_t conv = 0;
STSampleBuffer *conv_buf = hw->conv_buf;

if (hw->pcm_ops->run_buffer_in) {
hw->pcm_ops->run_buffer_in(hw);
Expand All @@ -1241,11 +1253,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
break;
}

proc = MIN(size / hw->info.bytes_per_frame,
conv_buf->size - conv_buf->pos);

hw->conv(conv_buf->samples + conv_buf->pos, buf, proc);
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
proc = audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_frame);

samples -= proc;
conv += proc;
Expand Down Expand Up @@ -1394,12 +1402,10 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw)

void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
{
ssize_t start = (ssize_t)hw->pos_emul - hw->pending_emul;
size_t start;

if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
assert(start < hw->size_emul);

*size = MIN(*size, hw->pending_emul);
*size = MIN(*size, hw->size_emul - start);
Expand All @@ -1412,16 +1418,22 @@ 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) {
size_t write_len, written;
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
size_t write_len, written, start;

if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
assert(start < hw->size_emul);

write_len = MIN(hw->pending_emul, hw->size_emul - start);

Expand Down Expand Up @@ -1462,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;
Expand Down Expand Up @@ -1821,6 +1839,7 @@ void AUD_remove_card (QEMUSoundCard *card)
g_free (card->name);
}

static struct audio_pcm_ops capture_pcm_ops;

CaptureVoiceOut *AUD_add_capture(
AudioState *s,
Expand Down Expand Up @@ -1866,6 +1885,7 @@ CaptureVoiceOut *AUD_add_capture(

hw = &cap->hw;
hw->s = s;
hw->pcm_ops = &capture_pcm_ops;
QLIST_INIT (&hw->sw_head);
QLIST_INIT (&cap->cb_head);

Expand Down

0 comments on commit 5c84638

Please sign in to comment.