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 <stdint.h> | 7 #include <stdint.h> |
8 #include <cstdlib> | 8 #include <cstdlib> |
9 #include <deque> | 9 #include <deque> |
10 #include <utility> | 10 #include <utility> |
(...skipping 29 matching lines...) Expand all Loading... |
40 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so | 40 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so |
41 // manually adjust the duration and timestamp after trimming. | 41 // manually adjust the duration and timestamp after trimming. |
42 void AccurateTrimStart(int frames_to_trim, | 42 void AccurateTrimStart(int frames_to_trim, |
43 const scoped_refptr<AudioBuffer> buffer, | 43 const scoped_refptr<AudioBuffer> buffer, |
44 const AudioTimestampHelper& timestamp_helper) { | 44 const AudioTimestampHelper& timestamp_helper) { |
45 buffer->TrimStart(frames_to_trim); | 45 buffer->TrimStart(frames_to_trim); |
46 buffer->set_timestamp(timestamp_helper.GetTimestamp()); | 46 buffer->set_timestamp(timestamp_helper.GetTimestamp()); |
47 } | 47 } |
48 | 48 |
49 // Returns an AudioBus whose frame buffer is backed by the provided AudioBuffer. | 49 // Returns an AudioBus whose frame buffer is backed by the provided AudioBuffer. |
50 scoped_ptr<AudioBus> CreateAudioBufferWrapper( | 50 std::unique_ptr<AudioBus> CreateAudioBufferWrapper( |
51 const scoped_refptr<AudioBuffer>& buffer) { | 51 const scoped_refptr<AudioBuffer>& buffer) { |
52 scoped_ptr<AudioBus> wrapper = | 52 std::unique_ptr<AudioBus> wrapper = |
53 AudioBus::CreateWrapper(buffer->channel_count()); | 53 AudioBus::CreateWrapper(buffer->channel_count()); |
54 wrapper->set_frames(buffer->frame_count()); | 54 wrapper->set_frames(buffer->frame_count()); |
55 for (int ch = 0; ch < buffer->channel_count(); ++ch) { | 55 for (int ch = 0; ch < buffer->channel_count(); ++ch) { |
56 wrapper->SetChannelData( | 56 wrapper->SetChannelData( |
57 ch, reinterpret_cast<float*>(buffer->channel_data()[ch])); | 57 ch, reinterpret_cast<float*>(buffer->channel_data()[ch])); |
58 } | 58 } |
59 return wrapper; | 59 return wrapper; |
60 } | 60 } |
61 | 61 |
62 } // namespace | 62 } // namespace |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 return true; | 368 return true; |
369 } | 369 } |
370 | 370 |
371 // Wait until we have enough data to crossfade or end of stream. | 371 // Wait until we have enough data to crossfade or end of stream. |
372 if (!input->end_of_stream() && | 372 if (!input->end_of_stream() && |
373 input->timestamp() + input->duration() < max_splice_end_timestamp_) { | 373 input->timestamp() + input->duration() < max_splice_end_timestamp_) { |
374 return true; | 374 return true; |
375 } | 375 } |
376 | 376 |
377 scoped_refptr<AudioBuffer> crossfade_buffer; | 377 scoped_refptr<AudioBuffer> crossfade_buffer; |
378 scoped_ptr<AudioBus> pre_splice = | 378 std::unique_ptr<AudioBus> pre_splice = |
379 ExtractCrossfadeFromPreSplice(&crossfade_buffer); | 379 ExtractCrossfadeFromPreSplice(&crossfade_buffer); |
380 | 380 |
381 // Crossfade the pre splice and post splice sections and transfer all relevant | 381 // Crossfade the pre splice and post splice sections and transfer all relevant |
382 // buffers into |output_sanitizer_|. | 382 // buffers into |output_sanitizer_|. |
383 CrossfadePostSplice(std::move(pre_splice), crossfade_buffer); | 383 CrossfadePostSplice(std::move(pre_splice), crossfade_buffer); |
384 | 384 |
385 // Clear the splice timestamp so new splices can be accepted. | 385 // Clear the splice timestamp so new splices can be accepted. |
386 reset_splice_timestamps(); | 386 reset_splice_timestamps(); |
387 return true; | 387 return true; |
388 } | 388 } |
(...skipping 22 matching lines...) Expand all Loading... |
411 // data from the last one. Leave this as a CHECK for now to figure out if | 411 // data from the last one. Leave this as a CHECK for now to figure out if |
412 // this case is possible. | 412 // this case is possible. |
413 CHECK(splice_timestamp_ == kNoTimestamp()); | 413 CHECK(splice_timestamp_ == kNoTimestamp()); |
414 splice_timestamp_ = splice_timestamp; | 414 splice_timestamp_ = splice_timestamp; |
415 max_splice_end_timestamp_ = splice_timestamp_ + max_crossfade_duration_; | 415 max_splice_end_timestamp_ = splice_timestamp_ + max_crossfade_duration_; |
416 pre_splice_sanitizer_->Reset(); | 416 pre_splice_sanitizer_->Reset(); |
417 post_splice_sanitizer_->Reset(); | 417 post_splice_sanitizer_->Reset(); |
418 have_all_pre_splice_buffers_ = false; | 418 have_all_pre_splice_buffers_ = false; |
419 } | 419 } |
420 | 420 |
421 scoped_ptr<AudioBus> AudioSplicer::ExtractCrossfadeFromPreSplice( | 421 std::unique_ptr<AudioBus> AudioSplicer::ExtractCrossfadeFromPreSplice( |
422 scoped_refptr<AudioBuffer>* crossfade_buffer) { | 422 scoped_refptr<AudioBuffer>* crossfade_buffer) { |
423 DCHECK(crossfade_buffer); | 423 DCHECK(crossfade_buffer); |
424 const AudioTimestampHelper& output_ts_helper = | 424 const AudioTimestampHelper& output_ts_helper = |
425 output_sanitizer_->timestamp_helper(); | 425 output_sanitizer_->timestamp_helper(); |
426 | 426 |
427 int frames_before_splice = | 427 int frames_before_splice = |
428 output_ts_helper.GetFramesToTarget(splice_timestamp_); | 428 output_ts_helper.GetFramesToTarget(splice_timestamp_); |
429 | 429 |
430 // Determine crossfade frame count based on available frames in each splicer | 430 // Determine crossfade frame count based on available frames in each splicer |
431 // and capping to the maximum crossfade duration. | 431 // and capping to the maximum crossfade duration. |
432 const int max_crossfade_frame_count = | 432 const int max_crossfade_frame_count = |
433 output_ts_helper.GetFramesToTarget(max_splice_end_timestamp_) - | 433 output_ts_helper.GetFramesToTarget(max_splice_end_timestamp_) - |
434 frames_before_splice; | 434 frames_before_splice; |
435 const int frames_to_crossfade = std::min( | 435 const int frames_to_crossfade = std::min( |
436 max_crossfade_frame_count, | 436 max_crossfade_frame_count, |
437 std::min(pre_splice_sanitizer_->GetFrameCount() - frames_before_splice, | 437 std::min(pre_splice_sanitizer_->GetFrameCount() - frames_before_splice, |
438 post_splice_sanitizer_->GetFrameCount())); | 438 post_splice_sanitizer_->GetFrameCount())); |
439 // There must always be frames to crossfade, otherwise the splice should not | 439 // There must always be frames to crossfade, otherwise the splice should not |
440 // have been generated. | 440 // have been generated. |
441 DCHECK_GT(frames_to_crossfade, 0); | 441 DCHECK_GT(frames_to_crossfade, 0); |
442 | 442 |
443 int frames_read = 0; | 443 int frames_read = 0; |
444 scoped_ptr<AudioBus> output_bus; | 444 std::unique_ptr<AudioBus> output_bus; |
445 while (pre_splice_sanitizer_->HasNextBuffer() && | 445 while (pre_splice_sanitizer_->HasNextBuffer() && |
446 frames_read < frames_to_crossfade) { | 446 frames_read < frames_to_crossfade) { |
447 scoped_refptr<AudioBuffer> preroll = pre_splice_sanitizer_->GetNextBuffer(); | 447 scoped_refptr<AudioBuffer> preroll = pre_splice_sanitizer_->GetNextBuffer(); |
448 | 448 |
449 // We don't know the channel count until we see the first buffer, so wait | 449 // We don't know the channel count until we see the first buffer, so wait |
450 // until the first buffer to allocate the output AudioBus. | 450 // until the first buffer to allocate the output AudioBus. |
451 if (!output_bus) { | 451 if (!output_bus) { |
452 output_bus = | 452 output_bus = |
453 AudioBus::Create(preroll->channel_count(), frames_to_crossfade); | 453 AudioBus::Create(preroll->channel_count(), frames_to_crossfade); |
454 // Allocate output buffer for crossfade. | 454 // Allocate output buffer for crossfade. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 CHECK(crossfade_buffer->get()); | 494 CHECK(crossfade_buffer->get()); |
495 | 495 |
496 // All necessary buffers have been processed, it's safe to reset. | 496 // All necessary buffers have been processed, it's safe to reset. |
497 pre_splice_sanitizer_->Reset(); | 497 pre_splice_sanitizer_->Reset(); |
498 DCHECK_EQ(output_bus->frames(), frames_read); | 498 DCHECK_EQ(output_bus->frames(), frames_read); |
499 DCHECK_EQ(output_ts_helper.GetFramesToTarget(splice_timestamp_), 0); | 499 DCHECK_EQ(output_ts_helper.GetFramesToTarget(splice_timestamp_), 0); |
500 return output_bus; | 500 return output_bus; |
501 } | 501 } |
502 | 502 |
503 void AudioSplicer::CrossfadePostSplice( | 503 void AudioSplicer::CrossfadePostSplice( |
504 scoped_ptr<AudioBus> pre_splice_bus, | 504 std::unique_ptr<AudioBus> pre_splice_bus, |
505 const scoped_refptr<AudioBuffer>& crossfade_buffer) { | 505 const scoped_refptr<AudioBuffer>& crossfade_buffer) { |
506 // Use the calculated timestamp and duration to ensure there's no extra gaps | 506 // Use the calculated timestamp and duration to ensure there's no extra gaps |
507 // or overlaps to process when adding the buffer to |output_sanitizer_|. | 507 // or overlaps to process when adding the buffer to |output_sanitizer_|. |
508 const AudioTimestampHelper& output_ts_helper = | 508 const AudioTimestampHelper& output_ts_helper = |
509 output_sanitizer_->timestamp_helper(); | 509 output_sanitizer_->timestamp_helper(); |
510 crossfade_buffer->set_timestamp(output_ts_helper.GetTimestamp()); | 510 crossfade_buffer->set_timestamp(output_ts_helper.GetTimestamp()); |
511 | 511 |
512 // AudioBuffer::ReadFrames() only allows output into an AudioBus, so wrap | 512 // AudioBuffer::ReadFrames() only allows output into an AudioBus, so wrap |
513 // our AudioBuffer in one so we can avoid extra data copies. | 513 // our AudioBuffer in one so we can avoid extra data copies. |
514 scoped_ptr<AudioBus> output_bus = CreateAudioBufferWrapper(crossfade_buffer); | 514 std::unique_ptr<AudioBus> output_bus = |
| 515 CreateAudioBufferWrapper(crossfade_buffer); |
515 | 516 |
516 // Extract crossfade section from the |post_splice_sanitizer_|. | 517 // Extract crossfade section from the |post_splice_sanitizer_|. |
517 int frames_read = 0, frames_to_trim = 0; | 518 int frames_read = 0, frames_to_trim = 0; |
518 scoped_refptr<AudioBuffer> remainder; | 519 scoped_refptr<AudioBuffer> remainder; |
519 while (post_splice_sanitizer_->HasNextBuffer() && | 520 while (post_splice_sanitizer_->HasNextBuffer() && |
520 frames_read < output_bus->frames()) { | 521 frames_read < output_bus->frames()) { |
521 scoped_refptr<AudioBuffer> postroll = | 522 scoped_refptr<AudioBuffer> postroll = |
522 post_splice_sanitizer_->GetNextBuffer(); | 523 post_splice_sanitizer_->GetNextBuffer(); |
523 const int frames_to_read = | 524 const int frames_to_read = |
524 std::min(postroll->frame_count(), output_bus->frames() - frames_read); | 525 std::min(postroll->frame_count(), output_bus->frames() - frames_read); |
(...skipping 26 matching lines...) Expand all Loading... |
551 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); | 552 AccurateTrimStart(frames_to_trim, remainder, output_ts_helper); |
552 CHECK(output_sanitizer_->AddInput(remainder)); | 553 CHECK(output_sanitizer_->AddInput(remainder)); |
553 } | 554 } |
554 | 555 |
555 // Transfer all remaining buffers out and reset once empty. | 556 // Transfer all remaining buffers out and reset once empty. |
556 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); | 557 CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get())); |
557 post_splice_sanitizer_->Reset(); | 558 post_splice_sanitizer_->Reset(); |
558 } | 559 } |
559 | 560 |
560 } // namespace media | 561 } // namespace media |
OLD | NEW |