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 "base/memory/scoped_ptr.h"
6 #include "media/base/audio_buffer.h"
7 #include "media/base/audio_bus.h"
8 #include "media/base/audio_discard_helper.h"
9 #include "media/base/buffers.h"
10 #include "media/base/decoder_buffer.h"
11 #include "media/base/test_helpers.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 static const float kDataStep
= 0.01f
;
17 static const size_t kSampleRate
= 48000;
19 static scoped_refptr
<DecoderBuffer
> CreateEncodedBuffer(
20 base::TimeDelta timestamp
,
21 base::TimeDelta duration
) {
22 scoped_refptr
<DecoderBuffer
> result(new DecoderBuffer(1));
23 result
->set_timestamp(timestamp
);
24 result
->set_duration(duration
);
28 static scoped_refptr
<AudioBuffer
> CreateDecodedBuffer(int frames
) {
29 return MakeAudioBuffer(kSampleFormatPlanarF32
,
39 static float ExtractDecodedData(const scoped_refptr
<AudioBuffer
>& buffer
,
41 // This is really inefficient, but we can't access the raw AudioBuffer if any
42 // start trimming has been applied.
43 scoped_ptr
<AudioBus
> temp_bus
= AudioBus::Create(buffer
->channel_count(), 1);
44 buffer
->ReadFrames(1, index
, 0, temp_bus
.get());
45 return temp_bus
->channel(0)[0];
48 TEST(AudioDiscardHelperTest
, TimeDeltaToFrames
) {
49 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
51 EXPECT_EQ(0u, discard_helper
.TimeDeltaToFrames(base::TimeDelta()));
54 discard_helper
.TimeDeltaToFrames(base::TimeDelta::FromMilliseconds(10)));
56 // Ensure partial frames are rounded down correctly. The equation below
57 // calculates a frame count with a fractional part < 0.5.
58 const int small_remainder
=
59 base::Time::kMicrosecondsPerSecond
* (kSampleRate
- 0.9) / kSampleRate
;
60 EXPECT_EQ(kSampleRate
- 1,
61 discard_helper
.TimeDeltaToFrames(
62 base::TimeDelta::FromMicroseconds(small_remainder
)));
64 // Ditto, but rounded up using a fractional part > 0.5.
65 const int large_remainder
=
66 base::Time::kMicrosecondsPerSecond
* (kSampleRate
- 0.4) / kSampleRate
;
67 EXPECT_EQ(kSampleRate
,
68 discard_helper
.TimeDeltaToFrames(
69 base::TimeDelta::FromMicroseconds(large_remainder
)));
72 TEST(AudioDiscardHelperTest
, BasicProcessBuffers
) {
73 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
74 ASSERT_FALSE(discard_helper
.initialized());
76 const base::TimeDelta kTimestamp
= base::TimeDelta();
78 // Use an estimated duration which doesn't match the number of decoded frames
79 // to ensure the helper is correctly setting durations based on output frames.
80 const base::TimeDelta kEstimatedDuration
=
81 base::TimeDelta::FromMilliseconds(9);
82 const base::TimeDelta kActualDuration
= base::TimeDelta::FromMilliseconds(10);
83 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kActualDuration
);
85 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
86 CreateEncodedBuffer(kTimestamp
, kEstimatedDuration
);
87 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
89 // Verify the basic case where nothing is discarded.
90 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
91 ASSERT_TRUE(discard_helper
.initialized());
92 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
93 EXPECT_EQ(kActualDuration
, decoded_buffer
->duration());
94 EXPECT_EQ(kTestFrames
, decoded_buffer
->frame_count());
96 // Verify a Reset() takes us back to an uninitialized state.
97 discard_helper
.Reset(0);
98 ASSERT_FALSE(discard_helper
.initialized());
100 // Verify a NULL output buffer returns false.
101 ASSERT_FALSE(discard_helper
.ProcessBuffers(encoded_buffer
, NULL
));
104 TEST(AudioDiscardHelperTest
, NegativeTimestampClampsToZero
) {
105 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
106 ASSERT_FALSE(discard_helper
.initialized());
108 const base::TimeDelta kTimestamp
= -base::TimeDelta::FromSeconds(1);
109 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
110 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
112 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
113 CreateEncodedBuffer(kTimestamp
, kDuration
);
114 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
116 // Verify the basic case where nothing is discarded.
117 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
118 ASSERT_TRUE(discard_helper
.initialized());
119 EXPECT_EQ(base::TimeDelta(), decoded_buffer
->timestamp());
120 EXPECT_EQ(kDuration
, decoded_buffer
->duration());
121 EXPECT_EQ(kTestFrames
, decoded_buffer
->frame_count());
124 TEST(AudioDiscardHelperTest
, ProcessBuffersWithInitialDiscard
) {
125 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
126 ASSERT_FALSE(discard_helper
.initialized());
128 const base::TimeDelta kTimestamp
= base::TimeDelta();
129 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
130 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
132 // Tell the helper we want to discard half of the initial frames.
133 const int kDiscardFrames
= kTestFrames
/ 2;
134 discard_helper
.Reset(kDiscardFrames
);
136 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
137 CreateEncodedBuffer(kTimestamp
, kDuration
);
138 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
140 // Verify half the frames end up discarded.
141 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
142 ASSERT_TRUE(discard_helper
.initialized());
143 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
144 EXPECT_EQ(kDuration
/ 2, decoded_buffer
->duration());
145 EXPECT_EQ(kDiscardFrames
, decoded_buffer
->frame_count());
146 ASSERT_FLOAT_EQ(kDiscardFrames
* kDataStep
,
147 ExtractDecodedData(decoded_buffer
, 0));
150 TEST(AudioDiscardHelperTest
, ProcessBuffersWithLargeInitialDiscard
) {
151 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
152 ASSERT_FALSE(discard_helper
.initialized());
154 const base::TimeDelta kTimestamp
= base::TimeDelta();
155 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
156 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
158 // Tell the helper we want to discard 1.5 buffers worth of frames.
159 discard_helper
.Reset(kTestFrames
* 1.5);
161 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
162 CreateEncodedBuffer(kTimestamp
, kDuration
);
163 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
165 // The first call should fail since no output buffer remains.
166 ASSERT_FALSE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
167 ASSERT_TRUE(discard_helper
.initialized());
169 // Generate another set of buffers and expect half the output frames.
170 encoded_buffer
= CreateEncodedBuffer(kTimestamp
+ kDuration
, kDuration
);
171 decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
172 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
174 // The timestamp should match that of the initial buffer.
175 const int kDiscardFrames
= kTestFrames
/ 2;
176 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
177 EXPECT_EQ(kDuration
/ 2, decoded_buffer
->duration());
178 EXPECT_EQ(kDiscardFrames
, decoded_buffer
->frame_count());
179 ASSERT_FLOAT_EQ(kDiscardFrames
* kDataStep
,
180 ExtractDecodedData(decoded_buffer
, 0));
183 TEST(AudioDiscardHelperTest
, AllowNonMonotonicTimestamps
) {
184 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
185 ASSERT_FALSE(discard_helper
.initialized());
187 const base::TimeDelta kTimestamp
= base::TimeDelta();
188 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
189 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
191 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
192 CreateEncodedBuffer(kTimestamp
, kDuration
);
193 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
195 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
196 ASSERT_TRUE(discard_helper
.initialized());
197 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
198 EXPECT_EQ(kDuration
, decoded_buffer
->duration());
199 EXPECT_EQ(kTestFrames
, decoded_buffer
->frame_count());
201 // Process the same input buffer again to ensure input timestamps which go
202 // backwards in time are not errors.
203 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
204 EXPECT_EQ(kTimestamp
+ kDuration
, decoded_buffer
->timestamp());
205 EXPECT_EQ(kDuration
, decoded_buffer
->duration());
206 EXPECT_EQ(kTestFrames
, decoded_buffer
->frame_count());
209 TEST(AudioDiscardHelperTest
, DiscardEndPadding
) {
210 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
211 ASSERT_FALSE(discard_helper
.initialized());
213 const base::TimeDelta kTimestamp
= base::TimeDelta();
214 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
215 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
217 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
218 CreateEncodedBuffer(kTimestamp
, kDuration
);
219 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
221 // Set a discard padding equivalent to half the buffer.
222 encoded_buffer
->set_discard_padding(
223 std::make_pair(base::TimeDelta(), kDuration
/ 2));
225 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
226 ASSERT_TRUE(discard_helper
.initialized());
227 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
228 EXPECT_EQ(kDuration
/ 2, decoded_buffer
->duration());
229 EXPECT_EQ(kTestFrames
/ 2, decoded_buffer
->frame_count());
232 TEST(AudioDiscardHelperTest
, BadDiscardEndPadding
) {
233 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
234 ASSERT_FALSE(discard_helper
.initialized());
236 const base::TimeDelta kTimestamp
= base::TimeDelta();
237 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
238 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
240 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
241 CreateEncodedBuffer(kTimestamp
, kDuration
);
242 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
244 // Set a discard padding equivalent to double the buffer size.
245 encoded_buffer
->set_discard_padding(
246 std::make_pair(base::TimeDelta(), kDuration
* 2));
248 // Verify the end discard padding is rejected.
249 ASSERT_FALSE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
250 ASSERT_TRUE(discard_helper
.initialized());
253 TEST(AudioDiscardHelperTest
, InitialDiscardAndDiscardEndPadding
) {
254 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
255 ASSERT_FALSE(discard_helper
.initialized());
257 const base::TimeDelta kTimestamp
= base::TimeDelta();
258 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
259 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
261 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
262 CreateEncodedBuffer(kTimestamp
, kDuration
);
263 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
265 // Set a discard padding equivalent to a quarter of the buffer.
266 encoded_buffer
->set_discard_padding(
267 std::make_pair(base::TimeDelta(), kDuration
/ 4));
269 // Set an initial discard of a quarter of the buffer.
270 const int kDiscardFrames
= kTestFrames
/ 4;
271 discard_helper
.Reset(kDiscardFrames
);
273 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
274 ASSERT_TRUE(discard_helper
.initialized());
275 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
276 EXPECT_EQ(kDuration
/ 2, decoded_buffer
->duration());
277 EXPECT_EQ(kTestFrames
/ 2, decoded_buffer
->frame_count());
278 ASSERT_FLOAT_EQ(kDiscardFrames
* kDataStep
,
279 ExtractDecodedData(decoded_buffer
, 0));
282 TEST(AudioDiscardHelperTest
, InitialDiscardAndDiscardPadding
) {
283 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
284 ASSERT_FALSE(discard_helper
.initialized());
286 const base::TimeDelta kTimestamp
= base::TimeDelta();
287 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
288 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
290 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
291 CreateEncodedBuffer(kTimestamp
, kDuration
);
292 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
294 // Set all the discard values to be different to ensure each is properly used.
295 const int kDiscardFrames
= kTestFrames
/ 4;
296 encoded_buffer
->set_discard_padding(
297 std::make_pair(kDuration
/ 8, kDuration
/ 16));
298 discard_helper
.Reset(kDiscardFrames
);
300 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
301 ASSERT_TRUE(discard_helper
.initialized());
302 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
303 EXPECT_EQ(kDuration
- kDuration
/ 4 - kDuration
/ 8 - kDuration
/ 16,
304 decoded_buffer
->duration());
305 EXPECT_EQ(kTestFrames
- kTestFrames
/ 4 - kTestFrames
/ 8 - kTestFrames
/ 16,
306 decoded_buffer
->frame_count());
309 TEST(AudioDiscardHelperTest
, InitialDiscardAndDiscardPaddingAndCodecDelay
) {
310 // Use a codec delay of 5ms.
311 const int kCodecDelay
= kSampleRate
/ 100 / 2;
312 AudioDiscardHelper
discard_helper(kSampleRate
, kCodecDelay
);
313 ASSERT_FALSE(discard_helper
.initialized());
314 discard_helper
.Reset(kCodecDelay
);
316 const base::TimeDelta kTimestamp
= base::TimeDelta();
317 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
318 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
320 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
321 CreateEncodedBuffer(kTimestamp
, kDuration
);
322 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
324 // Set a discard padding equivalent to half of the buffer.
325 encoded_buffer
->set_discard_padding(
326 std::make_pair(kDuration
/ 2, base::TimeDelta()));
328 // All of the first buffer should be discarded.
329 ASSERT_FALSE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
330 ASSERT_TRUE(discard_helper
.initialized());
332 // Processing another buffer (with the same discard padding) should discard
333 // the back half of the buffer since kCodecDelay is half a buffer.
334 encoded_buffer
->set_timestamp(kTimestamp
+ kDuration
);
335 decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
336 ASSERT_FLOAT_EQ(0.0f
, ExtractDecodedData(decoded_buffer
, 0));
337 ASSERT_NEAR(kCodecDelay
* kDataStep
,
338 ExtractDecodedData(decoded_buffer
, kCodecDelay
),
340 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
341 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
342 EXPECT_EQ(kDuration
/ 2, decoded_buffer
->duration());
343 EXPECT_EQ(kTestFrames
/ 2, decoded_buffer
->frame_count());
345 // Verify it was actually the latter half of the buffer that was removed.
346 ASSERT_FLOAT_EQ(0.0f
, ExtractDecodedData(decoded_buffer
, 0));
349 TEST(AudioDiscardHelperTest
, DelayedDiscardInitialDiscardAndDiscardPadding
) {
350 AudioDiscardHelper
discard_helper(kSampleRate
, 0);
351 ASSERT_FALSE(discard_helper
.initialized());
353 const base::TimeDelta kTimestamp
= base::TimeDelta();
354 const base::TimeDelta kDuration
= base::TimeDelta::FromMilliseconds(10);
355 const int kTestFrames
= discard_helper
.TimeDeltaToFrames(kDuration
);
357 scoped_refptr
<DecoderBuffer
> encoded_buffer
=
358 CreateEncodedBuffer(kTimestamp
, kDuration
);
360 // Set all the discard values to be different to ensure each is properly used.
361 const int kDiscardFrames
= kTestFrames
/ 4;
362 encoded_buffer
->set_discard_padding(
363 std::make_pair(kDuration
/ 8, kDuration
/ 16));
364 discard_helper
.Reset(kDiscardFrames
);
366 // Verify nothing is output for the first buffer, yet initialized is true.
367 ASSERT_FALSE(discard_helper
.ProcessBuffers(encoded_buffer
, NULL
));
368 ASSERT_TRUE(discard_helper
.initialized());
370 // Create an encoded buffer with no discard padding.
371 encoded_buffer
= CreateEncodedBuffer(kTimestamp
+ kDuration
, kDuration
);
372 scoped_refptr
<AudioBuffer
> decoded_buffer
= CreateDecodedBuffer(kTestFrames
);
374 // Verify that when the decoded buffer is consumed, the discards from the
375 // previous encoded buffer are applied.
376 ASSERT_TRUE(discard_helper
.ProcessBuffers(encoded_buffer
, decoded_buffer
));
377 EXPECT_EQ(kTimestamp
, decoded_buffer
->timestamp());
378 EXPECT_EQ(kDuration
- kDuration
/ 4 - kDuration
/ 8 - kDuration
/ 16,
379 decoded_buffer
->duration());
380 EXPECT_EQ(kTestFrames
- kTestFrames
/ 4 - kTestFrames
/ 8 - kTestFrames
/ 16,
381 decoded_buffer
->frame_count());