1// Copyright 2014 The Chromium 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 "media/base/audio_timestamp_helper.h"
6#include "media/base/buffers.h"
7#include "media/filters/audio_clock.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10namespace media {
11
12class AudioClockTest : public testing::Test {
13 public:
14  AudioClockTest()
15      : sample_rate_(10), clock_(base::TimeDelta(), sample_rate_) {}
16
17  virtual ~AudioClockTest() {}
18
19  void WroteAudio(int frames_written,
20                  int frames_requested,
21                  int delay_frames,
22                  float playback_rate) {
23    clock_.WroteAudio(
24        frames_written, frames_requested, delay_frames, playback_rate);
25  }
26
27  int FrontTimestampInDays() { return clock_.front_timestamp().InDays(); }
28
29  int FrontTimestampInMilliseconds() {
30    return clock_.front_timestamp().InMilliseconds();
31  }
32
33  int BackTimestampInMilliseconds() {
34    return clock_.back_timestamp().InMilliseconds();
35  }
36
37  int TimestampSinceLastWritingInMilliseconds(int milliseconds) {
38    return clock_.TimestampSinceWriting(base::TimeDelta::FromMilliseconds(
39                                            milliseconds)).InMilliseconds();
40  }
41
42  int TimeUntilPlaybackInMilliseconds(int timestamp_ms) {
43    return clock_.TimeUntilPlayback(base::TimeDelta::FromMilliseconds(
44                                        timestamp_ms)).InMilliseconds();
45  }
46
47  int ContiguousAudioDataBufferedInDays() {
48    return clock_.contiguous_audio_data_buffered().InDays();
49  }
50
51  int ContiguousAudioDataBufferedInMilliseconds() {
52    return clock_.contiguous_audio_data_buffered().InMilliseconds();
53  }
54
55  int ContiguousAudioDataBufferedAtSameRateInMilliseconds() {
56    return clock_.contiguous_audio_data_buffered_at_same_rate()
57        .InMilliseconds();
58  }
59
60  const int sample_rate_;
61  AudioClock clock_;
62
63 private:
64  DISALLOW_COPY_AND_ASSIGN(AudioClockTest);
65};
66
67TEST_F(AudioClockTest, FrontTimestampStartsAtStartTimestamp) {
68  base::TimeDelta expected = base::TimeDelta::FromSeconds(123);
69  AudioClock clock(expected, sample_rate_);
70
71  EXPECT_EQ(expected, clock.front_timestamp());
72}
73
74TEST_F(AudioClockTest, BackTimestampStartsAtStartTimestamp) {
75  base::TimeDelta expected = base::TimeDelta::FromSeconds(123);
76  AudioClock clock(expected, sample_rate_);
77
78  EXPECT_EQ(expected, clock.back_timestamp());
79}
80
81TEST_F(AudioClockTest, TimestampSinceWritingStartsAtStartTimestamp) {
82  base::TimeDelta expected = base::TimeDelta::FromSeconds(123);
83  AudioClock clock(expected, sample_rate_);
84
85  base::TimeDelta time_since_writing = base::TimeDelta::FromSeconds(456);
86  EXPECT_EQ(expected, clock.TimestampSinceWriting(time_since_writing));
87}
88
89TEST_F(AudioClockTest, ContiguousAudioDataBufferedStartsAtZero) {
90  EXPECT_EQ(base::TimeDelta(), clock_.contiguous_audio_data_buffered());
91}
92
93TEST_F(AudioClockTest, ContiguousAudioDataBufferedAtSameRateStartsAtZero) {
94  EXPECT_EQ(base::TimeDelta(),
95            clock_.contiguous_audio_data_buffered_at_same_rate());
96}
97
98TEST_F(AudioClockTest, Playback) {
99  // The first time we write data we should still expect our start timestamp
100  // due to delay.
101  WroteAudio(10, 10, 20, 1.0);
102  EXPECT_EQ(0, FrontTimestampInMilliseconds());
103  EXPECT_EQ(1000, BackTimestampInMilliseconds());
104  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
105  EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
106
107  // The media time should remain at start timestamp as we write data.
108  WroteAudio(10, 10, 20, 1.0);
109  EXPECT_EQ(0, FrontTimestampInMilliseconds());
110  EXPECT_EQ(2000, BackTimestampInMilliseconds());
111  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
112  EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
113
114  WroteAudio(10, 10, 20, 1.0);
115  EXPECT_EQ(0, FrontTimestampInMilliseconds());
116  EXPECT_EQ(3000, BackTimestampInMilliseconds());
117  EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
118  EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
119
120  // The media time should now start advanced now that delay has been covered.
121  WroteAudio(10, 10, 20, 1.0);
122  EXPECT_EQ(1000, FrontTimestampInMilliseconds());
123  EXPECT_EQ(4000, BackTimestampInMilliseconds());
124  EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
125  EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
126
127  WroteAudio(10, 10, 20, 1.0);
128  EXPECT_EQ(2000, FrontTimestampInMilliseconds());
129  EXPECT_EQ(5000, BackTimestampInMilliseconds());
130  EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
131  EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
132
133  // Introduce a rate change to slow down time:
134  //   - Current time will advance by one second until it hits rate change
135  //   - Contiguous audio data will start shrinking immediately
136  WroteAudio(10, 10, 20, 0.5);
137  EXPECT_EQ(3000, FrontTimestampInMilliseconds());
138  EXPECT_EQ(5500, BackTimestampInMilliseconds());
139  EXPECT_EQ(2500, ContiguousAudioDataBufferedInMilliseconds());
140  EXPECT_EQ(2000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
141
142  WroteAudio(10, 10, 20, 0.5);
143  EXPECT_EQ(4000, FrontTimestampInMilliseconds());
144  EXPECT_EQ(6000, BackTimestampInMilliseconds());
145  EXPECT_EQ(2000, ContiguousAudioDataBufferedInMilliseconds());
146  EXPECT_EQ(1000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
147
148  WroteAudio(10, 10, 20, 0.5);
149  EXPECT_EQ(5000, FrontTimestampInMilliseconds());
150  EXPECT_EQ(6500, BackTimestampInMilliseconds());
151  EXPECT_EQ(1500, ContiguousAudioDataBufferedInMilliseconds());
152  EXPECT_EQ(1500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
153
154  WroteAudio(10, 10, 20, 0.5);
155  EXPECT_EQ(5500, FrontTimestampInMilliseconds());
156  EXPECT_EQ(7000, BackTimestampInMilliseconds());
157  EXPECT_EQ(1500, ContiguousAudioDataBufferedInMilliseconds());
158  EXPECT_EQ(1500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
159
160  // Introduce a rate change to speed up time:
161  //   - Current time will advance by half a second until it hits rate change
162  //   - Contiguous audio data will start growing immediately
163  WroteAudio(10, 10, 20, 2);
164  EXPECT_EQ(6000, FrontTimestampInMilliseconds());
165  EXPECT_EQ(9000, BackTimestampInMilliseconds());
166  EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
167  EXPECT_EQ(1000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
168
169  WroteAudio(10, 10, 20, 2);
170  EXPECT_EQ(6500, FrontTimestampInMilliseconds());
171  EXPECT_EQ(11000, BackTimestampInMilliseconds());
172  EXPECT_EQ(4500, ContiguousAudioDataBufferedInMilliseconds());
173  EXPECT_EQ(500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
174
175  WroteAudio(10, 10, 20, 2);
176  EXPECT_EQ(7000, FrontTimestampInMilliseconds());
177  EXPECT_EQ(13000, BackTimestampInMilliseconds());
178  EXPECT_EQ(6000, ContiguousAudioDataBufferedInMilliseconds());
179  EXPECT_EQ(6000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
180
181  WroteAudio(10, 10, 20, 2);
182  EXPECT_EQ(9000, FrontTimestampInMilliseconds());
183  EXPECT_EQ(15000, BackTimestampInMilliseconds());
184  EXPECT_EQ(6000, ContiguousAudioDataBufferedInMilliseconds());
185  EXPECT_EQ(6000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
186
187  // Write silence to simulate reaching end of stream:
188  //   - Current time will advance by half a second until it hits silence
189  //   - Contiguous audio data will start shrinking towards zero
190  WroteAudio(0, 10, 20, 2);
191  EXPECT_EQ(11000, FrontTimestampInMilliseconds());
192  EXPECT_EQ(15000, BackTimestampInMilliseconds());
193  EXPECT_EQ(4000, ContiguousAudioDataBufferedInMilliseconds());
194  EXPECT_EQ(4000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
195
196  WroteAudio(0, 10, 20, 2);
197  EXPECT_EQ(13000, FrontTimestampInMilliseconds());
198  EXPECT_EQ(15000, BackTimestampInMilliseconds());
199  EXPECT_EQ(2000, ContiguousAudioDataBufferedInMilliseconds());
200  EXPECT_EQ(2000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
201
202  WroteAudio(0, 10, 20, 2);
203  EXPECT_EQ(15000, FrontTimestampInMilliseconds());
204  EXPECT_EQ(15000, BackTimestampInMilliseconds());
205  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
206  EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
207
208  // At this point media time should stop increasing.
209  WroteAudio(0, 10, 20, 2);
210  EXPECT_EQ(15000, FrontTimestampInMilliseconds());
211  EXPECT_EQ(15000, BackTimestampInMilliseconds());
212  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
213  EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
214}
215
216TEST_F(AudioClockTest, AlternatingAudioAndSilence) {
217  // Buffer #1: [0, 1000)
218  WroteAudio(10, 10, 20, 1.0);
219  EXPECT_EQ(0, FrontTimestampInMilliseconds());
220  EXPECT_EQ(1000, BackTimestampInMilliseconds());
221  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
222
223  // Buffer #2: 1000ms of silence
224  WroteAudio(0, 10, 20, 1.0);
225  EXPECT_EQ(0, FrontTimestampInMilliseconds());
226  EXPECT_EQ(1000, BackTimestampInMilliseconds());
227  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
228
229  // Buffer #3: [1000, 2000):
230  //   - Buffer #1 is at front with 1000ms of contiguous audio data
231  WroteAudio(10, 10, 20, 1.0);
232  EXPECT_EQ(0, FrontTimestampInMilliseconds());
233  EXPECT_EQ(2000, BackTimestampInMilliseconds());
234  EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
235
236  // Buffer #4: 1000ms of silence
237  //   - Buffer #1 has been played out
238  //   - Buffer #2 of silence leaves us with 0ms of contiguous audio data
239  WroteAudio(0, 10, 20, 1.0);
240  EXPECT_EQ(1000, FrontTimestampInMilliseconds());
241  EXPECT_EQ(2000, BackTimestampInMilliseconds());
242  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
243
244  // Buffer #5: [2000, 3000):
245  //   - Buffer #3 is at front with 1000ms of contiguous audio data
246  WroteAudio(10, 10, 20, 1.0);
247  EXPECT_EQ(1000, FrontTimestampInMilliseconds());
248  EXPECT_EQ(3000, BackTimestampInMilliseconds());
249  EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
250}
251
252TEST_F(AudioClockTest, ZeroDelay) {
253  // The first time we write data we should expect the first timestamp
254  // immediately.
255  WroteAudio(10, 10, 0, 1.0);
256  EXPECT_EQ(0, FrontTimestampInMilliseconds());
257  EXPECT_EQ(1000, BackTimestampInMilliseconds());
258  EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
259
260  // Ditto for all subsequent buffers.
261  WroteAudio(10, 10, 0, 1.0);
262  EXPECT_EQ(1000, FrontTimestampInMilliseconds());
263  EXPECT_EQ(2000, BackTimestampInMilliseconds());
264  EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
265
266  WroteAudio(10, 10, 0, 1.0);
267  EXPECT_EQ(2000, FrontTimestampInMilliseconds());
268  EXPECT_EQ(3000, BackTimestampInMilliseconds());
269  EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
270
271  // Ditto for silence.
272  WroteAudio(0, 10, 0, 1.0);
273  EXPECT_EQ(3000, FrontTimestampInMilliseconds());
274  EXPECT_EQ(3000, BackTimestampInMilliseconds());
275  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
276
277  WroteAudio(0, 10, 0, 1.0);
278  EXPECT_EQ(3000, FrontTimestampInMilliseconds());
279  EXPECT_EQ(3000, BackTimestampInMilliseconds());
280  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
281}
282
283TEST_F(AudioClockTest, TimestampSinceLastWriting) {
284  // Construct an audio clock with the following representation:
285  //
286  // |- existing  delay -|------------ calls to WroteAudio() -----------------|
287  // +-------------------+----------------+------------------+----------------+
288  // | 20 frames silence | 10 frames @ 1x | 10 frames @ 0.5x | 10 frames @ 2x |
289  // +-------------------+----------------+------------------+----------------+
290  // Media timestamp:    0              1000               1500             3500
291  // Wall clock time:  2000             3000               4000             5000
292  WroteAudio(10, 10, 40, 1.0);
293  WroteAudio(10, 10, 40, 0.5);
294  WroteAudio(10, 10, 40, 2.0);
295  EXPECT_EQ(0, FrontTimestampInMilliseconds());
296  EXPECT_EQ(3500, BackTimestampInMilliseconds());
297  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
298
299  // Simulate passing 2000ms of initial delay in the audio hardware.
300  EXPECT_EQ(0, TimestampSinceLastWritingInMilliseconds(0));
301  EXPECT_EQ(0, TimestampSinceLastWritingInMilliseconds(500));
302  EXPECT_EQ(0, TimestampSinceLastWritingInMilliseconds(1000));
303  EXPECT_EQ(0, TimestampSinceLastWritingInMilliseconds(1500));
304  EXPECT_EQ(0, TimestampSinceLastWritingInMilliseconds(2000));
305
306  // Now we should see the 1.0x buffer.
307  EXPECT_EQ(500, TimestampSinceLastWritingInMilliseconds(2500));
308  EXPECT_EQ(1000, TimestampSinceLastWritingInMilliseconds(3000));
309
310  // Now we should see the 0.5x buffer.
311  EXPECT_EQ(1250, TimestampSinceLastWritingInMilliseconds(3500));
312  EXPECT_EQ(1500, TimestampSinceLastWritingInMilliseconds(4000));
313
314  // Now we should see the 2.0x buffer.
315  EXPECT_EQ(2500, TimestampSinceLastWritingInMilliseconds(4500));
316  EXPECT_EQ(3500, TimestampSinceLastWritingInMilliseconds(5000));
317
318  // Times beyond the known length of the audio clock should return the last
319  // media timestamp we know of.
320  EXPECT_EQ(3500, TimestampSinceLastWritingInMilliseconds(5001));
321  EXPECT_EQ(3500, TimestampSinceLastWritingInMilliseconds(6000));
322}
323
324TEST_F(AudioClockTest, TimeUntilPlayback) {
325  // Construct an audio clock with the following representation:
326  //
327  //    existing
328  // |-  delay   -|------------------ calls to WroteAudio() ------------------|
329  // +------------+---------+------------+-----------+------------+-----------+
330  // | 20 silence | 10 @ 1x | 10 silence | 10 @ 0.5x | 10 silence | 10 @ 2.0x |
331  // +------------+---------+------------+-----------+------------+-----------+
332  // Media:       0       1000         1000        1500         1500        3500
333  // Wall:      2000      3000         4000        5000         6000        7000
334  WroteAudio(10, 10, 60, 1.0);
335  WroteAudio(0, 10, 60, 1.0);
336  WroteAudio(10, 10, 60, 0.5);
337  WroteAudio(0, 10, 60, 0.5);
338  WroteAudio(10, 10, 60, 2.0);
339  EXPECT_EQ(0, FrontTimestampInMilliseconds());
340  EXPECT_EQ(3500, BackTimestampInMilliseconds());
341  EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
342
343  // Media timestamp zero has to wait for silence to pass.
344  EXPECT_EQ(2000, TimeUntilPlaybackInMilliseconds(0));
345
346  // From then on out it's simply adding up the number of frames and taking
347  // silence into account.
348  EXPECT_EQ(2500, TimeUntilPlaybackInMilliseconds(500));
349  EXPECT_EQ(3000, TimeUntilPlaybackInMilliseconds(1000));
350  EXPECT_EQ(4500, TimeUntilPlaybackInMilliseconds(1250));
351  EXPECT_EQ(5000, TimeUntilPlaybackInMilliseconds(1500));
352  EXPECT_EQ(6500, TimeUntilPlaybackInMilliseconds(2500));
353  EXPECT_EQ(7000, TimeUntilPlaybackInMilliseconds(3500));
354}
355
356TEST_F(AudioClockTest, SupportsYearsWorthOfAudioData) {
357  // Use number of frames that would be likely to overflow 32-bit integer math.
358  const int huge_amount_of_frames = std::numeric_limits<int>::max();
359  const base::TimeDelta huge =
360      base::TimeDelta::FromSeconds(huge_amount_of_frames / sample_rate_);
361  EXPECT_EQ(2485, huge.InDays());  // Just to give some context on how big...
362
363  // Use zero delay to test calculation of current timestamp.
364  WroteAudio(huge_amount_of_frames, huge_amount_of_frames, 0, 1.0);
365  EXPECT_EQ(0, FrontTimestampInDays());
366  EXPECT_EQ(2485, ContiguousAudioDataBufferedInDays());
367
368  WroteAudio(huge_amount_of_frames, huge_amount_of_frames, 0, 1.0);
369  EXPECT_EQ(huge.InDays(), FrontTimestampInDays());
370  EXPECT_EQ(huge.InDays(), ContiguousAudioDataBufferedInDays());
371
372  WroteAudio(huge_amount_of_frames, huge_amount_of_frames, 0, 1.0);
373  EXPECT_EQ((huge * 2).InDays(), FrontTimestampInDays());
374  EXPECT_EQ(huge.InDays(), ContiguousAudioDataBufferedInDays());
375
376  WroteAudio(huge_amount_of_frames, huge_amount_of_frames, 0, 1.0);
377  EXPECT_EQ((huge * 3).InDays(), FrontTimestampInDays());
378  EXPECT_EQ(huge.InDays(), ContiguousAudioDataBufferedInDays());
379
380  // Use huge delay to test calculation of buffered data.
381  WroteAudio(
382      huge_amount_of_frames, huge_amount_of_frames, huge_amount_of_frames, 1.0);
383  EXPECT_EQ((huge * 3).InDays(), FrontTimestampInDays());
384  EXPECT_EQ((huge * 2).InDays(), ContiguousAudioDataBufferedInDays());
385}
386
387}  // namespace media
388