Skip to content

Commit

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

audio: bugfix collection.

# gpg: Signature made Thu 17 Jun 2021 13:40:56 BST
# gpg:                using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <[email protected]>" [full]
# gpg:                 aka "Gerd Hoffmann <[email protected]>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <[email protected]>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/audio-20210617-pull-request:
  coreaudio: Fix output stream format settings
  audio: Fix format specifications of debug logs
  hw/audio/sb16: Avoid assertion by restricting I/O sampling rate range
  jackaudio: avoid that the client name contains the word (NULL)
  audio: move code to audio/audio.c
  paaudio: remove unused stream flags
  alsaaudio: remove #ifdef DEBUG to avoid bit rot

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jun 18, 2021
2 parents b6d73e9 + 986bdbc commit 3ccf6cd
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 54 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,7 @@ F: qapi/audio.json
F: tests/qtest/ac97-test.c
F: tests/qtest/es1370-test.c
F: tests/qtest/intel-hda-test.c
F: tests/qtest/fuzz-sb16-test.c

Block layer core
M: Kevin Wolf <[email protected]>
Expand Down
10 changes: 4 additions & 6 deletions audio/alsaaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#define AUDIO_CAP "alsa"
#include "audio_int.h"

#define DEBUG_ALSA 0

struct pollhlp {
snd_pcm_t *handle;
struct pollfd *pfds;
Expand Down Expand Up @@ -587,16 +589,12 @@ static int alsa_open(bool in, struct alsa_params_req *req,

*handlep = handle;

if (obtfmt != req->fmt ||
obt->nchannels != req->nchannels ||
obt->freq != req->freq) {
if (DEBUG_ALSA || obtfmt != req->fmt ||
obt->nchannels != req->nchannels || obt->freq != req->freq) {
dolog ("Audio parameters for %s\n", typ);
alsa_dump_info(req, obt, obtfmt, apdo);
}

#ifdef DEBUG
alsa_dump_info(req, obt, obtfmt, apdo);
#endif
return 0;

err:
Expand Down
15 changes: 12 additions & 3 deletions audio/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "qapi/qapi-visit-audio.h"
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qemu-common.h"
#include "sysemu/replay.h"
#include "sysemu/runstate.h"
#include "ui/qemu-spice.h"
Expand Down Expand Up @@ -704,7 +705,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)

if (live == hwsamples) {
#ifdef DEBUG_OUT
dolog ("%s is full %d\n", sw->name, live);
dolog ("%s is full %zu\n", sw->name, live);
#endif
return 0;
}
Expand Down Expand Up @@ -994,7 +995,7 @@ static size_t audio_get_avail (SWVoiceIn *sw)
}

ldebug (
"%s: get_avail live %d ret %" PRId64 "\n",
"%s: get_avail live %zu ret %" PRId64 "\n",
SW_NAME (sw),
live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
);
Expand All @@ -1021,7 +1022,7 @@ static size_t audio_get_free(SWVoiceOut *sw)
dead = sw->hw->mix_buf->size - live;

#ifdef DEBUG_OUT
dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",
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);
Expand Down Expand Up @@ -2172,6 +2173,14 @@ const char *audio_get_id(QEMUSoundCard *card)
}
}

const char *audio_application_name(void)
{
const char *vm_name;

vm_name = qemu_get_vm_name();
return vm_name ? vm_name : "qemu";
}

void audio_rate_start(RateCtl *rate)
{
memset(rate, 0, sizeof(RateCtl));
Expand Down
2 changes: 2 additions & 0 deletions audio/audio_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size);

void audio_run(AudioState *s, const char *msg);

const char *audio_application_name(void);

typedef struct RateCtl {
int64_t start_ticks;
int64_t bytes_sent;
Expand Down
48 changes: 13 additions & 35 deletions audio/coreaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ typedef struct coreaudioVoiceOut {
int frameSizeSetting;
uint32_t bufferCount;
UInt32 audioDevicePropertyBufferFrameSize;
AudioStreamBasicDescription outputStreamBasicDescription;
AudioDeviceIOProcID ioprocid;
bool enabled;
} coreaudioVoiceOut;
Expand Down Expand Up @@ -114,24 +113,6 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
framesize);
}

static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
AudioStreamBasicDescription *d)
{
UInt32 size = sizeof(*d);
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyStreamFormat,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};

return AudioObjectGetPropertyData(id,
&addr,
0,
NULL,
&size,
d);
}

static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
AudioStreamBasicDescription *d)
{
Expand Down Expand Up @@ -373,6 +354,17 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
OSStatus status;
AudioValueRange frameRange;

AudioStreamBasicDescription streamBasicDescription = {
.mBitsPerChannel = core->hw.info.bits,
.mBytesPerFrame = core->hw.info.bytes_per_frame,
.mBytesPerPacket = core->hw.info.bytes_per_frame,
.mChannelsPerFrame = core->hw.info.nchannels,
.mFormatFlags = kLinearPCMFormatFlagIsFloat,
.mFormatID = kAudioFormatLinearPCM,
.mFramesPerPacket = 1,
.mSampleRate = core->hw.info.freq
};

status = coreaudio_get_voice(&core->outputDeviceID);
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr (status,
Expand Down Expand Up @@ -432,29 +424,16 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
}
core->hw.samples = core->bufferCount * core->audioDevicePropertyBufferFrameSize;

/* get StreamFormat */
status = coreaudio_get_streamformat(core->outputDeviceID,
&core->outputStreamBasicDescription);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr (status,
"Could not get Device Stream properties\n");
core->outputDeviceID = kAudioDeviceUnknown;
return status;
}

