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