1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <time.h>
9
10 #include <gtest/gtest.h>
11
12 extern "C" {
13 #include "dev_io.h" // tested
14 #include "dev_stream.h" // tested
15 #include "cras_rstream.h" // stubbed
16 #include "cras_iodev.h" // stubbed
17 #include "cras_shm.h"
18 #include "cras_types.h"
19 #include "utlist.h"
20
21 struct audio_thread_event_log* atlog;
22 }
23
24 #include "dev_io_stubs.h"
25 #include "iodev_stub.h"
26 #include "rstream_stub.h"
27
28 #define FAKE_POLL_FD 33
29
30 namespace {
31
32 class TimingSuite : public testing::Test{
33 protected:
SetUp()34 virtual void SetUp() {
35 atlog = static_cast<audio_thread_event_log*>(calloc(1, sizeof(*atlog)));
36 iodev_stub_reset();
37 rstream_stub_reset();
38 }
39
TearDown()40 virtual void TearDown() {
41 free(atlog);
42 }
43
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)44 timespec SingleInputDevNextWake(
45 size_t dev_cb_threshold,
46 size_t dev_level,
47 const timespec* level_timestamp,
48 cras_audio_format* dev_format,
49 const std::vector<StreamPtr>& streams,
50 CRAS_NODE_TYPE active_node_type = CRAS_NODE_TYPE_MIC) {
51 struct open_dev* dev_list_ = NULL;
52
53 DevicePtr dev = create_device(CRAS_STREAM_INPUT, dev_cb_threshold,
54 dev_format, active_node_type);
55 dev->dev->input_streaming = true;
56 DL_APPEND(dev_list_, dev->odev.get());
57
58 for (auto const& stream : streams) {
59 add_stream_to_dev(dev->dev, stream);
60 }
61
62 // Set response for frames_queued.
63 iodev_stub_frames_queued(dev->dev.get(), dev_level, *level_timestamp);
64
65 dev_io_send_captured_samples(dev_list_);
66
67 struct timespec dev_time;
68 dev_time.tv_sec = level_timestamp->tv_sec + 500; // Far in the future.
69 dev_io_next_input_wake(&dev_list_, &dev_time);
70 return dev_time;
71 }
72 };
73
74 // One device, one stream, write a callback of data and check the sleep time is
75 // one more wakeup interval.
TEST_F(TimingSuite,WaitAfterFill)76 TEST_F(TimingSuite, WaitAfterFill) {
77 const size_t cb_threshold = 480;
78
79 cras_audio_format format;
80 fill_audio_format(&format, 48000);
81
82 StreamPtr stream =
83 create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
84 // rstream's next callback is now and there is enough data to fill.
85 struct timespec start;
86 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
87 stream->rstream->next_cb_ts = start;
88 AddFakeDataToStream(stream.get(), 480);
89
90 std::vector<StreamPtr> streams;
91 streams.emplace_back(std::move(stream));
92 timespec dev_time = SingleInputDevNextWake(cb_threshold, 0, &start,
93 &format, streams);
94
95 // The next callback should be scheduled 10ms in the future.
96 // And the next wake up should reflect the only attached stream.
97 EXPECT_EQ(dev_time.tv_sec, streams[0]->rstream->next_cb_ts.tv_sec);
98 EXPECT_EQ(dev_time.tv_nsec, streams[0]->rstream->next_cb_ts.tv_nsec);
99 }
100
101 // One device with one stream which has block_size larger than the device buffer
102 // level. If the device buffer level = 0, the input device wake time should be
103 // set to (buffer_size / 2) / device_rate secs.
TEST_F(TimingSuite,LargeCallbackStreamWithEmptyBuffer)104 TEST_F(TimingSuite, LargeCallbackStreamWithEmptyBuffer) {
105 const size_t cb_threshold = 3000;
106 const size_t dev_cb_threshold = 1200;
107 const size_t dev_level = 0;
108
109 cras_audio_format format;
110 fill_audio_format(&format, 48000);
111
112 StreamPtr stream =
113 create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
114 struct timespec start;
115 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
116 stream->rstream->next_cb_ts = start;
117
118 std::vector<StreamPtr> streams;
119 streams.emplace_back(std::move(stream));
120 timespec dev_time = SingleInputDevNextWake(
121 dev_cb_threshold, dev_level, &start, &format, streams);
122
123 struct timespec delta;
124 subtract_timespecs(&dev_time, &start, &delta);
125 // The next dev wake ts should be 25ms since the buffer level is empty and
126 // 1200 / 48000 = 0.025.
127 EXPECT_EQ(delta.tv_sec, 0);
128 EXPECT_LT(delta.tv_nsec, 25000000 + 5000 * 1000);
129 EXPECT_GT(delta.tv_nsec, 25000000 - 5000 * 1000);
130 }
131
132 // One device with one stream which has block_size larger than the device buffer
133 // level. If the device buffer level = buffer_size / 2, the input device wake
134 // time should be set to max(0, 5ms) = 5ms to prevent busy loop occurs.
TEST_F(TimingSuite,LargeCallbackStreamWithHalfFullBuffer)135 TEST_F(TimingSuite, LargeCallbackStreamWithHalfFullBuffer) {
136 const size_t cb_threshold = 3000;
137 const size_t dev_cb_threshold = 1200;
138 const size_t dev_level = 1200;
139
140 cras_audio_format format;
141 fill_audio_format(&format, 48000);
142
143 StreamPtr stream =
144 create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
145 struct timespec start;
146 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
147 stream->rstream->next_cb_ts = start;
148
149 std::vector<StreamPtr> streams;
150 streams.emplace_back(std::move(stream));
151 timespec dev_time = SingleInputDevNextWake(
152 dev_cb_threshold, dev_level, &start, &format, streams);
153
154 struct timespec delta;
155 subtract_timespecs(&dev_time, &start, &delta);
156 // The next dev wake ts should be 5ms since the buffer level is half full.
157 EXPECT_EQ(delta.tv_sec, 0);
158 EXPECT_LT(delta.tv_nsec, 5000000 + 5000 * 1000);
159 EXPECT_GT(delta.tv_nsec, 5000000 - 5000 * 1000);
160 }
161
162 // One device(48k), one stream(44.1k), write a callback of data and check that
163 // the sleep time is correct when doing SRC.
TEST_F(TimingSuite,WaitAfterFillSRC)164 TEST_F(TimingSuite, WaitAfterFillSRC) {
165 cras_audio_format dev_format;
166 fill_audio_format(&dev_format, 48000);
167 cras_audio_format stream_format;
168 fill_audio_format(&stream_format, 44100);
169
170 StreamPtr stream =
171 create_stream(1, 1, CRAS_STREAM_INPUT, 441, &stream_format);
172 // rstream's next callback is now and there is enough data to fill.
173 struct timespec start;
174 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
175 stream->rstream->next_cb_ts = start;
176 AddFakeDataToStream(stream.get(), 441);
177
178 std::vector<StreamPtr> streams;
179 streams.emplace_back(std::move(stream));
180 timespec dev_time = SingleInputDevNextWake(480, 0, &start,
181 &dev_format, streams);
182
183 // The next callback should be scheduled 10ms in the future.
184 struct timespec delta;
185 subtract_timespecs(&dev_time, &start, &delta);
186 EXPECT_LT(9900 * 1000, delta.tv_nsec);
187 EXPECT_GT(10100 * 1000, delta.tv_nsec);
188 }
189
190 // One device, two streams. One stream is ready the other still needs data.
191 // Checks that the sleep interval is based on the time the device will take to
192 // supply the needed samples for stream2.
TEST_F(TimingSuite,WaitTwoStreamsSameFormat)193 TEST_F(TimingSuite, WaitTwoStreamsSameFormat) {
194 const size_t cb_threshold = 480;
195
196 cras_audio_format format;
197 fill_audio_format(&format, 48000);
198
199 // stream1's next callback is now and there is enough data to fill.
200 StreamPtr stream1 =
201 create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
202 struct timespec start;
203 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
204 stream1->rstream->next_cb_ts = start;
205 AddFakeDataToStream(stream1.get(), cb_threshold);
206
207 // stream2 is only half full.
208 StreamPtr stream2 =
209 create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
210 stream2->rstream->next_cb_ts = start;
211 AddFakeDataToStream(stream2.get(), 240);
212
213 std::vector<StreamPtr> streams;
214 streams.emplace_back(std::move(stream1));
215 streams.emplace_back(std::move(stream2));
216 timespec dev_time = SingleInputDevNextWake(cb_threshold, 0, &start,
217 &format, streams);
218
219 // Should wait for approximately 5 milliseconds for 240 samples at 48k.
220 struct timespec delta2;
221 subtract_timespecs(&dev_time, &start, &delta2);
222 EXPECT_LT(4900 * 1000, delta2.tv_nsec);
223 EXPECT_GT(5100 * 1000, delta2.tv_nsec);
224 }
225
226 // One device(44.1), two streams(44.1, 48). One stream is ready the other still
227 // needs data. Checks that the sleep interval is based on the time the device
228 // will take to supply the needed samples for stream2, stream2 is sample rate
229 // converted from the 44.1k device to the 48k stream.
TEST_F(TimingSuite,WaitTwoStreamsDifferentRates)230 TEST_F(TimingSuite, WaitTwoStreamsDifferentRates) {
231 cras_audio_format s1_format, s2_format;
232 fill_audio_format(&s1_format, 44100);
233 fill_audio_format(&s2_format, 48000);
234
235 // stream1's next callback is now and there is enough data to fill.
236 StreamPtr stream1 =
237 create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format);
238 struct timespec start;
239 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
240 stream1->rstream->next_cb_ts = start;
241 AddFakeDataToStream(stream1.get(), 441);
242 // stream2's next callback is now but there is only half a callback of data.
243 StreamPtr stream2 =
244 create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format);
245 stream2->rstream->next_cb_ts = start;
246 AddFakeDataToStream(stream2.get(), 240);
247
248 std::vector<StreamPtr> streams;
249 streams.emplace_back(std::move(stream1));
250 streams.emplace_back(std::move(stream2));
251 timespec dev_time = SingleInputDevNextWake(441, 0, &start,
252 &s1_format, streams);
253
254 // Should wait for approximately 5 milliseconds for 240 48k samples from the
255 // 44.1k device.
256 struct timespec delta2;
257 subtract_timespecs(&dev_time, &start, &delta2);
258 EXPECT_LT(4900 * 1000, delta2.tv_nsec);
259 EXPECT_GT(5100 * 1000, delta2.tv_nsec);
260 }
261
262 // One device, two streams. Both streams get a full callback of data and the
263 // device has enough samples for the next callback already. Checks that the
264 // shorter of the two streams times is used for the next sleep interval.
TEST_F(TimingSuite,WaitTwoStreamsDifferentWakeupTimes)265 TEST_F(TimingSuite, WaitTwoStreamsDifferentWakeupTimes) {
266 cras_audio_format s1_format, s2_format;
267 fill_audio_format(&s1_format, 44100);
268 fill_audio_format(&s2_format, 48000);
269
270 struct timespec start;
271 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
272
273 // stream1's next callback is in 3ms.
274 StreamPtr stream1 =
275 create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format);
276 stream1->rstream->next_cb_ts = start;
277 const timespec three_millis = { 0, 3 * 1000 * 1000 };
278 add_timespecs(&stream1->rstream->next_cb_ts, &three_millis);
279 AddFakeDataToStream(stream1.get(), 441);
280 // stream2 is also ready next cb in 5ms..
281 StreamPtr stream2 =
282 create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format);
283 stream2->rstream->next_cb_ts = start;
284 const timespec five_millis = { 0, 5 * 1000 * 1000 };
285 add_timespecs(&stream2->rstream->next_cb_ts, &five_millis);
286 AddFakeDataToStream(stream1.get(), 480);
287
288 std::vector<StreamPtr> streams;
289 streams.emplace_back(std::move(stream1));
290 streams.emplace_back(std::move(stream2));
291 timespec dev_time = SingleInputDevNextWake(441, 441, &start,
292 &s1_format, streams);
293
294 // Should wait for approximately 3 milliseconds for stream 1 first.
295 struct timespec delta2;
296 subtract_timespecs(&dev_time, &start, &delta2);
297 EXPECT_LT(2900 * 1000, delta2.tv_nsec);
298 EXPECT_GT(3100 * 1000, delta2.tv_nsec);
299 }
300
301 // One hotword stream attaches to hotword device. Input data has copied from
302 // device to stream but total number is less than cb_threshold. Hotword stream
303 // should be scheduled wake base on the samples needed to fill full shm.
TEST_F(TimingSuite,HotwordStreamUseDevTiming)304 TEST_F(TimingSuite, HotwordStreamUseDevTiming) {
305 cras_audio_format fmt;
306 fill_audio_format(&fmt, 48000);
307
308 struct timespec start, delay;
309 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
310
311 StreamPtr stream =
312 create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
313 stream->rstream->flags = HOTWORD_STREAM;
314 stream->rstream->next_cb_ts = start;
315 delay.tv_sec = 0;
316 delay.tv_nsec = 3 * 1000 * 1000;
317 add_timespecs(&stream->rstream->next_cb_ts, &delay);
318
319 // Add fake data to stream and device so its slightly less than cb_threshold.
320 // Expect to wait for samples to fill the full buffer (480 - 192) frames
321 // instead of using the next_cb_ts.
322 AddFakeDataToStream(stream.get(), 192);
323 std::vector<StreamPtr> streams;
324 streams.emplace_back(std::move(stream));
325 timespec dev_time = SingleInputDevNextWake(4096, 0, &start,
326 &fmt, streams);
327 struct timespec delta;
328 subtract_timespecs(&dev_time, &start, &delta);
329 // 288 frames worth of time = 6 ms.
330 EXPECT_EQ(6 * 1000 * 1000, delta.tv_nsec);
331 }
332
333 // One hotword stream attaches to hotword device. Input data burst to a number
334 // larger than cb_threshold. Also, stream is pending client reply.
335 // In this case stream fd is used to poll for next wake.
336 // And the dev wake time is unchanged from the default 20 seconds limit.
TEST_F(TimingSuite,HotwordStreamBulkDataIsPending)337 TEST_F(TimingSuite, HotwordStreamBulkDataIsPending) {
338 int poll_fd = 0;
339 cras_audio_format fmt;
340 fill_audio_format(&fmt, 48000);
341
342 struct timespec start;
343 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
344
345 StreamPtr stream =
346 create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
347 stream->rstream->flags = HOTWORD_STREAM;
348 stream->rstream->next_cb_ts = start;
349
350 AddFakeDataToStream(stream.get(), 480);
351 std::vector<StreamPtr> streams;
352 streams.emplace_back(std::move(stream));
353 // Stream is pending the reply from client.
354 rstream_stub_pending_reply(streams[0]->rstream.get(), 1);
355
356 // There is more than 1 cb_threshold of data in device.
357 timespec dev_time = SingleInputDevNextWake(
358 4096, 7000, &start, &fmt, streams, CRAS_NODE_TYPE_HOTWORD);
359
360 // Need to wait for stream fd in the next ppoll.
361 poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get());
362 EXPECT_EQ(FAKE_POLL_FD, poll_fd);
363
364 struct timespec delta;
365 subtract_timespecs(&dev_time, &start, &delta);
366 // Wake up time should be default 20 seconds because audio thread
367 // depends on reply from client to wake it up.
368 EXPECT_LT(19, delta.tv_sec);
369 EXPECT_GT(21, delta.tv_sec);
370 }
371
372 // One hotword stream attaches to hotword device. Input data burst to a number
373 // larger than cb_threshold. However, stream is not pending client reply.
374 // This happens if there was no data during capture_to_stream.
375 // In this case stream fd is NOT used to poll for next wake.
376 // And the dev wake time is changed to a 0 instead of default 20 seconds.
TEST_F(TimingSuite,HotwordStreamBulkDataIsNotPending)377 TEST_F(TimingSuite, HotwordStreamBulkDataIsNotPending) {
378 int poll_fd = 0;
379 cras_audio_format fmt;
380 fill_audio_format(&fmt, 48000);
381
382 struct timespec start;
383 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
384
385 StreamPtr stream =
386 create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
387 stream->rstream->flags = HOTWORD_STREAM;
388 stream->rstream->next_cb_ts = start;
389
390 AddFakeDataToStream(stream.get(), 480);
391 std::vector<StreamPtr> streams;
392 streams.emplace_back(std::move(stream));
393 // Stream is not pending the reply from client.
394 rstream_stub_pending_reply(streams[0]->rstream.get(), 0);
395
396 // There is more than 1 cb_threshold of data in device.
397 timespec dev_time = SingleInputDevNextWake(4096, 7000, &start,
398 &fmt, streams);
399
400 // Does not need to wait for stream fd in the next ppoll.
401 poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get());
402 EXPECT_EQ(-1, poll_fd);
403
404 struct timespec delta;
405 subtract_timespecs(&dev_time, &start, &delta);
406 // Wake up time should be very small because there is enough
407 // data to be send to client.
408 EXPECT_LT(delta.tv_sec, 0.1);
409 }
410
411 /* Stubs */
412 extern "C" {
413
cras_server_metrics_highest_hw_level(unsigned hw_level,enum CRAS_STREAM_DIRECTION direction)414 int cras_server_metrics_highest_hw_level(unsigned hw_level,
415 enum CRAS_STREAM_DIRECTION direction)
416 {
417 return 0;
418 }
419
cras_server_metrics_longest_fetch_delay(unsigned delay_msec)420 int cras_server_metrics_longest_fetch_delay(unsigned delay_msec)
421 {
422 return 0;
423 }
424
cras_server_metrics_num_underruns(unsigned num_underruns)425 int cras_server_metrics_num_underruns(unsigned num_underruns)
426 {
427 return 0;
428 }
429
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)430 int input_data_get_for_stream(
431 struct input_data *data,
432 struct cras_rstream *stream,
433 struct buffer_share *offsets,
434 struct cras_audio_area **area,
435 unsigned int *offset)
436 {
437 return 0;
438 }
439
input_data_put_for_stream(struct input_data * data,struct cras_rstream * stream,struct buffer_share * offsets,unsigned int frames)440 int input_data_put_for_stream(struct input_data *data,
441 struct cras_rstream *stream,
442 struct buffer_share *offsets,
443 unsigned int frames)
444 {
445 return 0;
446 }
cras_rstream_post_processing_format(const struct cras_rstream * stream,void * dev_ptr)447 struct cras_audio_format *cras_rstream_post_processing_format(
448 const struct cras_rstream *stream, void *dev_ptr)
449 {
450 return NULL;
451 }
452 } // extern "C"
453
454 } // namespace
455
main(int argc,char ** argv)456 int main(int argc, char** argv) {
457 ::testing::InitGoogleTest(&argc, argv);
458 return RUN_ALL_TESTS();
459 }
460