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 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 } | 90 } |
91 | 91 |
92 void AudioRendererImpl::StartRendering_Locked() { | 92 void AudioRendererImpl::StartRendering_Locked() { |
93 DVLOG(1) << __FUNCTION__; | 93 DVLOG(1) << __FUNCTION__; |
94 DCHECK(task_runner_->BelongsToCurrentThread()); | 94 DCHECK(task_runner_->BelongsToCurrentThread()); |
95 DCHECK_EQ(state_, kPlaying); | 95 DCHECK_EQ(state_, kPlaying); |
96 DCHECK(!sink_playing_); | 96 DCHECK(!sink_playing_); |
97 DCHECK_NE(algorithm_->playback_rate(), 0); | 97 DCHECK_NE(algorithm_->playback_rate(), 0); |
98 lock_.AssertAcquired(); | 98 lock_.AssertAcquired(); |
99 | 99 |
100 earliest_end_time_ = now_cb_.Run(); | |
101 sink_playing_ = true; | 100 sink_playing_ = true; |
102 | 101 |
103 base::AutoUnlock auto_unlock(lock_); | 102 base::AutoUnlock auto_unlock(lock_); |
104 sink_->Play(); | 103 sink_->Play(); |
105 } | 104 } |
106 | 105 |
107 void AudioRendererImpl::StopRendering() { | 106 void AudioRendererImpl::StopRendering() { |
108 DVLOG(1) << __FUNCTION__; | 107 DVLOG(1) << __FUNCTION__; |
109 DCHECK(task_runner_->BelongsToCurrentThread()); | 108 DCHECK(task_runner_->BelongsToCurrentThread()); |
110 DCHECK(rendering_); | 109 DCHECK(rendering_); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 DCHECK(!flush_cb_.is_null()); | 171 DCHECK(!flush_cb_.is_null()); |
173 | 172 |
174 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 173 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
175 received_end_of_stream_ = false; | 174 received_end_of_stream_ = false; |
176 rendered_end_of_stream_ = false; | 175 rendered_end_of_stream_ = false; |
177 | 176 |
178 // Flush() may have been called while underflowed/not fully buffered. | 177 // Flush() may have been called while underflowed/not fully buffered. |
179 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 178 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
180 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 179 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
181 | 180 |
182 earliest_end_time_ = now_cb_.Run(); | |
183 splicer_->Reset(); | 181 splicer_->Reset(); |
184 if (buffer_converter_) | 182 if (buffer_converter_) |
185 buffer_converter_->Reset(); | 183 buffer_converter_->Reset(); |
186 algorithm_->FlushBuffers(); | 184 algorithm_->FlushBuffers(); |
187 } | 185 } |
188 | 186 |
189 // Changes in buffering state are always posted. Flush callback must only be | 187 // Changes in buffering state are always posted. Flush callback must only be |
190 // run after buffering state has been set back to nothing. | 188 // run after buffering state has been set back to nothing. |
191 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 189 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
192 } | 190 } |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 // Mute audio by returning 0 when not playing. | 572 // Mute audio by returning 0 when not playing. |
575 if (state_ != kPlaying) { | 573 if (state_ != kPlaying) { |
576 audio_clock_->WroteSilence(requested_frames, delay_frames); | 574 audio_clock_->WroteSilence(requested_frames, delay_frames); |
577 return 0; | 575 return 0; |
578 } | 576 } |
579 | 577 |
580 // We use the following conditions to determine end of playback: | 578 // We use the following conditions to determine end of playback: |
581 // 1) Algorithm can not fill the audio callback buffer | 579 // 1) Algorithm can not fill the audio callback buffer |
582 // 2) We received an end of stream buffer | 580 // 2) We received an end of stream buffer |
583 // 3) We haven't already signalled that we've ended | 581 // 3) We haven't already signalled that we've ended |
584 // 4) Our estimated earliest end time has expired | 582 // 4) We've played all known audio data sent to hardware |
585 // | |
586 // TODO(enal): we should replace (4) with a check that the browser has no | |
587 // more audio data or at least use a delayed callback. | |
588 // | 583 // |
589 // We use the following conditions to determine underflow: | 584 // We use the following conditions to determine underflow: |
590 // 1) Algorithm can not fill the audio callback buffer | 585 // 1) Algorithm can not fill the audio callback buffer |
591 // 2) We have NOT received an end of stream buffer | 586 // 2) We have NOT received an end of stream buffer |
592 // 3) We are in the kPlaying state | 587 // 3) We are in the kPlaying state |
593 // | 588 // |
594 // Otherwise the buffer has data we can send to the device. | 589 // Otherwise the buffer has data we can send to the device. |
595 const base::TimeDelta media_timestamp_before_filling = | 590 const base::TimeDelta media_timestamp_before_filling = |
596 audio_clock_->CurrentMediaTimestamp(); | 591 audio_clock_->CurrentMediaTimestamp(); |
597 if (algorithm_->frames_buffered() > 0) { | 592 if (algorithm_->frames_buffered() > 0) { |
598 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); | 593 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); |
599 audio_clock_->WroteAudio( | 594 audio_clock_->WroteAudio( |
600 frames_written, delay_frames, playback_rate, algorithm_->GetTime()); | 595 frames_written, delay_frames, playback_rate, algorithm_->GetTime()); |
601 } | 596 } |
602 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); | 597 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); |
603 | 598 |
604 if (frames_written == 0) { | 599 if (frames_written == 0) { |
605 const base::TimeTicks now = now_cb_.Run(); | |
606 | |
607 if (received_end_of_stream_ && !rendered_end_of_stream_ && | 600 if (received_end_of_stream_ && !rendered_end_of_stream_ && |
608 now >= earliest_end_time_) { | 601 audio_clock_->CurrentMediaTimestamp() == |
| 602 audio_clock_->last_endpoint_timestamp()) { |
609 rendered_end_of_stream_ = true; | 603 rendered_end_of_stream_ = true; |
610 ended_cb_.Run(); | 604 ended_cb_.Run(); |
611 } else if (!received_end_of_stream_ && state_ == kPlaying) { | 605 } else if (!received_end_of_stream_ && state_ == kPlaying) { |
612 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { | 606 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { |
613 algorithm_->IncreaseQueueCapacity(); | 607 algorithm_->IncreaseQueueCapacity(); |
614 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 608 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
615 } | 609 } |
616 } else { | |
617 // We can't write any data this cycle. For example, we may have | |
618 // sent all available data to the audio device while not reaching | |
619 // |earliest_end_time_|. | |
620 } | 610 } |
621 } | 611 } |
622 | 612 |
623 if (CanRead_Locked()) { | 613 if (CanRead_Locked()) { |
624 task_runner_->PostTask(FROM_HERE, | 614 task_runner_->PostTask(FROM_HERE, |
625 base::Bind(&AudioRendererImpl::AttemptRead, | 615 base::Bind(&AudioRendererImpl::AttemptRead, |
626 weak_factory_.GetWeakPtr())); | 616 weak_factory_.GetWeakPtr())); |
627 } | 617 } |
628 | 618 |
629 // We only want to execute |time_cb_| if time has progressed and we haven't | 619 // We only want to execute |time_cb_| if time has progressed and we haven't |
630 // signaled end of stream yet. | 620 // signaled end of stream yet. |
631 if (media_timestamp_before_filling != | 621 if (media_timestamp_before_filling != |
632 audio_clock_->CurrentMediaTimestamp() && | 622 audio_clock_->CurrentMediaTimestamp() && |
633 !rendered_end_of_stream_) { | 623 !rendered_end_of_stream_) { |
634 time_cb = base::Bind(time_cb_, | 624 time_cb = base::Bind(time_cb_, |
635 audio_clock_->CurrentMediaTimestamp(), | 625 audio_clock_->CurrentMediaTimestamp(), |
636 audio_clock_->last_endpoint_timestamp()); | 626 audio_clock_->last_endpoint_timestamp()); |
637 } | 627 } |
638 | |
639 if (frames_written > 0) { | |
640 UpdateEarliestEndTime_Locked( | |
641 frames_written, playback_delay, now_cb_.Run()); | |
642 } | |
643 } | 628 } |
644 | 629 |
645 if (!time_cb.is_null()) | 630 if (!time_cb.is_null()) |
646 task_runner_->PostTask(FROM_HERE, time_cb); | 631 task_runner_->PostTask(FROM_HERE, time_cb); |
647 | 632 |
648 DCHECK_LE(frames_written, requested_frames); | 633 DCHECK_LE(frames_written, requested_frames); |
649 return frames_written; | 634 return frames_written; |
650 } | 635 } |
651 | 636 |
652 void AudioRendererImpl::UpdateEarliestEndTime_Locked( | |
653 int frames_filled, const base::TimeDelta& playback_delay, | |
654 const base::TimeTicks& time_now) { | |
655 DCHECK_GT(frames_filled, 0); | |
656 | |
657 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( | |
658 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond / | |
659 audio_parameters_.sample_rate()); | |
660 | |
661 lock_.AssertAcquired(); | |
662 earliest_end_time_ = std::max( | |
663 earliest_end_time_, time_now + playback_delay + predicted_play_time); | |
664 } | |
665 | |
666 void AudioRendererImpl::OnRenderError() { | 637 void AudioRendererImpl::OnRenderError() { |
667 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead | 638 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead |
668 // of trying to gracefully fall back to a fake sink. It's very likely | 639 // of trying to gracefully fall back to a fake sink. It's very likely |
669 // OnRenderError() should be removed and the audio stack handle errors without | 640 // OnRenderError() should be removed and the audio stack handle errors without |
670 // notifying clients. See http://crbug.com/234708 for details. | 641 // notifying clients. See http://crbug.com/234708 for details. |
671 HistogramRendererEvent(RENDER_ERROR); | 642 HistogramRendererEvent(RENDER_ERROR); |
672 error_cb_.Run(PIPELINE_ERROR_DECODE); | 643 error_cb_.Run(PIPELINE_ERROR_DECODE); |
673 } | 644 } |
674 | 645 |
675 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { | 646 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 << buffering_state; | 700 << buffering_state; |
730 DCHECK_NE(buffering_state_, buffering_state); | 701 DCHECK_NE(buffering_state_, buffering_state); |
731 lock_.AssertAcquired(); | 702 lock_.AssertAcquired(); |
732 buffering_state_ = buffering_state; | 703 buffering_state_ = buffering_state; |
733 | 704 |
734 task_runner_->PostTask(FROM_HERE, | 705 task_runner_->PostTask(FROM_HERE, |
735 base::Bind(buffering_state_cb_, buffering_state_)); | 706 base::Bind(buffering_state_cb_, buffering_state_)); |
736 } | 707 } |
737 | 708 |
738 } // namespace media | 709 } // namespace media |
OLD | NEW |