| 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 |