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 #[cfg(feature = "audio_aaudio")]
6 use android_audio::AndroidAudioStreamSourceGenerator;
7 use async_trait::async_trait;
8 use audio_streams::capture::AsyncCaptureBuffer;
9 use audio_streams::capture::AsyncCaptureBufferStream;
10 use audio_streams::AsyncPlaybackBufferStream;
11 use audio_streams::BoxError;
12 use audio_streams::StreamSource;
13 use audio_streams::StreamSourceGenerator;
14 #[cfg(feature = "audio_cras")]
15 use base::error;
16 use base::set_rt_prio_limit;
17 use base::set_rt_round_robin;
18 use cros_async::Executor;
19 use futures::channel::mpsc::UnboundedSender;
20 #[cfg(feature = "audio_cras")]
21 use libcras::CrasStreamSourceGenerator;
22 #[cfg(feature = "audio_cras")]
23 use libcras::CrasStreamType;
24 use serde::Deserialize;
25 use serde::Serialize;
26
27 use crate::virtio::snd::common_backend::async_funcs::CaptureBufferReader;
28 use crate::virtio::snd::common_backend::async_funcs::PlaybackBufferWriter;
29 use crate::virtio::snd::common_backend::stream_info::StreamInfo;
30 use crate::virtio::snd::common_backend::DirectionalStream;
31 use crate::virtio::snd::common_backend::Error;
32 use crate::virtio::snd::common_backend::PcmResponse;
33 use crate::virtio::snd::common_backend::SndData;
34 use crate::virtio::snd::parameters::Error as ParametersError;
35 use crate::virtio::snd::parameters::Parameters;
36
37 const AUDIO_THREAD_RTPRIO: u16 = 10; // Matches other cros audio clients.
38
39 pub(crate) type SysAudioStreamSourceGenerator = Box<dyn StreamSourceGenerator>;
40 pub(crate) type SysAudioStreamSource = Box<dyn StreamSource>;
41 pub(crate) type SysBufferReader = UnixBufferReader;
42
43 pub struct SysDirectionOutput {
44 pub async_playback_buffer_stream: Box<dyn audio_streams::AsyncPlaybackBufferStream>,
45 pub buffer_writer: Box<dyn PlaybackBufferWriter>,
46 }
47
48 pub(crate) struct SysAsyncStreamObjects {
49 pub(crate) stream: DirectionalStream,
50 pub(crate) pcm_sender: UnboundedSender<PcmResponse>,
51 }
52
53 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
54 pub enum StreamSourceBackend {
55 #[cfg(feature = "audio_aaudio")]
56 AAUDIO,
57 #[cfg(feature = "audio_cras")]
58 CRAS,
59 }
60
61 // Implemented to make backend serialization possible, since we deserialize from str.
62 impl From<StreamSourceBackend> for String {
from(backend: StreamSourceBackend) -> Self63 fn from(backend: StreamSourceBackend) -> Self {
64 match backend {
65 #[cfg(feature = "audio_aaudio")]
66 StreamSourceBackend::AAUDIO => "aaudio".to_owned(),
67 #[cfg(feature = "audio_cras")]
68 StreamSourceBackend::CRAS => "cras".to_owned(),
69 }
70 }
71 }
72
73 impl TryFrom<&str> for StreamSourceBackend {
74 type Error = ParametersError;
75
try_from(s: &str) -> Result<Self, Self::Error>76 fn try_from(s: &str) -> Result<Self, Self::Error> {
77 match s {
78 #[cfg(feature = "audio_aaudio")]
79 "aaudio" => Ok(StreamSourceBackend::AAUDIO),
80 #[cfg(feature = "audio_cras")]
81 "cras" => Ok(StreamSourceBackend::CRAS),
82 _ => Err(ParametersError::InvalidBackend),
83 }
84 }
85 }
86
87 #[cfg(feature = "audio_aaudio")]
create_aaudio_stream_source_generators( snd_data: &SndData, ) -> Vec<SysAudioStreamSourceGenerator>88 pub(crate) fn create_aaudio_stream_source_generators(
89 snd_data: &SndData,
90 ) -> Vec<SysAudioStreamSourceGenerator> {
91 let mut generators: Vec<Box<dyn StreamSourceGenerator>> =
92 Vec::with_capacity(snd_data.pcm_info_len());
93 for pcm_info in snd_data.pcm_info_iter() {
94 assert_eq!(pcm_info.features, 0); // Should be 0. Android audio backend does not support any features.
95 generators.push(Box::new(AndroidAudioStreamSourceGenerator::new()));
96 }
97 generators
98 }
99
100 #[cfg(feature = "audio_cras")]
create_cras_stream_source_generators( params: &Parameters, snd_data: &SndData, ) -> Vec<Box<dyn StreamSourceGenerator>>101 pub(crate) fn create_cras_stream_source_generators(
102 params: &Parameters,
103 snd_data: &SndData,
104 ) -> Vec<Box<dyn StreamSourceGenerator>> {
105 let mut generators: Vec<Box<dyn StreamSourceGenerator>> =
106 Vec::with_capacity(snd_data.pcm_info_len());
107 for pcm_info in snd_data.pcm_info_iter() {
108 let device_params = params.get_device_params(pcm_info).unwrap_or_else(|err| {
109 error!("Create cras stream source generator error: {}", err);
110 Default::default()
111 });
112 generators.push(Box::new(CrasStreamSourceGenerator::with_stream_type(
113 params.capture,
114 device_params.client_type.unwrap_or(params.client_type),
115 params.socket_type,
116 device_params
117 .stream_type
118 .unwrap_or(CrasStreamType::CRAS_STREAM_TYPE_DEFAULT),
119 )));
120 }
121 generators
122 }
123
124 #[allow(unused_variables)]
create_stream_source_generators( backend: StreamSourceBackend, params: &Parameters, snd_data: &SndData, ) -> Vec<Box<dyn StreamSourceGenerator>>125 pub(crate) fn create_stream_source_generators(
126 backend: StreamSourceBackend,
127 params: &Parameters,
128 snd_data: &SndData,
129 ) -> Vec<Box<dyn StreamSourceGenerator>> {
130 match backend {
131 #[cfg(feature = "audio_aaudio")]
132 StreamSourceBackend::AAUDIO => create_aaudio_stream_source_generators(snd_data),
133 #[cfg(feature = "audio_cras")]
134 StreamSourceBackend::CRAS => create_cras_stream_source_generators(params, snd_data),
135 }
136 }
137
set_audio_thread_priority() -> Result<(), base::Error>138 pub(crate) fn set_audio_thread_priority() -> Result<(), base::Error> {
139 set_rt_prio_limit(u64::from(AUDIO_THREAD_RTPRIO))
140 .and_then(|_| set_rt_round_robin(i32::from(AUDIO_THREAD_RTPRIO)))
141 }
142
143 impl StreamInfo {
144 /// (*)
145 /// `buffer_size` in `audio_streams` API indicates the buffer size in bytes that the stream
146 /// consumes (or transmits) each time (next_playback/capture_buffer).
147 /// `period_bytes` in virtio-snd device (or ALSA) indicates the device transmits (or
148 /// consumes) for each PCM message.
149 /// Therefore, `buffer_size` in `audio_streams` == `period_bytes` in virtio-snd.
set_up_async_playback_stream( &mut self, frame_size: usize, ex: &Executor, ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error>150 async fn set_up_async_playback_stream(
151 &mut self,
152 frame_size: usize,
153 ex: &Executor,
154 ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error> {
155 Ok(self
156 .stream_source
157 .as_mut()
158 .ok_or(Error::EmptyStreamSource)?
159 .async_new_async_playback_stream(
160 self.channels as usize,
161 self.format,
162 self.frame_rate,
163 // See (*)
164 self.period_bytes / frame_size,
165 ex,
166 )
167 .await
168 .map_err(Error::CreateStream)?
169 .1)
170 }
171
set_up_async_capture_stream( &mut self, frame_size: usize, ex: &Executor, ) -> Result<SysBufferReader, Error>172 pub(crate) async fn set_up_async_capture_stream(
173 &mut self,
174 frame_size: usize,
175 ex: &Executor,
176 ) -> Result<SysBufferReader, Error> {
177 let async_capture_buffer_stream = self
178 .stream_source
179 .as_mut()
180 .ok_or(Error::EmptyStreamSource)?
181 .async_new_async_capture_stream(
182 self.channels as usize,
183 self.format,
184 self.frame_rate,
185 self.period_bytes / frame_size,
186 &self.effects,
187 ex,
188 )
189 .await
190 .map_err(Error::CreateStream)?
191 .1;
192 Ok(SysBufferReader::new(async_capture_buffer_stream))
193 }
194
create_directionstream_output( &mut self, frame_size: usize, ex: &Executor, ) -> Result<DirectionalStream, Error>195 pub(crate) async fn create_directionstream_output(
196 &mut self,
197 frame_size: usize,
198 ex: &Executor,
199 ) -> Result<DirectionalStream, Error> {
200 let async_playback_buffer_stream =
201 self.set_up_async_playback_stream(frame_size, ex).await?;
202
203 let buffer_writer = UnixBufferWriter::new(self.period_bytes);
204
205 Ok(DirectionalStream::Output(SysDirectionOutput {
206 async_playback_buffer_stream,
207 buffer_writer: Box::new(buffer_writer),
208 }))
209 }
210 }
211
212 pub(crate) struct UnixBufferReader {
213 async_stream: Box<dyn AsyncCaptureBufferStream>,
214 }
215
216 impl UnixBufferReader {
new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self where Self: Sized,217 fn new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self
218 where
219 Self: Sized,
220 {
221 UnixBufferReader { async_stream }
222 }
223 }
224 #[async_trait(?Send)]
225 impl CaptureBufferReader for UnixBufferReader {
get_next_capture_period( &mut self, ex: &Executor, ) -> Result<AsyncCaptureBuffer, BoxError>226 async fn get_next_capture_period(
227 &mut self,
228 ex: &Executor,
229 ) -> Result<AsyncCaptureBuffer, BoxError> {
230 Ok(self
231 .async_stream
232 .next_capture_buffer(ex)
233 .await
234 .map_err(Error::FetchBuffer)?)
235 }
236 }
237
238 pub(crate) struct UnixBufferWriter {
239 guest_period_bytes: usize,
240 }
241
242 #[async_trait(?Send)]
243 impl PlaybackBufferWriter for UnixBufferWriter {
new(guest_period_bytes: usize) -> Self244 fn new(guest_period_bytes: usize) -> Self {
245 UnixBufferWriter { guest_period_bytes }
246 }
endpoint_period_bytes(&self) -> usize247 fn endpoint_period_bytes(&self) -> usize {
248 self.guest_period_bytes
249 }
250 }
251