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

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

Issue 436053002: Make media::AudioClock track frames written to compute time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix time_cb Created 6 years, 4 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 | Annotate | Revision Log
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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 140
141 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) { 141 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) {
142 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; 142 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
143 DCHECK(task_runner_->BelongsToCurrentThread()); 143 DCHECK(task_runner_->BelongsToCurrentThread());
144 144
145 base::AutoLock auto_lock(lock_); 145 base::AutoLock auto_lock(lock_);
146 DCHECK(!rendering_); 146 DCHECK(!rendering_);
147 DCHECK_EQ(state_, kFlushed); 147 DCHECK_EQ(state_, kFlushed);
148 148
149 start_timestamp_ = time; 149 start_timestamp_ = time;
150 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate()));
150 } 151 }
151 152
152 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { 153 base::TimeDelta AudioRendererImpl::CurrentMediaTime() {
153 DVLOG(1) << __FUNCTION__; 154 DVLOG(1) << __FUNCTION__;
154 DCHECK(task_runner_->BelongsToCurrentThread()); 155 DCHECK(task_runner_->BelongsToCurrentThread());
155 156
156 // TODO(scherkus): Finish implementing when ready to switch Pipeline to using 157 // TODO(scherkus): Finish implementing when ready to switch Pipeline to using
157 // TimeSource http://crbug.com/370634 158 // TimeSource http://crbug.com/370634
158 NOTIMPLEMENTED(); 159 NOTIMPLEMENTED();
159 160
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 195 }
195 196
196 void AudioRendererImpl::ResetDecoderDone() { 197 void AudioRendererImpl::ResetDecoderDone() {
197 DCHECK(task_runner_->BelongsToCurrentThread()); 198 DCHECK(task_runner_->BelongsToCurrentThread());
198 { 199 {
199 base::AutoLock auto_lock(lock_); 200 base::AutoLock auto_lock(lock_);
200 201
201 DCHECK_EQ(state_, kFlushed); 202 DCHECK_EQ(state_, kFlushed);
202 DCHECK(!flush_cb_.is_null()); 203 DCHECK(!flush_cb_.is_null());
203 204
204 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 205 audio_clock_.reset();
205 received_end_of_stream_ = false; 206 received_end_of_stream_ = false;
206 rendered_end_of_stream_ = false; 207 rendered_end_of_stream_ = false;
207 208
208 // Flush() may have been called while underflowed/not fully buffered. 209 // Flush() may have been called while underflowed/not fully buffered.
209 if (buffering_state_ != BUFFERING_HAVE_NOTHING) 210 if (buffering_state_ != BUFFERING_HAVE_NOTHING)
210 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); 211 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
211 212
212 splicer_->Reset(); 213 splicer_->Reset();
213 if (buffer_converter_) 214 if (buffer_converter_)
214 buffer_converter_->Reset(); 215 buffer_converter_->Reset();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // unnecessary upmixing overhead. 288 // unnecessary upmixing overhead.
288 stream->audio_decoder_config().channel_layout(), 289 stream->audio_decoder_config().channel_layout(),
289 ChannelLayoutToChannelCount( 290 ChannelLayoutToChannelCount(
290 stream->audio_decoder_config().channel_layout()), 291 stream->audio_decoder_config().channel_layout()),
291 hw_params.input_channels(), 292 hw_params.input_channels(),
292 hw_params.sample_rate(), 293 hw_params.sample_rate(),
293 hw_params.bits_per_sample(), 294 hw_params.bits_per_sample(),
294 hardware_config_->GetHighLatencyBufferSize()); 295 hardware_config_->GetHighLatencyBufferSize());
295 } 296 }
296 297
297 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 298 audio_clock_.reset(
299 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate()));
298 300
299 audio_buffer_stream_->Initialize( 301 audio_buffer_stream_->Initialize(
300 stream, 302 stream,
301 false, 303 false,
302 statistics_cb, 304 statistics_cb,
303 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, 305 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
304 weak_factory_.GetWeakPtr())); 306 weak_factory_.GetWeakPtr()));
305 } 307 }
306 308
307 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { 309 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 audio_delay_milliseconds); 544 audio_delay_milliseconds);
543 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 545 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
544 audio_parameters_.sample_rate()); 546 audio_parameters_.sample_rate());
545 int frames_written = 0; 547 int frames_written = 0;
546 base::Closure time_cb; 548 base::Closure time_cb;
547 { 549 {
548 base::AutoLock auto_lock(lock_); 550 base::AutoLock auto_lock(lock_);
549 551
550 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 552 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
551 if (!algorithm_) { 553 if (!algorithm_) {
552 audio_clock_->WroteSilence(requested_frames, delay_frames); 554 audio_clock_->WroteAudio(
555 0, requested_frames, delay_frames, playback_rate_);
553 return 0; 556 return 0;
554 } 557 }
555 558
556 if (playback_rate_ == 0) { 559 if (playback_rate_ == 0) {
557 audio_clock_->WroteSilence(requested_frames, delay_frames); 560 audio_clock_->WroteAudio(
561 0, requested_frames, delay_frames, playback_rate_);
558 return 0; 562 return 0;
559 } 563 }
560 564
561 // Mute audio by returning 0 when not playing. 565 // Mute audio by returning 0 when not playing.
562 if (state_ != kPlaying) { 566 if (state_ != kPlaying) {
563 audio_clock_->WroteSilence(requested_frames, delay_frames); 567 audio_clock_->WroteAudio(
568 0, requested_frames, delay_frames, playback_rate_);
564 return 0; 569 return 0;
565 } 570 }
566 571
567 // We use the following conditions to determine end of playback: 572 // We use the following conditions to determine end of playback:
568 // 1) Algorithm can not fill the audio callback buffer 573 // 1) Algorithm can not fill the audio callback buffer
569 // 2) We received an end of stream buffer 574 // 2) We received an end of stream buffer
570 // 3) We haven't already signalled that we've ended 575 // 3) We haven't already signalled that we've ended
571 // 4) We've played all known audio data sent to hardware 576 // 4) We've played all known audio data sent to hardware
572 // 577 //
573 // We use the following conditions to determine underflow: 578 // We use the following conditions to determine underflow:
574 // 1) Algorithm can not fill the audio callback buffer 579 // 1) Algorithm can not fill the audio callback buffer
575 // 2) We have NOT received an end of stream buffer 580 // 2) We have NOT received an end of stream buffer
576 // 3) We are in the kPlaying state 581 // 3) We are in the kPlaying state
577 // 582 //
578 // Otherwise the buffer has data we can send to the device. 583 // Otherwise the buffer has data we can send to the device.
579 const base::TimeDelta media_timestamp_before_filling =
580 audio_clock_->CurrentMediaTimestamp(base::TimeDelta());
581 if (algorithm_->frames_buffered() > 0) { 584 if (algorithm_->frames_buffered() > 0) {
582 frames_written = 585 frames_written =
583 algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_); 586 algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_);
584 audio_clock_->WroteAudio(
585 frames_written, delay_frames, playback_rate_, algorithm_->GetTime());
586 } 587 }
587 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); 588 base::TimeDelta previous_media_timestamp =
589 audio_clock_->current_media_timestamp();
590 audio_clock_->WroteAudio(
591 frames_written, requested_frames, delay_frames, playback_rate_);
588 592
589 if (frames_written == 0) { 593 if (frames_written == 0) {
590 if (received_end_of_stream_ && !rendered_end_of_stream_ && 594 if (received_end_of_stream_ && !rendered_end_of_stream_ &&
591 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()) == 595 !audio_clock_->audio_data_buffered()) {
592 audio_clock_->last_endpoint_timestamp()) {
593 rendered_end_of_stream_ = true; 596 rendered_end_of_stream_ = true;
594 task_runner_->PostTask(FROM_HERE, ended_cb_); 597 task_runner_->PostTask(FROM_HERE, ended_cb_);
595 } else if (!received_end_of_stream_ && state_ == kPlaying) { 598 } else if (!received_end_of_stream_ && state_ == kPlaying) {
596 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { 599 if (buffering_state_ != BUFFERING_HAVE_NOTHING) {
597 algorithm_->IncreaseQueueCapacity(); 600 algorithm_->IncreaseQueueCapacity();
598 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); 601 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
599 } 602 }
600 } 603 }
601 } 604 }
602 605
603 if (CanRead_Locked()) { 606 if (CanRead_Locked()) {
604 task_runner_->PostTask(FROM_HERE, 607 task_runner_->PostTask(FROM_HERE,
605 base::Bind(&AudioRendererImpl::AttemptRead, 608 base::Bind(&AudioRendererImpl::AttemptRead,
606 weak_factory_.GetWeakPtr())); 609 weak_factory_.GetWeakPtr()));
607 } 610 }
608 611
609 // We only want to execute |time_cb_| if time has progressed and we haven't 612 // Firing |ended_cb_| means we no longer need to run |time_cb_|.
610 // signaled end of stream yet. 613 if (!rendered_end_of_stream_ &&
611 if (media_timestamp_before_filling != 614 previous_media_timestamp != audio_clock_->current_media_timestamp()) {
612 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()) && 615 // Since |max_time| uses linear interpolation, only provide an upper bound
613 !rendered_end_of_stream_) { 616 // that is for audio data at the same playback rate. Failing to do so can
614 time_cb = 617 // make time jump backwards when the linear interpolated time advances
615 base::Bind(time_cb_, 618 // past buffered regions of audio at different rates.
616 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()), 619 base::TimeDelta current_timestamp =
617 audio_clock_->last_endpoint_timestamp()); 620 audio_clock_->current_media_timestamp();
621 base::TimeDelta max_time =
622 current_timestamp +
623 audio_clock_->contiguous_audio_data_buffered_at_same_rate();
624 time_cb = base::Bind(time_cb_, current_timestamp, max_time);
618 } 625 }
619 } 626 }
620 627
621 if (!time_cb.is_null()) 628 if (!time_cb.is_null())
622 task_runner_->PostTask(FROM_HERE, time_cb); 629 task_runner_->PostTask(FROM_HERE, time_cb);
623 630
624 DCHECK_LE(frames_written, requested_frames); 631 DCHECK_LE(frames_written, requested_frames);
625 return frames_written; 632 return frames_written;
626 } 633 }
627 634
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 << buffering_state; 700 << buffering_state;
694 DCHECK_NE(buffering_state_, buffering_state); 701 DCHECK_NE(buffering_state_, buffering_state);
695 lock_.AssertAcquired(); 702 lock_.AssertAcquired();
696 buffering_state_ = buffering_state; 703 buffering_state_ = buffering_state;
697 704
698 task_runner_->PostTask(FROM_HERE, 705 task_runner_->PostTask(FROM_HERE,
699 base::Bind(buffering_state_cb_, buffering_state_)); 706 base::Bind(buffering_state_cb_, buffering_state_));
700 } 707 }
701 708
702 } // namespace media 709 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698