qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v9 11/12] virtio-sound: implement audio capture (RX)


From: Volker Rümelin
Subject: Re: [PATCH v9 11/12] virtio-sound: implement audio capture (RX)
Date: Tue, 19 Sep 2023 08:47:34 +0200
User-agent: Mozilla Thunderbird

Am 13.09.23 um 09:33 schrieb Emmanouil Pitsidianakis:
To perform audio capture we duplicate the TX logic of the previous
commit with the following difference: we receive data from the QEMU
audio backend and write it in the virt queue IO buffers the guest sends
to QEMU. When they are full (i.e. they have `period_bytes` amount of
data) or when recording stops in QEMU's audio backend, the buffer is
returned to the guest by notifying it.

Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
 hw/virtio/trace-events |   3 +-
 hw/virtio/virtio-snd.c | 233 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 213 insertions(+), 23 deletions(-)

diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 6fe03f9790..1d3a001371 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -1048,26 +1131,133 @@ static void virtio_snd_pcm_out_cb(void *data, int available)
 }
 
 /*
- * Flush all buffer data from this stream's queue into the driver's virtual
- * queue.
+ * AUD_* input callback.
  *
- * @stream: VirtIOSoundPCMStream *stream
+ * @data: VirtIOSoundPCMStream stream
+ * @available: number of bytes that can be read with AUD_read()
  */
-static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream)
+static void virtio_snd_pcm_in_cb(void *data, int available)
 {
+    VirtIOSoundPCMStream *stream = data;
     VirtIOSoundPCMBlock *block;
-    VirtIOSoundPCMBlock *next;
+    virtio_snd_pcm_status resp = { 0 };
+    size_t size;
 
     WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
-        QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
-            AUD_write(stream->voice.out, block->data + block->offset, block->size);
-            virtqueue_push(block->vq, block->elem, sizeof(block->elem));
-            virtio_notify(VIRTIO_DEVICE(stream->s), block->vq);
-            QSIMPLEQ_REMOVE(&stream->queue, block, VirtIOSoundPCMBlock, entry);
+        while (!QSIMPLEQ_EMPTY(&stream->queue)) {
+            block = QSIMPLEQ_FIRST(&stream->queue);
+
+            for (;;) {
+                size = AUD_read(stream->voice.in,
+                        block->data + block->size,
+                        MIN(available, (stream->params.period_bytes - block->size)));
+                if (!size) {
+                    available = 0;
+                    break;
+                }
+                block->size += size;
+                available -= size;
+                if (block->size >= stream->params.period_bytes) {
+                    resp.status = cpu_to_le32(VIRTIO_SND_S_OK);
+                    resp.latency_bytes = 0;
+                    /* Copy data -if any- to guest */
+                    iov_from_buf(block->elem->in_sg,
+                                 block->elem->in_num,
+                                 0,
+                                 block->data,
+                                 stream->params.period_bytes);
+                    iov_from_buf(block->elem->in_sg,
+                                 block->elem->in_num,
+                                 block->size,
+                                 &resp,
+                                 sizeof(resp));
+                    virtqueue_push(block->vq,
+                                   block->elem,
+                                   sizeof(block->elem));

Hi Manos,

if I'm not completely mistaken, the third argument of a virtqueue_push() call is the size of the message copied into the virtio ring buffer, not the size of a pointer. As I wrote for the v8 series, the other virtqueue_push() calls also don't look right.

With best regards,
Volker

+                    virtio_notify(VIRTIO_DEVICE(stream->s),
+                                  block->vq);
+                    QSIMPLEQ_REMOVE_HEAD(&stream->queue, entry);
+                    virtio_snd_pcm_block_free(block);
+                    break;
+                }
+                if (!available) {
+                    break;
+                }
+            }
+            if (!available) {
+                break;
+            }
         }
     }
 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]