/* set Samplerate */
status = coreaudio_set_streamformat(core->outputDeviceID,
&core->outputStreamBasicDescription);
&streamBasicDescription);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr (status,
"Could not set samplerate %lf\n",
core->outputStreamBasicDescription.mSampleRate);
streamBasicDescription.mSampleRate);
core->outputDeviceID = kAudioDeviceUnknown;
return status;
}
Expand Down Expand Up @@ -598,7 +577,6 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);

core->bufferCount = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;

status = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
&voice_addr, handle_voice_change,
Expand Down
3 changes: 1 addition & 2 deletions audio/jackaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "qemu/module.h"
#include "qemu/atomic.h"
#include "qemu/main-loop.h"
#include "qemu-common.h"
#include "audio.h"

#define AUDIO_CAP "jack"
Expand Down Expand Up @@ -412,7 +411,7 @@ static int qjack_client_init(QJackClient *c)

snprintf(client_name, sizeof(client_name), "%s-%s",
c->out ? "out" : "in",
c->opt->client_name ? c->opt->client_name : qemu_get_vm_name());
c->opt->client_name ? c->opt->client_name : audio_application_name());

if (c->opt->exact_name) {
options |= JackUseExactName;
Expand Down
10 changes: 2 additions & 8 deletions audio/paaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu-common.h"
#include "audio.h"
#include "qapi/opts-visitor.h"

Expand Down Expand Up @@ -463,10 +462,7 @@ static pa_stream *qpa_simple_new (

pa_stream_set_state_callback(stream, stream_state_cb, c);

flags =
PA_STREAM_INTERPOLATE_TIMING
| PA_STREAM_AUTO_TIMING_UPDATE
| PA_STREAM_EARLY_REQUESTS;
flags = PA_STREAM_EARLY_REQUESTS;

if (dev) {
/* don't move the stream if the user specified a sink/source */
Expand Down Expand Up @@ -756,7 +752,6 @@ static int qpa_validate_per_direction_opts(Audiodev *dev,
/* common */
static void *qpa_conn_init(const char *server)
{
const char *vm_name;
PAConnection *c = g_malloc0(sizeof(PAConnection));
QTAILQ_INSERT_TAIL(&pa_conns, c, list);

Expand All @@ -765,9 +760,8 @@ static void *qpa_conn_init(const char *server)
goto fail;
}

vm_name = qemu_get_vm_name();
c->context = pa_context_new(pa_threaded_mainloop_get_api(c->mainloop),
vm_name ? vm_name : "qemu");
audio_application_name());
if (!c->context) {
goto fail;
}
Expand Down
14 changes: 14 additions & 0 deletions hw/audio/sb16.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ struct SB16State {
PortioList portio_list;
};

#define SAMPLE_RATE_MIN 5000
#define SAMPLE_RATE_MAX 45000

static void SB_audio_callback (void *opaque, int free);

static int magic_of_irq (int irq)
Expand Down Expand Up @@ -241,6 +244,17 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
int tmp = (256 - s->time_const);
s->freq = (1000000 + (tmp / 2)) / tmp;
}
if (s->freq < SAMPLE_RATE_MIN) {
qemu_log_mask(LOG_GUEST_ERROR,
"sampling range too low: %d, increasing to %u\n",
s->freq, SAMPLE_RATE_MIN);
s->freq = SAMPLE_RATE_MIN;
} else if (s->freq > SAMPLE_RATE_MAX) {
qemu_log_mask(LOG_GUEST_ERROR,
"sampling range too high: %d, decreasing to %u\n",
s->freq, SAMPLE_RATE_MAX);
s->freq = SAMPLE_RATE_MAX;
}

if (dma_len != -1) {
s->block_size = dma_len << s->fmt_stereo;
Expand Down
52 changes: 52 additions & 0 deletions tests/qtest/fuzz-sb16-test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* QTest fuzzer-generated testcase for sb16 audio device
*
* Copyright (c) 2021 Philippe Mathieu-Daudé <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "qemu/osdep.h"
#include "libqos/libqtest.h"

/*
* This used to trigger the assert in audio_calloc
* https://bugs.launchpad.net/qemu/+bug/1910603
*/
static void test_fuzz_sb16_0x1c(void)
{
QTestState *s = qtest_init("-M q35 -display none "
"-device sb16,audiodev=snd0 "
"-audiodev none,id=snd0");
qtest_outw(s, 0x22c, 0x41);
qtest_outb(s, 0x22c, 0x00);
qtest_outw(s, 0x22c, 0x1004);
qtest_outw(s, 0x22c, 0x001c);
qtest_quit(s);
}

static void test_fuzz_sb16_0x91(void)
{
QTestState *s = qtest_init("-M pc -display none "
"-device sb16,audiodev=none "
"-audiodev id=none,driver=none");
qtest_outw(s, 0x22c, 0xf141);
qtest_outb(s, 0x22c, 0x00);
qtest_outb(s, 0x22c, 0x24);
qtest_outb(s, 0x22c, 0x91);
qtest_quit(s);
}

int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();

g_test_init(&argc, &argv, NULL);

if (strcmp(arch, "i386") == 0) {
qtest_add_func("fuzz/test_fuzz_sb16/1c", test_fuzz_sb16_0x1c);
qtest_add_func("fuzz/test_fuzz_sb16/91", test_fuzz_sb16_0x91);
}

return g_test_run();
}
1 change: 1 addition & 0 deletions tests/qtest/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ slow_qtests = {
qtests_generic = \
(config_all_devices.has_key('CONFIG_MEGASAS_SCSI_PCI') ? ['fuzz-megasas-test'] : []) + \
(config_all_devices.has_key('CONFIG_VIRTIO_SCSI') ? ['fuzz-virtio-scsi-test'] : []) + \
(config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \
[
'cdrom-test',
'device-introspect-test',
Expand Down

0 comments on commit 3ccf6cd

Please sign in to comment.