Chromium Code Reviews| 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/pipeline.h" | 5 #include "media/base/pipeline.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/synchronization/condition_variable.h" | 19 #include "base/synchronization/condition_variable.h" |
| 20 #include "media/base/audio_decoder.h" | 20 #include "media/base/audio_decoder.h" |
| 21 #include "media/base/audio_renderer.h" | 21 #include "media/base/audio_renderer.h" |
| 22 #include "media/base/clock.h" | |
| 23 #include "media/base/filter_collection.h" | 22 #include "media/base/filter_collection.h" |
| 24 #include "media/base/media_log.h" | 23 #include "media/base/media_log.h" |
| 25 #include "media/base/text_renderer.h" | 24 #include "media/base/text_renderer.h" |
| 26 #include "media/base/text_track_config.h" | 25 #include "media/base/text_track_config.h" |
| 26 #include "media/base/time_delta_interpolator.h" | |
| 27 #include "media/base/video_decoder.h" | 27 #include "media/base/video_decoder.h" |
| 28 #include "media/base/video_decoder_config.h" | 28 #include "media/base/video_decoder_config.h" |
| 29 #include "media/base/video_renderer.h" | 29 #include "media/base/video_renderer.h" |
| 30 | 30 |
| 31 using base::TimeDelta; | 31 using base::TimeDelta; |
| 32 | 32 |
| 33 namespace media { | 33 namespace media { |
| 34 | 34 |
| 35 Pipeline::Pipeline( | 35 Pipeline::Pipeline( |
| 36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 37 MediaLog* media_log) | 37 MediaLog* media_log) |
| 38 : task_runner_(task_runner), | 38 : task_runner_(task_runner), |
| 39 media_log_(media_log), | 39 media_log_(media_log), |
| 40 running_(false), | 40 running_(false), |
| 41 did_loading_progress_(false), | 41 did_loading_progress_(false), |
| 42 volume_(1.0f), | 42 volume_(1.0f), |
| 43 playback_rate_(0.0f), | 43 playback_rate_(0.0f), |
| 44 clock_(new Clock(&default_tick_clock_)), | 44 interpolator_(new TimeDeltaInterpolator(&default_tick_clock_)), |
| 45 clock_state_(CLOCK_PAUSED), | 45 interpolation_state_(INTERPOLATION_STOPPED), |
| 46 status_(PIPELINE_OK), | 46 status_(PIPELINE_OK), |
| 47 state_(kCreated), | 47 state_(kCreated), |
| 48 audio_ended_(false), | 48 audio_ended_(false), |
| 49 video_ended_(false), | 49 video_ended_(false), |
| 50 text_ended_(false), | 50 text_ended_(false), |
| 51 audio_buffering_state_(BUFFERING_HAVE_NOTHING), | 51 audio_buffering_state_(BUFFERING_HAVE_NOTHING), |
| 52 video_buffering_state_(BUFFERING_HAVE_NOTHING), | 52 video_buffering_state_(BUFFERING_HAVE_NOTHING), |
| 53 demuxer_(NULL), | 53 demuxer_(NULL), |
| 54 underflow_disabled_for_testing_(false) { | 54 underflow_disabled_for_testing_(false) { |
| 55 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 55 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 base::AutoLock auto_lock(lock_); | 149 base::AutoLock auto_lock(lock_); |
| 150 volume_ = volume; | 150 volume_ = volume; |
| 151 if (running_) { | 151 if (running_) { |
| 152 task_runner_->PostTask(FROM_HERE, base::Bind( | 152 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 153 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); | 153 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 TimeDelta Pipeline::GetMediaTime() const { | 157 TimeDelta Pipeline::GetMediaTime() const { |
| 158 base::AutoLock auto_lock(lock_); | 158 base::AutoLock auto_lock(lock_); |
| 159 return std::min(clock_->Elapsed(), duration_); | 159 return std::min(interpolator_->GetInterpolatedTime(), duration_); |
| 160 } | 160 } |
| 161 | 161 |
| 162 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { | 162 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { |
| 163 base::AutoLock auto_lock(lock_); | 163 base::AutoLock auto_lock(lock_); |
| 164 return buffered_time_ranges_; | 164 return buffered_time_ranges_; |
| 165 } | 165 } |
| 166 | 166 |
| 167 TimeDelta Pipeline::GetMediaDuration() const { | 167 TimeDelta Pipeline::GetMediaDuration() const { |
| 168 base::AutoLock auto_lock(lock_); | 168 base::AutoLock auto_lock(lock_); |
| 169 return duration_; | 169 return duration_; |
| 170 } | 170 } |
| 171 | 171 |
| 172 bool Pipeline::DidLoadingProgress() { | 172 bool Pipeline::DidLoadingProgress() { |
| 173 base::AutoLock auto_lock(lock_); | 173 base::AutoLock auto_lock(lock_); |
| 174 bool ret = did_loading_progress_; | 174 bool ret = did_loading_progress_; |
| 175 did_loading_progress_ = false; | 175 did_loading_progress_ = false; |
| 176 return ret; | 176 return ret; |
| 177 } | 177 } |
| 178 | 178 |
| 179 PipelineStatistics Pipeline::GetStatistics() const { | 179 PipelineStatistics Pipeline::GetStatistics() const { |
| 180 base::AutoLock auto_lock(lock_); | 180 base::AutoLock auto_lock(lock_); |
| 181 return statistics_; | 181 return statistics_; |
| 182 } | 182 } |
| 183 | 183 |
| 184 void Pipeline::SetClockForTesting(Clock* clock) { | 184 void Pipeline::SetTimeDeltaInterpolatorForTesting( |
| 185 clock_.reset(clock); | 185 TimeDeltaInterpolator* interpolator) { |
| 186 interpolator_.reset(interpolator); | |
| 186 } | 187 } |
| 187 | 188 |
| 188 void Pipeline::SetErrorForTesting(PipelineStatus status) { | 189 void Pipeline::SetErrorForTesting(PipelineStatus status) { |
| 189 SetError(status); | 190 SetError(status); |
| 190 } | 191 } |
| 191 | 192 |
| 192 void Pipeline::SetState(State next_state) { | 193 void Pipeline::SetState(State next_state) { |
| 193 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); | 194 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); |
| 194 | 195 |
| 195 state_ = next_state; | 196 state_ = next_state; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 &Pipeline::ErrorChangedTask, base::Unretained(this), error)); | 284 &Pipeline::ErrorChangedTask, base::Unretained(this), error)); |
| 284 | 285 |
| 285 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 286 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
| 286 } | 287 } |
| 287 | 288 |
| 288 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 289 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
| 289 DCHECK(task_runner_->BelongsToCurrentThread()); | 290 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 290 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); | 291 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); |
| 291 base::AutoLock auto_lock(lock_); | 292 base::AutoLock auto_lock(lock_); |
| 292 | 293 |
| 293 if (clock_state_ == CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE && | 294 if (interpolation_state_ == INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE && |
| 294 time < clock_->Elapsed()) { | 295 time < interpolator_->GetInterpolatedTime()) { |
| 295 return; | 296 return; |
| 296 } | 297 } |
| 297 | 298 |
| 298 if (state_ == kSeeking) | 299 if (state_ == kSeeking) |
| 299 return; | 300 return; |
| 300 | 301 |
| 301 clock_->SetTime(time, max_time); | 302 interpolator_->SetTime(time, max_time); |
| 302 StartClockIfWaitingForTimeUpdate_Locked(); | 303 StartClockIfWaitingForTimeUpdate_Locked(); |
| 303 } | 304 } |
| 304 | 305 |
| 305 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { | 306 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { |
| 306 DCHECK(task_runner_->BelongsToCurrentThread()); | 307 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 307 | 308 |
| 308 if (audio_renderer_) | 309 if (audio_renderer_) |
| 309 return; | 310 return; |
| 310 | 311 |
| 311 if (state_ == kSeeking) | 312 if (state_ == kSeeking) |
| 312 return; | 313 return; |
| 313 | 314 |
| 314 base::AutoLock auto_lock(lock_); | 315 base::AutoLock auto_lock(lock_); |
| 315 DCHECK_NE(clock_state_, CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE); | 316 DCHECK_NE(interpolation_state_, INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE); |
| 316 clock_->SetMaxTime(max_time); | 317 interpolator_->SetMaxTime(max_time); |
| 317 } | 318 } |
| 318 | 319 |
| 319 void Pipeline::SetDuration(TimeDelta duration) { | 320 void Pipeline::SetDuration(TimeDelta duration) { |
| 320 DCHECK(IsRunning()); | 321 DCHECK(IsRunning()); |
| 321 media_log_->AddEvent( | 322 media_log_->AddEvent( |
| 322 media_log_->CreateTimeEvent( | 323 media_log_->CreateTimeEvent( |
| 323 MediaLogEvent::DURATION_SET, "duration", duration)); | 324 MediaLogEvent::DURATION_SET, "duration", duration)); |
| 324 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); | 325 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); |
| 325 | 326 |
| 326 base::AutoLock auto_lock(lock_); | 327 base::AutoLock auto_lock(lock_); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 | 372 |
| 372 case kInitVideoRenderer: | 373 case kInitVideoRenderer: |
| 373 return InitializeVideoRenderer(done_cb); | 374 return InitializeVideoRenderer(done_cb); |
| 374 | 375 |
| 375 case kInitPrerolling: | 376 case kInitPrerolling: |
| 376 filter_collection_.reset(); | 377 filter_collection_.reset(); |
| 377 { | 378 { |
| 378 base::AutoLock l(lock_); | 379 base::AutoLock l(lock_); |
| 379 // We do not want to start the clock running. We only want to set the | 380 // We do not want to start the clock running. We only want to set the |
| 380 // base media time so our timestamp calculations will be correct. | 381 // base media time so our timestamp calculations will be correct. |
| 381 clock_->SetTime(base::TimeDelta(), base::TimeDelta()); | 382 interpolator_->SetTime(base::TimeDelta(), base::TimeDelta()); |
| 382 } | 383 } |
| 383 if (!audio_renderer_ && !video_renderer_) { | 384 if (!audio_renderer_ && !video_renderer_) { |
| 384 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); | 385 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); |
| 385 return; | 386 return; |
| 386 } | 387 } |
| 387 | 388 |
| 388 { | 389 { |
| 389 PipelineMetadata metadata; | 390 PipelineMetadata metadata; |
| 390 metadata.has_audio = audio_renderer_; | 391 metadata.has_audio = audio_renderer_; |
| 391 metadata.has_video = video_renderer_; | 392 metadata.has_video = video_renderer_; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 633 | 634 |
| 634 void Pipeline::PlaybackRateChangedTask(float playback_rate) { | 635 void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
| 635 DCHECK(task_runner_->BelongsToCurrentThread()); | 636 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 636 | 637 |
| 637 // Playback rate changes are only carried out while playing. | 638 // Playback rate changes are only carried out while playing. |
| 638 if (state_ != kPlaying) | 639 if (state_ != kPlaying) |
| 639 return; | 640 return; |
| 640 | 641 |
| 641 { | 642 { |
| 642 base::AutoLock auto_lock(lock_); | 643 base::AutoLock auto_lock(lock_); |
| 643 clock_->SetPlaybackRate(playback_rate); | 644 interpolator_->SetPlaybackRate(playback_rate); |
| 644 } | 645 } |
| 645 | 646 |
| 646 if (audio_renderer_) | 647 if (audio_renderer_) |
| 647 audio_renderer_->SetPlaybackRate(playback_rate_); | 648 audio_renderer_->SetPlaybackRate(playback_rate_); |
| 648 if (video_renderer_) | 649 if (video_renderer_) |
| 649 video_renderer_->SetPlaybackRate(playback_rate_); | 650 video_renderer_->SetPlaybackRate(playback_rate_); |
| 650 } | 651 } |
| 651 | 652 |
| 652 void Pipeline::VolumeChangedTask(float volume) { | 653 void Pipeline::VolumeChangedTask(float volume) { |
| 653 DCHECK(task_runner_->BelongsToCurrentThread()); | 654 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 682 seek_cb_ = seek_cb; | 683 seek_cb_ = seek_cb; |
| 683 audio_ended_ = false; | 684 audio_ended_ = false; |
| 684 video_ended_ = false; | 685 video_ended_ = false; |
| 685 text_ended_ = false; | 686 text_ended_ = false; |
| 686 start_timestamp_ = time; | 687 start_timestamp_ = time; |
| 687 | 688 |
| 688 // Kick off seeking! | 689 // Kick off seeking! |
| 689 { | 690 { |
| 690 base::AutoLock auto_lock(lock_); | 691 base::AutoLock auto_lock(lock_); |
| 691 PauseClockAndStopRendering_Locked(); | 692 PauseClockAndStopRendering_Locked(); |
| 692 clock_->SetTime(time, time); | 693 interpolator_->SetTime(time, time); |
|
acolwell GONE FROM CHROMIUM
2014/07/09 00:42:46
This form appears to be used in a bunch of places.
scherkus (not reviewing)
2014/07/09 01:54:31
I'm going to the keep the API roughly intact for t
| |
| 693 } | 694 } |
| 694 DoSeek(time, base::Bind( | 695 DoSeek(time, base::Bind( |
| 695 &Pipeline::OnStateTransition, base::Unretained(this))); | 696 &Pipeline::OnStateTransition, base::Unretained(this))); |
| 696 } | 697 } |
| 697 | 698 |
| 698 void Pipeline::DoAudioRendererEnded() { | 699 void Pipeline::DoAudioRendererEnded() { |
| 699 DCHECK(task_runner_->BelongsToCurrentThread()); | 700 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 700 | 701 |
| 701 if (state_ != kPlaying) | 702 if (state_ != kPlaying) |
| 702 return; | 703 return; |
| 703 | 704 |
| 704 DCHECK(!audio_ended_); | 705 DCHECK(!audio_ended_); |
| 705 audio_ended_ = true; | 706 audio_ended_ = true; |
| 706 | 707 |
| 707 // Start clock since there is no more audio to trigger clock updates. | 708 // Start clock since there is no more audio to trigger clock updates. |
| 708 { | 709 { |
| 709 base::AutoLock auto_lock(lock_); | 710 base::AutoLock auto_lock(lock_); |
| 710 clock_->SetMaxTime(duration_); | 711 interpolator_->SetMaxTime(duration_); |
| 711 StartClockIfWaitingForTimeUpdate_Locked(); | 712 StartClockIfWaitingForTimeUpdate_Locked(); |
| 712 } | 713 } |
| 713 | 714 |
| 714 RunEndedCallbackIfNeeded(); | 715 RunEndedCallbackIfNeeded(); |
| 715 } | 716 } |
| 716 | 717 |
| 717 void Pipeline::DoVideoRendererEnded() { | 718 void Pipeline::DoVideoRendererEnded() { |
| 718 DCHECK(task_runner_->BelongsToCurrentThread()); | 719 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 719 | 720 |
| 720 if (state_ != kPlaying) | 721 if (state_ != kPlaying) |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 746 | 747 |
| 747 if (video_renderer_ && !video_ended_) | 748 if (video_renderer_ && !video_ended_) |
| 748 return; | 749 return; |
| 749 | 750 |
| 750 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) | 751 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) |
| 751 return; | 752 return; |
| 752 | 753 |
| 753 { | 754 { |
| 754 base::AutoLock auto_lock(lock_); | 755 base::AutoLock auto_lock(lock_); |
| 755 PauseClockAndStopRendering_Locked(); | 756 PauseClockAndStopRendering_Locked(); |
| 756 clock_->SetTime(duration_, duration_); | 757 interpolator_->SetTime(duration_, duration_); |
| 757 } | 758 } |
| 758 | 759 |
| 759 DCHECK_EQ(status_, PIPELINE_OK); | 760 DCHECK_EQ(status_, PIPELINE_OK); |
| 760 ended_cb_.Run(); | 761 ended_cb_.Run(); |
| 761 } | 762 } |
| 762 | 763 |
| 763 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, | 764 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, |
| 764 const TextTrackConfig& config) { | 765 const TextTrackConfig& config) { |
| 765 DCHECK(task_runner_->BelongsToCurrentThread()); | 766 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 766 // TODO(matthewjheaney): fix up text_ended_ when text stream | 767 // TODO(matthewjheaney): fix up text_ended_ when text stream |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 863 DCHECK(WaitingForEnoughData()); | 864 DCHECK(WaitingForEnoughData()); |
| 864 DCHECK(task_runner_->BelongsToCurrentThread()); | 865 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 865 | 866 |
| 866 base::AutoLock auto_lock(lock_); | 867 base::AutoLock auto_lock(lock_); |
| 867 PauseClockAndStopRendering_Locked(); | 868 PauseClockAndStopRendering_Locked(); |
| 868 } | 869 } |
| 869 | 870 |
| 870 void Pipeline::StartPlayback() { | 871 void Pipeline::StartPlayback() { |
| 871 DVLOG(1) << __FUNCTION__; | 872 DVLOG(1) << __FUNCTION__; |
| 872 DCHECK_EQ(state_, kPlaying); | 873 DCHECK_EQ(state_, kPlaying); |
| 873 DCHECK_EQ(clock_state_, CLOCK_PAUSED); | 874 DCHECK_EQ(interpolation_state_, INTERPOLATION_STOPPED); |
| 874 DCHECK(!WaitingForEnoughData()); | 875 DCHECK(!WaitingForEnoughData()); |
| 875 DCHECK(task_runner_->BelongsToCurrentThread()); | 876 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 876 | 877 |
| 877 if (audio_renderer_) { | 878 if (audio_renderer_) { |
| 878 // We use audio stream to update the clock. So if there is such a | 879 // We use audio stream to update the clock. So if there is such a |
| 879 // stream, we pause the clock until we receive a valid timestamp. | 880 // stream, we pause the clock until we receive a valid timestamp. |
| 880 base::AutoLock auto_lock(lock_); | 881 base::AutoLock auto_lock(lock_); |
| 881 clock_state_ = CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE; | 882 interpolation_state_ = INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE; |
| 882 audio_renderer_->StartRendering(); | 883 audio_renderer_->StartRendering(); |
| 883 } else { | 884 } else { |
| 884 base::AutoLock auto_lock(lock_); | 885 base::AutoLock auto_lock(lock_); |
| 885 clock_state_ = CLOCK_PLAYING; | 886 interpolation_state_ = INTERPOLATION_STARTED; |
| 886 clock_->SetMaxTime(duration_); | 887 interpolator_->SetMaxTime(duration_); |
|
acolwell GONE FROM CHROMIUM
2014/07/09 00:42:46
Yeah.. this stuff should be in the interpolator_
scherkus (not reviewing)
2014/07/09 01:54:31
Ditto.
| |
| 887 clock_->Play(); | 888 interpolator_->StartInterpolating(); |
| 888 } | 889 } |
| 889 } | 890 } |
| 890 | 891 |
| 891 void Pipeline::PauseClockAndStopRendering_Locked() { | 892 void Pipeline::PauseClockAndStopRendering_Locked() { |
| 892 lock_.AssertAcquired(); | 893 lock_.AssertAcquired(); |
| 893 switch (clock_state_) { | 894 switch (interpolation_state_) { |
| 894 case CLOCK_PAUSED: | 895 case INTERPOLATION_STOPPED: |
| 895 return; | 896 return; |
| 896 | 897 |
| 897 case CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE: | 898 case INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE: |
| 898 audio_renderer_->StopRendering(); | 899 audio_renderer_->StopRendering(); |
| 899 break; | 900 break; |
| 900 | 901 |
| 901 case CLOCK_PLAYING: | 902 case INTERPOLATION_STARTED: |
| 902 if (audio_renderer_) | 903 if (audio_renderer_) |
| 903 audio_renderer_->StopRendering(); | 904 audio_renderer_->StopRendering(); |
| 904 clock_->Pause(); | 905 interpolator_->StopInterpolating(); |
| 905 break; | 906 break; |
| 906 } | 907 } |
| 907 | 908 |
| 908 clock_state_ = CLOCK_PAUSED; | 909 interpolation_state_ = INTERPOLATION_STOPPED; |
| 909 } | 910 } |
| 910 | 911 |
| 911 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 912 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 912 lock_.AssertAcquired(); | 913 lock_.AssertAcquired(); |
| 913 if (clock_state_ != CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE) | 914 if (interpolation_state_ != INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE) |
| 914 return; | 915 return; |
| 915 | 916 |
| 916 clock_state_ = CLOCK_PLAYING; | 917 interpolation_state_ = INTERPOLATION_STARTED; |
| 917 clock_->Play(); | 918 interpolator_->StartInterpolating(); |
| 918 } | 919 } |
| 919 | 920 |
| 920 } // namespace media | 921 } // namespace media |
| OLD | NEW |