1 // Copyright (c) 2012 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_splicer.h"
9 #include "media/base/audio_timestamp_helper.h"
10 #include "media/base/buffers.h"
11 #include "media/base/test_helpers.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace media {
15
16 // Do not change this format. AddInput() and GetValue() only work with float.
17 static const SampleFormat kSampleFormat = kSampleFormatF32;
18 COMPILE_ASSERT(kSampleFormat == kSampleFormatF32, invalid_splice_format);
19
20 static const int kChannels = 1;
21 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO;
22 static const int kDefaultSampleRate = 44100;
23 static const int kDefaultBufferSize = 100;
24
25 class AudioSplicerTest : public ::testing::Test {
26 public:
AudioSplicerTest()27 AudioSplicerTest()
28 : splicer_(kDefaultSampleRate),
29 input_timestamp_helper_(kDefaultSampleRate) {
30 input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
31 }
32
GetNextInputBuffer(float value)33 scoped_refptr<AudioBuffer> GetNextInputBuffer(float value) {
34 return GetNextInputBuffer(value, kDefaultBufferSize);
35 }
36
GetNextInputBuffer(float value,int frame_size)37 scoped_refptr<AudioBuffer> GetNextInputBuffer(float value, int frame_size) {
38 scoped_refptr<AudioBuffer> buffer =
39 MakeAudioBuffer<float>(kSampleFormat,
40 kChannelLayout,
41 kChannels,
42 kDefaultSampleRate,
43 value,
44 0.0f,
45 frame_size,
46 input_timestamp_helper_.GetTimestamp());
47 input_timestamp_helper_.AddFrames(frame_size);
48 return buffer;
49 }
50
GetValue(const scoped_refptr<AudioBuffer> & buffer)51 float GetValue(const scoped_refptr<AudioBuffer>& buffer) {
52 return reinterpret_cast<const float*>(buffer->channel_data()[0])[0];
53 }
54
VerifyData(const scoped_refptr<AudioBuffer> & buffer,float value)55 bool VerifyData(const scoped_refptr<AudioBuffer>& buffer, float value) {
56 int frames = buffer->frame_count();
57 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
58 buffer->ReadFrames(frames, 0, 0, bus.get());
59 for (int ch = 0; ch < buffer->channel_count(); ++ch) {
60 for (int i = 0; i < frames; ++i) {
61 if (bus->channel(ch)[i] != value)
62 return false;
63 }
64 }
65 return true;
66 }
67
VerifyNextBuffer(const scoped_refptr<AudioBuffer> & input)68 void VerifyNextBuffer(const scoped_refptr<AudioBuffer>& input) {
69 ASSERT_TRUE(splicer_.HasNextBuffer());
70 scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer();
71 EXPECT_EQ(input->timestamp(), output->timestamp());
72 EXPECT_EQ(input->duration(), output->duration());
73 EXPECT_EQ(input->frame_count(), output->frame_count());
74 EXPECT_TRUE(VerifyData(output, GetValue(input)));
75 }
76
VerifyPreSpliceOutput(const scoped_refptr<AudioBuffer> & overlapped_buffer,const scoped_refptr<AudioBuffer> & overlapping_buffer,int expected_pre_splice_size,base::TimeDelta expected_pre_splice_duration)77 void VerifyPreSpliceOutput(
78 const scoped_refptr<AudioBuffer>& overlapped_buffer,
79 const scoped_refptr<AudioBuffer>& overlapping_buffer,
80 int expected_pre_splice_size,
81 base::TimeDelta expected_pre_splice_duration) {
82 ASSERT_TRUE(splicer_.HasNextBuffer());
83 scoped_refptr<AudioBuffer> pre_splice_output = splicer_.GetNextBuffer();
84 EXPECT_EQ(overlapped_buffer->timestamp(), pre_splice_output->timestamp());
85 EXPECT_EQ(expected_pre_splice_size, pre_splice_output->frame_count());
86 EXPECT_EQ(expected_pre_splice_duration, pre_splice_output->duration());
87 EXPECT_TRUE(VerifyData(pre_splice_output, GetValue(overlapped_buffer)));
88 }
89
VerifyCrossfadeOutput(const scoped_refptr<AudioBuffer> & overlapped_buffer_1,const scoped_refptr<AudioBuffer> & overlapped_buffer_2,const scoped_refptr<AudioBuffer> & overlapping_buffer,int second_overlap_index,int expected_crossfade_size,base::TimeDelta expected_crossfade_duration)90 void VerifyCrossfadeOutput(
91 const scoped_refptr<AudioBuffer>& overlapped_buffer_1,
92 const scoped_refptr<AudioBuffer>& overlapped_buffer_2,
93 const scoped_refptr<AudioBuffer>& overlapping_buffer,
94 int second_overlap_index,
95 int expected_crossfade_size,
96 base::TimeDelta expected_crossfade_duration) {
97 ASSERT_TRUE(splicer_.HasNextBuffer());
98
99 scoped_refptr<AudioBuffer> crossfade_output = splicer_.GetNextBuffer();
100 EXPECT_EQ(expected_crossfade_size, crossfade_output->frame_count());
101 EXPECT_EQ(expected_crossfade_duration, crossfade_output->duration());
102
103 // The splice timestamp may be adjusted by a microsecond.
104 EXPECT_NEAR(overlapping_buffer->timestamp().InMicroseconds(),
105 crossfade_output->timestamp().InMicroseconds(),
106 1);
107
108 // Verify the actual crossfade.
109 const int frames = crossfade_output->frame_count();
110 float overlapped_value = GetValue(overlapped_buffer_1);
111 const float overlapping_value = GetValue(overlapping_buffer);
112 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
113 crossfade_output->ReadFrames(frames, 0, 0, bus.get());
114 for (int ch = 0; ch < crossfade_output->channel_count(); ++ch) {
115 float cf_ratio = 0;
116 const float cf_increment = 1.0f / frames;
117 for (int i = 0; i < frames; ++i, cf_ratio += cf_increment) {
118 if (overlapped_buffer_2.get() && i >= second_overlap_index)
119 overlapped_value = GetValue(overlapped_buffer_2);
120 const float actual = bus->channel(ch)[i];
121 const float expected =
122 (1.0f - cf_ratio) * overlapped_value + cf_ratio * overlapping_value;
123 ASSERT_FLOAT_EQ(expected, actual) << "i=" << i;
124 }
125 }
126 }
127
AddInput(const scoped_refptr<AudioBuffer> & input)128 bool AddInput(const scoped_refptr<AudioBuffer>& input) {
129 // Since the splicer doesn't make copies it's working directly on the input
130 // buffers. We must make a copy before adding to ensure the original buffer
131 // is not modified in unexpected ways.
132 scoped_refptr<AudioBuffer> buffer_copy =
133 input->end_of_stream()
134 ? AudioBuffer::CreateEOSBuffer()
135 : AudioBuffer::CopyFrom(kSampleFormat,
136 input->channel_layout(),
137 input->channel_count(),
138 input->sample_rate(),
139 input->frame_count(),
140 &input->channel_data()[0],
141 input->timestamp());
142 return splicer_.AddInput(buffer_copy);
143 }
144
max_crossfade_duration()145 base::TimeDelta max_crossfade_duration() {
146 return splicer_.max_crossfade_duration_;
147 }
148
149 protected:
150 AudioSplicer splicer_;
151 AudioTimestampHelper input_timestamp_helper_;
152
153 DISALLOW_COPY_AND_ASSIGN(AudioSplicerTest);
154 };
155
TEST_F(AudioSplicerTest,PassThru)156 TEST_F(AudioSplicerTest, PassThru) {
157 EXPECT_FALSE(splicer_.HasNextBuffer());
158
159 // Test single buffer pass-thru behavior.
160 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
161 EXPECT_TRUE(AddInput(input_1));
162 VerifyNextBuffer(input_1);
163 EXPECT_FALSE(splicer_.HasNextBuffer());
164
165 // Test that multiple buffers can be queued in the splicer.
166 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
167 scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
168 EXPECT_TRUE(AddInput(input_2));
169 EXPECT_TRUE(AddInput(input_3));
170 VerifyNextBuffer(input_2);
171 VerifyNextBuffer(input_3);
172 EXPECT_FALSE(splicer_.HasNextBuffer());
173 }
174
TEST_F(AudioSplicerTest,Reset)175 TEST_F(AudioSplicerTest, Reset) {
176 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
177 EXPECT_TRUE(AddInput(input_1));
178 ASSERT_TRUE(splicer_.HasNextBuffer());
179
180 splicer_.Reset();
181 EXPECT_FALSE(splicer_.HasNextBuffer());
182
183 // Add some bytes to the timestamp helper so that the
184 // next buffer starts many frames beyond the end of
185 // |input_1|. This is to make sure that Reset() actually
186 // clears its state and doesn't try to insert a gap.
187 input_timestamp_helper_.AddFrames(100);
188
189 // Verify that a new input buffer passes through as expected.
190 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
191 EXPECT_TRUE(AddInput(input_2));
192 VerifyNextBuffer(input_2);
193 EXPECT_FALSE(splicer_.HasNextBuffer());
194 }
195
TEST_F(AudioSplicerTest,EndOfStream)196 TEST_F(AudioSplicerTest, EndOfStream) {
197 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
198 scoped_refptr<AudioBuffer> input_2 = AudioBuffer::CreateEOSBuffer();
199 scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.2f);
200 EXPECT_TRUE(input_2->end_of_stream());
201
202 EXPECT_TRUE(AddInput(input_1));
203 EXPECT_TRUE(AddInput(input_2));
204
205 VerifyNextBuffer(input_1);
206
207 scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
208 EXPECT_FALSE(splicer_.HasNextBuffer());
209 EXPECT_TRUE(output_2->end_of_stream());
210
211 // Verify that buffers can be added again after Reset().
212 splicer_.Reset();
213 EXPECT_TRUE(AddInput(input_3));
214 VerifyNextBuffer(input_3);
215 EXPECT_FALSE(splicer_.HasNextBuffer());
216 }
217
218 // Test the gap insertion code.
219 // +--------------+ +--------------+
220 // |11111111111111| |22222222222222|
221 // +--------------+ +--------------+
222 // Results in:
223 // +--------------+----+--------------+
224 // |11111111111111|0000|22222222222222|
225 // +--------------+----+--------------+
TEST_F(AudioSplicerTest,GapInsertion)226 TEST_F(AudioSplicerTest, GapInsertion) {
227 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
228
229 // Add bytes to the timestamp helper so that the next buffer
230 // will have a starting timestamp that indicates a gap is
231 // present.
232 const int kGapSize = 7;
233 input_timestamp_helper_.AddFrames(kGapSize);
234 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
235
236 EXPECT_TRUE(AddInput(input_1));
237 EXPECT_TRUE(AddInput(input_2));
238
239 // Verify that the first input buffer passed through unmodified.
240 VerifyNextBuffer(input_1);
241
242 // Verify the contents of the gap buffer.
243 scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
244 base::TimeDelta gap_timestamp =
245 input_1->timestamp() + input_1->duration();
246 base::TimeDelta gap_duration = input_2->timestamp() - gap_timestamp;
247 EXPECT_GT(gap_duration, base::TimeDelta());
248 EXPECT_EQ(gap_timestamp, output_2->timestamp());
249 EXPECT_NEAR(
250 gap_duration.InMicroseconds(), output_2->duration().InMicroseconds(), 1);
251 EXPECT_EQ(kGapSize, output_2->frame_count());
252 EXPECT_TRUE(VerifyData(output_2, 0.0f));
253
254 // Verify that the second input buffer passed through unmodified.
255 VerifyNextBuffer(input_2);
256 EXPECT_FALSE(splicer_.HasNextBuffer());
257 }
258
259 // Test that an error is signalled when the gap between input buffers is
260 // too large.
TEST_F(AudioSplicerTest,GapTooLarge)261 TEST_F(AudioSplicerTest, GapTooLarge) {
262 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
263
264 // Add a seconds worth of bytes so that an unacceptably large
265 // gap exists between |input_1| and |input_2|.
266 const int kGapSize = kDefaultSampleRate;
267 input_timestamp_helper_.AddFrames(kGapSize);
268 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
269
270 EXPECT_TRUE(AddInput(input_1));
271 EXPECT_FALSE(AddInput(input_2));
272
273 VerifyNextBuffer(input_1);
274
275 // Verify that the second buffer is not available.
276 EXPECT_FALSE(splicer_.HasNextBuffer());
277
278 // Reset the timestamp helper so it can generate a buffer that is
279 // right after |input_1|.
280 input_timestamp_helper_.SetBaseTimestamp(
281 input_1->timestamp() + input_1->duration());
282
283 // Verify that valid buffers are still accepted.
284 scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
285 EXPECT_TRUE(AddInput(input_3));
286 VerifyNextBuffer(input_3);
287 EXPECT_FALSE(splicer_.HasNextBuffer());
288 }
289
290 // Verifies that an error is signalled if AddInput() is called
291 // with a timestamp that is earlier than the first buffer added.
TEST_F(AudioSplicerTest,BufferAddedBeforeBase)292 TEST_F(AudioSplicerTest, BufferAddedBeforeBase) {
293 input_timestamp_helper_.SetBaseTimestamp(
294 base::TimeDelta::FromMicroseconds(10));
295 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
296
297 // Reset the timestamp helper so the next buffer will have a timestamp earlier
298 // than |input_1|.
299 input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta::FromSeconds(0));
300 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.1f);
301
302 EXPECT_GT(input_1->timestamp(), input_2->timestamp());
303 EXPECT_TRUE(AddInput(input_1));
304 EXPECT_FALSE(AddInput(input_2));
305 }
306
307 // Test when one buffer partially overlaps another.
308 // +--------------+
309 // |11111111111111|
310 // +--------------+
311 // +--------------+
312 // |22222222222222|
313 // +--------------+
314 // Results in:
315 // +--------------+----------+
316 // |11111111111111|2222222222|
317 // +--------------+----------+
TEST_F(AudioSplicerTest,PartialOverlap)318 TEST_F(AudioSplicerTest, PartialOverlap) {
319 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
320
321 // Reset timestamp helper so that the next buffer will have a
322 // timestamp that starts in the middle of |input_1|.
323 const int kOverlapSize = input_1->frame_count() / 4;
324 input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
325 input_timestamp_helper_.AddFrames(input_1->frame_count() - kOverlapSize);
326
327 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
328
329 EXPECT_TRUE(AddInput(input_1));
330 EXPECT_TRUE(AddInput(input_2));
331
332 // Verify that the first input buffer passed through unmodified.
333 VerifyNextBuffer(input_1);
334
335 ASSERT_TRUE(splicer_.HasNextBuffer());
336 scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
337 EXPECT_FALSE(splicer_.HasNextBuffer());
338
339 // Verify that the second input buffer was truncated to only contain
340 // the samples that are after the end of |input_1|.
341 base::TimeDelta expected_timestamp =
342 input_1->timestamp() + input_1->duration();
343 base::TimeDelta expected_duration =
344 (input_2->timestamp() + input_2->duration()) - expected_timestamp;
345 EXPECT_EQ(expected_timestamp, output_2->timestamp());
346 EXPECT_EQ(expected_duration, output_2->duration());
347 EXPECT_TRUE(VerifyData(output_2, GetValue(input_2)));
348 }
349
350 // Test that an input buffer that is completely overlapped by a buffer
351 // that was already added is dropped.
352 // +--------------+
353 // |11111111111111|
354 // +--------------+
355 // +-----+
356 // |22222|
357 // +-----+
358 // +-------------+
359 // |3333333333333|
360 // +-------------+
361 // Results in:
362 // +--------------+-------------+
363 // |11111111111111|3333333333333|
364 // +--------------+-------------+
TEST_F(AudioSplicerTest,DropBuffer)365 TEST_F(AudioSplicerTest, DropBuffer) {
366 scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
367
368 // Reset timestamp helper so that the next buffer will have a
369 // timestamp that starts in the middle of |input_1|.
370 const int kOverlapOffset = input_1->frame_count() / 2;
371 const int kOverlapSize = input_1->frame_count() / 4;
372 input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
373 input_timestamp_helper_.AddFrames(kOverlapOffset);
374
375 scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f, kOverlapSize);
376
377 // Reset the timestamp helper so the next buffer will be right after
378 // |input_1|.
379 input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
380 input_timestamp_helper_.AddFrames(input_1->frame_count());
381 scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
382
383 EXPECT_TRUE(AddInput(input_1));
384 EXPECT_TRUE(AddInput(input_2));
385 EXPECT_TRUE(AddInput(input_3));
386
387 VerifyNextBuffer(input_1);
388 VerifyNextBuffer(input_3);
389 EXPECT_FALSE(splicer_.HasNextBuffer());
390 }
391
392 // Test crossfade when one buffer partially overlaps another.
393 // +--------------+
394 // |11111111111111|
395 // +--------------+
396 // +--------------+
397 // |22222222222222|
398 // +--------------+
399 // Results in:
400 // +----------+----+----------+
401 // |1111111111|xxxx|2222222222|
402 // +----------+----+----------+
403 // Where "xxxx" represents the crossfaded portion of the signal.
TEST_F(AudioSplicerTest,PartialOverlapCrossfade)404 TEST_F(AudioSplicerTest, PartialOverlapCrossfade) {
405 const int kCrossfadeSize =
406 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
407 const int kBufferSize = kCrossfadeSize * 2;
408
409 scoped_refptr<AudioBuffer> extra_pre_splice_buffer =
410 GetNextInputBuffer(0.2f, kBufferSize);
411 scoped_refptr<AudioBuffer> overlapped_buffer =
412 GetNextInputBuffer(1.0f, kBufferSize);
413
414 // Reset timestamp helper so that the next buffer will have a timestamp that
415 // starts in the middle of |overlapped_buffer|.
416 input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
417 input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() -
418 kCrossfadeSize);
419 splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
420 scoped_refptr<AudioBuffer> overlapping_buffer =
421 GetNextInputBuffer(0.0f, kBufferSize);
422
423 // |extra_pre_splice_buffer| is entirely before the splice and should be ready
424 // for output.
425 EXPECT_TRUE(AddInput(extra_pre_splice_buffer));
426 VerifyNextBuffer(extra_pre_splice_buffer);
427
428 // The splicer should be internally queuing input since |overlapped_buffer| is
429 // part of the splice.
430 EXPECT_TRUE(AddInput(overlapped_buffer));
431 EXPECT_FALSE(splicer_.HasNextBuffer());
432
433 // |overlapping_buffer| completes the splice.
434 splicer_.SetSpliceTimestamp(kNoTimestamp());
435 EXPECT_TRUE(AddInput(overlapping_buffer));
436 ASSERT_TRUE(splicer_.HasNextBuffer());
437
438 // Add one more buffer to make sure it's passed through untouched.
439 scoped_refptr<AudioBuffer> extra_post_splice_buffer =
440 GetNextInputBuffer(0.5f, kBufferSize);
441 EXPECT_TRUE(AddInput(extra_post_splice_buffer));
442
443 VerifyPreSpliceOutput(overlapped_buffer,
444 overlapping_buffer,
445 221,
446 base::TimeDelta::FromMicroseconds(5011));
447
448 // Due to rounding the crossfade size may vary by up to a frame.
449 const int kExpectedCrossfadeSize = 220;
450 EXPECT_NEAR(kExpectedCrossfadeSize, kCrossfadeSize, 1);
451
452 VerifyCrossfadeOutput(overlapped_buffer,
453 NULL,
454 overlapping_buffer,
455 0,
456 kExpectedCrossfadeSize,
457 base::TimeDelta::FromMicroseconds(4988));
458
459 // Retrieve the remaining portion after crossfade.
460 ASSERT_TRUE(splicer_.HasNextBuffer());
461 scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
462 EXPECT_EQ(base::TimeDelta::FromMicroseconds(20022),
463 post_splice_output->timestamp());
464 EXPECT_EQ(overlapping_buffer->frame_count() - kExpectedCrossfadeSize,
465 post_splice_output->frame_count());
466 EXPECT_EQ(base::TimeDelta::FromMicroseconds(5034),
467 post_splice_output->duration());
468
469 EXPECT_TRUE(VerifyData(post_splice_output, GetValue(overlapping_buffer)));
470
471 VerifyNextBuffer(extra_post_splice_buffer);
472 EXPECT_FALSE(splicer_.HasNextBuffer());
473 }
474
475 // Test crossfade when one buffer partially overlaps another, but an end of
476 // stream buffer is received before the crossfade duration is reached.
477 // +--------------+
478 // |11111111111111|
479 // +--------------+
480 // +---------++---+
481 // |222222222||EOS|
482 // +---------++---+
483 // Results in:
484 // +----------+----+----++---+
485 // |1111111111|xxxx|2222||EOS|
486 // +----------+----+----++---+
487 // Where "x" represents the crossfaded portion of the signal.
TEST_F(AudioSplicerTest,PartialOverlapCrossfadeEndOfStream)488 TEST_F(AudioSplicerTest, PartialOverlapCrossfadeEndOfStream) {
489 const int kCrossfadeSize =
490 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
491
492 scoped_refptr<AudioBuffer> overlapped_buffer =
493 GetNextInputBuffer(1.0f, kCrossfadeSize * 2);
494
495 // Reset timestamp helper so that the next buffer will have a timestamp that
496 // starts 3/4 of the way into |overlapped_buffer|.
497 input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
498 input_timestamp_helper_.AddFrames(3 * overlapped_buffer->frame_count() / 4);
499 splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
500 scoped_refptr<AudioBuffer> overlapping_buffer =
501 GetNextInputBuffer(0.0f, kCrossfadeSize / 3);
502
503 // The splicer should be internally queuing input since |overlapped_buffer| is
504 // part of the splice.
505 EXPECT_TRUE(AddInput(overlapped_buffer));
506 EXPECT_FALSE(splicer_.HasNextBuffer());
507
508 // |overlapping_buffer| should not have enough data to complete the splice, so
509 // ensure output is not available.
510 splicer_.SetSpliceTimestamp(kNoTimestamp());
511 EXPECT_TRUE(AddInput(overlapping_buffer));
512 EXPECT_FALSE(splicer_.HasNextBuffer());
513
514 // Now add an EOS buffer which should complete the splice.
515 EXPECT_TRUE(AddInput(AudioBuffer::CreateEOSBuffer()));
516
517 VerifyPreSpliceOutput(overlapped_buffer,
518 overlapping_buffer,
519 331,
520 base::TimeDelta::FromMicroseconds(7505));
521 VerifyCrossfadeOutput(overlapped_buffer,
522 NULL,
523 overlapping_buffer,
524 0,
525 overlapping_buffer->frame_count(),
526 overlapping_buffer->duration());
527
528 // Ensure the last buffer is an EOS buffer.
529 ASSERT_TRUE(splicer_.HasNextBuffer());
530 scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
531 EXPECT_TRUE(post_splice_output->end_of_stream());
532
533 EXPECT_FALSE(splicer_.HasNextBuffer());
534 }
535
536 // Test crossfade when one buffer partially overlaps another, but the amount of
537 // overlapped data is less than the crossfade duration.
538 // +------------+
539 // |111111111111|
540 // +------------+
541 // +--------------+
542 // |22222222222222|
543 // +--------------+
544 // Results in:
545 // +----------+-+------------+
546 // |1111111111|x|222222222222|
547 // +----------+-+------------+
548 // Where "x" represents the crossfaded portion of the signal.
TEST_F(AudioSplicerTest,PartialOverlapCrossfadeShortPreSplice)549 TEST_F(AudioSplicerTest, PartialOverlapCrossfadeShortPreSplice) {
550 const int kCrossfadeSize =
551 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
552
553 scoped_refptr<AudioBuffer> overlapped_buffer =
554 GetNextInputBuffer(1.0f, kCrossfadeSize / 2);
555
556 // Reset timestamp helper so that the next buffer will have a timestamp that
557 // starts in the middle of |overlapped_buffer|.
558 input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
559 input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() / 2);
560 splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
561 scoped_refptr<AudioBuffer> overlapping_buffer =
562 GetNextInputBuffer(0.0f, kCrossfadeSize * 2);
563
564 // The splicer should be internally queuing input since |overlapped_buffer| is
565 // part of the splice.
566 EXPECT_TRUE(AddInput(overlapped_buffer));
567 EXPECT_FALSE(splicer_.HasNextBuffer());
568
569 // |overlapping_buffer| completes the splice.
570 splicer_.SetSpliceTimestamp(kNoTimestamp());
571 EXPECT_TRUE(AddInput(overlapping_buffer));
572
573 const int kExpectedPreSpliceSize = 55;
574 const base::TimeDelta kExpectedPreSpliceDuration =
575 base::TimeDelta::FromMicroseconds(1247);
576 VerifyPreSpliceOutput(overlapped_buffer,
577 overlapping_buffer,
578 kExpectedPreSpliceSize,
579 kExpectedPreSpliceDuration);
580 VerifyCrossfadeOutput(overlapped_buffer,
581 NULL,
582 overlapping_buffer,
583 0,
584 kExpectedPreSpliceSize,
585 kExpectedPreSpliceDuration);
586
587 // Retrieve the remaining portion after crossfade.
588 ASSERT_TRUE(splicer_.HasNextBuffer());
589 scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
590 EXPECT_EQ(overlapping_buffer->timestamp() + kExpectedPreSpliceDuration,
591 post_splice_output->timestamp());
592 EXPECT_EQ(overlapping_buffer->frame_count() - kExpectedPreSpliceSize,
593 post_splice_output->frame_count());
594 EXPECT_EQ(overlapping_buffer->duration() - kExpectedPreSpliceDuration,
595 post_splice_output->duration());
596
597 EXPECT_TRUE(VerifyData(post_splice_output, GetValue(overlapping_buffer)));
598 EXPECT_FALSE(splicer_.HasNextBuffer());
599 }
600
601 // Test behavior when a splice frame is incorrectly marked and does not actually
602 // overlap.
603 // +----------+
604 // |1111111111|
605 // +----------+
606 // +--------------+
607 // |22222222222222|
608 // +--------------+
609 // Results in:
610 // +----------+--------------+
611 // |1111111111|22222222222222|
612 // +----------+--------------+
TEST_F(AudioSplicerTest,IncorrectlyMarkedSplice)613 TEST_F(AudioSplicerTest, IncorrectlyMarkedSplice) {
614 const int kBufferSize =
615 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
616
617 scoped_refptr<AudioBuffer> first_buffer =
618 GetNextInputBuffer(1.0f, kBufferSize);
619 // Fuzz the duration slightly so that the buffer overlaps the splice timestamp
620 // by a microsecond, which is not enough to crossfade.
621 const base::TimeDelta kSpliceTimestamp =
622 input_timestamp_helper_.GetTimestamp() -
623 base::TimeDelta::FromMicroseconds(1);
624 splicer_.SetSpliceTimestamp(kSpliceTimestamp);
625 scoped_refptr<AudioBuffer> second_buffer =
626 GetNextInputBuffer(0.0f, kBufferSize);
627 second_buffer->set_timestamp(kSpliceTimestamp);
628
629 // The splicer should be internally queuing input since |first_buffer| is part
630 // of the supposed splice.
631 EXPECT_TRUE(AddInput(first_buffer));
632 EXPECT_FALSE(splicer_.HasNextBuffer());
633
634 // |second_buffer| should complete the supposed splice, so ensure output is
635 // now available.
636 splicer_.SetSpliceTimestamp(kNoTimestamp());
637 EXPECT_TRUE(AddInput(second_buffer));
638
639 VerifyNextBuffer(first_buffer);
640 VerifyNextBuffer(second_buffer);
641 EXPECT_FALSE(splicer_.HasNextBuffer());
642 }
643
644 // Test behavior when a splice frame is incorrectly marked and there is a gap
645 // between whats in the pre splice and post splice.
646 // +--------+
647 // |11111111|
648 // +--------+
649 // +--------------+
650 // |22222222222222|
651 // +--------------+
652 // Results in:
653 // +--------+-+--------------+
654 // |11111111|0|22222222222222|
655 // +--------+-+--------------+
TEST_F(AudioSplicerTest,IncorrectlyMarkedSpliceWithGap)656 TEST_F(AudioSplicerTest, IncorrectlyMarkedSpliceWithGap) {
657 const int kBufferSize =
658 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
659 const int kGapSize = 2;
660
661 scoped_refptr<AudioBuffer> first_buffer =
662 GetNextInputBuffer(1.0f, kBufferSize - kGapSize);
663 scoped_refptr<AudioBuffer> gap_buffer =
664 GetNextInputBuffer(0.0f, kGapSize);
665 splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
666 scoped_refptr<AudioBuffer> second_buffer =
667 GetNextInputBuffer(0.0f, kBufferSize);
668
669 // The splicer should pass through the first buffer since it's not part of the
670 // splice.
671 EXPECT_TRUE(AddInput(first_buffer));
672 VerifyNextBuffer(first_buffer);
673
674 // Do not add |gap_buffer|.
675
676 // |second_buffer| will complete the supposed splice.
677 splicer_.SetSpliceTimestamp(kNoTimestamp());
678 EXPECT_TRUE(AddInput(second_buffer));
679
680 VerifyNextBuffer(gap_buffer);
681 VerifyNextBuffer(second_buffer);
682 EXPECT_FALSE(splicer_.HasNextBuffer());
683 }
684
685 // Test behavior when a splice frame is incorrectly marked and there is a gap
686 // between what's in the pre splice and post splice that is too large to recover
687 // from.
688 // +--------+
689 // |11111111|
690 // +--------+
691 // +------+
692 // |222222|
693 // +------+
694 // Results in an error and not a crash.
TEST_F(AudioSplicerTest,IncorrectlyMarkedSpliceWithBadGap)695 TEST_F(AudioSplicerTest, IncorrectlyMarkedSpliceWithBadGap) {
696 const int kBufferSize =
697 input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
698 const int kGapSize = kBufferSize +
699 input_timestamp_helper_.GetFramesToTarget(
700 base::TimeDelta::FromMilliseconds(
701 AudioSplicer::kMaxTimeDeltaInMilliseconds + 1));
702
703 scoped_refptr<AudioBuffer> first_buffer =
704 GetNextInputBuffer(1.0f, kBufferSize);
705 scoped_refptr<AudioBuffer> gap_buffer =
706 GetNextInputBuffer(0.0f, kGapSize);
707 splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
708 scoped_refptr<AudioBuffer> second_buffer =
709 GetNextInputBuffer(0.0f, kBufferSize);
710
711 // The splicer should pass through the first buffer since it's not part of the
712 // splice.
713 EXPECT_TRUE(AddInput(first_buffer));
714 VerifyNextBuffer(first_buffer);
715
716 // Do not add |gap_buffer|.
717
718 // |second_buffer| will complete the supposed splice.
719 splicer_.SetSpliceTimestamp(kNoTimestamp());
720 EXPECT_FALSE(AddInput(second_buffer));
721 }
722
723 // Ensure we don't crash when a splice frame is incorrectly marked such that the
724 // splice timestamp has already passed when SetSpliceTimestamp() is called.
725 // This can happen if the encoded timestamps are too far behind the decoded
726 // timestamps.
TEST_F(AudioSplicerTest,IncorrectlyMarkedPastSplice)727 TEST_F(AudioSplicerTest, IncorrectlyMarkedPastSplice) {
728 const int kBufferSize = 200;
729
730 scoped_refptr<AudioBuffer> first_buffer =
731 GetNextInputBuffer(1.0f, kBufferSize);
732 EXPECT_TRUE(AddInput(first_buffer));
733 VerifyNextBuffer(first_buffer);
734
735 // Start the splice at a timestamp which has already occurred.
736 splicer_.SetSpliceTimestamp(base::TimeDelta());
737
738 scoped_refptr<AudioBuffer> second_buffer =
739 GetNextInputBuffer(0.5f, kBufferSize);
740 EXPECT_TRUE(AddInput(second_buffer));
741 EXPECT_FALSE(splicer_.HasNextBuffer());
742
743 // |third_buffer| will complete the supposed splice. The buffer size is set
744 // such that unchecked the splicer would try to trim off a negative number of
745 // frames.
746 splicer_.SetSpliceTimestamp(kNoTimestamp());
747 scoped_refptr<AudioBuffer> third_buffer =
748 GetNextInputBuffer(0.0f, kBufferSize * 10);
749 third_buffer->set_timestamp(base::TimeDelta());
750 EXPECT_TRUE(AddInput(third_buffer));
751
752 // The second buffer should come through unmodified.
753 VerifyNextBuffer(second_buffer);
754
755 // The third buffer should be partially dropped since it overlaps the second.
756 ASSERT_TRUE(splicer_.HasNextBuffer());
757 const base::TimeDelta second_buffer_end_ts =
758 second_buffer->timestamp() + second_buffer->duration();
759 scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer();
760 EXPECT_EQ(second_buffer_end_ts, output->timestamp());
761 EXPECT_EQ(third_buffer->duration() -
762 (second_buffer_end_ts - third_buffer->timestamp()),
763 output->duration());
764 EXPECT_TRUE(VerifyData(output, GetValue(third_buffer)));
765 }
766
767 } // namespace media
768