@@ -448,12 +448,9 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
stream = virtio_snd_pcm_get_stream(s, stream_id);
if (stream == NULL) {
- stream = g_new0(VirtIOSoundPCMStream, 1);
+ stream = &s->streams[stream_id];
stream->active = false;
- stream->id = stream_id;
stream->pcm = s->pcm;
- stream->s = s;
- QSIMPLEQ_INIT(&stream->queue);
/*
* stream_id >= s->snd_conf.streams was checked before so this is
@@ -463,14 +460,6 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
}
virtio_snd_get_qemu_audsettings(&as, params);
- stream->info.direction = stream_id < s->snd_conf.streams / 2 +
- (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
- stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
- stream->info.features = 0;
- stream->info.channels_min = 1;
- stream->info.channels_max = as.nchannels;
- stream->info.formats = supported_formats;
- stream->info.rates = supported_rates;
stream->params = *params;
stream->positions[0] = VIRTIO_SND_CHMAP_FL;
@@ -1040,6 +1029,25 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
vsnd->vmstate =
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
+ vsnd->streams = g_new0(VirtIOSoundPCMStream, vsnd->snd_conf.streams);
+
+ for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
+ VirtIOSoundPCMStream *stream = &vsnd->streams[i];
+
+ stream->id = i;
+ stream->s = vsnd;
+ QSIMPLEQ_INIT(&stream->queue);
+ stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
+ stream->info.features = 0;
+ stream->info.formats = supported_formats;
+ stream->info.rates = supported_rates;
+ stream->info.direction =
+ i < vsnd->snd_conf.streams / 2 + (vsnd->snd_conf.streams & 1)
+ ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
+ stream->info.channels_min = 1;
+ stream->info.channels_max = 2;
+ }
+
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
vsnd->pcm->snd = vsnd;
vsnd->pcm->streams =
@@ -1280,14 +1288,13 @@ static void virtio_snd_unrealize(DeviceState *dev)
qemu_del_vm_change_state_handler(vsnd->vmstate);
trace_virtio_snd_unrealize(vsnd);
- if (vsnd->pcm) {
+ if (vsnd->streams) {
if (vsnd->pcm->streams) {
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
stream = vsnd->pcm->streams[i];
if (stream) {
virtio_snd_process_cmdq(stream->s);
virtio_snd_pcm_close(stream);
- g_free(stream);
}
}
g_free(vsnd->pcm->streams);
@@ -1295,6 +1302,8 @@ static void virtio_snd_unrealize(DeviceState *dev)
g_free(vsnd->pcm->pcm_params);
g_free(vsnd->pcm);
vsnd->pcm = NULL;
+ g_free(vsnd->streams);
+ vsnd->streams = NULL;
}
AUD_remove_card(&vsnd->card);
virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
@@ -215,6 +215,7 @@ struct VirtIOSound {
VirtQueue *queues[VIRTIO_SND_VQ_MAX];
uint64_t features;
VirtIOSoundPCM *pcm;
+ VirtIOSoundPCMStream *streams;
QEMUSoundCard card;
VMChangeStateEntry *vmstate;
virtio_snd_config snd_conf;
It is much easier to migrate an array of structs than individual structs that are accessed via a pointer to a pointer to an array of pointers to struct. For this reason, allocate an array of streams in virtio_snd_realize() and initialise all stream variables that are constant at runtime immediately after allocation. This makes it easier to remove the virtio_snd_set_pcm_params() and virtio_snd_pcm_prepare() calls in the realisation phase and to migrate the audio streams of the virtio sound device after the next few patches. Signed-off-by: Volker RĂ¼melin <vr_qemu@t-online.de> --- hw/audio/virtio-snd.c | 37 ++++++++++++++++++++++------------- include/hw/audio/virtio-snd.h | 1 + 2 files changed, 24 insertions(+), 14 deletions(-)