| 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)); |
| 56 media_log_->AddEvent( | 56 media_log_->AddEvent( |
| 57 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 57 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
| 58 clock_->SetTime(base::TimeDelta(), base::TimeDelta()); | 58 interpolator_->SetInterpolationRange(base::TimeDelta(), base::TimeDelta()); |
| 59 } | 59 } |
| 60 | 60 |
| 61 Pipeline::~Pipeline() { | 61 Pipeline::~Pipeline() { |
| 62 DCHECK(thread_checker_.CalledOnValidThread()) | 62 DCHECK(thread_checker_.CalledOnValidThread()) |
| 63 << "Pipeline must be destroyed on same thread that created it"; | 63 << "Pipeline must be destroyed on same thread that created it"; |
| 64 DCHECK(!running_) << "Stop() must complete before destroying object"; | 64 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 65 DCHECK(stop_cb_.is_null()); | 65 DCHECK(stop_cb_.is_null()); |
| 66 DCHECK(seek_cb_.is_null()); | 66 DCHECK(seek_cb_.is_null()); |
| 67 | 67 |
| 68 media_log_->AddEvent( | 68 media_log_->AddEvent( |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 base::AutoLock auto_lock(lock_); | 150 base::AutoLock auto_lock(lock_); |
| 151 volume_ = volume; | 151 volume_ = volume; |
| 152 if (running_) { | 152 if (running_) { |
| 153 task_runner_->PostTask(FROM_HERE, base::Bind( | 153 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 154 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); | 154 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); |
| 155 } | 155 } |
| 156 } | 156 } |
| 157 | 157 |
| 158 TimeDelta Pipeline::GetMediaTime() const { | 158 TimeDelta Pipeline::GetMediaTime() const { |
| 159 base::AutoLock auto_lock(lock_); | 159 base::AutoLock auto_lock(lock_); |
| 160 return std::min(clock_->Elapsed(), duration_); | 160 return std::min(interpolator_->GetInterpolatedTime(), duration_); |
| 161 } | 161 } |
| 162 | 162 |
| 163 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { | 163 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { |
| 164 base::AutoLock auto_lock(lock_); | 164 base::AutoLock auto_lock(lock_); |
| 165 return buffered_time_ranges_; | 165 return buffered_time_ranges_; |
| 166 } | 166 } |
| 167 | 167 |
| 168 TimeDelta Pipeline::GetMediaDuration() const { | 168 TimeDelta Pipeline::GetMediaDuration() const { |
| 169 base::AutoLock auto_lock(lock_); | 169 base::AutoLock auto_lock(lock_); |
| 170 return duration_; | 170 return duration_; |
| 171 } | 171 } |
| 172 | 172 |
| 173 bool Pipeline::DidLoadingProgress() { | 173 bool Pipeline::DidLoadingProgress() { |
| 174 base::AutoLock auto_lock(lock_); | 174 base::AutoLock auto_lock(lock_); |
| 175 bool ret = did_loading_progress_; | 175 bool ret = did_loading_progress_; |
| 176 did_loading_progress_ = false; | 176 did_loading_progress_ = false; |
| 177 return ret; | 177 return ret; |
| 178 } | 178 } |
| 179 | 179 |
| 180 PipelineStatistics Pipeline::GetStatistics() const { | 180 PipelineStatistics Pipeline::GetStatistics() const { |
| 181 base::AutoLock auto_lock(lock_); | 181 base::AutoLock auto_lock(lock_); |
| 182 return statistics_; | 182 return statistics_; |
| 183 } | 183 } |
| 184 | 184 |
| 185 void Pipeline::SetClockForTesting(Clock* clock) { | 185 void Pipeline::SetTimeDeltaInterpolatorForTesting( |
| 186 clock_.reset(clock); | 186 TimeDeltaInterpolator* interpolator) { |
| 187 interpolator_.reset(interpolator); |
| 187 } | 188 } |
| 188 | 189 |
| 189 void Pipeline::SetErrorForTesting(PipelineStatus status) { | 190 void Pipeline::SetErrorForTesting(PipelineStatus status) { |
| 190 SetError(status); | 191 SetError(status); |
| 191 } | 192 } |
| 192 | 193 |
| 193 void Pipeline::SetState(State next_state) { | 194 void Pipeline::SetState(State next_state) { |
| 194 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); | 195 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); |
| 195 | 196 |
| 196 state_ = next_state; | 197 state_ = next_state; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 &Pipeline::ErrorChangedTask, base::Unretained(this), error)); | 281 &Pipeline::ErrorChangedTask, base::Unretained(this), error)); |
| 281 | 282 |
| 282 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 283 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
| 283 } | 284 } |
| 284 | 285 |
| 285 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 286 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
| 286 DCHECK(task_runner_->BelongsToCurrentThread()); | 287 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 287 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); | 288 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); |
| 288 base::AutoLock auto_lock(lock_); | 289 base::AutoLock auto_lock(lock_); |
| 289 | 290 |
| 290 if (clock_state_ == CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE && | 291 if (interpolation_state_ == INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE && |
| 291 time < clock_->Elapsed()) { | 292 time < interpolator_->GetInterpolatedTime()) { |
| 292 return; | 293 return; |
| 293 } | 294 } |
| 294 | 295 |
| 295 if (state_ == kSeeking) | 296 if (state_ == kSeeking) |
| 296 return; | 297 return; |
| 297 | 298 |
| 298 clock_->SetTime(time, max_time); | 299 interpolator_->SetInterpolationRange(time, max_time); |
| 299 StartClockIfWaitingForTimeUpdate_Locked(); | 300 StartClockIfWaitingForTimeUpdate_Locked(); |
| 300 } | 301 } |
| 301 | 302 |
| 302 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { | 303 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { |
| 303 DCHECK(task_runner_->BelongsToCurrentThread()); | 304 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 304 | 305 |
| 305 if (audio_renderer_) | 306 if (audio_renderer_) |
| 306 return; | 307 return; |
| 307 | 308 |
| 308 if (state_ == kSeeking) | 309 if (state_ == kSeeking) |
| 309 return; | 310 return; |
| 310 | 311 |
| 311 base::AutoLock auto_lock(lock_); | 312 base::AutoLock auto_lock(lock_); |
| 312 DCHECK_NE(clock_state_, CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE); | 313 DCHECK_NE(interpolation_state_, INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE); |
| 313 clock_->SetMaxTime(max_time); | 314 interpolator_->SetUpperBound(max_time); |
| 314 } | 315 } |
| 315 | 316 |
| 316 void Pipeline::SetDuration(TimeDelta duration) { | 317 void Pipeline::SetDuration(TimeDelta duration) { |
| 317 DCHECK(IsRunning()); | 318 DCHECK(IsRunning()); |
| 318 media_log_->AddEvent( | 319 media_log_->AddEvent( |
| 319 media_log_->CreateTimeEvent( | 320 media_log_->CreateTimeEvent( |
| 320 MediaLogEvent::DURATION_SET, "duration", duration)); | 321 MediaLogEvent::DURATION_SET, "duration", duration)); |
| 321 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); | 322 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); |
| 322 | 323 |
| 323 base::AutoLock auto_lock(lock_); | 324 base::AutoLock auto_lock(lock_); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 stream->video_decoder_config().natural_size(); | 391 stream->video_decoder_config().natural_size(); |
| 391 } | 392 } |
| 392 metadata_cb_.Run(metadata); | 393 metadata_cb_.Run(metadata); |
| 393 } | 394 } |
| 394 } | 395 } |
| 395 | 396 |
| 396 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | 397 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
| 397 | 398 |
| 398 { | 399 { |
| 399 base::AutoLock auto_lock(lock_); | 400 base::AutoLock auto_lock(lock_); |
| 400 clock_->SetTime(start_timestamp_, start_timestamp_); | 401 interpolator_->SetInterpolationRange(start_timestamp_, |
| 402 start_timestamp_); |
| 401 } | 403 } |
| 402 | 404 |
| 403 if (audio_renderer_) | 405 if (audio_renderer_) |
| 404 audio_renderer_->StartPlayingFrom(start_timestamp_); | 406 audio_renderer_->StartPlayingFrom(start_timestamp_); |
| 405 if (video_renderer_) | 407 if (video_renderer_) |
| 406 video_renderer_->StartPlayingFrom(start_timestamp_); | 408 video_renderer_->StartPlayingFrom(start_timestamp_); |
| 407 if (text_renderer_) | 409 if (text_renderer_) |
| 408 text_renderer_->StartPlaying(); | 410 text_renderer_->StartPlaying(); |
| 409 | 411 |
| 410 PlaybackRateChangedTask(GetPlaybackRate()); | 412 PlaybackRateChangedTask(GetPlaybackRate()); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 | 637 |
| 636 void Pipeline::PlaybackRateChangedTask(float playback_rate) { | 638 void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
| 637 DCHECK(task_runner_->BelongsToCurrentThread()); | 639 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 638 | 640 |
| 639 // Playback rate changes are only carried out while playing. | 641 // Playback rate changes are only carried out while playing. |
| 640 if (state_ != kPlaying) | 642 if (state_ != kPlaying) |
| 641 return; | 643 return; |
| 642 | 644 |
| 643 { | 645 { |
| 644 base::AutoLock auto_lock(lock_); | 646 base::AutoLock auto_lock(lock_); |
| 645 clock_->SetPlaybackRate(playback_rate); | 647 interpolator_->SetPlaybackRate(playback_rate); |
| 646 } | 648 } |
| 647 | 649 |
| 648 if (audio_renderer_) | 650 if (audio_renderer_) |
| 649 audio_renderer_->SetPlaybackRate(playback_rate_); | 651 audio_renderer_->SetPlaybackRate(playback_rate_); |
| 650 if (video_renderer_) | 652 if (video_renderer_) |
| 651 video_renderer_->SetPlaybackRate(playback_rate_); | 653 video_renderer_->SetPlaybackRate(playback_rate_); |
| 652 } | 654 } |
| 653 | 655 |
| 654 void Pipeline::VolumeChangedTask(float volume) { | 656 void Pipeline::VolumeChangedTask(float volume) { |
| 655 DCHECK(task_runner_->BelongsToCurrentThread()); | 657 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 698 |
| 697 if (state_ != kPlaying) | 699 if (state_ != kPlaying) |
| 698 return; | 700 return; |
| 699 | 701 |
| 700 DCHECK(!audio_ended_); | 702 DCHECK(!audio_ended_); |
| 701 audio_ended_ = true; | 703 audio_ended_ = true; |
| 702 | 704 |
| 703 // Start clock since there is no more audio to trigger clock updates. | 705 // Start clock since there is no more audio to trigger clock updates. |
| 704 { | 706 { |
| 705 base::AutoLock auto_lock(lock_); | 707 base::AutoLock auto_lock(lock_); |
| 706 clock_->SetMaxTime(duration_); | 708 interpolator_->SetUpperBound(duration_); |
| 707 StartClockIfWaitingForTimeUpdate_Locked(); | 709 StartClockIfWaitingForTimeUpdate_Locked(); |
| 708 } | 710 } |
| 709 | 711 |
| 710 RunEndedCallbackIfNeeded(); | 712 RunEndedCallbackIfNeeded(); |
| 711 } | 713 } |
| 712 | 714 |
| 713 void Pipeline::DoVideoRendererEnded() { | 715 void Pipeline::DoVideoRendererEnded() { |
| 714 DCHECK(task_runner_->BelongsToCurrentThread()); | 716 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 715 | 717 |
| 716 if (state_ != kPlaying) | 718 if (state_ != kPlaying) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 742 | 744 |
| 743 if (video_renderer_ && !video_ended_) | 745 if (video_renderer_ && !video_ended_) |
| 744 return; | 746 return; |
| 745 | 747 |
| 746 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) | 748 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) |
| 747 return; | 749 return; |
| 748 | 750 |
| 749 { | 751 { |
| 750 base::AutoLock auto_lock(lock_); | 752 base::AutoLock auto_lock(lock_); |
| 751 PauseClockAndStopRendering_Locked(); | 753 PauseClockAndStopRendering_Locked(); |
| 752 clock_->SetTime(duration_, duration_); | 754 interpolator_->SetInterpolationRange(duration_, duration_); |
| 753 } | 755 } |
| 754 | 756 |
| 755 DCHECK_EQ(status_, PIPELINE_OK); | 757 DCHECK_EQ(status_, PIPELINE_OK); |
| 756 ended_cb_.Run(); | 758 ended_cb_.Run(); |
| 757 } | 759 } |
| 758 | 760 |
| 759 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, | 761 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, |
| 760 const TextTrackConfig& config) { | 762 const TextTrackConfig& config) { |
| 761 DCHECK(task_runner_->BelongsToCurrentThread()); | 763 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 762 // TODO(matthewjheaney): fix up text_ended_ when text stream | 764 // TODO(matthewjheaney): fix up text_ended_ when text stream |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 << " " << new_buffering_state << ") " | 817 << " " << new_buffering_state << ") " |
| 816 << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); | 818 << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); |
| 817 DCHECK(task_runner_->BelongsToCurrentThread()); | 819 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 818 bool was_waiting_for_enough_data = WaitingForEnoughData(); | 820 bool was_waiting_for_enough_data = WaitingForEnoughData(); |
| 819 | 821 |
| 820 *buffering_state = new_buffering_state; | 822 *buffering_state = new_buffering_state; |
| 821 | 823 |
| 822 // Disable underflow by ignoring updates that renderers have ran out of data | 824 // Disable underflow by ignoring updates that renderers have ran out of data |
| 823 // after we have started the clock. | 825 // after we have started the clock. |
| 824 if (state_ == kPlaying && underflow_disabled_for_testing_ && | 826 if (state_ == kPlaying && underflow_disabled_for_testing_ && |
| 825 clock_state_ != CLOCK_PAUSED) { | 827 interpolation_state_ != INTERPOLATION_STOPPED) { |
| 826 return; | 828 return; |
| 827 } | 829 } |
| 828 | 830 |
| 829 // Renderer underflowed. | 831 // Renderer underflowed. |
| 830 if (!was_waiting_for_enough_data && WaitingForEnoughData()) { | 832 if (!was_waiting_for_enough_data && WaitingForEnoughData()) { |
| 831 PausePlayback(); | 833 PausePlayback(); |
| 832 | 834 |
| 833 // TODO(scherkus): Fire BUFFERING_HAVE_NOTHING callback to alert clients of | 835 // TODO(scherkus): Fire BUFFERING_HAVE_NOTHING callback to alert clients of |
| 834 // underflow state http://crbug.com/144683 | 836 // underflow state http://crbug.com/144683 |
| 835 return; | 837 return; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 860 DCHECK(WaitingForEnoughData()); | 862 DCHECK(WaitingForEnoughData()); |
| 861 DCHECK(task_runner_->BelongsToCurrentThread()); | 863 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 862 | 864 |
| 863 base::AutoLock auto_lock(lock_); | 865 base::AutoLock auto_lock(lock_); |
| 864 PauseClockAndStopRendering_Locked(); | 866 PauseClockAndStopRendering_Locked(); |
| 865 } | 867 } |
| 866 | 868 |
| 867 void Pipeline::StartPlayback() { | 869 void Pipeline::StartPlayback() { |
| 868 DVLOG(1) << __FUNCTION__; | 870 DVLOG(1) << __FUNCTION__; |
| 869 DCHECK_EQ(state_, kPlaying); | 871 DCHECK_EQ(state_, kPlaying); |
| 870 DCHECK_EQ(clock_state_, CLOCK_PAUSED); | 872 DCHECK_EQ(interpolation_state_, INTERPOLATION_STOPPED); |
| 871 DCHECK(!WaitingForEnoughData()); | 873 DCHECK(!WaitingForEnoughData()); |
| 872 DCHECK(task_runner_->BelongsToCurrentThread()); | 874 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 873 | 875 |
| 874 if (audio_renderer_) { | 876 if (audio_renderer_) { |
| 875 // We use audio stream to update the clock. So if there is such a | 877 // We use audio stream to update the clock. So if there is such a |
| 876 // stream, we pause the clock until we receive a valid timestamp. | 878 // stream, we pause the clock until we receive a valid timestamp. |
| 877 base::AutoLock auto_lock(lock_); | 879 base::AutoLock auto_lock(lock_); |
| 878 clock_state_ = CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE; | 880 interpolation_state_ = INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE; |
| 879 audio_renderer_->StartRendering(); | 881 audio_renderer_->StartRendering(); |
| 880 } else { | 882 } else { |
| 881 base::AutoLock auto_lock(lock_); | 883 base::AutoLock auto_lock(lock_); |
| 882 clock_state_ = CLOCK_PLAYING; | 884 interpolation_state_ = INTERPOLATION_STARTED; |
| 883 clock_->SetMaxTime(duration_); | 885 interpolator_->SetUpperBound(duration_); |
| 884 clock_->Play(); | 886 interpolator_->StartInterpolating(); |
| 885 } | 887 } |
| 886 } | 888 } |
| 887 | 889 |
| 888 void Pipeline::PauseClockAndStopRendering_Locked() { | 890 void Pipeline::PauseClockAndStopRendering_Locked() { |
| 889 lock_.AssertAcquired(); | 891 lock_.AssertAcquired(); |
| 890 switch (clock_state_) { | 892 switch (interpolation_state_) { |
| 891 case CLOCK_PAUSED: | 893 case INTERPOLATION_STOPPED: |
| 892 return; | 894 return; |
| 893 | 895 |
| 894 case CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE: | 896 case INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE: |
| 895 audio_renderer_->StopRendering(); | 897 audio_renderer_->StopRendering(); |
| 896 break; | 898 break; |
| 897 | 899 |
| 898 case CLOCK_PLAYING: | 900 case INTERPOLATION_STARTED: |
| 899 if (audio_renderer_) | 901 if (audio_renderer_) |
| 900 audio_renderer_->StopRendering(); | 902 audio_renderer_->StopRendering(); |
| 901 clock_->Pause(); | 903 interpolator_->StopInterpolating(); |
| 902 break; | 904 break; |
| 903 } | 905 } |
| 904 | 906 |
| 905 clock_state_ = CLOCK_PAUSED; | 907 interpolation_state_ = INTERPOLATION_STOPPED; |
| 906 } | 908 } |
| 907 | 909 |
| 908 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 910 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 909 lock_.AssertAcquired(); | 911 lock_.AssertAcquired(); |
| 910 if (clock_state_ != CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE) | 912 if (interpolation_state_ != INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE) |
| 911 return; | 913 return; |
| 912 | 914 |
| 913 clock_state_ = CLOCK_PLAYING; | 915 interpolation_state_ = INTERPOLATION_STARTED; |
| 914 clock_->Play(); | 916 interpolator_->StartInterpolating(); |
| 915 } | 917 } |
| 916 | 918 |
| 917 } // namespace media | 919 } // namespace media |
| OLD | NEW |