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