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 |