audio_streams_conformance_test: support playback test for cras_stream

Support playback test for cras_stream.
It does not support `cargo build --features=chromeos` to enable
the libcras support due to the sys_util dependency of libcras.

The output result is like:

==
audio_streams_conformance_test -P cras --iterations 100

Playback Source: CRAS
Channels: 2
Format: S16LE
Sample rate: 48000 frames/s
Buffer size: 240 frames
Iterations: 100

Cold start latency: 239.692005ms
Records count: 100
[Step] min: 4.68 ms, max: 65.29 ms, average: 5.61 ms, standard
deviation: 6.03 ms.
[Linear Regression] rate: 47576.23 frames/s, standard error: 284.42

BUG=b:238038707
TEST=emerge-${BOARD} audio_streams_conformance_test
TEST=audio_streams_conformance_test -P cras

Change-Id: I2547df7b15cd36adb5452ab09d2a38e417b04dbf
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3864013
Tested-by: Judy Hsiao <judyhsiao@google.com>
Commit-Queue: Judy Hsiao <judyhsiao@google.com>
Reviewed-by: Chih-Yang Hsia <paulhsia@chromium.org>
Auto-Submit: Judy Hsiao <judyhsiao@google.com>
This commit is contained in:
Judy Hsiao 2022-08-29 22:50:32 +00:00 committed by crosvm LUCI
parent 3174c86a36
commit dbd67e522a
6 changed files with 137 additions and 8 deletions

View file

@ -8,12 +8,22 @@ edition = "2021"
name = "audio_streams_conformance_test"
path = "src/main.rs"
[features]
audio_cras = ["dep:libcras"]
chromeos = ["audio_cras"]
[dependencies]
argh = "*"
audio_streams = { path = "../../common/audio_streams" } # provided by ebuild
audio_streams = "*"
cfg-if = "1.0.0"
cros_async = { path = "../../cros_async" } # provided by ebuild
num = "*"
libcras = { version = "*", optional = true }
remain = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "*"
thiserror = "1.0.20"
[patch.crates-io]
audio_streams = { path = "../../common/audio_streams"} # ignored by ebuild
libcras = { path = "../../libcras_stub" } # ignored by ebuild

View file

@ -10,17 +10,20 @@ use audio_streams::*;
use serde::Serialize;
use super::error::Error;
use super::sys::StreamSource as SysStreamSource;
// maybe use StreamSourceGenerator directly
#[derive(Copy, Clone, Debug, PartialEq, Serialize)]
pub enum StreamSourceEnum {
NoopStream,
Sys(SysStreamSource),
}
impl fmt::Display for StreamSourceEnum {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
StreamSourceEnum::NoopStream => write!(f, "noop"),
StreamSourceEnum::Sys(stream_source) => stream_source.fmt(f),
}
}
}
@ -30,7 +33,7 @@ impl FromStr for StreamSourceEnum {
fn from_str(s: &str) -> ::std::result::Result<StreamSourceEnum, Self::Err> {
match s {
"noop" => Ok(StreamSourceEnum::NoopStream),
_ => Err(Error::InvalidStreamSuorce(s.to_owned())),
_ => SysStreamSource::try_from(s).map(StreamSourceEnum::Sys),
}
}
}
@ -60,7 +63,7 @@ fn default_stream_source() -> StreamSourceEnum {
}
#[derive(Copy, Clone, Debug, FromArgs, Serialize)]
/// test test
/// audio_streams_conformance_test
pub struct Args {
/// the StreamSource to use for playback. (default: noop).
#[argh(
@ -69,7 +72,7 @@ pub struct Args {
default = "default_stream_source()",
from_str_fn(StreamSourceEnum::from_str)
)]
pub playback_source: StreamSourceEnum,
pub stream_source: StreamSourceEnum,
/// the channel numbers. (default: 2)
#[argh(option, short = 'c', default = "default_channels()")]
pub channels: usize,
@ -107,7 +110,7 @@ Sample rate: {} frames/s
Buffer size: {} frames
Iterations: {}
"#,
self.playback_source,
self.stream_source,
self.channels,
self.format,
self.rate,

View file

@ -11,17 +11,26 @@ use cros_async::Executor;
mod args;
mod error;
mod performance_data;
mod sys;
use crate::args::*;
use crate::error::Error;
use crate::error::Result;
use crate::performance_data::*;
use crate::sys::create_stream_source_generator as sys_create_stream_source_generators;
fn create_stream_source_generators(args: &Args) -> Box<dyn StreamSourceGenerator> {
match args.stream_source {
StreamSourceEnum::NoopStream => Box::new(NoopStreamSourceGenerator::new()),
StreamSourceEnum::Sys(stream_source) => {
sys_create_stream_source_generators(stream_source, args)
}
}
}
async fn run_playback(ex: &Executor, args: &Args) -> Result<PerformanceData> {
let mut data = PerformanceData::default();
let generator: Box<dyn StreamSourceGenerator> = match args.playback_source {
StreamSourceEnum::NoopStream => Box::new(NoopStreamSourceGenerator::new()),
};
let generator: Box<dyn StreamSourceGenerator> = create_stream_source_generators(args);
let num_channels = args.channels;
let format = args.format;
let frame_rate = args.rate;

View file

@ -0,0 +1,16 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cfg_if::cfg_if! {
if #[cfg(unix)] {
mod unix;
use unix as platform;
} else if #[cfg(windows)] {
mod windows;
use windows as platform;
}
}
pub(crate) use platform::create_stream_source_generator;
pub use platform::StreamSource;

View file

@ -0,0 +1,62 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::fmt;
use audio_streams::StreamSourceGenerator;
#[cfg(feature = "audio_cras")]
use libcras::{CrasClientType, CrasSocketType, CrasStreamSourceGenerator};
use serde::Serialize;
use crate::args::*;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub enum StreamSource {
#[cfg(feature = "audio_cras")]
CRAS,
}
impl TryFrom<&str> for StreamSource {
type Error = Error;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match s {
#[cfg(feature = "audio_cras")]
"cras" => Ok(StreamSource::CRAS),
_ => Err(Error::InvalidStreamSuorce(s.to_owned())),
}
}
}
impl fmt::Display for StreamSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
#[cfg(feature = "audio_cras")]
StreamSource::CRAS => write!(f, "cras"),
_ => write!(f, "unknow stream source"),
}
}
}
#[allow(unused_variables)]
#[cfg(feature = "audio_cras")]
fn create_cras_stream_source_generator(args: &Args) -> Box<dyn StreamSourceGenerator> {
Box::new(CrasStreamSourceGenerator::new(
false,
CrasClientType::CRAS_CLIENT_TYPE_TEST,
CrasSocketType::Legacy,
))
}
#[allow(unused_variables)]
pub(crate) fn create_stream_source_generator(
stream_source: StreamSource,
args: &Args,
) -> Box<dyn StreamSourceGenerator> {
match stream_source {
#[cfg(feature = "audio_cras")]
StreamSource::CRAS => create_cras_stream_source_generator(args),
}
}

View file

@ -0,0 +1,29 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use audio_streams::StreamSourceGenerator;
use crate::args::*;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum StreamSource {}
#[derive(Copy, Clone, Debug, FromArgs, Serialize)]
pub enum StreamSourceParam {}
impl TryFrom<&str> for StreamSource {
type Error = Error;
fn try_from(s: &str) -> Result<Self, Self::Error> {
todo!();
}
}
pub(crate) fn create_stream_source_generator(
stream_source: StreamSource,
args: &Args,
) -> Vec<Box<dyn StreamSourceGenerator>> {
todo!();
}