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.
5 #include "media/base/audio_timestamp_helper.h"
6 #include "media/filters/audio_clock.h"
7 #include "testing/gtest/include/gtest/gtest.h"
11 class AudioClockTest
: public testing::Test
{
14 : sample_rate_(10), clock_(base::TimeDelta(), sample_rate_
) {}
16 ~AudioClockTest() override
{}
18 void WroteAudio(int frames_written
,
21 double playback_rate
) {
23 frames_written
, frames_requested
, delay_frames
, playback_rate
);
26 int FrontTimestampInDays() { return clock_
.front_timestamp().InDays(); }
28 int FrontTimestampInMilliseconds() {
29 return clock_
.front_timestamp().InMilliseconds();
32 int BackTimestampInMilliseconds() {
33 return clock_
.back_timestamp().InMilliseconds();
36 int TimeUntilPlaybackInMilliseconds(int timestamp_ms
) {
37 return clock_
.TimeUntilPlayback(base::TimeDelta::FromMilliseconds(
38 timestamp_ms
)).InMilliseconds();
41 int ContiguousAudioDataBufferedInDays() {
42 base::TimeDelta total
, same_rate_total
;
43 clock_
.ContiguousAudioDataBufferedForTesting(&total
, &same_rate_total
);
44 return total
.InDays();
47 int ContiguousAudioDataBufferedInMilliseconds() {
48 base::TimeDelta total
, same_rate_total
;
49 clock_
.ContiguousAudioDataBufferedForTesting(&total
, &same_rate_total
);
50 return total
.InMilliseconds();
53 int ContiguousAudioDataBufferedAtSameRateInMilliseconds() {
54 base::TimeDelta total
, same_rate_total
;
55 clock_
.ContiguousAudioDataBufferedForTesting(&total
, &same_rate_total
);
56 return same_rate_total
.InMilliseconds();
59 const int sample_rate_
;
63 DISALLOW_COPY_AND_ASSIGN(AudioClockTest
);
66 TEST_F(AudioClockTest
, FrontTimestampStartsAtStartTimestamp
) {
67 base::TimeDelta expected
= base::TimeDelta::FromSeconds(123);
68 AudioClock
clock(expected
, sample_rate_
);
70 EXPECT_EQ(expected
, clock
.front_timestamp());
73 TEST_F(AudioClockTest
, BackTimestampStartsAtStartTimestamp
) {
74 base::TimeDelta expected
= base::TimeDelta::FromSeconds(123);
75 AudioClock
clock(expected
, sample_rate_
);
77 EXPECT_EQ(expected
, clock
.back_timestamp());
80 TEST_F(AudioClockTest
, Playback
) {
81 // The first time we write data we should still expect our start timestamp
83 WroteAudio(10, 10, 20, 1.0);
84 EXPECT_EQ(0, FrontTimestampInMilliseconds());
85 EXPECT_EQ(1000, BackTimestampInMilliseconds());
86 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
87 EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
89 // The media time should remain at start timestamp as we write data.
90 WroteAudio(10, 10, 20, 1.0);
91 EXPECT_EQ(0, FrontTimestampInMilliseconds());
92 EXPECT_EQ(2000, BackTimestampInMilliseconds());
93 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
94 EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
96 WroteAudio(10, 10, 20, 1.0);
97 EXPECT_EQ(0, FrontTimestampInMilliseconds());
98 EXPECT_EQ(3000, BackTimestampInMilliseconds());
99 EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
100 EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
102 // The media time should now start advanced now that delay has been covered.
103 WroteAudio(10, 10, 20, 1.0);
104 EXPECT_EQ(1000, FrontTimestampInMilliseconds());
105 EXPECT_EQ(4000, BackTimestampInMilliseconds());
106 EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
107 EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
109 WroteAudio(10, 10, 20, 1.0);
110 EXPECT_EQ(2000, FrontTimestampInMilliseconds());
111 EXPECT_EQ(5000, BackTimestampInMilliseconds());
112 EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
113 EXPECT_EQ(3000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
115 // Introduce a rate change to slow down time:
116 // - Current time will advance by one second until it hits rate change
117 // - Contiguous audio data will start shrinking immediately
118 WroteAudio(10, 10, 20, 0.5);
119 EXPECT_EQ(3000, FrontTimestampInMilliseconds());
120 EXPECT_EQ(5500, BackTimestampInMilliseconds());
121 EXPECT_EQ(2500, ContiguousAudioDataBufferedInMilliseconds());
122 EXPECT_EQ(2000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
124 WroteAudio(10, 10, 20, 0.5);
125 EXPECT_EQ(4000, FrontTimestampInMilliseconds());
126 EXPECT_EQ(6000, BackTimestampInMilliseconds());
127 EXPECT_EQ(2000, ContiguousAudioDataBufferedInMilliseconds());
128 EXPECT_EQ(1000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
130 WroteAudio(10, 10, 20, 0.5);
131 EXPECT_EQ(5000, FrontTimestampInMilliseconds());
132 EXPECT_EQ(6500, BackTimestampInMilliseconds());
133 EXPECT_EQ(1500, ContiguousAudioDataBufferedInMilliseconds());
134 EXPECT_EQ(1500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
136 WroteAudio(10, 10, 20, 0.5);
137 EXPECT_EQ(5500, FrontTimestampInMilliseconds());
138 EXPECT_EQ(7000, BackTimestampInMilliseconds());
139 EXPECT_EQ(1500, ContiguousAudioDataBufferedInMilliseconds());
140 EXPECT_EQ(1500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
142 // Introduce a rate change to speed up time:
143 // - Current time will advance by half a second until it hits rate change
144 // - Contiguous audio data will start growing immediately
145 WroteAudio(10, 10, 20, 2);
146 EXPECT_EQ(6000, FrontTimestampInMilliseconds());
147 EXPECT_EQ(9000, BackTimestampInMilliseconds());
148 EXPECT_EQ(3000, ContiguousAudioDataBufferedInMilliseconds());
149 EXPECT_EQ(1000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
151 WroteAudio(10, 10, 20, 2);
152 EXPECT_EQ(6500, FrontTimestampInMilliseconds());
153 EXPECT_EQ(11000, BackTimestampInMilliseconds());
154 EXPECT_EQ(4500, ContiguousAudioDataBufferedInMilliseconds());
155 EXPECT_EQ(500, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
157 WroteAudio(10, 10, 20, 2);
158 EXPECT_EQ(7000, FrontTimestampInMilliseconds());
159 EXPECT_EQ(13000, BackTimestampInMilliseconds());
160 EXPECT_EQ(6000, ContiguousAudioDataBufferedInMilliseconds());
161 EXPECT_EQ(6000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
163 WroteAudio(10, 10, 20, 2);
164 EXPECT_EQ(9000, FrontTimestampInMilliseconds());
165 EXPECT_EQ(15000, BackTimestampInMilliseconds());
166 EXPECT_EQ(6000, ContiguousAudioDataBufferedInMilliseconds());
167 EXPECT_EQ(6000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
169 // Write silence to simulate reaching end of stream:
170 // - Current time will advance by half a second until it hits silence
171 // - Contiguous audio data will start shrinking towards zero
172 WroteAudio(0, 10, 20, 2);
173 EXPECT_EQ(11000, FrontTimestampInMilliseconds());
174 EXPECT_EQ(15000, BackTimestampInMilliseconds());
175 EXPECT_EQ(4000, ContiguousAudioDataBufferedInMilliseconds());
176 EXPECT_EQ(4000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
178 WroteAudio(0, 10, 20, 2);
179 EXPECT_EQ(13000, FrontTimestampInMilliseconds());
180 EXPECT_EQ(15000, BackTimestampInMilliseconds());
181 EXPECT_EQ(2000, ContiguousAudioDataBufferedInMilliseconds());
182 EXPECT_EQ(2000, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
184 WroteAudio(0, 10, 20, 2);
185 EXPECT_EQ(15000, FrontTimestampInMilliseconds());
186 EXPECT_EQ(15000, BackTimestampInMilliseconds());
187 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
188 EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
190 // At this point media time should stop increasing.
191 WroteAudio(0, 10, 20, 2);
192 EXPECT_EQ(15000, FrontTimestampInMilliseconds());
193 EXPECT_EQ(15000, BackTimestampInMilliseconds());
194 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
195 EXPECT_EQ(0, ContiguousAudioDataBufferedAtSameRateInMilliseconds());
198 TEST_F(AudioClockTest
, AlternatingAudioAndSilence
) {
199 // Buffer #1: [0, 1000)
200 WroteAudio(10, 10, 20, 1.0);
201 EXPECT_EQ(0, FrontTimestampInMilliseconds());
202 EXPECT_EQ(1000, BackTimestampInMilliseconds());
203 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
205 // Buffer #2: 1000ms of silence
206 WroteAudio(0, 10, 20, 1.0);
207 EXPECT_EQ(0, FrontTimestampInMilliseconds());
208 EXPECT_EQ(1000, BackTimestampInMilliseconds());
209 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
211 // Buffer #3: [1000, 2000):
212 // - Buffer #1 is at front with 1000ms of contiguous audio data
213 WroteAudio(10, 10, 20, 1.0);
214 EXPECT_EQ(0, FrontTimestampInMilliseconds());
215 EXPECT_EQ(2000, BackTimestampInMilliseconds());
216 EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
218 // Buffer #4: 1000ms of silence
219 // - Buffer #1 has been played out
220 // - Buffer #2 of silence leaves us with 0ms of contiguous audio data
221 WroteAudio(0, 10, 20, 1.0);
222 EXPECT_EQ(1000, FrontTimestampInMilliseconds());
223 EXPECT_EQ(2000, BackTimestampInMilliseconds());
224 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
226 // Buffer #5: [2000, 3000):
227 // - Buffer #3 is at front with 1000ms of contiguous audio data
228 WroteAudio(10, 10, 20, 1.0);
229 EXPECT_EQ(1000, FrontTimestampInMilliseconds());
230 EXPECT_EQ(3000, BackTimestampInMilliseconds());
231 EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
234 TEST_F(AudioClockTest
, ZeroDelay
) {
235 // The first time we write data we should expect the first timestamp
237 WroteAudio(10, 10, 0, 1.0);
238 EXPECT_EQ(0, FrontTimestampInMilliseconds());
239 EXPECT_EQ(1000, BackTimestampInMilliseconds());
240 EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
242 // Ditto for all subsequent buffers.
243 WroteAudio(10, 10, 0, 1.0);
244 EXPECT_EQ(1000, FrontTimestampInMilliseconds());
245 EXPECT_EQ(2000, BackTimestampInMilliseconds());
246 EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
248 WroteAudio(10, 10, 0, 1.0);
249 EXPECT_EQ(2000, FrontTimestampInMilliseconds());
250 EXPECT_EQ(3000, BackTimestampInMilliseconds());
251 EXPECT_EQ(1000, ContiguousAudioDataBufferedInMilliseconds());
253 // Ditto for silence.
254 WroteAudio(0, 10, 0, 1.0);
255 EXPECT_EQ(3000, FrontTimestampInMilliseconds());
256 EXPECT_EQ(3000, BackTimestampInMilliseconds());
257 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
259 WroteAudio(0, 10, 0, 1.0);
260 EXPECT_EQ(3000, FrontTimestampInMilliseconds());
261 EXPECT_EQ(3000, BackTimestampInMilliseconds());
262 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
265 TEST_F(AudioClockTest
, TimeUntilPlayback
) {
266 // Construct an audio clock with the following representation:
269 // |- delay -|------------------ calls to WroteAudio() ------------------|
270 // +------------+---------+------------+-----------+------------+-----------+
271 // | 20 silence | 10 @ 1x | 10 silence | 10 @ 0.5x | 10 silence | 10 @ 2.0x |
272 // +------------+---------+------------+-----------+------------+-----------+
273 // Media: 0 1000 1000 1500 1500 3500
274 // Wall: 2000 3000 4000 5000 6000 7000
275 WroteAudio(10, 10, 60, 1.0);
276 WroteAudio(0, 10, 60, 1.0);
277 WroteAudio(10, 10, 60, 0.5);
278 WroteAudio(0, 10, 60, 0.5);
279 WroteAudio(10, 10, 60, 2.0);
280 EXPECT_EQ(0, FrontTimestampInMilliseconds());
281 EXPECT_EQ(3500, BackTimestampInMilliseconds());
282 EXPECT_EQ(0, ContiguousAudioDataBufferedInMilliseconds());
284 // Media timestamp zero has to wait for silence to pass.
285 EXPECT_EQ(2000, TimeUntilPlaybackInMilliseconds(0));
287 // From then on out it's simply adding up the number of frames and taking
288 // silence into account.
289 EXPECT_EQ(2500, TimeUntilPlaybackInMilliseconds(500));
290 EXPECT_EQ(3000, TimeUntilPlaybackInMilliseconds(1000));
291 EXPECT_EQ(4500, TimeUntilPlaybackInMilliseconds(1250));
292 EXPECT_EQ(5000, TimeUntilPlaybackInMilliseconds(1500));
293 EXPECT_EQ(6500, TimeUntilPlaybackInMilliseconds(2500));
294 EXPECT_EQ(7000, TimeUntilPlaybackInMilliseconds(3500));
297 TEST_F(AudioClockTest
, SupportsYearsWorthOfAudioData
) {
298 // Use number of frames that would be likely to overflow 32-bit integer math.
299 const int huge_amount_of_frames
= std::numeric_limits
<int>::max();
300 const base::TimeDelta huge
=
301 base::TimeDelta::FromSeconds(huge_amount_of_frames
/ sample_rate_
);
302 EXPECT_EQ(2485, huge
.InDays()); // Just to give some context on how big...
304 // Use zero delay to test calculation of current timestamp.
305 WroteAudio(huge_amount_of_frames
, huge_amount_of_frames
, 0, 1.0);
306 EXPECT_EQ(0, FrontTimestampInDays());
307 EXPECT_EQ(2485, ContiguousAudioDataBufferedInDays());
309 WroteAudio(huge_amount_of_frames
, huge_amount_of_frames
, 0, 1.0);
310 EXPECT_EQ(huge
.InDays(), FrontTimestampInDays());
311 EXPECT_EQ(huge
.InDays(), ContiguousAudioDataBufferedInDays());
313 WroteAudio(huge_amount_of_frames
, huge_amount_of_frames
, 0, 1.0);
314 EXPECT_EQ((huge
* 2).InDays(), FrontTimestampInDays());
315 EXPECT_EQ(huge
.InDays(), ContiguousAudioDataBufferedInDays());
317 WroteAudio(huge_amount_of_frames
, huge_amount_of_frames
, 0, 1.0);
318 EXPECT_EQ((huge
* 3).InDays(), FrontTimestampInDays());
319 EXPECT_EQ(huge
.InDays(), ContiguousAudioDataBufferedInDays());
321 // Use huge delay to test calculation of buffered data.
323 huge_amount_of_frames
, huge_amount_of_frames
, huge_amount_of_frames
, 1.0);
324 EXPECT_EQ((huge
* 3).InDays(), FrontTimestampInDays());
325 EXPECT_EQ((huge
* 2).InDays(), ContiguousAudioDataBufferedInDays());
328 TEST_F(AudioClockTest
, CompensateForSuspendedWrites
) {
329 // Buffer 6 seconds of delay and 1 second of audio data.
330 WroteAudio(10, 10, 60, 1.0);
332 // Media timestamp zero has to wait for silence to pass.
333 const int kBaseTimeMs
= 6000;
334 EXPECT_EQ(kBaseTimeMs
, TimeUntilPlaybackInMilliseconds(0));
336 // Elapsing frames less than we have buffered should do nothing.
337 const int kDelayFrames
= 2;
338 for (int i
= 1000; i
<= kBaseTimeMs
; i
+= 1000) {
339 clock_
.CompensateForSuspendedWrites(base::TimeDelta::FromMilliseconds(i
),
341 EXPECT_EQ(kBaseTimeMs
- (i
- 1000), TimeUntilPlaybackInMilliseconds(0));
343 // Write silence to simulate maintaining a 7s output buffer.
344 WroteAudio(0, 10, 60, 1.0);
347 // Exhausting all frames should advance timestamps and prime the buffer with
348 // our delay frames value.
349 clock_
.CompensateForSuspendedWrites(base::TimeDelta::FromMilliseconds(7000),
351 EXPECT_EQ(kDelayFrames
* 100, TimeUntilPlaybackInMilliseconds(1000));