• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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