// Copyright (c) 2014 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include extern "C" { #include "audio_thread_log.h" #include "byte_buffer.h" #include "cras_audio_area.h" #include "cras_rstream.h" #include "cras_shm.h" #include "cras_types.h" #include "dev_stream.h" } namespace { extern "C" { struct audio_thread_event_log* atlog; // For audio_thread_log.h use. int atlog_rw_shm_fd; int atlog_ro_shm_fd; unsigned int max_frames_for_conversion(unsigned int stream_frames, unsigned int stream_rate, unsigned int device_rate); }; static struct timespec clock_gettime_retspec; static struct timespec cb_ts; static const int kBufferFrames = 1024; static const struct cras_audio_format fmt_s16le_44_1 = { SND_PCM_FORMAT_S16_LE, 44100, 2, }; static const struct cras_audio_format fmt_s16le_48 = { SND_PCM_FORMAT_S16_LE, 48000, 2, }; static const struct cras_audio_format fmt_s16le_48_mono = { SND_PCM_FORMAT_S16_LE, 48000, 1, }; static const struct cras_audio_format fmt_s16le_8 = { SND_PCM_FORMAT_S16_LE, 8000, 2, }; struct cras_audio_area_copy_call { const struct cras_audio_area* dst; unsigned int dst_offset; unsigned int dst_format_bytes; const struct cras_audio_area* src; unsigned int src_offset; float software_gain_scaler; }; struct fmt_conv_call { struct cras_fmt_conv* conv; uint8_t* in_buf; uint8_t* out_buf; size_t in_frames; size_t out_frames; }; struct mix_add_call { int16_t* dst; int16_t* src; unsigned int count; unsigned int index; int mute; float mix_vol; }; struct rstream_get_readable_call { struct cras_rstream* rstream; unsigned int offset; unsigned int num_called; }; static int config_format_converter_called; static const struct cras_audio_format* config_format_converter_from_fmt; static int config_format_converter_frames; static struct cras_fmt_conv* config_format_converter_conv; static struct cras_audio_format in_fmt; static struct cras_audio_format out_fmt; static struct cras_audio_area_copy_call copy_area_call; static struct fmt_conv_call conv_frames_call; static int cras_audio_area_create_num_channels_val; static int cras_fmt_conversion_needed_val; static int cras_fmt_conv_set_linear_resample_rates_called; static float cras_fmt_conv_set_linear_resample_rates_from; static float cras_fmt_conv_set_linear_resample_rates_to; static unsigned int rstream_playable_frames_ret; static struct mix_add_call mix_add_call; static struct rstream_get_readable_call rstream_get_readable_call; static unsigned int rstream_get_readable_num; static uint8_t* rstream_get_readable_ptr; static struct cras_audio_format* cras_rstream_post_processing_format_val; static int cras_rstream_audio_ready_called; static int cras_rstream_audio_ready_count; static int cras_rstream_is_pending_reply_ret; static int cras_rstream_flush_old_audio_messages_called; static int cras_server_metrics_missed_cb_event_called; static char* atlog_name; class CreateSuite : public testing::Test { protected: virtual void SetUp() { in_fmt.format = SND_PCM_FORMAT_S16_LE; out_fmt.format = SND_PCM_FORMAT_S16_LE; in_fmt.num_channels = 2; out_fmt.num_channels = 2; SetupShm(&rstream_.shm); rstream_.stream_id = 0x10001; rstream_.buffer_frames = kBufferFrames; rstream_.cb_threshold = kBufferFrames / 2; rstream_.is_draining = 0; rstream_.stream_type = CRAS_STREAM_TYPE_DEFAULT; rstream_.direction = CRAS_STREAM_OUTPUT; rstream_.format.format = SND_PCM_FORMAT_S16_LE; rstream_.format.num_channels = 2; rstream_.format = fmt_s16le_44_1; rstream_.flags = 0; rstream_.num_missed_cb = 0; config_format_converter_from_fmt = NULL; config_format_converter_called = 0; cras_fmt_conversion_needed_val = 0; cras_fmt_conv_set_linear_resample_rates_called = 0; cras_rstream_audio_ready_called = 0; cras_rstream_audio_ready_count = 0; cras_rstream_is_pending_reply_ret = 0; cras_rstream_flush_old_audio_messages_called = 0; cras_server_metrics_missed_cb_event_called = 0; memset(©_area_call, 0xff, sizeof(copy_area_call)); memset(&conv_frames_call, 0xff, sizeof(conv_frames_call)); ASSERT_FALSE(asprintf(&atlog_name, "/ATlog-%d", getpid()) < 0); /* To avoid un-used variable warning. */ atlog_rw_shm_fd = atlog_ro_shm_fd = -1; atlog = audio_thread_event_log_init(atlog_name); devstr.stream = &rstream_; devstr.conv = NULL; devstr.conv_buffer = NULL; devstr.conv_buffer_size_frames = 0; area = (struct cras_audio_area*)calloc( 1, sizeof(*area) + 2 * sizeof(struct cras_channel_area)); area->num_channels = 2; channel_area_set_channel(&area->channels[0], CRAS_CH_FL); channel_area_set_channel(&area->channels[1], CRAS_CH_FR); area->channels[0].step_bytes = 4; area->channels[0].buf = (uint8_t*)(cap_buf); area->channels[1].step_bytes = 4; area->channels[1].buf = (uint8_t*)(cap_buf + 1); area->frames = kBufferFrames; stream_area = (struct cras_audio_area*)calloc( 1, sizeof(*area) + 2 * sizeof(struct cras_channel_area)); stream_area->num_channels = 2; rstream_.audio_area = stream_area; int16_t* shm_samples = (int16_t*)rstream_.shm->samples; stream_area->channels[0].step_bytes = 4; stream_area->channels[0].buf = (uint8_t*)(shm_samples); stream_area->channels[1].step_bytes = 4; stream_area->channels[1].buf = (uint8_t*)(shm_samples + 1); } virtual void TearDown() { free(area); free(stream_area); free(rstream_.shm->header); free(rstream_.shm->samples); free(rstream_.shm); audio_thread_event_log_deinit(atlog, atlog_name); free(atlog_name); } void SetupShm(struct cras_audio_shm** shm_out) { int16_t* buf; struct cras_audio_shm* shm; uint32_t used_size; shm = static_cast( calloc(1, sizeof(struct cras_audio_shm))); shm->header = static_cast( calloc(1, sizeof(struct cras_audio_shm_header))); cras_shm_set_frame_bytes(shm, 4); used_size = kBufferFrames * cras_shm_frame_bytes(shm); cras_shm_set_used_size(shm, used_size); shm->samples = static_cast( calloc(1, cras_shm_calculate_samples_size(used_size))); shm->samples_info.length = cras_shm_calculate_samples_size(used_size); buf = (int16_t*)shm->samples; for (size_t i = 0; i < kBufferFrames * 2; i++) buf[i] = i; cras_shm_set_mute(shm, 0); cras_shm_set_volume_scaler(shm, 1.0); *shm_out = shm; } void SetUpFmtConv(unsigned int in_rate, unsigned int out_rate, unsigned int conv_buf_size) { in_fmt.frame_rate = in_rate; out_fmt.frame_rate = out_rate; cras_fmt_conversion_needed_val = 1; devstr.conv = (struct cras_fmt_conv*)0xdead; devstr.conv_buffer = (struct byte_buffer*)byte_buffer_create(conv_buf_size * 4); devstr.conv_buffer_size_frames = kBufferFrames * 2; devstr.conv_area = (struct cras_audio_area*)calloc( 1, sizeof(*area) + 2 * sizeof(*area->channels)); devstr.conv_area->num_channels = 2; devstr.conv_area->channels[0].step_bytes = 4; devstr.conv_area->channels[0].buf = (uint8_t*)(devstr.conv_buffer->bytes); devstr.conv_area->channels[1].step_bytes = 4; devstr.conv_area->channels[1].buf = (uint8_t*)(devstr.conv_buffer->bytes + 1); } struct dev_stream devstr; struct cras_audio_area* area; struct cras_audio_area* stream_area; int16_t cap_buf[kBufferFrames * 2]; struct cras_rstream rstream_; }; TEST_F(CreateSuite, CaptureNoSRC) { float software_gain_scaler = 10; dev_stream_capture(&devstr, area, 0, software_gain_scaler); EXPECT_EQ(stream_area, copy_area_call.dst); EXPECT_EQ(0, copy_area_call.dst_offset); EXPECT_EQ(4, copy_area_call.dst_format_bytes); EXPECT_EQ(area, copy_area_call.src); EXPECT_EQ(software_gain_scaler, copy_area_call.software_gain_scaler); } TEST_F(CreateSuite, CaptureSRCSmallConverterBuffer) { float software_gain_scaler = 10; unsigned int conv_buf_avail_at_input_rate; int nread; SetUpFmtConv(44100, 32000, kBufferFrames / 4); nread = dev_stream_capture(&devstr, area, 0, software_gain_scaler); // |nread| is bound by small converter buffer size (kBufferFrames / 4) conv_buf_avail_at_input_rate = cras_frames_at_rate( out_fmt.frame_rate, (kBufferFrames / 4), in_fmt.frame_rate); EXPECT_EQ(conv_buf_avail_at_input_rate, nread); EXPECT_EQ((struct cras_fmt_conv*)0xdead, conv_frames_call.conv); EXPECT_EQ((uint8_t*)cap_buf, conv_frames_call.in_buf); EXPECT_EQ(devstr.conv_buffer->bytes, conv_frames_call.out_buf); EXPECT_EQ(conv_buf_avail_at_input_rate, conv_frames_call.in_frames); // Expect number of output frames is limited by the size of converter buffer. EXPECT_EQ(kBufferFrames / 4, conv_frames_call.out_frames); EXPECT_EQ(stream_area, copy_area_call.dst); EXPECT_EQ(0, copy_area_call.dst_offset); EXPECT_EQ(4, copy_area_call.dst_format_bytes); EXPECT_EQ(devstr.conv_area, copy_area_call.src); EXPECT_EQ(software_gain_scaler, copy_area_call.software_gain_scaler); free(devstr.conv_area); byte_buffer_destroy(&devstr.conv_buffer); } TEST_F(CreateSuite, CaptureSRCLargeConverterBuffer) { float software_gain_scaler = 10; unsigned int stream_avail_at_input_rate; int nread; SetUpFmtConv(44100, 32000, kBufferFrames * 2); nread = dev_stream_capture(&devstr, area, 0, software_gain_scaler); // Available frames at stream side is bound by cb_threshold, which // equals to kBufferFrames / 2. stream_avail_at_input_rate = cras_frames_at_rate( out_fmt.frame_rate, (kBufferFrames / 2), in_fmt.frame_rate); EXPECT_EQ(stream_avail_at_input_rate, nread); EXPECT_EQ((struct cras_fmt_conv*)0xdead, conv_frames_call.conv); EXPECT_EQ((uint8_t*)cap_buf, conv_frames_call.in_buf); EXPECT_EQ(devstr.conv_buffer->bytes, conv_frames_call.out_buf); // Expect number of input frames is limited by |stream_avail_at_input_rate| // at format conversion. EXPECT_EQ(stream_avail_at_input_rate, conv_frames_call.in_frames); // Expect number of output frames is limited by the size of converter buffer. EXPECT_EQ(kBufferFrames * 2, conv_frames_call.out_frames); EXPECT_EQ(stream_area, copy_area_call.dst); EXPECT_EQ(0, copy_area_call.dst_offset); EXPECT_EQ(4, copy_area_call.dst_format_bytes); EXPECT_EQ(devstr.conv_area, copy_area_call.src); EXPECT_EQ(software_gain_scaler, copy_area_call.software_gain_scaler); free(devstr.conv_area); byte_buffer_destroy(&devstr.conv_buffer); } TEST_F(CreateSuite, CreateSRC44to48) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_44_1; in_fmt.frame_rate = 44100; // Input to converter is stream rate. out_fmt.frame_rate = 48000; // Output from converter is device rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device output. unsigned int device_frames = cras_frames_at_rate(in_fmt.frame_rate, kBufferFrames, out_fmt.frame_rate); EXPECT_LE(kBufferFrames, device_frames); // Soundness check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC44from48Input) { struct dev_stream* dev_stream; struct cras_audio_format processed_fmt = fmt_s16le_48; processed_fmt.num_channels = 1; rstream_.format = fmt_s16le_44_1; rstream_.direction = CRAS_STREAM_INPUT; in_fmt.frame_rate = 48000; // Input to converter is device rate. out_fmt.frame_rate = 44100; // Output from converter is stream rate. config_format_converter_conv = reinterpret_cast(0x33); cras_rstream_post_processing_format_val = &processed_fmt; dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device input. unsigned int device_frames = cras_frames_at_rate(out_fmt.frame_rate, kBufferFrames, in_fmt.frame_rate); EXPECT_LE(kBufferFrames, device_frames); // Soundness check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_EQ(&processed_fmt, config_format_converter_from_fmt); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC48to44) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_48; in_fmt.frame_rate = 48000; // Stream rate. out_fmt.frame_rate = 44100; // Device rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream input. EXPECT_LE(kBufferFrames, config_format_converter_frames); EXPECT_LE(kBufferFrames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC48from44Input) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; in_fmt.frame_rate = 44100; // Device rate. out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. EXPECT_LE(kBufferFrames, config_format_converter_frames); EXPECT_LE(kBufferFrames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC8to48) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_8; in_fmt.frame_rate = 8000; // Stream rate. out_fmt.frame_rate = 48000; // Device rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device output. unsigned int device_frames = cras_frames_at_rate(in_fmt.frame_rate, kBufferFrames, out_fmt.frame_rate); EXPECT_LE(kBufferFrames, device_frames); // Soundness check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC8from48Input) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_8; rstream_.direction = CRAS_STREAM_INPUT; in_fmt.frame_rate = 48000; // Device rate. out_fmt.frame_rate = 8000; // Stream rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device input. unsigned int device_frames = cras_frames_at_rate(out_fmt.frame_rate, kBufferFrames, in_fmt.frame_rate); EXPECT_LE(kBufferFrames, device_frames); // Soundness check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC48to8) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_48; in_fmt.frame_rate = 48000; // Stream rate. out_fmt.frame_rate = 8000; // Device rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream input. EXPECT_LE(kBufferFrames, config_format_converter_frames); EXPECT_LE(kBufferFrames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC48from8Input) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; in_fmt.frame_rate = 8000; // Device rate. out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. EXPECT_LE(kBufferFrames, config_format_converter_frames); EXPECT_LE(kBufferFrames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CreateSRC48MonoFrom44StereoInput) { struct dev_stream* dev_stream; rstream_.format = fmt_s16le_48_mono; rstream_.direction = CRAS_STREAM_INPUT; in_fmt.frame_rate = 44100; // Device rate. out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. EXPECT_LE(kBufferFrames, config_format_converter_frames); EXPECT_LE(kBufferFrames, dev_stream->conv_buffer_size_frames); EXPECT_EQ(dev_stream->conv_buffer_size_frames * 4, dev_stream->conv_buffer->max_size); EXPECT_EQ(2, cras_audio_area_create_num_channels_val); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, CaptureAvailConvBufHasSamples) { struct dev_stream* dev_stream; unsigned int avail; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast(NULL), dev_stream->conv_buffer); EXPECT_LE( cras_frames_at_rate(in_fmt.frame_rate, kBufferFrames, out_fmt.frame_rate), dev_stream->conv_buffer_size_frames); EXPECT_EQ(dev_stream->conv_buffer_size_frames * 4, dev_stream->conv_buffer->max_size); EXPECT_EQ(2, cras_audio_area_create_num_channels_val); buf_increment_write(dev_stream->conv_buffer, 50 * 4); avail = dev_stream_capture_avail(dev_stream); EXPECT_EQ(cras_frames_at_rate(48000, 512 - 50, 44100), avail); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, SetDevRateNotMasterDev) { struct dev_stream* dev_stream; unsigned int dev_id = 9; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; rstream_.master_dev.dev_id = 4; config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 0); EXPECT_EQ(1, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_EQ(44541, cras_fmt_conv_set_linear_resample_rates_to); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 1); EXPECT_EQ(2, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_LE(44541, cras_fmt_conv_set_linear_resample_rates_to); dev_stream_set_dev_rate(dev_stream, 44100, 1.0, 1.01, -1); EXPECT_EQ(3, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_GE(43663, cras_fmt_conv_set_linear_resample_rates_to); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, SetDevRateMasterDev) { struct dev_stream* dev_stream; unsigned int dev_id = 9; unsigned int expected_ts_nsec; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; rstream_.master_dev.dev_id = dev_id; config_format_converter_conv = reinterpret_cast(0x33); dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 0); EXPECT_EQ(1, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_to); expected_ts_nsec = 1000000000.0 * kBufferFrames / 2.0 / 48000.0 / 1.01; EXPECT_EQ(0, rstream_.sleep_interval_ts.tv_sec); EXPECT_EQ(expected_ts_nsec, rstream_.sleep_interval_ts.tv_nsec); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 1); EXPECT_EQ(2, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_LE(44100, cras_fmt_conv_set_linear_resample_rates_to); expected_ts_nsec = 1000000000.0 * kBufferFrames / 2.0 / 48000.0 / 1.01; EXPECT_EQ(0, rstream_.sleep_interval_ts.tv_sec); EXPECT_EQ(expected_ts_nsec, rstream_.sleep_interval_ts.tv_nsec); dev_stream_set_dev_rate(dev_stream, 44100, 1.0, 1.33, -1); EXPECT_EQ(3, cras_fmt_conv_set_linear_resample_rates_called); EXPECT_EQ(44100, cras_fmt_conv_set_linear_resample_rates_from); EXPECT_GE(44100, cras_fmt_conv_set_linear_resample_rates_to); expected_ts_nsec = 1000000000.0 * kBufferFrames / 2.0 / 48000.0; EXPECT_EQ(0, rstream_.sleep_interval_ts.tv_sec); EXPECT_EQ(expected_ts_nsec, rstream_.sleep_interval_ts.tv_nsec); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, StreamMixNoFrames) { struct dev_stream dev_stream; struct cras_audio_format fmt; dev_stream.conv = NULL; rstream_playable_frames_ret = 0; fmt.num_channels = 2; fmt.format = SND_PCM_FORMAT_S16_LE; EXPECT_EQ(0, dev_stream_mix(&dev_stream, &fmt, 0, 3)); } TEST_F(CreateSuite, StreamMixNoConv) { struct dev_stream dev_stream; const unsigned int nfr = 100; struct cras_audio_format fmt; dev_stream.conv = NULL; dev_stream.stream = reinterpret_cast(0x5446); rstream_playable_frames_ret = nfr; rstream_get_readable_num = nfr; rstream_get_readable_ptr = reinterpret_cast(0x4000); rstream_get_readable_call.num_called = 0; fmt.num_channels = 2; fmt.format = SND_PCM_FORMAT_S16_LE; EXPECT_EQ(nfr, dev_stream_mix(&dev_stream, &fmt, (uint8_t*)0x5000, nfr)); EXPECT_EQ((int16_t*)0x5000, mix_add_call.dst); EXPECT_EQ((int16_t*)0x4000, mix_add_call.src); EXPECT_EQ(200, mix_add_call.count); EXPECT_EQ(1, mix_add_call.index); EXPECT_EQ(dev_stream.stream, rstream_get_readable_call.rstream); EXPECT_EQ(0, rstream_get_readable_call.offset); EXPECT_EQ(1, rstream_get_readable_call.num_called); } TEST_F(CreateSuite, StreamMixNoConvTwoPass) { struct dev_stream dev_stream; const unsigned int nfr = 100; const unsigned int bytes_per_sample = 2; const unsigned int num_channels = 2; const unsigned int bytes_per_frame = bytes_per_sample * num_channels; struct cras_audio_format fmt; dev_stream.conv = NULL; dev_stream.stream = reinterpret_cast(0x5446); rstream_playable_frames_ret = nfr; rstream_get_readable_num = nfr / 2; rstream_get_readable_ptr = reinterpret_cast(0x4000); rstream_get_readable_call.num_called = 0; fmt.num_channels = 2; fmt.format = SND_PCM_FORMAT_S16_LE; EXPECT_EQ(nfr, dev_stream_mix(&dev_stream, &fmt, (uint8_t*)0x5000, nfr)); const unsigned int half_offset = nfr / 2 * bytes_per_frame; EXPECT_EQ((int16_t*)(0x5000 + half_offset), mix_add_call.dst); EXPECT_EQ((int16_t*)0x4000, mix_add_call.src); EXPECT_EQ(nfr / 2 * num_channels, mix_add_call.count); EXPECT_EQ(1, mix_add_call.index); EXPECT_EQ(dev_stream.stream, rstream_get_readable_call.rstream); EXPECT_EQ(nfr / 2, rstream_get_readable_call.offset); EXPECT_EQ(2, rstream_get_readable_call.num_called); } TEST_F(CreateSuite, DevStreamFlushAudioMessages) { struct dev_stream* dev_stream; unsigned int dev_id = 9; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); dev_stream_flush_old_audio_messages(dev_stream); EXPECT_EQ(1, cras_rstream_flush_old_audio_messages_called); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, DevStreamIsPending) { struct dev_stream* dev_stream; unsigned int dev_id = 9; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); // dev_stream_is_pending_reply is only a wrapper. cras_rstream_is_pending_reply_ret = 0; EXPECT_EQ(0, dev_stream_is_pending_reply(dev_stream)); cras_rstream_is_pending_reply_ret = 1; EXPECT_EQ(1, dev_stream_is_pending_reply(dev_stream)); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, StreamCanSend) { struct dev_stream* dev_stream; unsigned int dev_id = 9; int written_frames; int rc; struct timespec expected_next_cb_ts; rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 0; // Case 1: Not enough samples. Time is not late enough. // Stream can not send data to client. clock_gettime_retspec.tv_sec = 0; clock_gettime_retspec.tv_nsec = 0; rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(0, cras_rstream_audio_ready_called); EXPECT_EQ(0, cras_server_metrics_missed_cb_event_called); EXPECT_EQ(0, rc); // Case 2: Not enough samples. Time is late enough. // Stream can not send data to client. // Assume time is greater than next_cb_ts. clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 500; // However, written frames is less than cb_threshold. // Stream still can not send samples to client. rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(0, cras_rstream_audio_ready_called); EXPECT_EQ(0, cras_server_metrics_missed_cb_event_called); EXPECT_EQ(0, rc); // Case 3: Enough samples. Time is not late enough. // Stream can not send data to client. // Assume time is less than next_cb_ts. clock_gettime_retspec.tv_sec = 0; clock_gettime_retspec.tv_nsec = 0; // Enough samples are written. written_frames = rstream_.cb_threshold + 10; cras_shm_buffer_written(rstream_.shm, written_frames); // Stream still can not send samples to client. rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(0, cras_rstream_audio_ready_called); EXPECT_EQ(0, cras_server_metrics_missed_cb_event_called); EXPECT_EQ(0, rc); // Case 4: Enough samples. Time is late enough. // Stream should send one cb_threshold to client. clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 500; rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); EXPECT_EQ(rstream_.cb_threshold, cras_rstream_audio_ready_count); EXPECT_EQ(0, cras_server_metrics_missed_cb_event_called); EXPECT_EQ(0, rc); // Check next_cb_ts is increased by one sleep interval. expected_next_cb_ts.tv_sec = 1; expected_next_cb_ts.tv_nsec = 0; add_timespecs(&expected_next_cb_ts, &rstream_.sleep_interval_ts); EXPECT_EQ(expected_next_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); EXPECT_EQ(expected_next_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); // Reset stub data of interest. cras_rstream_audio_ready_called = 0; cras_rstream_audio_ready_count = 0; rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 0; // Case 5: Enough samples. Time is late enough and it is too late // such that a new next_cb_ts is in the past. // Stream should send one cb_threshold to client and reset schedule. clock_gettime_retspec.tv_sec = 2; clock_gettime_retspec.tv_nsec = 0; rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); EXPECT_EQ(rstream_.cb_threshold, cras_rstream_audio_ready_count); EXPECT_EQ(1, cras_server_metrics_missed_cb_event_called); EXPECT_EQ(0, rc); // Check next_cb_ts is rest to be now plus one sleep interval. expected_next_cb_ts.tv_sec = 2; expected_next_cb_ts.tv_nsec = 0; add_timespecs(&expected_next_cb_ts, &rstream_.sleep_interval_ts); EXPECT_EQ(expected_next_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); EXPECT_EQ(expected_next_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, StreamCanSendBulkAudio) { struct dev_stream* dev_stream; unsigned int dev_id = 9; int written_frames; int rc; struct timespec expected_next_cb_ts; rstream_.direction = CRAS_STREAM_INPUT; rstream_.flags |= BULK_AUDIO_OK; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 0; // Case 1: Not enough samples. Time is not late enough. // Bulk audio stream can not send data to client. clock_gettime_retspec.tv_sec = 0; clock_gettime_retspec.tv_nsec = 0; rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(0, cras_rstream_audio_ready_called); EXPECT_EQ(0, rc); // Case 2: Not enough samples. Time is late enough. // Bulk audio stream can not send data to client. // Assume time is greater than next_cb_ts. clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 500; // However, written frames is less than cb_threshold. // Stream still can not send samples to client. rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(0, cras_rstream_audio_ready_called); EXPECT_EQ(0, rc); // Case 3: Enough samples. Time is not late enough. // Bulk audio stream CAN send data to client. // Assume time is less than next_cb_ts. clock_gettime_retspec.tv_sec = 0; clock_gettime_retspec.tv_nsec = 0; // Enough samples are written. written_frames = rstream_.cb_threshold + 10; cras_shm_buffer_written(rstream_.shm, written_frames); // Bulk audio stream can send all written samples to client. rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); EXPECT_EQ(written_frames, cras_rstream_audio_ready_count); EXPECT_EQ(0, rc); // Case 4: Enough samples. Time is late enough. // Bulk audio stream can send all written samples to client. // Reset stub data of interest. cras_rstream_audio_ready_called = 0; cras_rstream_audio_ready_count = 0; rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 0; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 500; rc = dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); EXPECT_EQ(written_frames, cras_rstream_audio_ready_count); EXPECT_EQ(0, rc); // Check next_cb_ts is increased by one sleep interval. expected_next_cb_ts.tv_sec = 1; expected_next_cb_ts.tv_nsec = 0; add_timespecs(&expected_next_cb_ts, &rstream_.sleep_interval_ts); EXPECT_EQ(expected_next_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); EXPECT_EQ(expected_next_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, TriggerOnlyStreamSendOnlyOnce) { struct dev_stream* dev_stream; unsigned int dev_id = 9; rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); dev_stream->stream->flags = TRIGGER_ONLY; dev_stream->stream->triggered = 0; // Check first trigger callback called. cras_shm_buffer_written(rstream_.shm, rstream_.cb_threshold); clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 0; dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); EXPECT_EQ(1, dev_stream->stream->triggered); // No future callback will be called for TRIGGER_ONLY streams. cras_shm_buffer_written(rstream_.shm, rstream_.cb_threshold); clock_gettime_retspec.tv_sec = 2; clock_gettime_retspec.tv_nsec = 0; dev_stream_capture_update_rstream(dev_stream); EXPECT_EQ(1, cras_rstream_audio_ready_called); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, InputDevStreamWakeTimeByNextCbTs) { struct dev_stream* dev_stream; unsigned int dev_id = 9; int rc; unsigned int curr_level = 0; int written_frames; struct timespec level_tstamp = {.tv_sec = 1, .tv_nsec = 0}; struct timespec wake_time_out = {.tv_sec = 0, .tv_nsec = 0}; rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 500000; // Assume there are enough samples for stream. written_frames = rstream_.cb_threshold + 10; cras_shm_buffer_written(rstream_.shm, written_frames); rc = dev_stream_wake_time(dev_stream, curr_level, &level_tstamp, rstream_.cb_threshold, 0, &wake_time_out); // The next wake up time is determined by next_cb_ts on dev_stream. EXPECT_EQ(rstream_.next_cb_ts.tv_sec, wake_time_out.tv_sec); EXPECT_EQ(rstream_.next_cb_ts.tv_nsec, wake_time_out.tv_nsec); EXPECT_EQ(0, rc); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, InputDevStreamWakeTimeByDevice) { struct dev_stream* dev_stream; unsigned int dev_id = 9; int rc; unsigned int curr_level = 100; int written_frames; struct timespec level_tstamp = {.tv_sec = 1, .tv_nsec = 0}; struct timespec wake_time_out = {.tv_sec = 0, .tv_nsec = 0}; struct timespec expected_tstamp = {.tv_sec = 0, .tv_nsec = 0}; struct timespec needed_time_for_device = {.tv_sec = 0, .tv_nsec = 0}; int needed_frames_from_device = 0; rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_48, (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream, that is, 1.005 seconds. rstream_.next_cb_ts.tv_sec = 1; rstream_.next_cb_ts.tv_nsec = 5000000; // 5ms // Assume there are not enough samples for stream. written_frames = 123; cras_shm_buffer_written(rstream_.shm, written_frames); // Compute wake up time for device level to reach enough samples // for one cb_threshold: // Device has 100 samples (48K rate). // Stream has 123 samples (44.1K rate) // cb_threshold = 512 samples. // Stream needs 512 - 123 = 389 samples. // Converted to device rate => 389 * 48000.0 / 44100 = 423.4 samples // => 424 samples. // Device needs another 424 - 100 = 324 samples. // Time for 252 samples = 324 / 48000 = 0.00675 sec. // So expected wake up time for samples is at level_tstamp + 0.00675 sec = // 1.00675 seconds. needed_frames_from_device = cras_frames_at_rate(44100, rstream_.cb_threshold - written_frames, 48000); needed_frames_from_device -= curr_level; cras_frames_to_time(needed_frames_from_device, 48000, &needed_time_for_device); expected_tstamp.tv_sec = level_tstamp.tv_sec; expected_tstamp.tv_nsec = level_tstamp.tv_nsec; add_timespecs(&expected_tstamp, &needed_time_for_device); // Set the stub data for cras_fmt_conv_out_frames_to_in. out_fmt.frame_rate = 44100; in_fmt.frame_rate = 48000; rc = dev_stream_wake_time(dev_stream, curr_level, &level_tstamp, rstream_.cb_threshold, 0, &wake_time_out); // The next wake up time is determined by needed time for device level // to reach enough samples for one cb_threshold. EXPECT_EQ(expected_tstamp.tv_sec, wake_time_out.tv_sec); EXPECT_EQ(expected_tstamp.tv_nsec, wake_time_out.tv_nsec); EXPECT_EQ(0, rc); // Assume current level is larger than cb_threshold. // The wake up time is determined by next_cb_ts. curr_level += rstream_.cb_threshold; rc = dev_stream_wake_time(dev_stream, curr_level, &level_tstamp, rstream_.cb_threshold, 0, &wake_time_out); EXPECT_EQ(rstream_.next_cb_ts.tv_sec, wake_time_out.tv_sec); EXPECT_EQ(rstream_.next_cb_ts.tv_nsec, wake_time_out.tv_nsec); EXPECT_EQ(0, rc); dev_stream_destroy(dev_stream); } TEST_F(CreateSuite, UpdateNextWakeTime) { struct dev_stream* dev_stream; unsigned int dev_id = 9; struct timespec expected_next_cb_ts; rstream_.direction = CRAS_STREAM_OUTPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, (void*)0x55, &cb_ts); // Case 1: The new next_cb_ts is greater than now. Do not need to reschedule. rstream_.next_cb_ts.tv_sec = 2; rstream_.next_cb_ts.tv_nsec = 0; clock_gettime_retspec.tv_sec = 2; clock_gettime_retspec.tv_nsec = 500; expected_next_cb_ts = rstream_.next_cb_ts; dev_stream_update_next_wake_time(dev_stream); EXPECT_EQ(0, cras_server_metrics_missed_cb_event_called); add_timespecs(&expected_next_cb_ts, &rstream_.sleep_interval_ts); EXPECT_EQ(expected_next_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); EXPECT_EQ(expected_next_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); // Case 2: The new next_cb_ts is less than now. Need to reset schedule. rstream_.next_cb_ts.tv_sec = 2; rstream_.next_cb_ts.tv_nsec = 0; clock_gettime_retspec.tv_sec = 3; clock_gettime_retspec.tv_nsec = 0; expected_next_cb_ts = clock_gettime_retspec; dev_stream_update_next_wake_time(dev_stream); EXPECT_EQ(1, cras_server_metrics_missed_cb_event_called); add_timespecs(&expected_next_cb_ts, &rstream_.sleep_interval_ts); EXPECT_EQ(expected_next_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); EXPECT_EQ(expected_next_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); dev_stream_destroy(dev_stream); } // Test set_playback_timestamp. TEST(DevStreamTimimg, SetPlaybackTimeStampSimple) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 0; cras_set_playback_timestamp(48000, 24000, &ts); EXPECT_EQ(1, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 499900000); EXPECT_LE(ts.tv_nsec, 500100000); } TEST(DevStreamTimimg, SetPlaybackTimeStampWrap) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 750000000; cras_set_playback_timestamp(48000, 24000, &ts); EXPECT_EQ(2, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 249900000); EXPECT_LE(ts.tv_nsec, 250100000); } TEST(DevStreamTimimg, SetPlaybackTimeStampWrapTwice) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 750000000; cras_set_playback_timestamp(48000, 72000, &ts); EXPECT_EQ(3, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 249900000); EXPECT_LE(ts.tv_nsec, 250100000); } // Test set_capture_timestamp. TEST(DevStreamTimimg, SetCaptureTimeStampSimple) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 750000000; cras_set_capture_timestamp(48000, 24000, &ts); EXPECT_EQ(1, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 249900000); EXPECT_LE(ts.tv_nsec, 250100000); } TEST(DevStreamTimimg, SetCaptureTimeStampWrap) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 1; clock_gettime_retspec.tv_nsec = 0; cras_set_capture_timestamp(48000, 24000, &ts); EXPECT_EQ(0, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 499900000); EXPECT_LE(ts.tv_nsec, 500100000); } TEST(DevStreamTimimg, SetCaptureTimeStampWrapPartial) { struct cras_timespec ts; clock_gettime_retspec.tv_sec = 2; clock_gettime_retspec.tv_nsec = 750000000; cras_set_capture_timestamp(48000, 72000, &ts); EXPECT_EQ(1, ts.tv_sec); EXPECT_GE(ts.tv_nsec, 249900000); EXPECT_LE(ts.tv_nsec, 250100000); } TEST(MaxFramesForConverter, 8to48) { EXPECT_EQ(481, max_frames_for_conversion(80, // Stream frames. 8000, // Stream rate. 48000)); // Device rate. } TEST(MaxFramesForConverter, 48to8) { EXPECT_EQ(81, max_frames_for_conversion(80, // Stream frames. 48000, // Stream rate. 8000)); // Device rate. } /* Stubs */ extern "C" { int cras_rstream_audio_ready(struct cras_rstream* stream, size_t count) { cras_rstream_audio_ready_count = count; cras_rstream_audio_ready_called++; return 0; } int cras_rstream_request_audio(struct cras_rstream* stream, const struct timespec* now) { return 0; } void cras_rstream_record_fetch_interval(struct cras_rstream* rstream, const struct timespec* now) {} void cras_rstream_update_input_write_pointer(struct cras_rstream* rstream) {} void cras_rstream_update_output_read_pointer(struct cras_rstream* rstream) {} void cras_rstream_dev_offset_update(struct cras_rstream* rstream, unsigned int frames, unsigned int dev_id) {} void cras_rstream_dev_attach(struct cras_rstream* rstream, unsigned int dev_id, void* dev_ptr) {} void cras_rstream_dev_detach(struct cras_rstream* rstream, unsigned int dev_id) {} unsigned int cras_rstream_dev_offset(const struct cras_rstream* rstream, unsigned int dev_id) { return 0; } unsigned int cras_rstream_playable_frames(struct cras_rstream* rstream, unsigned int dev_id) { return rstream_playable_frames_ret; } float cras_rstream_get_volume_scaler(struct cras_rstream* rstream) { return 1.0; } uint8_t* cras_rstream_get_readable_frames(struct cras_rstream* rstream, unsigned int offset, size_t* frames) { rstream_get_readable_call.rstream = rstream; rstream_get_readable_call.offset = offset; rstream_get_readable_call.num_called++; *frames = rstream_get_readable_num; return rstream_get_readable_ptr; } int cras_rstream_get_mute(const struct cras_rstream* rstream) { return 0; } void cras_rstream_update_queued_frames(struct cras_rstream* rstream) {} struct cras_audio_format* cras_rstream_post_processing_format( const struct cras_rstream* stream, void* dev_ptr) { return cras_rstream_post_processing_format_val; } void* buffer_share_get_data(const struct buffer_share* mix, unsigned int id) { return NULL; }; void cras_apm_list_start_apm(struct cras_apm_list* list, void* dev_ptr){}; void cras_apm_list_stop_apm(struct cras_apm_list* list, void* dev_ptr){}; int config_format_converter(struct cras_fmt_conv** conv, enum CRAS_STREAM_DIRECTION dir, const struct cras_audio_format* from, const struct cras_audio_format* to, unsigned int frames) { config_format_converter_called++; config_format_converter_from_fmt = from; config_format_converter_frames = frames; *conv = config_format_converter_conv; return 0; } void cras_fmt_conv_destroy(struct cras_fmt_conv* conv) {} size_t cras_fmt_conv_convert_frames(struct cras_fmt_conv* conv, uint8_t* in_buf, uint8_t* out_buf, unsigned int* in_frames, unsigned int out_frames) { unsigned int ret; conv_frames_call.conv = conv; conv_frames_call.in_buf = in_buf; conv_frames_call.out_buf = out_buf; conv_frames_call.in_frames = *in_frames; ret = cras_frames_at_rate(in_fmt.frame_rate, *in_frames, out_fmt.frame_rate); conv_frames_call.out_frames = out_frames; if (ret > out_frames) { ret = out_frames; *in_frames = cras_frames_at_rate(out_fmt.frame_rate, ret, in_fmt.frame_rate); } return ret; } void cras_mix_add(snd_pcm_format_t fmt, uint8_t* dst, uint8_t* src, unsigned int count, unsigned int index, int mute, float mix_vol) { mix_add_call.dst = (int16_t*)dst; mix_add_call.src = (int16_t*)src; mix_add_call.count = count; mix_add_call.index = index; mix_add_call.mute = mute; mix_add_call.mix_vol = mix_vol; } struct cras_audio_area* cras_audio_area_create(int num_channels) { cras_audio_area_create_num_channels_val = num_channels; return NULL; } void cras_audio_area_destroy(struct cras_audio_area* area) {} void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, const struct cras_audio_format* fmt, uint8_t* base_buffer) {} void cras_audio_area_config_channels(struct cras_audio_area* area, const struct cras_audio_format* fmt) {} unsigned int cras_audio_area_copy(const struct cras_audio_area* dst, unsigned int dst_offset, const struct cras_audio_format* dst_fmt, const struct cras_audio_area* src, unsigned int src_offset, float software_gain_scaler) { copy_area_call.dst = dst; copy_area_call.dst_offset = dst_offset; copy_area_call.dst_format_bytes = cras_get_format_bytes(dst_fmt); copy_area_call.src = src; copy_area_call.src_offset = src_offset; copy_area_call.software_gain_scaler = software_gain_scaler; return src->frames; } size_t cras_fmt_conv_in_frames_to_out(struct cras_fmt_conv* conv, size_t in_frames) { return cras_frames_at_rate(in_fmt.frame_rate, in_frames, out_fmt.frame_rate); } size_t cras_fmt_conv_out_frames_to_in(struct cras_fmt_conv* conv, size_t out_frames) { return cras_frames_at_rate(out_fmt.frame_rate, out_frames, in_fmt.frame_rate); } const struct cras_audio_format* cras_fmt_conv_in_format( const struct cras_fmt_conv* conv) { return &in_fmt; } const struct cras_audio_format* cras_fmt_conv_out_format( const struct cras_fmt_conv* conv) { return &out_fmt; } int cras_fmt_conversion_needed(const struct cras_fmt_conv* conv) { return cras_fmt_conversion_needed_val; } void cras_fmt_conv_set_linear_resample_rates(struct cras_fmt_conv* conv, float from, float to) { cras_fmt_conv_set_linear_resample_rates_from = from; cras_fmt_conv_set_linear_resample_rates_to = to; cras_fmt_conv_set_linear_resample_rates_called++; } int cras_rstream_is_pending_reply(const struct cras_rstream* stream) { return cras_rstream_is_pending_reply_ret; } int cras_rstream_flush_old_audio_messages(struct cras_rstream* stream) { cras_rstream_flush_old_audio_messages_called++; return 0; } int cras_server_metrics_missed_cb_event(struct cras_rstream* stream) { cras_server_metrics_missed_cb_event_called++; return 0; } // From librt. int clock_gettime(clockid_t clk_id, struct timespec* tp) { tp->tv_sec = clock_gettime_retspec.tv_sec; tp->tv_nsec = clock_gettime_retspec.tv_nsec; return 0; } } // extern "C" } // namespace int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }