Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / base / audio_discard_helper_unittest.cc
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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);
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.
329   ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
330   ASSERT_TRUE(discard_helper.initialized());
331
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),
339               kDataStep * 1000);
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());
344
345   // Verify it was actually the latter half of the buffer that was removed.
346   ASSERT_FLOAT_EQ(0.0f, ExtractDecodedData(decoded_buffer, 0));
347 }
348
349 TEST(AudioDiscardHelperTest, DelayedDiscardInitialDiscardAndDiscardPadding) {
350   AudioDiscardHelper discard_helper(kSampleRate, 0);
351   ASSERT_FALSE(discard_helper.initialized());
352
353   const base::TimeDelta kTimestamp = base::TimeDelta();
354   const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
355   const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
356
357   scoped_refptr<DecoderBuffer> encoded_buffer =
358       CreateEncodedBuffer(kTimestamp, kDuration);
359
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);
365
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());
369
370   // Create an encoded buffer with no discard padding.
371   encoded_buffer = CreateEncodedBuffer(kTimestamp + kDuration, kDuration);
372   scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
373
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());
382 }
383
384 }  // namespace media