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 "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"
13
14 namespace media {
15
16 static const float kDataStep = 0.01f;
17 static const size_t kSampleRate = 48000;
18
CreateEncodedBuffer(base::TimeDelta timestamp,base::TimeDelta duration)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);
25 return result;
26 }
27
CreateDecodedBuffer(int frames)28 static scoped_refptr<AudioBuffer> CreateDecodedBuffer(int frames) {
29 return MakeAudioBuffer(kSampleFormatPlanarF32,
30 CHANNEL_LAYOUT_MONO,
31 1,
32 kSampleRate,
33 0.0f,
34 kDataStep,
35 frames,
36 kNoTimestamp());
37 }
38
ExtractDecodedData(const scoped_refptr<AudioBuffer> & buffer,int index)39 static float ExtractDecodedData(const scoped_refptr<AudioBuffer>& buffer,
40 int index) {
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];
46 }
47
TEST(AudioDiscardHelperTest,TimeDeltaToFrames)48 TEST(AudioDiscardHelperTest, TimeDeltaToFrames) {
49 AudioDiscardHelper discard_helper(kSampleRate, 0);
50
51 EXPECT_EQ(0u, discard_helper.TimeDeltaToFrames(base::TimeDelta()));
52 EXPECT_EQ(
53 kSampleRate / 100,
54 discard_helper.TimeDeltaToFrames(base::TimeDelta::FromMilliseconds(10)));
55
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)));
63
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)));
70 }
71
TEST(AudioDiscardHelperTest,BasicProcessBuffers)72 TEST(AudioDiscardHelperTest, BasicProcessBuffers) {
73 AudioDiscardHelper discard_helper(kSampleRate, 0);
74 ASSERT_FALSE(discard_helper.initialized());
75
76 const base::TimeDelta kTimestamp = base::TimeDelta();
77
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);
84
85 scoped_refptr<DecoderBuffer> encoded_buffer =
86 CreateEncodedBuffer(kTimestamp, kEstimatedDuration);
87 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
88
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());
95
96 // Verify a Reset() takes us back to an uninitialized state.
97 discard_helper.Reset(0);
98 ASSERT_FALSE(discard_helper.initialized());
99
100 // Verify a NULL output buffer returns false.
101 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL));
102 }
103
TEST(AudioDiscardHelperTest,NegativeTimestampClampsToZero)104 TEST(AudioDiscardHelperTest, NegativeTimestampClampsToZero) {
105 AudioDiscardHelper discard_helper(kSampleRate, 0);
106 ASSERT_FALSE(discard_helper.initialized());
107
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);
111
112 scoped_refptr<DecoderBuffer> encoded_buffer =
113 CreateEncodedBuffer(kTimestamp, kDuration);
114 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
115
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());
122 }
123
TEST(AudioDiscardHelperTest,ProcessBuffersWithInitialDiscard)124 TEST(AudioDiscardHelperTest, ProcessBuffersWithInitialDiscard) {
125 AudioDiscardHelper discard_helper(kSampleRate, 0);
126 ASSERT_FALSE(discard_helper.initialized());
127
128 const base::TimeDelta kTimestamp = base::TimeDelta();
129 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
130 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
131
132 // Tell the helper we want to discard half of the initial frames.
133 const int kDiscardFrames = kTestFrames / 2;
134 discard_helper.Reset(kDiscardFrames);
135
136 scoped_refptr<DecoderBuffer> encoded_buffer =
137 CreateEncodedBuffer(kTimestamp, kDuration);
138 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
139
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));
148 }
149
TEST(AudioDiscardHelperTest,ProcessBuffersWithLargeInitialDiscard)150 TEST(AudioDiscardHelperTest, ProcessBuffersWithLargeInitialDiscard) {
151 AudioDiscardHelper discard_helper(kSampleRate, 0);
152 ASSERT_FALSE(discard_helper.initialized());
153
154 const base::TimeDelta kTimestamp = base::TimeDelta();
155 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
156 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
157
158 // Tell the helper we want to discard 1.5 buffers worth of frames.
159 discard_helper.Reset(kTestFrames * 1.5);
160
161 scoped_refptr<DecoderBuffer> encoded_buffer =
162 CreateEncodedBuffer(kTimestamp, kDuration);
163 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
164
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());
168
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));
173
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));
181 }
182
TEST(AudioDiscardHelperTest,AllowNonMonotonicTimestamps)183 TEST(AudioDiscardHelperTest, AllowNonMonotonicTimestamps) {
184 AudioDiscardHelper discard_helper(kSampleRate, 0);
185 ASSERT_FALSE(discard_helper.initialized());
186
187 const base::TimeDelta kTimestamp = base::TimeDelta();
188 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
189 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
190
191 scoped_refptr<DecoderBuffer> encoded_buffer =
192 CreateEncodedBuffer(kTimestamp, kDuration);
193 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
194
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());
200
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());
207 }
208
TEST(AudioDiscardHelperTest,DiscardEndPadding)209 TEST(AudioDiscardHelperTest, DiscardEndPadding) {
210 AudioDiscardHelper discard_helper(kSampleRate, 0);
211 ASSERT_FALSE(discard_helper.initialized());
212
213 const base::TimeDelta kTimestamp = base::TimeDelta();
214 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
215 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
216
217 scoped_refptr<DecoderBuffer> encoded_buffer =
218 CreateEncodedBuffer(kTimestamp, kDuration);
219 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
220
221 // Set a discard padding equivalent to half the buffer.
222 encoded_buffer->set_discard_padding(
223 std::make_pair(base::TimeDelta(), kDuration / 2));
224
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());
230 }
231
TEST(AudioDiscardHelperTest,BadDiscardEndPadding)232 TEST(AudioDiscardHelperTest, BadDiscardEndPadding) {
233 AudioDiscardHelper discard_helper(kSampleRate, 0);
234 ASSERT_FALSE(discard_helper.initialized());
235
236 const base::TimeDelta kTimestamp = base::TimeDelta();
237 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
238 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
239
240 scoped_refptr<DecoderBuffer> encoded_buffer =
241 CreateEncodedBuffer(kTimestamp, kDuration);
242 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
243
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));
247
248 // Verify the end discard padding is rejected.
249 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
250 ASSERT_TRUE(discard_helper.initialized());
251 }
252
TEST(AudioDiscardHelperTest,InitialDiscardAndDiscardEndPadding)253 TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardEndPadding) {
254 AudioDiscardHelper discard_helper(kSampleRate, 0);
255 ASSERT_FALSE(discard_helper.initialized());
256
257 const base::TimeDelta kTimestamp = base::TimeDelta();
258 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
259 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
260
261 scoped_refptr<DecoderBuffer> encoded_buffer =
262 CreateEncodedBuffer(kTimestamp, kDuration);
263 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
264
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));
268
269 // Set an initial discard of a quarter of the buffer.
270 const int kDiscardFrames = kTestFrames / 4;
271 discard_helper.Reset(kDiscardFrames);
272
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));
280 }
281
TEST(AudioDiscardHelperTest,InitialDiscardAndDiscardPadding)282 TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardPadding) {
283 AudioDiscardHelper discard_helper(kSampleRate, 0);
284 ASSERT_FALSE(discard_helper.initialized());
285
286 const base::TimeDelta kTimestamp = base::TimeDelta();
287 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
288 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
289
290 scoped_refptr<DecoderBuffer> encoded_buffer =
291 CreateEncodedBuffer(kTimestamp, kDuration);
292 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
293
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);
299
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());
307 }
308
TEST(AudioDiscardHelperTest,InitialDiscardAndDiscardPaddingAndDecoderDelay)309 TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardPaddingAndDecoderDelay) {
310 // Use a decoder delay of 5ms.
311 const int kDecoderDelay = kSampleRate / 100 / 2;
312 AudioDiscardHelper discard_helper(kSampleRate, kDecoderDelay);
313 ASSERT_FALSE(discard_helper.initialized());
314 discard_helper.Reset(kDecoderDelay);
315
316 const base::TimeDelta kTimestamp = base::TimeDelta();
317 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
318 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
319
320 scoped_refptr<DecoderBuffer> encoded_buffer =
321 CreateEncodedBuffer(kTimestamp, kDuration);
322 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
323
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()));
327
328 // All of the first buffer should be discarded, half from the inital delay and
329 // another half from the front discard padding.
330 //
331 // Encoded Discard Delay
332 // |--------| |---------| |----|
333 // |AAAAAAAA| --> |....|AAAA| --> |AAAA| -------> NULL
334 // |--------| |---------| |----|
335 // Decoded Discard Front Padding
336 //
337 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
338 ASSERT_TRUE(discard_helper.initialized());
339
340 // Processing another buffer that has front discard set to half the buffer's
341 // duration should discard the back half of the buffer since kDecoderDelay is
342 // half a buffer. The end padding should not be discarded until another
343 // buffer is processed. kDuration / 4 is chosen for the end discard since it
344 // will force the end discard to start after position zero within the next
345 // decoded buffer.
346 //
347 // Encoded Discard Front Padding (from B)
348 // |--------| |---------| |----|
349 // |BBBBBBBB| --> |AAAA|BBBB| ----------> |AAAA|
350 // |--------| |---------| |----|
351 // Decoded
352 // (includes carryover from A)
353 //
354 encoded_buffer->set_timestamp(encoded_buffer->timestamp() + kDuration);
355 encoded_buffer->set_discard_padding(
356 std::make_pair(kDuration / 2, kDuration / 4));
357 decoded_buffer = CreateDecodedBuffer(kTestFrames);
358 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
359 ASSERT_NEAR(kDecoderDelay * kDataStep,
360 ExtractDecodedData(decoded_buffer, kDecoderDelay),
361 kDataStep / 1000);
362 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
363 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
364 EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
365 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
366
367 // Verify it was actually the latter half of the buffer that was removed.
368 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
369
370 // Verify the end discard padding is carried over to the next buffer. Use
371 // kDuration / 2 for the end discard padding so that the next buffer has its
372 // start entirely discarded.
373 //
374 // Encoded Discard End Padding (from B)
375 // |--------| |---------| |-------|
376 // |CCCCCCCC| --> |BBBB|CCCC| ----------> |BB|CCCC|
377 // |--------| |---------| |-------|
378 // Decoded
379 // (includes carryover from B)
380 //
381 encoded_buffer->set_timestamp(encoded_buffer->timestamp() + kDuration);
382 encoded_buffer->set_discard_padding(
383 std::make_pair(base::TimeDelta(), kDuration / 2));
384 decoded_buffer = CreateDecodedBuffer(kTestFrames);
385 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
386 EXPECT_EQ(kTimestamp + kDuration / 2, decoded_buffer->timestamp());
387 EXPECT_EQ(3 * kDuration / 4, decoded_buffer->duration());
388 EXPECT_EQ(3 * kTestFrames / 4, decoded_buffer->frame_count());
389
390 // Verify it was actually the second quarter of the buffer that was removed.
391 const int kDiscardFrames = kTestFrames / 4;
392 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
393 ASSERT_FLOAT_EQ(
394 kDiscardFrames * 2 * kDataStep,
395 ExtractDecodedData(decoded_buffer, kDecoderDelay - kDiscardFrames));
396
397 // One last test to ensure carryover discard from the start works.
398 //
399 // Encoded Discard End Padding (from C)
400 // |--------| |---------| |----|
401 // |DDDDDDDD| --> |CCCC|DDDD| ----------> |DDDD|
402 // |--------| |---------| |----|
403 // Decoded
404 // (includes carryover from C)
405 //
406 encoded_buffer->set_timestamp(encoded_buffer->timestamp() + kDuration);
407 encoded_buffer->set_discard_padding(DecoderBuffer::DiscardPadding());
408 decoded_buffer = CreateDecodedBuffer(kTestFrames);
409 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
410 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
411 EXPECT_EQ(kTimestamp + kDuration / 2 + 3 * kDuration / 4,
412 decoded_buffer->timestamp());
413 EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
414 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
415 ASSERT_FLOAT_EQ(kTestFrames / 2 * kDataStep,
416 ExtractDecodedData(decoded_buffer, 0));
417 }
418
TEST(AudioDiscardHelperTest,DelayedDiscardInitialDiscardAndDiscardPadding)419 TEST(AudioDiscardHelperTest, DelayedDiscardInitialDiscardAndDiscardPadding) {
420 AudioDiscardHelper discard_helper(kSampleRate, 0);
421 ASSERT_FALSE(discard_helper.initialized());
422
423 const base::TimeDelta kTimestamp = base::TimeDelta();
424 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
425 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
426
427 scoped_refptr<DecoderBuffer> encoded_buffer =
428 CreateEncodedBuffer(kTimestamp, kDuration);
429
430 // Set all the discard values to be different to ensure each is properly used.
431 const int kDiscardFrames = kTestFrames / 4;
432 encoded_buffer->set_discard_padding(
433 std::make_pair(kDuration / 8, kDuration / 16));
434 discard_helper.Reset(kDiscardFrames);
435
436 // Verify nothing is output for the first buffer, yet initialized is true.
437 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL));
438 ASSERT_TRUE(discard_helper.initialized());
439
440 // Create an encoded buffer with no discard padding.
441 encoded_buffer = CreateEncodedBuffer(kTimestamp + kDuration, kDuration);
442 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
443
444 // Verify that when the decoded buffer is consumed, the discards from the
445 // previous encoded buffer are applied.
446 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
447 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
448 EXPECT_EQ(kDuration - kDuration / 4 - kDuration / 8 - kDuration / 16,
449 decoded_buffer->duration());
450 EXPECT_EQ(kTestFrames - kTestFrames / 4 - kTestFrames / 8 - kTestFrames / 16,
451 decoded_buffer->frame_count());
452 }
453
TEST(AudioDiscardHelperTest,CompleteDiscard)454 TEST(AudioDiscardHelperTest, CompleteDiscard) {
455 AudioDiscardHelper discard_helper(kSampleRate, 0);
456 ASSERT_FALSE(discard_helper.initialized());
457
458 const base::TimeDelta kTimestamp = base::TimeDelta();
459 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
460 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
461 discard_helper.Reset(0);
462
463 scoped_refptr<DecoderBuffer> encoded_buffer =
464 CreateEncodedBuffer(kTimestamp, kDuration);
465 encoded_buffer->set_discard_padding(
466 std::make_pair(kInfiniteDuration(), base::TimeDelta()));
467 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
468
469 // Verify all of the first buffer is discarded.
470 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
471 ASSERT_TRUE(discard_helper.initialized());
472 encoded_buffer->set_timestamp(kTimestamp + kDuration);
473 encoded_buffer->set_discard_padding(DecoderBuffer::DiscardPadding());
474
475 // Verify a second buffer goes through untouched.
476 decoded_buffer = CreateDecodedBuffer(kTestFrames / 2);
477 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
478 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
479 EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
480 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
481 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
482 }
483
TEST(AudioDiscardHelperTest,CompleteDiscardWithDelayedDiscard)484 TEST(AudioDiscardHelperTest, CompleteDiscardWithDelayedDiscard) {
485 AudioDiscardHelper discard_helper(kSampleRate, 0);
486 ASSERT_FALSE(discard_helper.initialized());
487
488 const base::TimeDelta kTimestamp = base::TimeDelta();
489 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
490 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
491 discard_helper.Reset(0);
492
493 scoped_refptr<DecoderBuffer> encoded_buffer =
494 CreateEncodedBuffer(kTimestamp, kDuration);
495 encoded_buffer->set_discard_padding(
496 std::make_pair(kInfiniteDuration(), base::TimeDelta()));
497 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
498
499 // Setup a delayed discard.
500 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL));
501 ASSERT_TRUE(discard_helper.initialized());
502
503 // Verify the first output buffer is dropped.
504 encoded_buffer->set_timestamp(kTimestamp + kDuration);
505 encoded_buffer->set_discard_padding(DecoderBuffer::DiscardPadding());
506 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
507
508 // Verify the second buffer goes through untouched.
509 encoded_buffer->set_timestamp(kTimestamp + 2 * kDuration);
510 decoded_buffer = CreateDecodedBuffer(kTestFrames / 2);
511 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
512 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
513 EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
514 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
515 ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
516 }
517
TEST(AudioDiscardHelperTest,CompleteDiscardWithInitialDiscardDecoderDelay)518 TEST(AudioDiscardHelperTest, CompleteDiscardWithInitialDiscardDecoderDelay) {
519 // Use a decoder delay of 5ms.
520 const int kDecoderDelay = kSampleRate / 100 / 2;
521 AudioDiscardHelper discard_helper(kSampleRate, kDecoderDelay);
522 ASSERT_FALSE(discard_helper.initialized());
523 discard_helper.Reset(kDecoderDelay);
524
525 const base::TimeDelta kTimestamp = base::TimeDelta();
526 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
527 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
528
529 scoped_refptr<DecoderBuffer> encoded_buffer =
530 CreateEncodedBuffer(kTimestamp, kDuration);
531 encoded_buffer->set_discard_padding(
532 std::make_pair(kInfiniteDuration(), base::TimeDelta()));
533 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
534
535 // Verify all of the first buffer is discarded.
536 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
537 ASSERT_TRUE(discard_helper.initialized());
538 encoded_buffer->set_timestamp(kTimestamp + kDuration);
539 encoded_buffer->set_discard_padding(DecoderBuffer::DiscardPadding());
540
541 // Verify 5ms off the front of the second buffer is discarded.
542 decoded_buffer = CreateDecodedBuffer(kTestFrames * 2);
543 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
544 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
545 EXPECT_EQ(kDuration * 2 - kDuration / 2, decoded_buffer->duration());
546 EXPECT_EQ(kTestFrames * 2 - kDecoderDelay, decoded_buffer->frame_count());
547 ASSERT_FLOAT_EQ(kDecoderDelay * kDataStep,
548 ExtractDecodedData(decoded_buffer, 0));
549 }
550
551 } // namespace media
552