diff options
Diffstat (limited to 'cras/src/tests/timing_unittest.cc')
-rw-r--r-- | cras/src/tests/timing_unittest.cc | 1246 |
1 files changed, 0 insertions, 1246 deletions
diff --git a/cras/src/tests/timing_unittest.cc b/cras/src/tests/timing_unittest.cc deleted file mode 100644 index 964f30c3..00000000 --- a/cras/src/tests/timing_unittest.cc +++ /dev/null @@ -1,1246 +0,0 @@ -// Copyright 2017 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 <stdint.h> -#include <stdio.h> -#include <syslog.h> -#include <time.h> - -#include <memory> - -extern "C" { -#include "cras_iodev.h" // stubbed -#include "cras_rstream.h" // stubbed -#include "cras_shm.h" -#include "cras_types.h" -#include "dev_io.h" // tested -#include "dev_stream.h" // tested -#include "utlist.h" - -struct audio_thread_event_log* atlog; -} - -#include "dev_io_stubs.h" -#include "iodev_stub.h" -#include "metrics_stub.h" -#include "rstream_stub.h" - -#define FAKE_POLL_FD 33 - -namespace { - -class TimingSuite : public testing::Test { - protected: - virtual void SetUp() { - atlog = static_cast<audio_thread_event_log*>(calloc(1, sizeof(*atlog))); - iodev_stub_reset(); - rstream_stub_reset(); - } - - virtual void TearDown() { free(atlog); } - - timespec SingleInputDevNextWake( - size_t dev_cb_threshold, - size_t dev_level, - const timespec* level_timestamp, - cras_audio_format* dev_format, - const std::vector<StreamPtr>& streams, - CRAS_NODE_TYPE active_node_type = CRAS_NODE_TYPE_MIC) { - struct open_dev* dev_list_ = NULL; - - DevicePtr dev = create_device(CRAS_STREAM_INPUT, dev_cb_threshold, - dev_format, active_node_type); - dev->dev->input_streaming = true; - DL_APPEND(dev_list_, dev->odev.get()); - - for (auto const& stream : streams) { - add_stream_to_dev(dev->dev, stream); - } - - // Set response for frames_queued. - iodev_stub_frames_queued(dev->dev.get(), dev_level, *level_timestamp); - - dev_io_send_captured_samples(dev_list_); - - struct timespec dev_time; - dev_time.tv_sec = level_timestamp->tv_sec + 500; // Far in the future. - dev_io_next_input_wake(&dev_list_, &dev_time); - return dev_time; - } - - timespec SingleOutputDevNextWake( - size_t dev_cb_threshold, - size_t dev_level, - const timespec* level_timestamp, - cras_audio_format* dev_format, - const std::vector<StreamPtr>& streams, - const timespec* dev_wake_ts, - CRAS_NODE_TYPE active_node_type = CRAS_NODE_TYPE_HEADPHONE) { - struct open_dev* dev_list_ = NULL; - - DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, dev_cb_threshold, - dev_format, active_node_type); - DL_APPEND(dev_list_, dev->odev.get()); - - for (auto const& stream : streams) { - add_stream_to_dev(dev->dev, stream); - } - - dev->odev->wake_ts = *dev_wake_ts; - - // Set response for frames_queued. - iodev_stub_frames_queued(dev->dev.get(), dev_level, *level_timestamp); - - struct timespec dev_time; - dev_time.tv_sec = level_timestamp->tv_sec + 500; // Far in the future. - dev_io_next_output_wake(&dev_list_, &dev_time); - return dev_time; - } -}; - -extern "C" { -// From librt. Fix now at this time. -int clock_gettime(clockid_t clk_id, struct timespec* tp) { - tp->tv_sec = 12345; - tp->tv_nsec = 987654321; - return 0; -} -}; - -// Add a new input stream, make sure the initial next_cb_ts is 0. -TEST_F(TimingSuite, NewInputStreamInit) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr dev = - create_device(CRAS_STREAM_INPUT, 1024, &format, CRAS_NODE_TYPE_MIC); - DL_APPEND(idev_list_, dev->odev.get()); - struct cras_iodev* iodev = dev->odev->dev; - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_INPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); - - EXPECT_EQ(0, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(0, rstream->next_cb_ts.tv_nsec); - - dev_stream_destroy(iodev->streams); -} - -// There is the pseudo code about wake up time for an input device. -// -// function set_input_dev_wake_ts(dev): -// wake_ts = now + 20s #rule_1 -// -// cap_limit = MIN(dev_stream_capture_avail(stream)) for stream on dev -// -// for stream in dev: -// wake_ts = MIN(get_input_wake_time(stream, cap_limit), wake_ts) -// for stream on dev #rule_2 -// if cap_limit: -// wake_ts = MIN(get_input_dev_max_wake_ts(dev), wake_ts) #rule_3 -// -// device.wake_ts = wake_ts -// -// function get_input_wake_time(stream, cap_limit): -// needed_frames_from_device = dev_stream_capture_avail(stream) -// -// if needed_frames_from_device > cap_limit: #rule_4 -// return None -// -// if stream is USE_DEV_TIMING and stream is pending reply: #rule_5 -// return None -// -// time_for_sample = The time when device gets enough samples #rule_6 -// -// wake_time_out = MAX(stream.next_cb_ts, time_for_sample) #rule_7 -// -// if stream is USE_DEV_TIMING: -// wake_time_out = time_for_sample #rule_8 -// -// return wake_time_out -// -// function get_input_dev_max_wake_ts(dev): -// return MAX(5ms, The time when hw_level = buffer_size / 2) #rule_9 -// -// -// dev_stream_capture_avail: The number of frames free to be written to in a -// capture stream. -// -// The following unittests will check these logics. - -// Test rule_1. -// The device wake up time should be 20s from now. -TEST_F(TimingSuite, InputWakeTimeNoStreamWithBigBufferDevice) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - std::vector<StreamPtr> streams; - timespec dev_time = - SingleInputDevNextWake(4800000, 0, &start, &format, streams); - - const timespec add_millis = {20, 0}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_2, rule_4(Stream 1), rule_7(Stream 2) -// Stream 1: next_cb_ts = now, cb_threshold = 480, dev_offset = 0 -// Stream 2: next_cb_ts = now + 5s, cb_threshold = 480, dev_offset = 200 -// Stream 1 need 480 frames and Stream 2 need 240 frames. So 240 will be the -// cap_limit and Stream 1 will be ignored. The next wake up time should be -// the next_cb_ts of stream2. -TEST_F(TimingSuite, InputWakeTimeTwoStreamsWithFramesInside) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_INPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - rstream_stub_dev_offset(stream2->rstream.get(), 1, 200); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - timespec dev_time = - SingleInputDevNextWake(480000, 0, &start, &format, streams); - - EXPECT_EQ(start.tv_sec + 5, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_2, rule_7 -// Stream 1: next_cb_ts = now + 2s, cb_threshold = 480, dev_offset = 0 -// Stream 2: next_cb_ts = now + 5s, cb_threshold = 480, dev_offset = 0 -// The audio thread will choose the earliest next_cb_ts because the they have -// the same value of needed_frames_from_device. The next wake up time should -// be the next_cb_ts of stream1. -TEST_F(TimingSuite, InputWakeTimeTwoEmptyStreams) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - stream1->rstream->next_cb_ts.tv_sec += 2; - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_INPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - timespec dev_time = - SingleInputDevNextWake(480000, 0, &start, &format, streams); - - EXPECT_EQ(start.tv_sec + 2, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_3. -// If cap_limit is zero from stream, input_dev_max_wake_ts should not -// be taken into account. -TEST_F(TimingSuite, InputWakeTimeOneFullStreamWithDeviceWakeUp) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start, stream_wake; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // Set the next stream wake to be 10ms from now. - const timespec ten_millis = {0, 10 * 1000 * 1000}; - stream_wake = start; - add_timespecs(&stream_wake, &ten_millis); - stream->rstream->next_cb_ts = stream_wake; - - // Add fake data so the stream has no room for more data. - AddFakeDataToStream(stream.get(), 480); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec wake_time = SingleInputDevNextWake(240, 0, &start, &format, streams); - - // Input device would wake at 5ms from now, but since stream cap_limit == 0 - // the final wake_time is determined by stream. - EXPECT_EQ(stream_wake.tv_sec, wake_time.tv_sec); - EXPECT_EQ(stream_wake.tv_nsec, wake_time.tv_nsec); -} - -// Test rule_3 and rule_9. -// One empty stream with small device buffer. It should wake up when there are -// buffer_size / 2 frames in device buffer. -TEST_F(TimingSuite, InputWakeTimeOneStreamWithDeviceWakeUp) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // The next callback of the new stream is 0. - stream->rstream->next_cb_ts.tv_sec = 0; - stream->rstream->next_cb_ts.tv_nsec = 0; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(240, 0, &start, &format, streams); - // The device wake up time should be 5ms from now. At that time there are - // 240 frames in the device. - const timespec add_millis = {0, 5 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_5. -// The stream with USE_DEV_TIMING flag will be ignore if it is pending reply. -TEST_F(TimingSuite, InputWakeTimeOneStreamUsingDevTimingWithPendingReply) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // The next callback should be ignored. - stream->rstream->next_cb_ts = start; - stream->rstream->next_cb_ts.tv_sec += 10; - stream->rstream->flags = USE_DEV_TIMING; - rstream_stub_pending_reply(stream->rstream.get(), 1); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(4800, 0, &start, &format, streams); - - // The device wake up time should be 100ms from now. At that time the hw_level - // is buffer_size / 2. - const timespec add_millis = {0, 100 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_6. -// Add a new stream, the wake up time is the time when it has enough data to -// post. -TEST_F(TimingSuite, InputWakeTimeOneStreamWithEmptyDevice) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // The next callback of the new stream is 0. - stream->rstream->next_cb_ts.tv_sec = 0; - stream->rstream->next_cb_ts.tv_nsec = 0; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(600, 0, &start, &format, streams); - - // The device wake up time should be 10ms from now. At that time the - // stream will have 480 samples to post. - const timespec ten_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &ten_millis); - EXPECT_EQ(0, streams[0]->rstream->next_cb_ts.tv_sec); - EXPECT_EQ(0, streams[0]->rstream->next_cb_ts.tv_nsec); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_6. -// Add a new stream with enough frames in device, check the wake up time is -// right now. -TEST_F(TimingSuite, InputWakeTimeOneStreamWithFullDevice) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // The next callback of the new stream is 0. - stream->rstream->next_cb_ts.tv_sec = 0; - stream->rstream->next_cb_ts.tv_nsec = 0; - - // If there are enough frames in the device, we should wake up immediately. - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = - SingleInputDevNextWake(480, 480, &start, &format, streams); - EXPECT_EQ(0, streams[0]->rstream->next_cb_ts.tv_sec); - EXPECT_EQ(0, streams[0]->rstream->next_cb_ts.tv_nsec); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_8. -// The stream with USE_DEV_TIMING flag should wake up when it has enough frames -// to post. -TEST_F(TimingSuite, InputWakeTimeOneStreamUsingDevTiming) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // The next callback should be ignored. - stream->rstream->next_cb_ts = start; - stream->rstream->next_cb_ts.tv_sec += 10; - stream->rstream->flags = USE_DEV_TIMING; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(600, 0, &start, &format, streams); - - // The device wake up time should be 10ms from now. At that time the - // stream will have 480 samples to post. - const timespec add_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_9. -// The device wake up time should be 10ms from now. At that time the hw_level -// is buffer_size / 2. -TEST_F(TimingSuite, InputWakeTimeNoStreamSmallBufferDevice) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - std::vector<StreamPtr> streams; - timespec dev_time = SingleInputDevNextWake(480, 0, &start, &format, streams); - - const timespec add_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_9. -// There are more than buffer_size / 2 frames in the device. The device needs -// to sleep at least 5ms. -TEST_F(TimingSuite, InputWakeTimeOneStreamWithEnoughFramesInDevice) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // Make next_cb_ts far from now. - stream->rstream->next_cb_ts = start; - stream->rstream->next_cb_ts.tv_sec += 10; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = - SingleInputDevNextWake(480, 480, &start, &format, streams); - - const timespec add_millis = {0, 5 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// One device, one stream, write a callback of data and check the sleep time is -// one more wakeup interval. -TEST_F(TimingSuite, WaitAfterFill) { - const size_t cb_threshold = 480; - - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = - create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); - // rstream's next callback is now and there is enough data to fill. - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream->rstream->next_cb_ts = start; - AddFakeDataToStream(stream.get(), 480); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = - SingleInputDevNextWake(cb_threshold, 0, &start, &format, streams); - - // The next callback should be scheduled 10ms in the future. - // And the next wake up should reflect the only attached stream. - const timespec ten_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &ten_millis); - EXPECT_EQ(start.tv_sec, streams[0]->rstream->next_cb_ts.tv_sec); - EXPECT_EQ(start.tv_nsec, streams[0]->rstream->next_cb_ts.tv_nsec); - EXPECT_EQ(dev_time.tv_sec, streams[0]->rstream->next_cb_ts.tv_sec); - EXPECT_EQ(dev_time.tv_nsec, streams[0]->rstream->next_cb_ts.tv_nsec); -} - -// One device with one stream which has block_size larger than the device buffer -// level. If the device buffer level = 0, the input device wake time should be -// set to (buffer_size / 2) / device_rate secs. -TEST_F(TimingSuite, LargeCallbackStreamWithEmptyBuffer) { - const size_t cb_threshold = 3000; - const size_t dev_cb_threshold = 1200; - const size_t dev_level = 0; - - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = - create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream->rstream->next_cb_ts = start; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(dev_cb_threshold, dev_level, - &start, &format, streams); - - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - // The next dev wake ts should be 25ms since the buffer level is empty and - // 1200 / 48000 = 0.025. - EXPECT_EQ(delta.tv_sec, 0); - EXPECT_LT(delta.tv_nsec, 25000000 + 5000 * 1000); - EXPECT_GT(delta.tv_nsec, 25000000 - 5000 * 1000); -} - -// One device with one stream which has block_size larger than the device buffer -// level. If the device buffer level = buffer_size / 2, the input device wake -// time should be set to max(0, 5ms) = 5ms to prevent busy loop occurs. -TEST_F(TimingSuite, LargeCallbackStreamWithHalfFullBuffer) { - const size_t cb_threshold = 3000; - const size_t dev_cb_threshold = 1200; - const size_t dev_level = 1200; - - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = - create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream->rstream->next_cb_ts = start; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(dev_cb_threshold, dev_level, - &start, &format, streams); - - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - // The next dev wake ts should be 5ms since the buffer level is half full. - EXPECT_EQ(delta.tv_sec, 0); - EXPECT_LT(delta.tv_nsec, 5000000 + 5000 * 1000); - EXPECT_GT(delta.tv_nsec, 5000000 - 5000 * 1000); -} - -// One device(48k), one stream(44.1k), write a callback of data and check that -// the sleep time is correct when doing SRC. -TEST_F(TimingSuite, WaitAfterFillSRC) { - cras_audio_format dev_format; - fill_audio_format(&dev_format, 48000); - cras_audio_format stream_format; - fill_audio_format(&stream_format, 44100); - - StreamPtr stream = - create_stream(1, 1, CRAS_STREAM_INPUT, 441, &stream_format); - // rstream's next callback is now and there is enough data to fill. - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream->rstream->next_cb_ts = start; - AddFakeDataToStream(stream.get(), 441); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = - SingleInputDevNextWake(480, 0, &start, &dev_format, streams); - - // The next callback should be scheduled 10ms in the future. - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - EXPECT_LT(9900 * 1000, delta.tv_nsec); - EXPECT_GT(10100 * 1000, delta.tv_nsec); -} - -// One device, two streams. One stream is ready the other still needs data. -// Checks that the sleep interval is based on the time the device will take to -// supply the needed samples for stream2. -TEST_F(TimingSuite, WaitTwoStreamsSameFormat) { - const size_t cb_threshold = 480; - - cras_audio_format format; - fill_audio_format(&format, 48000); - - // stream1's next callback is now and there is enough data to fill. - StreamPtr stream1 = - create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream1->rstream->next_cb_ts = start; - AddFakeDataToStream(stream1.get(), cb_threshold); - - // stream2 is only half full. - StreamPtr stream2 = - create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); - stream2->rstream->next_cb_ts = start; - AddFakeDataToStream(stream2.get(), 240); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - timespec dev_time = - SingleInputDevNextWake(cb_threshold, 0, &start, &format, streams); - - // Should wait for approximately 5 milliseconds for 240 samples at 48k. - struct timespec delta2; - subtract_timespecs(&dev_time, &start, &delta2); - EXPECT_LT(4900 * 1000, delta2.tv_nsec); - EXPECT_GT(5100 * 1000, delta2.tv_nsec); -} - -// One device(44.1), two streams(44.1, 48). One stream is ready the other still -// needs data. Checks that the sleep interval is based on the time the device -// will take to supply the needed samples for stream2, stream2 is sample rate -// converted from the 44.1k device to the 48k stream. -TEST_F(TimingSuite, WaitTwoStreamsDifferentRates) { - cras_audio_format s1_format, s2_format; - fill_audio_format(&s1_format, 44100); - fill_audio_format(&s2_format, 48000); - - // stream1's next callback is now and there is enough data to fill. - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream1->rstream->next_cb_ts = start; - AddFakeDataToStream(stream1.get(), 441); - // stream2's next callback is now but there is only half a callback of data. - StreamPtr stream2 = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format); - stream2->rstream->next_cb_ts = start; - AddFakeDataToStream(stream2.get(), 240); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - timespec dev_time = - SingleInputDevNextWake(441, 0, &start, &s1_format, streams); - - // Should wait for approximately 5 milliseconds for 240 48k samples from the - // 44.1k device. - struct timespec delta2; - subtract_timespecs(&dev_time, &start, &delta2); - EXPECT_LT(4900 * 1000, delta2.tv_nsec); - EXPECT_GT(5100 * 1000, delta2.tv_nsec); -} - -// One device, two streams. Both streams get a full callback of data and the -// device has enough samples for the next callback already. Checks that the -// shorter of the two streams times is used for the next sleep interval. -TEST_F(TimingSuite, WaitTwoStreamsDifferentWakeupTimes) { - cras_audio_format s1_format, s2_format; - fill_audio_format(&s1_format, 44100); - fill_audio_format(&s2_format, 48000); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - // stream1's next callback is in 3ms. - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format); - stream1->rstream->next_cb_ts = start; - const timespec three_millis = {0, 3 * 1000 * 1000}; - add_timespecs(&stream1->rstream->next_cb_ts, &three_millis); - AddFakeDataToStream(stream1.get(), 441); - // stream2 is also ready next cb in 5ms.. - StreamPtr stream2 = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format); - stream2->rstream->next_cb_ts = start; - const timespec five_millis = {0, 5 * 1000 * 1000}; - add_timespecs(&stream2->rstream->next_cb_ts, &five_millis); - AddFakeDataToStream(stream1.get(), 480); - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - timespec dev_time = - SingleInputDevNextWake(441, 441, &start, &s1_format, streams); - - // Should wait for approximately 3 milliseconds for stream 1 first. - struct timespec delta2; - subtract_timespecs(&dev_time, &start, &delta2); - EXPECT_LT(2900 * 1000, delta2.tv_nsec); - EXPECT_GT(3100 * 1000, delta2.tv_nsec); -} - -// One hotword stream attaches to hotword device. Input data has copied from -// device to stream but total number is less than cb_threshold. Hotword stream -// should be scheduled wake base on the samples needed to fill full shm. -TEST_F(TimingSuite, HotwordStreamUseDevTiming) { - cras_audio_format fmt; - fill_audio_format(&fmt, 48000); - - struct timespec start, delay; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt); - stream->rstream->flags = HOTWORD_STREAM; - stream->rstream->next_cb_ts = start; - delay.tv_sec = 0; - delay.tv_nsec = 3 * 1000 * 1000; - add_timespecs(&stream->rstream->next_cb_ts, &delay); - - // Add fake data to stream and device so its slightly less than cb_threshold. - // Expect to wait for samples to fill the full buffer (480 - 192) frames - // instead of using the next_cb_ts. - AddFakeDataToStream(stream.get(), 192); - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - timespec dev_time = SingleInputDevNextWake(4096, 0, &start, &fmt, streams); - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - // 288 frames worth of time = 6 ms. - EXPECT_EQ(6 * 1000 * 1000, delta.tv_nsec); -} - -// One hotword stream attaches to hotword device. Input data burst to a number -// larger than cb_threshold. Also, stream is pending client reply. -// In this case stream fd is used to poll for next wake. -// And the dev wake time is unchanged from the default 20 seconds limit. -TEST_F(TimingSuite, HotwordStreamBulkDataIsPending) { - int poll_fd = 0; - cras_audio_format fmt; - fill_audio_format(&fmt, 48000); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt); - stream->rstream->flags = HOTWORD_STREAM; - stream->rstream->next_cb_ts = start; - - AddFakeDataToStream(stream.get(), 480); - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - // Stream is pending the reply from client. - rstream_stub_pending_reply(streams[0]->rstream.get(), 1); - - // There is more than 1 cb_threshold of data in device. - timespec dev_time = SingleInputDevNextWake(4096, 7000, &start, &fmt, streams, - CRAS_NODE_TYPE_HOTWORD); - - // Need to wait for stream fd in the next ppoll. - poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get()); - EXPECT_EQ(FAKE_POLL_FD, poll_fd); - - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - // Wake up time should be default 20 seconds because audio thread - // depends on reply from client to wake it up. - EXPECT_LT(19, delta.tv_sec); - EXPECT_GT(21, delta.tv_sec); -} - -// One hotword stream attaches to hotword device. Input data burst to a number -// larger than cb_threshold. However, stream is not pending client reply. -// This happens if there was no data during capture_to_stream. -// In this case stream fd is NOT used to poll for next wake. -// And the dev wake time is changed to a 0 instead of default 20 seconds. -TEST_F(TimingSuite, HotwordStreamBulkDataIsNotPending) { - int poll_fd = 0; - cras_audio_format fmt; - fill_audio_format(&fmt, 48000); - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt); - stream->rstream->flags = HOTWORD_STREAM; - stream->rstream->next_cb_ts = start; - - AddFakeDataToStream(stream.get(), 480); - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - // Stream is not pending the reply from client. - rstream_stub_pending_reply(streams[0]->rstream.get(), 0); - - // There is more than 1 cb_threshold of data in device. - timespec dev_time = SingleInputDevNextWake(4096, 7000, &start, &fmt, streams); - - // Does not need to wait for stream fd in the next ppoll. - poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get()); - EXPECT_EQ(-1, poll_fd); - - struct timespec delta; - subtract_timespecs(&dev_time, &start, &delta); - // Wake up time should be very small because there is enough - // data to be send to client. - EXPECT_LT(delta.tv_sec, 0.1); -} - -// When a new output stream is added, there are two rules to determine the -// initial next_cb_ts. -// 1. If there is a matched input stream, use the next_cb_ts and -// sleep_interval_ts from that input stream as the initial values. -// 2. If the device already has streams, the next_cb_ts will be the earliest -// next callback time from these streams. -// 3. If there are no other streams, the next_cb_ts will be set to the time -// when the valid frames in device is lower than cb_threshold. (If it is -// already lower than cb_threshold, set next_cb_ts to now.) - -// Test rule 1. -// There is a matched input stream. The next_cb_ts of the newly added output -// stream will use the next_cb_ts from the input stream. -TEST_F(TimingSuite, NewOutputStreamInitExistMatchedStream) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr out_dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, out_dev->odev.get()); - struct cras_iodev* out_iodev = out_dev->odev->dev; - - DevicePtr in_dev = - create_device(CRAS_STREAM_INPUT, 1024, &format, CRAS_NODE_TYPE_MIC); - DL_APPEND(idev_list_, in_dev->odev.get()); - - StreamPtr in_stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - add_stream_to_dev(in_dev->dev, in_stream); - in_stream->rstream->next_cb_ts.tv_sec = 54321; - in_stream->rstream->next_cb_ts.tv_nsec = 12345; - in_stream->rstream->sleep_interval_ts.tv_sec = 321; - in_stream->rstream->sleep_interval_ts.tv_nsec = 123; - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &out_iodev, 1); - - EXPECT_EQ(in_stream->rstream->next_cb_ts.tv_sec, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(in_stream->rstream->next_cb_ts.tv_nsec, - rstream->next_cb_ts.tv_nsec); - EXPECT_EQ(in_stream->rstream->sleep_interval_ts.tv_sec, - rstream->sleep_interval_ts.tv_sec); - EXPECT_EQ(in_stream->rstream->sleep_interval_ts.tv_nsec, - rstream->sleep_interval_ts.tv_nsec); - - dev_stream_destroy(out_iodev->streams); -} - -// Test rule 2. -// The device already has streams, the next_cb_ts will be the earliest -// next_cb_ts from these streams. -TEST_F(TimingSuite, NewOutputStreamInitStreamInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); - struct cras_iodev* iodev = dev->odev->dev; - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - add_stream_to_dev(dev->dev, stream); - stream->rstream->next_cb_ts.tv_sec = 54321; - stream->rstream->next_cb_ts.tv_nsec = 12345; - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); - - EXPECT_EQ(stream->rstream->next_cb_ts.tv_sec, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(stream->rstream->next_cb_ts.tv_nsec, rstream->next_cb_ts.tv_nsec); - - dev_stream_destroy(iodev->streams->next); -} - -// Test rule 3. -// The there are no streams and no frames in device buffer. The next_cb_ts -// will be set to now. -TEST_F(TimingSuite, NewOutputStreamInitNoStreamNoFramesInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); - struct cras_iodev* iodev = dev->odev->dev; - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); - - EXPECT_EQ(start.tv_sec, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(start.tv_nsec, rstream->next_cb_ts.tv_nsec); - - dev_stream_destroy(iodev->streams); -} - -// Test rule 2. -// The there are no streams and some valid frames in device buffer. The -// next_cb_ts will be set to the time that valid frames in device is lower -// than cb_threshold. -TEST_F(TimingSuite, NewOutputStreamInitNoStreamSomeFramesInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); - struct cras_iodev* iodev = dev->odev->dev; - - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - iodev_stub_valid_frames(iodev, 960, start); - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); - - // The next_cb_ts should be 10ms from now. At that time there are - // only 480 valid frames in the device. - const timespec add_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &add_millis); - EXPECT_EQ(start.tv_sec, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(start.tv_nsec, rstream->next_cb_ts.tv_nsec); - - dev_stream_destroy(iodev->streams); -} - -// There is the pseudo code about wake up time for a output device. -// -// function dev_io_next_output_wake(dev): -// wake_ts = get_next_stream_wake_from_list(dev.streams) -// if cras_iodev_odev_should_wake(dev): -// wake_ts = MIN(wake_ts, dev.wake_ts) # rule_1 -// -// function get_next_stream_wake_from_list(streams): -// for stream in streams: -// if stream is draining: # rule_2 -// continue -// if stream is pending reply: # rule_3 -// continue -// if stream is USE_DEV_TIMING: # rule_4 -// continue -// min_ts = MIN(min_ts, stream.next_cb_ts) # rule_5 -// return min_ts -// -// # This function is in iodev so we don't test its logic here. -// function cras_iodev_odev_should_wake(dev): -// if dev.is_free_running: -// return False -// if dev.state == NORMAL_RUN or dev.state == NO_STREAM_RUN: -// return True -// return False - -// Test rule_1. -// The wake up time should be the earlier time amoung streams and devices. -TEST_F(TimingSuite, OutputWakeTimeOneStreamWithEarlierStreamWakeTime) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream->rstream->next_cb_ts = start; - stream->rstream->next_cb_ts.tv_sec += 1; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 2; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 1, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_1. -// The wake up time should be the earlier time amoung streams and devices. -TEST_F(TimingSuite, OutputWakeTimeOneStreamWithEarlierDeviceWakeTime) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream->rstream->next_cb_ts = start; - stream->rstream->next_cb_ts.tv_sec += 2; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 1; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 1, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_2. -// The stream 1 is draining so it will be ignored. The wake up time should be -// the next_cb_ts of stream 2. -TEST_F(TimingSuite, OutputWakeTimeTwoStreamsWithOneIsDraining) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - stream1->rstream->next_cb_ts.tv_sec += 2; - stream1->rstream->is_draining = 1; - stream1->rstream->queued_frames = 480; - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_OUTPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 10; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 5, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_3. -// The stream 1 is pending reply so it will be ignored. The wake up time should -// be the next_cb_ts of stream 2. -TEST_F(TimingSuite, OutputWakeTimeTwoStreamsWithOneIsPendingReply) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - stream1->rstream->next_cb_ts.tv_sec += 2; - rstream_stub_pending_reply(stream1->rstream.get(), 1); - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_OUTPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 10; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 5, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_4. -// The stream 1 is uning device timing so it will be ignored. The wake up time -// should be the next_cb_ts of stream 2. -TEST_F(TimingSuite, OutputWakeTimeTwoStreamsWithOneIsUsingDevTiming) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - stream1->rstream->next_cb_ts.tv_sec += 2; - stream1->rstream->flags = USE_DEV_TIMING; - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_OUTPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 10; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 5, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// Test rule_5. -// The wake up time should be the next_cb_ts of streams. -TEST_F(TimingSuite, OutputWakeTimeTwoStreams) { - cras_audio_format format; - fill_audio_format(&format, 48000); - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - - StreamPtr stream1 = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - stream1->rstream->next_cb_ts = start; - stream1->rstream->next_cb_ts.tv_sec += 2; - - StreamPtr stream2 = create_stream(1, 2, CRAS_STREAM_OUTPUT, 480, &format); - stream2->rstream->next_cb_ts = start; - stream2->rstream->next_cb_ts.tv_sec += 5; - - std::vector<StreamPtr> streams; - streams.emplace_back(std::move(stream1)); - streams.emplace_back(std::move(stream2)); - - struct timespec dev_wake_ts = start; - dev_wake_ts.tv_sec += 10; - - timespec dev_time = - SingleOutputDevNextWake(48000, 0, &start, &format, streams, &dev_wake_ts); - - EXPECT_EQ(start.tv_sec + 2, dev_time.tv_sec); - EXPECT_EQ(start.tv_nsec, dev_time.tv_nsec); -} - -// One device, one stream, fetch stream and check the sleep time is one more -// wakeup interval. -TEST_F(TimingSuite, OutputStreamsUpdateAfterFetching) { - cras_audio_format format; - fill_audio_format(&format, 48000); - - StreamPtr stream = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); - - // rstream's next callback is now. - struct timespec start; - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - stream->rstream->next_cb_ts = start; - - struct open_dev* dev_list_ = NULL; - - DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(dev_list_, dev->odev.get()); - - add_stream_to_dev(dev->dev, stream); - - dev_io_playback_fetch(dev_list_); - - // The next callback should be scheduled 10ms in the future. - const timespec ten_millis = {0, 10 * 1000 * 1000}; - add_timespecs(&start, &ten_millis); - EXPECT_EQ(start.tv_sec, stream->rstream->next_cb_ts.tv_sec); - EXPECT_EQ(start.tv_nsec, stream->rstream->next_cb_ts.tv_nsec); -} - -// TODO(yuhsuan): There are some time scheduling rules in cras_iodev. Maybe we -// can move them into dev_io so that all timing related codes are in the same -// file or leave them in iodev_unittest like now. -// 1. Device's wake_ts update: cras_iodev_frames_to_play_in_sleep. -// 2. wake_ts update when removing stream: cras_iodev_rm_stream. - -/* Stubs */ -extern "C" { - -int input_data_get_for_stream(struct input_data* data, - struct cras_rstream* stream, - struct buffer_share* offsets, - struct cras_audio_area** area, - unsigned int* offset) { - return 0; -} - -int input_data_put_for_stream(struct input_data* data, - struct cras_rstream* stream, - struct buffer_share* offsets, - unsigned int frames) { - return 0; -} - -float input_data_get_software_gain_scaler(struct input_data* data, - float idev_sw_gain_scaler, - struct cras_rstream* stream) { - return 1.0; -} - -struct cras_audio_format* cras_rstream_post_processing_format( - const struct cras_rstream* stream, - void* dev_ptr) { - return NULL; -} - -int cras_audio_thread_event_drop_samples() { - return 0; -} - -int cras_audio_thread_event_severe_underrun() { - return 0; -} - -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){}; -} // extern "C" - -} // namespace - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - openlog(NULL, LOG_PERROR, LOG_USER); - return RUN_ALL_TESTS(); -} |