OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/audio_splicer.h" | 5 #include "media/base/audio_splicer.h" |
6 | 6 |
7 #include <cstdlib> | 7 #include <cstdlib> |
8 #include <deque> | 8 #include <deque> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 // in the source content. Unit is frames. | 28 // in the source content. Unit is frames. |
29 static const int kMinGapSize = 2; | 29 static const int kMinGapSize = 2; |
30 | 30 |
31 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so | 31 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so |
32 // manually adjust the duration and timestamp after trimming. | 32 // manually adjust the duration and timestamp after trimming. |
33 static void AccurateTrimStart(int frames_to_trim, | 33 static void AccurateTrimStart(int frames_to_trim, |
34 const scoped_refptr<AudioBuffer> buffer, | 34 const scoped_refptr<AudioBuffer> buffer, |
35 const AudioTimestampHelper& timestamp_helper) { | 35 const AudioTimestampHelper& timestamp_helper) { |
36 buffer->TrimStart(frames_to_trim); | 36 buffer->TrimStart(frames_to_trim); |
37 buffer->set_timestamp(timestamp_helper.GetTimestamp()); | 37 buffer->set_timestamp(timestamp_helper.GetTimestamp()); |
38 buffer->set_duration( | |
39 timestamp_helper.GetFrameDuration(buffer->frame_count())); | |
40 } | |
41 | |
42 // AudioBuffer::TrimEnd() is not as accurate as the timestamp helper, so | |
43 // manually adjust the duration after trimming. | |
44 static void AccurateTrimEnd(int frames_to_trim, | |
45 const scoped_refptr<AudioBuffer> buffer, | |
46 const AudioTimestampHelper& timestamp_helper) { | |
47 DCHECK_LT(std::abs(timestamp_helper.GetFramesToTarget(buffer->timestamp())), | |
48 kMinGapSize); | |
49 buffer->TrimEnd(frames_to_trim); | |
50 buffer->set_duration( | |
51 timestamp_helper.GetFrameDuration(buffer->frame_count())); | |
52 } | 38 } |
53 | 39 |
54 // Returns an AudioBus whose frame buffer is backed by the provided AudioBuffer. | 40 // Returns an AudioBus whose frame buffer is backed by the provided AudioBuffer. |
55 static scoped_ptr<AudioBus> CreateAudioBufferWrapper( | 41 static scoped_ptr<AudioBus> CreateAudioBufferWrapper( |
56 const scoped_refptr<AudioBuffer>& buffer) { | 42 const scoped_refptr<AudioBuffer>& buffer) { |
57 scoped_ptr<AudioBus> wrapper = | 43 scoped_ptr<AudioBus> wrapper = |
58 AudioBus::CreateWrapper(buffer->channel_count()); | 44 AudioBus::CreateWrapper(buffer->channel_count()); |
59 wrapper->set_frames(buffer->frame_count()); | 45 wrapper->set_frames(buffer->frame_count()); |
60 for (int ch = 0; ch < buffer->channel_count(); ++ch) { | 46 for (int ch = 0; ch < buffer->channel_count(); ++ch) { |
61 wrapper->SetChannelData( | 47 wrapper->SetChannelData( |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 AddOutputBuffer(input); | 156 AddOutputBuffer(input); |
171 return true; | 157 return true; |
172 } | 158 } |
173 | 159 |
174 if (frames_to_fill > 0) { | 160 if (frames_to_fill > 0) { |
175 DVLOG(1) << "Gap detected @ " << expected_timestamp.InMicroseconds() | 161 DVLOG(1) << "Gap detected @ " << expected_timestamp.InMicroseconds() |
176 << " us: " << delta.InMicroseconds() << " us"; | 162 << " us: " << delta.InMicroseconds() << " us"; |
177 | 163 |
178 // Create a buffer with enough silence samples to fill the gap and | 164 // Create a buffer with enough silence samples to fill the gap and |
179 // add it to the output buffer. | 165 // add it to the output buffer. |
180 scoped_refptr<AudioBuffer> gap = AudioBuffer::CreateEmptyBuffer( | 166 scoped_refptr<AudioBuffer> gap = |
181 input->channel_layout(), | 167 AudioBuffer::CreateEmptyBuffer(input->channel_layout(), |
182 input->channel_count(), | 168 input->channel_count(), |
183 input->sample_rate(), | 169 input->sample_rate(), |
184 frames_to_fill, | 170 frames_to_fill, |
185 expected_timestamp, | 171 expected_timestamp); |
186 output_timestamp_helper_.GetFrameDuration(frames_to_fill)); | |
187 AddOutputBuffer(gap); | 172 AddOutputBuffer(gap); |
188 | 173 |
189 // Add the input buffer now that the gap has been filled. | 174 // Add the input buffer now that the gap has been filled. |
190 AddOutputBuffer(input); | 175 AddOutputBuffer(input); |
191 return true; | 176 return true; |
192 } | 177 } |
193 | 178 |
194 // Overlapping buffers marked as splice frames are handled by AudioSplicer, | 179 // Overlapping buffers marked as splice frames are handled by AudioSplicer, |
195 // but decoder and demuxer quirks may sometimes produce overlapping samples | 180 // but decoder and demuxer quirks may sometimes produce overlapping samples |
196 // which need to be sanitized. | 181 // which need to be sanitized. |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 const int frames_to_read = | 421 const int frames_to_read = |
437 std::min(preroll->frame_count() - frames_before_splice, | 422 std::min(preroll->frame_count() - frames_before_splice, |
438 output_bus->frames() - frames_read); | 423 output_bus->frames() - frames_read); |
439 preroll->ReadFrames( | 424 preroll->ReadFrames( |
440 frames_to_read, frames_before_splice, frames_read, output_bus.get()); | 425 frames_to_read, frames_before_splice, frames_read, output_bus.get()); |
441 frames_read += frames_to_read; | 426 frames_read += frames_to_read; |
442 | 427 |
443 // If only part of the buffer was consumed, trim it appropriately and stick | 428 // If only part of the buffer was consumed, trim it appropriately and stick |
444 // it into the output queue. | 429 // it into the output queue. |
445 if (frames_before_splice) { | 430 if (frames_before_splice) { |
446 AccurateTrimEnd(preroll->frame_count() - frames_before_splice, | 431 preroll->TrimEnd(preroll->frame_count() - frames_before_splice); |
447 preroll, | |
448 output_ts_helper); | |
449 CHECK(output_sanitizer_->AddInput(preroll)); | 432 CHECK(output_sanitizer_->AddInput(preroll)); |
450 frames_before_splice = 0; | 433 frames_before_splice = 0; |
451 } | 434 } |
452 } | 435 } |
453 | 436 |
454 // All necessary buffers have been processed, it's safe to reset. | 437 // All necessary buffers have been processed, it's safe to reset. |
455 pre_splice_sanitizer_->Reset(); | 438 pre_splice_sanitizer_->Reset(); |
456 DCHECK_EQ(output_bus->frames(), frames_read); | 439 DCHECK_EQ(output_bus->frames(), frames_read); |
457 DCHECK_EQ(output_ts_helper.GetFramesToTarget(splice_timestamp_), 0); | 440 DCHECK_EQ(output_ts_helper.GetFramesToTarget(splice_timestamp_), 0); |
458 return output_bus.Pass(); | 441 return output_bus.Pass(); |
459 } | 442 } |
460 | 443 |
461 void AudioSplicer::CrossfadePostSplice( | 444 void AudioSplicer::CrossfadePostSplice( |
462 scoped_ptr<AudioBus> pre_splice_bus, | 445 scoped_ptr<AudioBus> pre_splice_bus, |
463 scoped_refptr<AudioBuffer> crossfade_buffer) { | 446 scoped_refptr<AudioBuffer> crossfade_buffer) { |
464 // Use the calculated timestamp and duration to ensure there's no extra gaps | 447 // Use the calculated timestamp and duration to ensure there's no extra gaps |
465 // or overlaps to process when adding the buffer to |output_sanitizer_|. | 448 // or overlaps to process when adding the buffer to |output_sanitizer_|. |
466 const AudioTimestampHelper& output_ts_helper = | 449 const AudioTimestampHelper& output_ts_helper = |
467 output_sanitizer_->timestamp_helper(); | 450 output_sanitizer_->timestamp_helper(); |
468 crossfade_buffer->set_timestamp(output_ts_helper.GetTimestamp()); | 451 crossfade_buffer->set_timestamp(output_ts_helper.GetTimestamp()); |
469 crossfade_buffer->set_duration( | |
470 output_ts_helper.GetFrameDuration(pre_splice_bus->frames())); | |
471 | 452 |
472 // AudioBuffer::ReadFrames() only allows output into an AudioBus, so wrap | 453 // AudioBuffer::ReadFrames() only allows output into an AudioBus, so wrap |
473 // our AudioBuffer in one so we can avoid extra data copies. | 454 // our AudioBuffer in one so we can avoid extra data copies. |
474 scoped_ptr<AudioBus> output_bus = CreateAudioBufferWrapper(crossfade_buffer); | 455 scoped_ptr<AudioBus> output_bus = CreateAudioBufferWrapper(crossfade_buffer); |
475 | 456 |
476 // Extract crossfade section from the |post_splice_sanitizer_|. | 457 // Extract crossfade section from the |post_splice_sanitizer_|. |
477 int frames_read = 0, frames_to_trim = 0; | 458 int frames_read = 0, frames_to_trim = 0; |
478 scoped_refptr<AudioBuffer> remainder; | 459 scoped_refptr<AudioBuffer> remainder; |
479 while (post_splice_sanitizer_->HasNextBuffer() && | 460 while (post_splice_sanitizer_->HasNextBuffer() && |
480 frames_read < output_bus->frames()) { | 461 frames_read < output_bus->frames()) { |
(...skipping 30 matching lines...) Expand all Loading... |
511 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); | 492 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); |
512 CHECK(output_sanitizer_->AddInput(remainder)); | 493 CHECK(output_sanitizer_->AddInput(remainder)); |
513 } | 494 } |
514 | 495 |
515 // Transfer all remaining buffers out and reset once empty. | 496 // Transfer all remaining buffers out and reset once empty. |
516 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 497 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
517 post_splice_sanitizer_->Reset(); | 498 post_splice_sanitizer_->Reset(); |
518 } | 499 } |
519 | 500 |
520 } // namespace media | 501 } // namespace media |
OLD | NEW |