blob: 640ca932dfd83961ee392e2ffcb55280c579c9f6 [file] [log] [blame]
// 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 <gtest/gtest.h>
#include <stdio.h>
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(&copy_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<struct cras_audio_shm*>(
calloc(1, sizeof(struct cras_audio_shm)));
shm->header = static_cast<struct cras_audio_shm_header*>(
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<uint8_t*>(
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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<byte_buffer*>(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<struct cras_fmt_conv*>(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<struct cras_fmt_conv*>(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<cras_rstream*>(0x5446);
rstream_playable_frames_ret = nfr;
rstream_get_readable_num = nfr;
rstream_get_readable_ptr = reinterpret_cast<uint8_t*>(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<cras_rstream*>(0x5446);
rstream_playable_frames_ret = nfr;
rstream_get_readable_num = nfr / 2;
rstream_get_readable_ptr = reinterpret_cast<uint8_t*>(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();
}