summaryrefslogtreecommitdiff
path: root/cras/src/tests/timing_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/tests/timing_unittest.cc')
-rw-r--r--cras/src/tests/timing_unittest.cc1246
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();
-}