xref: /aosp_15_r20/external/crosvm/devices/src/virtio/snd/sys/windows.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // TODO(b/275406212): Deleted resampler code to make upstream easier. The resample
6 // will be in win_audio now
7 use std::io;
8 use std::io::Read;
9 use std::rc::Rc;
10 use std::slice;
11 use std::sync::Arc;
12 
13 use async_trait::async_trait;
14 use audio_streams::capture::AsyncCaptureBuffer;
15 use audio_streams::capture::AsyncCaptureBufferStream;
16 use audio_streams::AsyncPlaybackBuffer;
17 use audio_streams::AsyncPlaybackBufferStream;
18 use audio_streams::BoxError;
19 use base::error;
20 pub(crate) use base::set_audio_thread_priority;
21 use base::warn;
22 use cros_async::sync::RwLock as AsyncRwLock;
23 use cros_async::Executor;
24 use data_model::Le32;
25 use futures::channel::mpsc::UnboundedReceiver;
26 use futures::channel::mpsc::UnboundedSender;
27 use futures::SinkExt;
28 use serde::Deserialize;
29 use serde::Serialize;
30 use sync::Mutex;
31 use vm_memory::GuestMemory;
32 use win_audio::async_stream::WinAudioStreamSourceGenerator;
33 use win_audio::AudioSharedFormat;
34 use win_audio::WinAudioServer;
35 use win_audio::WinStreamSourceGenerator;
36 use win_audio::ANDROID_CAPTURE_FRAME_SIZE_BYTES;
37 use win_audio::BYTES_PER_32FLOAT;
38 
39 use crate::virtio::snd::common_backend::async_funcs::CaptureBufferReader;
40 use crate::virtio::snd::common_backend::async_funcs::PlaybackBufferWriter;
41 use crate::virtio::snd::common_backend::stream_info::StreamInfo;
42 use crate::virtio::snd::common_backend::DirectionalStream;
43 use crate::virtio::snd::common_backend::Error;
44 use crate::virtio::snd::common_backend::PcmResponse;
45 use crate::virtio::snd::common_backend::SndData;
46 use crate::virtio::snd::constants::StatusCode;
47 use crate::virtio::snd::layout::virtio_snd_pcm_status;
48 use crate::virtio::snd::parameters::Error as ParametersError;
49 use crate::virtio::snd::parameters::Parameters;
50 use crate::virtio::DescriptorChain;
51 use crate::virtio::Reader;
52 
53 pub(crate) type SysAudioStreamSourceGenerator = Box<dyn WinStreamSourceGenerator>;
54 pub(crate) type SysAudioStreamSource = Box<dyn WinAudioServer>;
55 pub(crate) type SysBufferReader = WinBufferReader;
56 
57 pub struct SysDirectionOutput {
58     pub async_playback_buffer_stream:
59         Arc<AsyncRwLock<Box<dyn audio_streams::AsyncPlaybackBufferStream>>>,
60     pub buffer_writer: Rc<AsyncRwLock<Box<dyn PlaybackBufferWriter>>>,
61 }
62 
63 pub(crate) struct SysAsyncStreamObjects {
64     pub(crate) stream: DirectionalStream,
65     pub(crate) pcm_sender: UnboundedSender<PcmResponse>,
66 }
67 
68 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
69 pub enum StreamSourceBackend {
70     WINAUDIO,
71 }
72 
73 // Implemented to make backend serialization possible, since we deserialize from str.
74 impl From<StreamSourceBackend> for String {
from(backend: StreamSourceBackend) -> Self75     fn from(backend: StreamSourceBackend) -> Self {
76         match backend {
77             StreamSourceBackend::WINAUDIO => "winaudio".to_owned(),
78         }
79     }
80 }
81 
82 impl TryFrom<&str> for StreamSourceBackend {
83     type Error = ParametersError;
84 
try_from(s: &str) -> Result<Self, Self::Error>85     fn try_from(s: &str) -> Result<Self, Self::Error> {
86         match s {
87             "winaudio" => Ok(StreamSourceBackend::WINAUDIO),
88             _ => Err(ParametersError::InvalidBackend),
89         }
90     }
91 }
92 
create_stream_source_generators( _backend: StreamSourceBackend, _params: &Parameters, _snd_data: &SndData, ) -> Vec<SysAudioStreamSourceGenerator>93 pub(crate) fn create_stream_source_generators(
94     _backend: StreamSourceBackend,
95     _params: &Parameters,
96     _snd_data: &SndData,
97 ) -> Vec<SysAudioStreamSourceGenerator> {
98     vec![
99         Box::new(WinAudioStreamSourceGenerator {}),
100         Box::new(WinAudioStreamSourceGenerator {}),
101     ]
102 }
103 
104 impl StreamInfo {
set_up_async_playback_stream( &mut self, frame_size: usize, audio_client_guid: Option<String>, ex: &Executor, ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error>105     async fn set_up_async_playback_stream(
106         &mut self,
107         frame_size: usize,
108         audio_client_guid: Option<String>,
109         ex: &Executor,
110     ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error> {
111         let (async_playback_buffer_stream, _) = self
112             .stream_source
113             .as_mut()
114             .ok_or(Error::EmptyStreamSource)?
115             .new_async_playback_stream_and_get_shared_format(
116                 self.channels as usize,
117                 self.format,
118                 self.frame_rate as usize,
119                 // `buffer_size` in `audio_streams` API indicates the buffer size in bytes that the
120                 // stream consumes (or transmits) each time
121                 // (next_playback/capture_buffer). `period_bytes` in virtio-snd
122                 // device (or ALSA) indicates the device transmits (or
123                 // consumes) for each PCM message.
124                 // Therefore, `buffer_size` in `audio_streams` == `period_bytes` in virtio-snd.
125                 self.period_bytes / frame_size,
126                 ex,
127                 audio_client_guid,
128             )
129             .map_err(Error::CreateStream)?;
130         Ok(async_playback_buffer_stream)
131     }
132 
set_up_async_capture_stream( &mut self, frame_size: usize, ex: &Executor, ) -> Result<SysBufferReader, Error>133     pub(crate) async fn set_up_async_capture_stream(
134         &mut self,
135         frame_size: usize,
136         ex: &Executor,
137     ) -> Result<SysBufferReader, Error> {
138         let (async_capture_buffer_stream, audio_shared_format) = self
139             .stream_source
140             .as_mut()
141             .ok_or(Error::EmptyStreamSource)?
142             .new_async_capture_stream_and_get_shared_format(
143                 self.channels as usize,
144                 self.format,
145                 self.frame_rate,
146                 self.period_bytes / frame_size,
147                 ex,
148             )
149             .map_err(Error::CreateStream)?;
150         let mut buffer_reader = WinBufferReader::new(async_capture_buffer_stream);
151         Ok(buffer_reader)
152     }
153 
create_directionstream_output( &mut self, frame_size: usize, audio_client_guid: Option<String>, ex: &Executor, ) -> Result<DirectionalStream, Error>154     pub(crate) async fn create_directionstream_output(
155         &mut self,
156         frame_size: usize,
157         audio_client_guid: Option<String>,
158         ex: &Executor,
159     ) -> Result<DirectionalStream, Error> {
160         if self.playback_stream_cache.is_none() {
161             let async_playback_buffer_stream = self
162                 .set_up_async_playback_stream(frame_size, audio_client_guid, ex)
163                 .await?;
164 
165             let buffer_writer = WinBufferWriter::new(self.period_bytes);
166 
167             self.playback_stream_cache = Some((
168                 Arc::new(AsyncRwLock::new(async_playback_buffer_stream)),
169                 Rc::new(AsyncRwLock::new(Box::new(buffer_writer))),
170             ));
171         }
172         let playback_stream_cache = self
173             .playback_stream_cache
174             .as_ref()
175             .expect("playback stream cache is None. This shouldn't be possible");
176 
177         Ok(DirectionalStream::Output(SysDirectionOutput {
178             async_playback_buffer_stream: playback_stream_cache.0.clone(),
179             buffer_writer: playback_stream_cache.1.clone(),
180         }))
181     }
182 }
183 
184 pub(crate) struct WinBufferReader {
185     async_stream: Box<dyn AsyncCaptureBufferStream>,
186 }
187 
188 impl WinBufferReader {
new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self189     fn new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self {
190         WinBufferReader { async_stream }
191     }
192 }
193 
194 #[async_trait(?Send)]
195 impl CaptureBufferReader for WinBufferReader {
get_next_capture_period( &mut self, ex: &Executor, ) -> Result<AsyncCaptureBuffer, BoxError>196     async fn get_next_capture_period(
197         &mut self,
198         ex: &Executor,
199     ) -> Result<AsyncCaptureBuffer, BoxError> {
200         self.async_stream.next_capture_buffer(ex).await
201     }
202 }
203 
204 pub(crate) struct WinBufferWriter {
205     guest_period_bytes: usize,
206 }
207 
208 #[async_trait(?Send)]
209 impl PlaybackBufferWriter for WinBufferWriter {
new(guest_period_bytes: usize) -> Self210     fn new(guest_period_bytes: usize) -> Self {
211         WinBufferWriter { guest_period_bytes }
212     }
213 
endpoint_period_bytes(&self) -> usize214     fn endpoint_period_bytes(&self) -> usize {
215         self.guest_period_bytes
216     }
217 
218     // This method implementation may diverge downstream due to vendor specific requirements.
copy_to_buffer( &mut self, dst_buf: &mut AsyncPlaybackBuffer<'_>, reader: &mut Reader, ) -> Result<usize, Error>219     fn copy_to_buffer(
220         &mut self,
221         dst_buf: &mut AsyncPlaybackBuffer<'_>,
222         reader: &mut Reader,
223     ) -> Result<usize, Error> {
224         dst_buf.copy_from(reader).map_err(Error::Io)
225     }
226 }
227