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, ex: &Executor, ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error>105 async fn set_up_async_playback_stream(
106 &mut self,
107 frame_size: usize,
108 ex: &Executor,
109 ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error> {
110 let (async_playback_buffer_stream, _) = self
111 .stream_source
112 .as_mut()
113 .ok_or(Error::EmptyStreamSource)?
114 .new_async_playback_stream_and_get_shared_format(
115 self.channels as usize,
116 self.format,
117 self.frame_rate as usize,
118 // `buffer_size` in `audio_streams` API indicates the buffer size in bytes that the
119 // stream consumes (or transmits) each time
120 // (next_playback/capture_buffer). `period_bytes` in virtio-snd
121 // device (or ALSA) indicates the device transmits (or
122 // consumes) for each PCM message.
123 // Therefore, `buffer_size` in `audio_streams` == `period_bytes` in virtio-snd.
124 self.period_bytes / frame_size,
125 ex,
126 )
127 .map_err(Error::CreateStream)?;
128 Ok(async_playback_buffer_stream)
129 }
130
set_up_async_capture_stream( &mut self, frame_size: usize, ex: &Executor, ) -> Result<SysBufferReader, Error>131 pub(crate) async fn set_up_async_capture_stream(
132 &mut self,
133 frame_size: usize,
134 ex: &Executor,
135 ) -> Result<SysBufferReader, Error> {
136 let (async_capture_buffer_stream, audio_shared_format) = self
137 .stream_source
138 .as_mut()
139 .ok_or(Error::EmptyStreamSource)?
140 .new_async_capture_stream_and_get_shared_format(
141 self.channels as usize,
142 self.format,
143 self.frame_rate,
144 self.period_bytes / frame_size,
145 ex,
146 )
147 .map_err(Error::CreateStream)?;
148 let mut buffer_reader = WinBufferReader::new(async_capture_buffer_stream);
149 Ok(buffer_reader)
150 }
151
create_directionstream_output( &mut self, frame_size: usize, ex: &Executor, ) -> Result<DirectionalStream, Error>152 pub(crate) async fn create_directionstream_output(
153 &mut self,
154 frame_size: usize,
155 ex: &Executor,
156 ) -> Result<DirectionalStream, Error> {
157 if self.playback_stream_cache.is_none() {
158 let async_playback_buffer_stream =
159 self.set_up_async_playback_stream(frame_size, ex).await?;
160
161 let buffer_writer = WinBufferWriter::new(self.period_bytes);
162
163 self.playback_stream_cache = Some((
164 Arc::new(AsyncRwLock::new(async_playback_buffer_stream)),
165 Rc::new(AsyncRwLock::new(Box::new(buffer_writer))),
166 ));
167 }
168 let playback_stream_cache = self
169 .playback_stream_cache
170 .as_ref()
171 .expect("playback stream cache is None. This shouldn't be possible");
172
173 Ok(DirectionalStream::Output(SysDirectionOutput {
174 async_playback_buffer_stream: playback_stream_cache.0.clone(),
175 buffer_writer: playback_stream_cache.1.clone(),
176 }))
177 }
178 }
179
180 pub(crate) struct WinBufferReader {
181 async_stream: Box<dyn AsyncCaptureBufferStream>,
182 }
183
184 impl WinBufferReader {
new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self185 fn new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self {
186 WinBufferReader { async_stream }
187 }
188 }
189
190 #[async_trait(?Send)]
191 impl CaptureBufferReader for WinBufferReader {
get_next_capture_period( &mut self, ex: &Executor, ) -> Result<AsyncCaptureBuffer, BoxError>192 async fn get_next_capture_period(
193 &mut self,
194 ex: &Executor,
195 ) -> Result<AsyncCaptureBuffer, BoxError> {
196 self.async_stream.next_capture_buffer(ex).await
197 }
198 }
199
200 pub(crate) struct WinBufferWriter {
201 guest_period_bytes: usize,
202 }
203
204 #[async_trait(?Send)]
205 impl PlaybackBufferWriter for WinBufferWriter {
new(guest_period_bytes: usize) -> Self206 fn new(guest_period_bytes: usize) -> Self {
207 WinBufferWriter { guest_period_bytes }
208 }
209
endpoint_period_bytes(&self) -> usize210 fn endpoint_period_bytes(&self) -> usize {
211 self.guest_period_bytes
212 }
213
214 // 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>215 fn copy_to_buffer(
216 &mut self,
217 dst_buf: &mut AsyncPlaybackBuffer<'_>,
218 reader: &mut Reader,
219 ) -> Result<usize, Error> {
220 dst_buf.copy_from(reader).map_err(Error::Io)
221 }
222 }
223