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
14namespace media {
15
16static const float kDataStep = 0.01f;
17static const size_t kSampleRate = 48000;
18
19static 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
28static 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
39static 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
48TEST(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
72TEST(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
104TEST(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
124TEST(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
150TEST(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
183TEST(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
209TEST(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
232TEST(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
253TEST(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
282TEST(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
309TEST(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
419TEST(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
454TEST(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
484TEST(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
518TEST(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