Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 518613002: Have AudioRendererImpl advance time until it's told to stop. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/renderer_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 141
142 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) { 142 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) {
143 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; 143 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
144 DCHECK(task_runner_->BelongsToCurrentThread()); 144 DCHECK(task_runner_->BelongsToCurrentThread());
145 145
146 base::AutoLock auto_lock(lock_); 146 base::AutoLock auto_lock(lock_);
147 DCHECK(!rendering_); 147 DCHECK(!rendering_);
148 DCHECK_EQ(state_, kFlushed); 148 DCHECK_EQ(state_, kFlushed);
149 149
150 start_timestamp_ = time; 150 start_timestamp_ = time;
151 ended_timestamp_ = kInfiniteDuration();
151 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); 152 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate()));
152 } 153 }
153 154
154 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { 155 base::TimeDelta AudioRendererImpl::CurrentMediaTime() {
155 DVLOG(2) << __FUNCTION__; 156 DVLOG(2) << __FUNCTION__;
156 DCHECK(task_runner_->BelongsToCurrentThread()); 157 DCHECK(task_runner_->BelongsToCurrentThread());
157 158
158 // TODO(scherkus): Finish implementing when ready to switch Pipeline to using 159 // TODO(scherkus): Finish implementing when ready to switch Pipeline to using
159 // TimeSource http://crbug.com/370634 160 // TimeSource http://crbug.com/370634
160 NOTIMPLEMENTED(); 161 NOTIMPLEMENTED();
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 } 541 }
541 542
542 int AudioRendererImpl::Render(AudioBus* audio_bus, 543 int AudioRendererImpl::Render(AudioBus* audio_bus,
543 int audio_delay_milliseconds) { 544 int audio_delay_milliseconds) {
544 const int requested_frames = audio_bus->frames(); 545 const int requested_frames = audio_bus->frames();
545 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( 546 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
546 audio_delay_milliseconds); 547 audio_delay_milliseconds);
547 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 548 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
548 audio_parameters_.sample_rate()); 549 audio_parameters_.sample_rate());
549 int frames_written = 0; 550 int frames_written = 0;
550 base::Closure time_cb;
551 { 551 {
552 base::AutoLock auto_lock(lock_); 552 base::AutoLock auto_lock(lock_);
553 553
554 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 554 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
555 if (!algorithm_) { 555 if (!algorithm_) {
556 audio_clock_->WroteAudio( 556 audio_clock_->WroteAudio(
557 0, requested_frames, delay_frames, playback_rate_); 557 0, requested_frames, delay_frames, playback_rate_);
558 return 0; 558 return 0;
559 } 559 }
560 560
(...skipping 19 matching lines...) Expand all
580 // We use the following conditions to determine underflow: 580 // We use the following conditions to determine underflow:
581 // 1) Algorithm can not fill the audio callback buffer 581 // 1) Algorithm can not fill the audio callback buffer
582 // 2) We have NOT received an end of stream buffer 582 // 2) We have NOT received an end of stream buffer
583 // 3) We are in the kPlaying state 583 // 3) We are in the kPlaying state
584 // 584 //
585 // Otherwise the buffer has data we can send to the device. 585 // Otherwise the buffer has data we can send to the device.
586 if (algorithm_->frames_buffered() > 0) { 586 if (algorithm_->frames_buffered() > 0) {
587 frames_written = 587 frames_written =
588 algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_); 588 algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_);
589 } 589 }
590 audio_clock_->WroteAudio(
591 frames_written, requested_frames, delay_frames, playback_rate_);
592 590
591 // Per the TimeSource API the media time should always increase even after
592 // we've rendered all known audio data. Doing so simplifies scenarios where
593 // we have other sources of media data that need to be scheduled after audio
594 // data has ended.
595 //
596 // That being said, we don't want to advance time when underflowed as we
597 // know more decoded frames will eventually arrive. If we did, we would
598 // throw things out of sync when said decoded frames arrive.
599 int frames_after_end_of_stream = 0;
593 if (frames_written == 0) { 600 if (frames_written == 0) {
594 if (received_end_of_stream_ && !rendered_end_of_stream_ && 601 if (received_end_of_stream_) {
595 !audio_clock_->audio_data_buffered()) { 602 if (ended_timestamp_ == kInfiniteDuration())
596 rendered_end_of_stream_ = true; 603 ended_timestamp_ = audio_clock_->back_timestamp();
597 task_runner_->PostTask(FROM_HERE, ended_cb_); 604 frames_after_end_of_stream = requested_frames;
598 } else if (!received_end_of_stream_ && state_ == kPlaying) { 605 } else if (state_ == kPlaying &&
599 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { 606 buffering_state_ != BUFFERING_HAVE_NOTHING) {
600 algorithm_->IncreaseQueueCapacity(); 607 algorithm_->IncreaseQueueCapacity();
601 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); 608 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
602 }
603 } 609 }
604 } 610 }
605 611
612 audio_clock_->WroteAudio(frames_written + frames_after_end_of_stream,
613 requested_frames,
614 delay_frames,
615 playback_rate_);
616
606 if (CanRead_Locked()) { 617 if (CanRead_Locked()) {
607 task_runner_->PostTask(FROM_HERE, 618 task_runner_->PostTask(FROM_HERE,
608 base::Bind(&AudioRendererImpl::AttemptRead, 619 base::Bind(&AudioRendererImpl::AttemptRead,
609 weak_factory_.GetWeakPtr())); 620 weak_factory_.GetWeakPtr()));
610 } 621 }
611 622
612 // Firing |ended_cb_| means we no longer need to run |time_cb_|. 623 if (last_timestamp_update_ != audio_clock_->front_timestamp()) {
613 if (!rendered_end_of_stream_ &&
614 last_timestamp_update_ != audio_clock_->current_media_timestamp()) {
615 // Since |max_time| uses linear interpolation, only provide an upper bound 624 // Since |max_time| uses linear interpolation, only provide an upper bound
616 // that is for audio data at the same playback rate. Failing to do so can 625 // that is for audio data at the same playback rate. Failing to do so can
617 // make time jump backwards when the linear interpolated time advances 626 // make time jump backwards when the linear interpolated time advances
618 // past buffered regions of audio at different rates. 627 // past buffered regions of audio at different rates.
619 last_timestamp_update_ = audio_clock_->current_media_timestamp(); 628 last_timestamp_update_ = audio_clock_->front_timestamp();
620 base::TimeDelta max_time = 629 base::TimeDelta max_time =
621 last_timestamp_update_ + 630 last_timestamp_update_ +
622 audio_clock_->contiguous_audio_data_buffered_at_same_rate(); 631 audio_clock_->contiguous_audio_data_buffered_at_same_rate();
623 time_cb = base::Bind(time_cb_, last_timestamp_update_, max_time); 632 task_runner_->PostTask(
633 FROM_HERE, base::Bind(time_cb_, last_timestamp_update_, max_time));
634
635 if (last_timestamp_update_ >= ended_timestamp_ &&
636 !rendered_end_of_stream_) {
637 rendered_end_of_stream_ = true;
638 task_runner_->PostTask(FROM_HERE, ended_cb_);
639 }
624 } 640 }
625 } 641 }
626 642
627 if (!time_cb.is_null())
628 task_runner_->PostTask(FROM_HERE, time_cb);
629
630 DCHECK_LE(frames_written, requested_frames); 643 DCHECK_LE(frames_written, requested_frames);
631 return frames_written; 644 return frames_written;
632 } 645 }
633 646
634 void AudioRendererImpl::OnRenderError() { 647 void AudioRendererImpl::OnRenderError() {
635 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead 648 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
636 // of trying to gracefully fall back to a fake sink. It's very likely 649 // of trying to gracefully fall back to a fake sink. It's very likely
637 // OnRenderError() should be removed and the audio stack handle errors without 650 // OnRenderError() should be removed and the audio stack handle errors without
638 // notifying clients. See http://crbug.com/234708 for details. 651 // notifying clients. See http://crbug.com/234708 for details.
639 HistogramRendererEvent(RENDER_ERROR); 652 HistogramRendererEvent(RENDER_ERROR);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 << buffering_state; 712 << buffering_state;
700 DCHECK_NE(buffering_state_, buffering_state); 713 DCHECK_NE(buffering_state_, buffering_state);
701 lock_.AssertAcquired(); 714 lock_.AssertAcquired();
702 buffering_state_ = buffering_state; 715 buffering_state_ = buffering_state;
703 716
704 task_runner_->PostTask(FROM_HERE, 717 task_runner_->PostTask(FROM_HERE,
705 base::Bind(buffering_state_cb_, buffering_state_)); 718 base::Bind(buffering_state_cb_, buffering_state_));
706 } 719 }
707 720
708 } // namespace media 721 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/renderer_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698