• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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