OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

virtio-dev message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Re: [virtio-dev] Request for a new device number for a virtio-audio device.


On Fri, May 10, 2019 at 02:15:00PM +0000, Anton Yakovlev wrote:
> > Why do you think this is needed?
> 
> When you implement an audio device, you usually start with what we call "manual mode". It works, but only for simple use cases. There're two major challenges here.
> 
> 1) An application can use audio device in many different ways. It may fill the entire buffer with frames and let it draining. It may provides data in form of relatively big chunks. But usually you will face with so called "low latency" applications. These try to reduce result latency by providing small chunks of data. In extreme cases, the driver may receive requests containing only 5-10 frames. It means an amount of both system calls and requests to the device will grow. At some point this rate may become quite noticable. But things may become even worse, if an application activates both streams (playback and capture) at the same time. For example, voice chat applications (trying to reduce latency as much as possible) may hang you VM because of huge amount of small requests on both PCM streams. Thus, no requests/traps/hypercalls to the device while a stream is running - no problems here.
> 
> 2) Everybody wants to reduce a latency as much as possible. One of the most logical way is to allow to mmap data buffer into the user space memory. (Actually, in some cases you even have no choice here, like in case of the WaveRT interface in Windows.) But memory mapped buffer means, that you either have a very little or have not at all an idea what is going on with buffer content. Even if you have information about when and where an application writes to or reads from the buffer (ALSA enforces an application to maintain its appl_ptr value), you will have a lot of headache with tracking the rewind/forward cases. I can't say for everyone, but our experiments with using "manual mode" here all failed. From other side, the isochronous nature of PCM stream and the nature of sound card itself suggest you right solution. You don't need to care about what and how an application does with a buffer. Since it's expected from the device to read/write data with constant rate. Thus, you can do the same in your virtual audio device. And it works like a charm!
> 
> We wanted to be ready for every possible use case, that's why we combined solutions for described issues into what we call "automatic mode". The funniest thing is, according to our tests, in automatic mode you can have stable and clean playback/capturing even under the very high CPU pressure.

Thanks for contributing your virtio-snd spec to the discussion!

Shared memory isn't a native concept to VIRTIO.  The device and the
driver don't assume shared memory access in the general case (i.e.
virtqueue buffers could even be copied and virtio-blk, virtio-net, etc
would still work!).

There is currently a spec extension on the mailing list to add Shared
Memory Resources to VIRTIO and new device types will use it.  However, I
don't think this is necessary for this use case.

Two techniques can be used to minimize virtqueue notifications:

1. Polling has become a commonly used technique over the last several
   years.  Both the driver and the device may disable notifications and
   simply peek at the ring indices to detect new buffers from the other
   side.

2. For synchronization and to reduce notifications the device could
   support bundling playback and capture into a single buffer so that
   only 1 virtqueue is used:

   /* A packet of PCM data associated with a stream */
   struct virtio_audio_pcm_data {
       unsigned stream_id;
       uint8_t data[num_frames * num_channels * bytes_per_sample];
   };

   /* An exchange of playback and capture PCM data */
   struct virtio_audio_pcm {
       /* Write (Driver -> Device) */
       /* Note that all playback and capture streams must have the same
	* sample rate.
        */
       unsigned num_playback; /* 0 or more */
       unsigned num_capture; /* 0 or more */

       /* All playback and capture streams transfer this number of
	* frames of PCM data.
        */
       unsigned num_frames;

       struct virtio_audio_pcm_data playback[num_playback];

       /* Read (Device -> Driver) */
       struct virtio_audio_pcm_data capture[num_capture];
       /* TODO status and error codes */
   };

   In other words, a single struct virtio_audio_pcm delivers playback
   samples to the device and returns capture samples to the driver.

   I used arrays so that multiple streams with the same sample rate can
   be bundled together.

Attachment: signature.asc
Description: PGP signature



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]