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