| 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/filters/audio_renderer_impl.h" | 5 #include "media/filters/audio_renderer_impl.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 17 #include "media/base/audio_buffer.h" | 17 #include "media/base/audio_buffer.h" |
| 18 #include "media/base/audio_buffer_converter.h" | 18 #include "media/base/audio_buffer_converter.h" |
| 19 #include "media/base/audio_hardware_config.h" | 19 #include "media/base/audio_hardware_config.h" |
| 20 #include "media/base/audio_splicer.h" | 20 #include "media/base/audio_splicer.h" |
| 21 #include "media/base/bind_to_current_loop.h" | 21 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/demuxer_stream.h" | 22 #include "media/base/demuxer_stream.h" |
| 23 #include "media/filters/audio_clock.h" |
| 23 #include "media/filters/decrypting_demuxer_stream.h" | 24 #include "media/filters/decrypting_demuxer_stream.h" |
| 24 | 25 |
| 25 namespace media { | 26 namespace media { |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 enum AudioRendererEvent { | 30 enum AudioRendererEvent { |
| 30 INITIALIZED, | 31 INITIALIZED, |
| 31 RENDER_ERROR, | 32 RENDER_ERROR, |
| 32 RENDER_EVENT_MAX = RENDER_ERROR, | 33 RENDER_EVENT_MAX = RENDER_ERROR, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 50 audio_buffer_stream_(task_runner, | 51 audio_buffer_stream_(task_runner, |
| 51 decoders.Pass(), | 52 decoders.Pass(), |
| 52 set_decryptor_ready_cb), | 53 set_decryptor_ready_cb), |
| 53 hardware_config_(hardware_config), | 54 hardware_config_(hardware_config), |
| 54 now_cb_(base::Bind(&base::TimeTicks::Now)), | 55 now_cb_(base::Bind(&base::TimeTicks::Now)), |
| 55 state_(kUninitialized), | 56 state_(kUninitialized), |
| 56 sink_playing_(false), | 57 sink_playing_(false), |
| 57 pending_read_(false), | 58 pending_read_(false), |
| 58 received_end_of_stream_(false), | 59 received_end_of_stream_(false), |
| 59 rendered_end_of_stream_(false), | 60 rendered_end_of_stream_(false), |
| 60 audio_time_buffered_(kNoTimestamp()), | |
| 61 current_time_(kNoTimestamp()), | |
| 62 underflow_disabled_(false), | 61 underflow_disabled_(false), |
| 63 preroll_aborted_(false), | 62 preroll_aborted_(false), |
| 64 weak_factory_(this) { | 63 weak_factory_(this) { |
| 65 audio_buffer_stream_.set_splice_observer(base::Bind( | 64 audio_buffer_stream_.set_splice_observer(base::Bind( |
| 66 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
| 67 audio_buffer_stream_.set_config_change_observer(base::Bind( | 66 audio_buffer_stream_.set_config_change_observer(base::Bind( |
| 68 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
| 69 } | 68 } |
| 70 | 69 |
| 71 AudioRendererImpl::~AudioRendererImpl() { | 70 AudioRendererImpl::~AudioRendererImpl() { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 void AudioRendererImpl::ResetDecoderDone() { | 161 void AudioRendererImpl::ResetDecoderDone() { |
| 163 DCHECK(task_runner_->BelongsToCurrentThread()); | 162 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 164 { | 163 { |
| 165 base::AutoLock auto_lock(lock_); | 164 base::AutoLock auto_lock(lock_); |
| 166 if (state_ == kStopped) | 165 if (state_ == kStopped) |
| 167 return; | 166 return; |
| 168 | 167 |
| 169 DCHECK_EQ(state_, kPaused); | 168 DCHECK_EQ(state_, kPaused); |
| 170 DCHECK(!flush_cb_.is_null()); | 169 DCHECK(!flush_cb_.is_null()); |
| 171 | 170 |
| 172 audio_time_buffered_ = kNoTimestamp(); | 171 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
| 173 current_time_ = kNoTimestamp(); | |
| 174 received_end_of_stream_ = false; | 172 received_end_of_stream_ = false; |
| 175 rendered_end_of_stream_ = false; | 173 rendered_end_of_stream_ = false; |
| 176 preroll_aborted_ = false; | 174 preroll_aborted_ = false; |
| 177 | 175 |
| 178 earliest_end_time_ = now_cb_.Run(); | 176 earliest_end_time_ = now_cb_.Run(); |
| 179 splicer_->Reset(); | 177 splicer_->Reset(); |
| 180 if (buffer_converter_) | 178 if (buffer_converter_) |
| 181 buffer_converter_->Reset(); | 179 buffer_converter_->Reset(); |
| 182 algorithm_->FlushBuffers(); | 180 algorithm_->FlushBuffers(); |
| 183 } | 181 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 const AudioParameters& hw_params = hardware_config_->GetOutputConfig(); | 279 const AudioParameters& hw_params = hardware_config_->GetOutputConfig(); |
| 282 audio_parameters_.Reset(hw_params.format(), | 280 audio_parameters_.Reset(hw_params.format(), |
| 283 hw_params.channel_layout(), | 281 hw_params.channel_layout(), |
| 284 hw_params.channels(), | 282 hw_params.channels(), |
| 285 hw_params.input_channels(), | 283 hw_params.input_channels(), |
| 286 hw_params.sample_rate(), | 284 hw_params.sample_rate(), |
| 287 hw_params.bits_per_sample(), | 285 hw_params.bits_per_sample(), |
| 288 hardware_config_->GetHighLatencyBufferSize()); | 286 hardware_config_->GetHighLatencyBufferSize()); |
| 289 } | 287 } |
| 290 | 288 |
| 289 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
| 290 |
| 291 audio_buffer_stream_.Initialize( | 291 audio_buffer_stream_.Initialize( |
| 292 stream, | 292 stream, |
| 293 false, | 293 false, |
| 294 statistics_cb, | 294 statistics_cb, |
| 295 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 295 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| 296 weak_factory_.GetWeakPtr())); | 296 weak_factory_.GetWeakPtr())); |
| 297 } | 297 } |
| 298 | 298 |
| 299 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 299 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
| 300 DCHECK(task_runner_->BelongsToCurrentThread()); | 300 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 bool AudioRendererImpl::IsBeforePrerollTime( | 558 bool AudioRendererImpl::IsBeforePrerollTime( |
| 559 const scoped_refptr<AudioBuffer>& buffer) { | 559 const scoped_refptr<AudioBuffer>& buffer) { |
| 560 DCHECK_EQ(state_, kPrerolling); | 560 DCHECK_EQ(state_, kPrerolling); |
| 561 return buffer && !buffer->end_of_stream() && | 561 return buffer && !buffer->end_of_stream() && |
| 562 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_; | 562 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_; |
| 563 } | 563 } |
| 564 | 564 |
| 565 int AudioRendererImpl::Render(AudioBus* audio_bus, | 565 int AudioRendererImpl::Render(AudioBus* audio_bus, |
| 566 int audio_delay_milliseconds) { | 566 int audio_delay_milliseconds) { |
| 567 const int requested_frames = audio_bus->frames(); | 567 const int requested_frames = audio_bus->frames(); |
| 568 base::TimeDelta current_time = kNoTimestamp(); | |
| 569 base::TimeDelta max_time = kNoTimestamp(); | |
| 570 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( | 568 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( |
| 571 audio_delay_milliseconds); | 569 audio_delay_milliseconds); |
| 572 | 570 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * |
| 571 audio_parameters_.sample_rate()); |
| 573 int frames_written = 0; | 572 int frames_written = 0; |
| 573 base::Closure time_cb; |
| 574 base::Closure underflow_cb; | 574 base::Closure underflow_cb; |
| 575 { | 575 { |
| 576 base::AutoLock auto_lock(lock_); | 576 base::AutoLock auto_lock(lock_); |
| 577 | 577 |
| 578 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 578 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
| 579 if (!algorithm_) | 579 if (!algorithm_) { |
| 580 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 580 return 0; | 581 return 0; |
| 582 } |
| 581 | 583 |
| 582 float playback_rate = algorithm_->playback_rate(); | 584 float playback_rate = algorithm_->playback_rate(); |
| 583 if (playback_rate == 0) | 585 if (playback_rate == 0) { |
| 586 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 584 return 0; | 587 return 0; |
| 588 } |
| 585 | 589 |
| 586 // Mute audio by returning 0 when not playing. | 590 // Mute audio by returning 0 when not playing. |
| 587 if (state_ != kPlaying) | 591 if (state_ != kPlaying) { |
| 592 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 588 return 0; | 593 return 0; |
| 594 } |
| 589 | 595 |
| 590 // We use the following conditions to determine end of playback: | 596 // We use the following conditions to determine end of playback: |
| 591 // 1) Algorithm can not fill the audio callback buffer | 597 // 1) Algorithm can not fill the audio callback buffer |
| 592 // 2) We received an end of stream buffer | 598 // 2) We received an end of stream buffer |
| 593 // 3) We haven't already signalled that we've ended | 599 // 3) We haven't already signalled that we've ended |
| 594 // 4) Our estimated earliest end time has expired | 600 // 4) Our estimated earliest end time has expired |
| 595 // | 601 // |
| 596 // TODO(enal): we should replace (4) with a check that the browser has no | 602 // TODO(enal): we should replace (4) with a check that the browser has no |
| 597 // more audio data or at least use a delayed callback. | 603 // more audio data or at least use a delayed callback. |
| 598 // | 604 // |
| 599 // We use the following conditions to determine underflow: | 605 // We use the following conditions to determine underflow: |
| 600 // 1) Algorithm can not fill the audio callback buffer | 606 // 1) Algorithm can not fill the audio callback buffer |
| 601 // 2) We have NOT received an end of stream buffer | 607 // 2) We have NOT received an end of stream buffer |
| 602 // 3) We are in the kPlaying state | 608 // 3) We are in the kPlaying state |
| 603 // | 609 // |
| 604 // Otherwise the buffer has data we can send to the device. | 610 // Otherwise the buffer has data we can send to the device. |
| 605 const base::TimeDelta time_before_filling = algorithm_->GetTime(); | 611 const base::TimeDelta media_timestamp_before_filling = |
| 606 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); | 612 audio_clock_->CurrentMediaTimestamp(); |
| 613 if (algorithm_->frames_buffered() > 0) { |
| 614 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); |
| 615 audio_clock_->WroteAudio( |
| 616 frames_written, delay_frames, playback_rate, algorithm_->GetTime()); |
| 617 } |
| 618 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); |
| 619 |
| 607 if (frames_written == 0) { | 620 if (frames_written == 0) { |
| 608 const base::TimeTicks now = now_cb_.Run(); | 621 const base::TimeTicks now = now_cb_.Run(); |
| 609 | 622 |
| 610 if (received_end_of_stream_ && !rendered_end_of_stream_ && | 623 if (received_end_of_stream_ && !rendered_end_of_stream_ && |
| 611 now >= earliest_end_time_) { | 624 now >= earliest_end_time_) { |
| 612 rendered_end_of_stream_ = true; | 625 rendered_end_of_stream_ = true; |
| 613 ended_cb_.Run(); | 626 ended_cb_.Run(); |
| 614 } else if (!received_end_of_stream_ && state_ == kPlaying && | 627 } else if (!received_end_of_stream_ && state_ == kPlaying && |
| 615 !underflow_disabled_) { | 628 !underflow_disabled_) { |
| 616 ChangeState_Locked(kUnderflow); | 629 ChangeState_Locked(kUnderflow); |
| 617 underflow_cb = underflow_cb_; | 630 underflow_cb = underflow_cb_; |
| 618 } else { | 631 } else { |
| 619 // We can't write any data this cycle. For example, we may have | 632 // We can't write any data this cycle. For example, we may have |
| 620 // sent all available data to the audio device while not reaching | 633 // sent all available data to the audio device while not reaching |
| 621 // |earliest_end_time_|. | 634 // |earliest_end_time_|. |
| 622 } | 635 } |
| 623 } | 636 } |
| 624 | 637 |
| 625 if (CanRead_Locked()) { | 638 if (CanRead_Locked()) { |
| 626 task_runner_->PostTask(FROM_HERE, | 639 task_runner_->PostTask(FROM_HERE, |
| 627 base::Bind(&AudioRendererImpl::AttemptRead, | 640 base::Bind(&AudioRendererImpl::AttemptRead, |
| 628 weak_factory_.GetWeakPtr())); | 641 weak_factory_.GetWeakPtr())); |
| 629 } | 642 } |
| 630 | 643 |
| 631 // Adjust the delay according to playback rate. | 644 // We only want to execute |time_cb_| if time has progressed and we haven't |
| 632 base::TimeDelta adjusted_playback_delay = base::TimeDelta::FromMicroseconds( | 645 // signaled end of stream yet. |
| 633 ceil(playback_delay.InMicroseconds() * playback_rate)); | 646 if (media_timestamp_before_filling != |
| 634 | 647 audio_clock_->CurrentMediaTimestamp() && |
| 635 // The |audio_time_buffered_| is the ending timestamp of the last frame | 648 !rendered_end_of_stream_) { |
| 636 // buffered at the audio device. |playback_delay| is the amount of time | 649 time_cb = base::Bind(time_cb_, |
| 637 // buffered at the audio device. The current time can be computed by their | 650 audio_clock_->CurrentMediaTimestamp(), |
| 638 // difference. | 651 audio_clock_->last_endpoint_timestamp()); |
| 639 if (audio_time_buffered_ != kNoTimestamp()) { | |
| 640 base::TimeDelta previous_time = current_time_; | |
| 641 current_time_ = audio_time_buffered_ - adjusted_playback_delay; | |
| 642 | |
| 643 // Time can change in one of two ways: | |
| 644 // 1) The time of the audio data at the audio device changed, or | |
| 645 // 2) The playback delay value has changed | |
| 646 // | |
| 647 // We only want to set |current_time| (and thus execute |time_cb_|) if | |
| 648 // time has progressed and we haven't signaled end of stream yet. | |
| 649 // | |
| 650 // Why? The current latency of the system results in getting the last call | |
| 651 // to FillBuffer() later than we'd like, which delays firing the 'ended' | |
| 652 // event, which delays the looping/trigging performance of short sound | |
| 653 // effects. | |
| 654 // | |
| 655 // TODO(scherkus): revisit this and switch back to relying on playback | |
| 656 // delay after we've revamped our audio IPC subsystem. | |
| 657 if (current_time_ > previous_time && !rendered_end_of_stream_) { | |
| 658 current_time = current_time_; | |
| 659 } | |
| 660 } else if (frames_written > 0) { | |
| 661 // Nothing has been buffered yet, so use the first buffer's timestamp. | |
| 662 DCHECK(time_before_filling != kNoTimestamp()); | |
| 663 current_time_ = current_time = | |
| 664 time_before_filling - adjusted_playback_delay; | |
| 665 } | 652 } |
| 666 | 653 |
| 667 // The call to FillBuffer() on |algorithm_| has increased the amount of | |
| 668 // buffered audio data. Update the new amount of time buffered. | |
| 669 max_time = algorithm_->GetTime(); | |
| 670 audio_time_buffered_ = max_time; | |
| 671 | |
| 672 if (frames_written > 0) { | 654 if (frames_written > 0) { |
| 673 UpdateEarliestEndTime_Locked( | 655 UpdateEarliestEndTime_Locked( |
| 674 frames_written, playback_delay, now_cb_.Run()); | 656 frames_written, playback_delay, now_cb_.Run()); |
| 675 } | 657 } |
| 676 } | 658 } |
| 677 | 659 |
| 678 if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) | 660 if (!time_cb.is_null()) |
| 679 time_cb_.Run(current_time, max_time); | 661 time_cb.Run(); |
| 680 | 662 |
| 681 if (!underflow_cb.is_null()) | 663 if (!underflow_cb.is_null()) |
| 682 underflow_cb.Run(); | 664 underflow_cb.Run(); |
| 683 | 665 |
| 684 DCHECK_LE(frames_written, requested_frames); | 666 DCHECK_LE(frames_written, requested_frames); |
| 685 return frames_written; | 667 return frames_written; |
| 686 } | 668 } |
| 687 | 669 |
| 688 void AudioRendererImpl::UpdateEarliestEndTime_Locked( | 670 void AudioRendererImpl::UpdateEarliestEndTime_Locked( |
| 689 int frames_filled, const base::TimeDelta& playback_delay, | 671 int frames_filled, const base::TimeDelta& playback_delay, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 DCHECK(expecting_config_changes_); | 746 DCHECK(expecting_config_changes_); |
| 765 buffer_converter_->ResetTimestampState(); | 747 buffer_converter_->ResetTimestampState(); |
| 766 // Drain flushed buffers from the converter so the AudioSplicer receives all | 748 // Drain flushed buffers from the converter so the AudioSplicer receives all |
| 767 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should | 749 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should |
| 768 // only appear after config changes, AddInput() should never fail here. | 750 // only appear after config changes, AddInput() should never fail here. |
| 769 while (buffer_converter_->HasNextBuffer()) | 751 while (buffer_converter_->HasNextBuffer()) |
| 770 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); | 752 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); |
| 771 } | 753 } |
| 772 | 754 |
| 773 } // namespace media | 755 } // namespace media |
| OLD | NEW |