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" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 struct Pipeline::PipelineInitState { | 64 struct Pipeline::PipelineInitState { |
65 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
66 scoped_refptr<VideoDecoder> video_decoder; | 66 scoped_refptr<VideoDecoder> video_decoder; |
67 }; | 67 }; |
68 | 68 |
69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
70 : message_loop_(message_loop->message_loop_proxy()), | 70 : message_loop_(message_loop->message_loop_proxy()), |
71 media_log_(media_log), | 71 media_log_(media_log), |
72 running_(false), | 72 running_(false), |
73 seek_pending_(false), | 73 seek_pending_(false), |
74 stop_pending_(false), | |
75 tearing_down_(false), | 74 tearing_down_(false), |
76 error_caused_teardown_(false), | 75 error_caused_teardown_(false), |
77 playback_rate_change_pending_(false), | 76 playback_rate_change_pending_(false), |
78 did_loading_progress_(false), | 77 did_loading_progress_(false), |
79 total_bytes_(0), | 78 total_bytes_(0), |
80 natural_size_(0, 0), | 79 natural_size_(0, 0), |
81 volume_(1.0f), | 80 volume_(1.0f), |
82 playback_rate_(0.0f), | 81 playback_rate_(0.0f), |
83 pending_playback_rate_(0.0f), | 82 pending_playback_rate_(0.0f), |
84 clock_(new Clock(&base::Time::Now)), | 83 clock_(new Clock(&base::Time::Now)), |
85 waiting_for_clock_update_(false), | 84 waiting_for_clock_update_(false), |
86 status_(PIPELINE_OK), | 85 status_(PIPELINE_OK), |
87 has_audio_(false), | 86 has_audio_(false), |
88 has_video_(false), | 87 has_video_(false), |
89 state_(kCreated), | 88 state_(kCreated), |
90 seek_timestamp_(kNoTimestamp()), | 89 seek_timestamp_(kNoTimestamp()), |
91 audio_ended_(false), | 90 audio_ended_(false), |
92 video_ended_(false), | 91 video_ended_(false), |
93 audio_disabled_(false), | 92 audio_disabled_(false), |
94 creation_time_(base::Time::Now()) { | 93 creation_time_(base::Time::Now()) { |
95 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 94 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
96 media_log_->AddEvent( | 95 media_log_->AddEvent( |
97 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 96 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
98 } | 97 } |
99 | 98 |
100 Pipeline::~Pipeline() { | 99 Pipeline::~Pipeline() { |
101 base::AutoLock auto_lock(lock_); | 100 base::AutoLock auto_lock(lock_); |
102 DCHECK(!running_) << "Stop() must complete before destroying object"; | 101 DCHECK(!running_) << "Stop() must complete before destroying object"; |
103 DCHECK(!stop_pending_); | 102 DCHECK(stop_cb_.is_null()); |
104 DCHECK(!seek_pending_); | 103 DCHECK(!seek_pending_); |
105 | 104 |
106 media_log_->AddEvent( | 105 media_log_->AddEvent( |
107 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); | 106 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); |
108 } | 107 } |
109 | 108 |
110 void Pipeline::Start(scoped_ptr<FilterCollection> collection, | 109 void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
111 const PipelineStatusCB& ended_cb, | 110 const PipelineStatusCB& ended_cb, |
112 const PipelineStatusCB& error_cb, | 111 const PipelineStatusCB& error_cb, |
113 const PipelineStatusCB& start_cb) { | 112 const PipelineStatusCB& start_cb) { |
(...skipping 21 matching lines...) Expand all Loading... |
135 | 134 |
136 message_loop_->PostTask(FROM_HERE, base::Bind( | 135 message_loop_->PostTask(FROM_HERE, base::Bind( |
137 &Pipeline::SeekTask, this, time, seek_cb)); | 136 &Pipeline::SeekTask, this, time, seek_cb)); |
138 } | 137 } |
139 | 138 |
140 bool Pipeline::IsRunning() const { | 139 bool Pipeline::IsRunning() const { |
141 base::AutoLock auto_lock(lock_); | 140 base::AutoLock auto_lock(lock_); |
142 return running_; | 141 return running_; |
143 } | 142 } |
144 | 143 |
145 bool Pipeline::IsInitialized() const { | |
146 // TODO(scherkus): perhaps replace this with a bool that is set/get under the | |
147 // lock, because this is breaching the contract that |state_| is only accessed | |
148 // on |message_loop_|. | |
149 base::AutoLock auto_lock(lock_); | |
150 switch (state_) { | |
151 case kPausing: | |
152 case kFlushing: | |
153 case kSeeking: | |
154 case kStarting: | |
155 case kStarted: | |
156 return true; | |
157 default: | |
158 return false; | |
159 } | |
160 } | |
161 | |
162 bool Pipeline::HasAudio() const { | 144 bool Pipeline::HasAudio() const { |
163 base::AutoLock auto_lock(lock_); | 145 base::AutoLock auto_lock(lock_); |
164 return has_audio_; | 146 return has_audio_; |
165 } | 147 } |
166 | 148 |
167 bool Pipeline::HasVideo() const { | 149 bool Pipeline::HasVideo() const { |
168 base::AutoLock auto_lock(lock_); | 150 base::AutoLock auto_lock(lock_); |
169 return has_video_; | 151 return has_video_; |
170 } | 152 } |
171 | 153 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 bool ret = did_loading_progress_; | 231 bool ret = did_loading_progress_; |
250 did_loading_progress_ = false; | 232 did_loading_progress_ = false; |
251 return ret; | 233 return ret; |
252 } | 234 } |
253 | 235 |
254 PipelineStatistics Pipeline::GetStatistics() const { | 236 PipelineStatistics Pipeline::GetStatistics() const { |
255 base::AutoLock auto_lock(lock_); | 237 base::AutoLock auto_lock(lock_); |
256 return statistics_; | 238 return statistics_; |
257 } | 239 } |
258 | 240 |
| 241 bool Pipeline::IsInitializedForTesting() { |
| 242 DCHECK(message_loop_->BelongsToCurrentThread()) |
| 243 << "Tests should run on the same thread as Pipeline"; |
| 244 switch (state_) { |
| 245 case kPausing: |
| 246 case kFlushing: |
| 247 case kSeeking: |
| 248 case kStarting: |
| 249 case kStarted: |
| 250 return true; |
| 251 default: |
| 252 return false; |
| 253 } |
| 254 } |
| 255 |
259 void Pipeline::SetClockForTesting(Clock* clock) { | 256 void Pipeline::SetClockForTesting(Clock* clock) { |
260 clock_.reset(clock); | 257 clock_.reset(clock); |
261 } | 258 } |
262 | 259 |
263 void Pipeline::SetErrorForTesting(PipelineStatus status) { | 260 void Pipeline::SetErrorForTesting(PipelineStatus status) { |
264 SetError(status); | 261 SetError(status); |
265 } | 262 } |
266 | 263 |
267 void Pipeline::SetState(State next_state) { | 264 void Pipeline::SetState(State next_state) { |
268 if (state_ != kStarted && next_state == kStarted && | 265 if (state_ != kStarted && next_state == kStarted && |
(...skipping 14 matching lines...) Expand all Loading... |
283 bool Pipeline::IsPipelineStopped() { | 280 bool Pipeline::IsPipelineStopped() { |
284 DCHECK(message_loop_->BelongsToCurrentThread()); | 281 DCHECK(message_loop_->BelongsToCurrentThread()); |
285 return state_ == kStopped || state_ == kError; | 282 return state_ == kStopped || state_ == kError; |
286 } | 283 } |
287 | 284 |
288 bool Pipeline::IsPipelineTearingDown() { | 285 bool Pipeline::IsPipelineTearingDown() { |
289 DCHECK(message_loop_->BelongsToCurrentThread()); | 286 DCHECK(message_loop_->BelongsToCurrentThread()); |
290 return tearing_down_; | 287 return tearing_down_; |
291 } | 288 } |
292 | 289 |
293 bool Pipeline::IsPipelineStopPending() { | |
294 DCHECK(message_loop_->BelongsToCurrentThread()); | |
295 return stop_pending_; | |
296 } | |
297 | |
298 bool Pipeline::IsPipelineSeeking() { | 290 bool Pipeline::IsPipelineSeeking() { |
299 DCHECK(message_loop_->BelongsToCurrentThread()); | 291 DCHECK(message_loop_->BelongsToCurrentThread()); |
300 if (!seek_pending_) | 292 if (!seek_pending_) |
301 return false; | 293 return false; |
302 DCHECK(kSeeking == state_ || kPausing == state_ || | 294 DCHECK(kSeeking == state_ || kPausing == state_ || |
303 kFlushing == state_ || kStarting == state_) | 295 kFlushing == state_ || kStarting == state_) |
304 << "Current state : " << state_; | 296 << "Current state : " << state_; |
305 return true; | 297 return true; |
306 } | 298 } |
307 | 299 |
(...skipping 27 matching lines...) Expand all Loading... |
335 | 327 |
336 // static | 328 // static |
337 Pipeline::State Pipeline::FindNextState(State current) { | 329 Pipeline::State Pipeline::FindNextState(State current) { |
338 // TODO(scherkus): refactor InitializeTask() to make use of this function. | 330 // TODO(scherkus): refactor InitializeTask() to make use of this function. |
339 if (current == kPausing) { | 331 if (current == kPausing) { |
340 return kFlushing; | 332 return kFlushing; |
341 } else if (current == kFlushing) { | 333 } else if (current == kFlushing) { |
342 // We will always honor Seek() before Stop(). This is based on the | 334 // We will always honor Seek() before Stop(). This is based on the |
343 // assumption that we never accept Seek() after Stop(). | 335 // assumption that we never accept Seek() after Stop(). |
344 DCHECK(IsPipelineSeeking() || | 336 DCHECK(IsPipelineSeeking() || |
345 IsPipelineStopPending() || | 337 !stop_cb_.is_null() || |
346 IsPipelineTearingDown()); | 338 IsPipelineTearingDown()); |
347 return IsPipelineSeeking() ? kSeeking : kStopping; | 339 return IsPipelineSeeking() ? kSeeking : kStopping; |
348 } else if (current == kSeeking) { | 340 } else if (current == kSeeking) { |
349 return kStarting; | 341 return kStarting; |
350 } else if (current == kStarting) { | 342 } else if (current == kStarting) { |
351 return kStarted; | 343 return kStarted; |
352 } else if (current == kStopping) { | 344 } else if (current == kStopping) { |
353 return error_caused_teardown_ ? kError : kStopped; | 345 return error_caused_teardown_ ? kError : kStopped; |
354 } else { | 346 } else { |
355 return current; | 347 return current; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 if (state_ == kInitVideoDecoder && | 617 if (state_ == kInitVideoDecoder && |
626 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | 618 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { |
627 state_ = kInitAudioRenderer; | 619 state_ = kInitAudioRenderer; |
628 } else { | 620 } else { |
629 SetError(last_stage_status); | 621 SetError(last_stage_status); |
630 return; | 622 return; |
631 } | 623 } |
632 } | 624 } |
633 | 625 |
634 // If we have received the stop or error signal, return immediately. | 626 // If we have received the stop or error signal, return immediately. |
635 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 627 if (!stop_cb_.is_null() || IsPipelineStopped() || !IsPipelineOk()) |
636 return; | 628 return; |
637 | 629 |
638 DCHECK(state_ == kInitDemuxer || | 630 DCHECK(state_ == kInitDemuxer || |
639 state_ == kInitAudioDecoder || | 631 state_ == kInitAudioDecoder || |
640 state_ == kInitAudioRenderer || | 632 state_ == kInitAudioRenderer || |
641 state_ == kInitVideoDecoder || | 633 state_ == kInitVideoDecoder || |
642 state_ == kInitVideoRenderer); | 634 state_ == kInitVideoRenderer); |
643 | 635 |
644 // Demuxer created, create audio decoder. | 636 // Demuxer created, create audio decoder. |
645 if (state_ == kInitDemuxer) { | 637 if (state_ == kInitDemuxer) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 | 698 |
707 // This method is called as a result of the client calling Pipeline::Stop() or | 699 // This method is called as a result of the client calling Pipeline::Stop() or |
708 // as the result of an error condition. | 700 // as the result of an error condition. |
709 // We stop the filters in the reverse order. | 701 // We stop the filters in the reverse order. |
710 // | 702 // |
711 // TODO(scherkus): beware! this can get posted multiple times since we post | 703 // TODO(scherkus): beware! this can get posted multiple times since we post |
712 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 704 // Stop() tasks even if we've already stopped. Perhaps this should no-op for |
713 // additional calls, however most of this logic will be changing. | 705 // additional calls, however most of this logic will be changing. |
714 void Pipeline::StopTask(const base::Closure& stop_cb) { | 706 void Pipeline::StopTask(const base::Closure& stop_cb) { |
715 DCHECK(message_loop_->BelongsToCurrentThread()); | 707 DCHECK(message_loop_->BelongsToCurrentThread()); |
716 DCHECK(!IsPipelineStopPending()); | 708 DCHECK(stop_cb_.is_null()); |
717 DCHECK_NE(state_, kStopped); | 709 DCHECK_NE(state_, kStopped); |
718 | 710 |
719 if (video_decoder_) { | 711 if (video_decoder_) { |
720 video_decoder_->PrepareForShutdownHack(); | 712 video_decoder_->PrepareForShutdownHack(); |
721 video_decoder_ = NULL; | 713 video_decoder_ = NULL; |
722 } | 714 } |
723 | 715 |
724 if (IsPipelineTearingDown() && error_caused_teardown_) { | 716 if (IsPipelineTearingDown() && error_caused_teardown_) { |
725 // If we are stopping due to SetError(), stop normally instead of | 717 // If we are stopping due to SetError(), stop normally instead of |
726 // going to error state and calling |error_cb_|. This converts | 718 // going to error state and calling |error_cb_|. This converts |
727 // the teardown in progress from an error teardown into one that acts | 719 // the teardown in progress from an error teardown into one that acts |
728 // like the error never occurred. | 720 // like the error never occurred. |
729 base::AutoLock auto_lock(lock_); | 721 base::AutoLock auto_lock(lock_); |
730 status_ = PIPELINE_OK; | 722 status_ = PIPELINE_OK; |
731 error_caused_teardown_ = false; | 723 error_caused_teardown_ = false; |
732 } | 724 } |
733 | 725 |
734 stop_cb_ = stop_cb; | 726 stop_cb_ = stop_cb; |
735 | 727 |
736 stop_pending_ = true; | |
737 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { | 728 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { |
738 // We will tear down pipeline immediately when there is no seek operation | 729 // We will tear down pipeline immediately when there is no seek operation |
739 // pending and no teardown in progress. This should include the case where | 730 // pending and no teardown in progress. This should include the case where |
740 // we are partially initialized. | 731 // we are partially initialized. |
741 TearDownPipeline(); | 732 TearDownPipeline(); |
742 } | 733 } |
743 } | 734 } |
744 | 735 |
745 void Pipeline::ErrorChangedTask(PipelineStatus error) { | 736 void Pipeline::ErrorChangedTask(PipelineStatus error) { |
746 DCHECK(message_loop_->BelongsToCurrentThread()); | 737 DCHECK(message_loop_->BelongsToCurrentThread()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 DCHECK(message_loop_->BelongsToCurrentThread()); | 790 DCHECK(message_loop_->BelongsToCurrentThread()); |
800 if (!running_ || tearing_down_) | 791 if (!running_ || tearing_down_) |
801 return; | 792 return; |
802 | 793 |
803 if (audio_renderer_) | 794 if (audio_renderer_) |
804 audio_renderer_->SetVolume(volume); | 795 audio_renderer_->SetVolume(volume); |
805 } | 796 } |
806 | 797 |
807 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { | 798 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { |
808 DCHECK(message_loop_->BelongsToCurrentThread()); | 799 DCHECK(message_loop_->BelongsToCurrentThread()); |
809 DCHECK(!IsPipelineStopPending()); | 800 DCHECK(stop_cb_.is_null()); |
810 | 801 |
811 // Suppress seeking if we're not fully started. | 802 // Suppress seeking if we're not fully started. |
812 if (state_ != kStarted) { | 803 if (state_ != kStarted) { |
813 // TODO(scherkus): should we run the callback? I'm tempted to say the API | 804 // TODO(scherkus): should we run the callback? I'm tempted to say the API |
814 // will only execute the first Seek() request. | 805 // will only execute the first Seek() request. |
815 DVLOG(1) << "Media pipeline has not started, ignoring seek to " | 806 DVLOG(1) << "Media pipeline has not started, ignoring seek to " |
816 << time.InMicroseconds() << " (current state: " << state_ << ")"; | 807 << time.InMicroseconds() << " (current state: " << state_ << ")"; |
817 return; | 808 return; |
818 } | 809 } |
819 | 810 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 | 960 |
970 base::AutoLock auto_lock(lock_); | 961 base::AutoLock auto_lock(lock_); |
971 // We use audio stream to update the clock. So if there is such a stream, | 962 // We use audio stream to update the clock. So if there is such a stream, |
972 // we pause the clock until we receive a valid timestamp. | 963 // we pause the clock until we receive a valid timestamp. |
973 waiting_for_clock_update_ = true; | 964 waiting_for_clock_update_ = true; |
974 if (!has_audio_) { | 965 if (!has_audio_) { |
975 clock_->SetMaxTime(clock_->Duration()); | 966 clock_->SetMaxTime(clock_->Duration()); |
976 StartClockIfWaitingForTimeUpdate_Locked(); | 967 StartClockIfWaitingForTimeUpdate_Locked(); |
977 } | 968 } |
978 | 969 |
979 if (IsPipelineStopPending()) { | 970 // Check if we have a pending stop request that needs to be honored. |
980 // We had a pending stop request need to be honored right now. | 971 if (!stop_cb_.is_null()) { |
981 TearDownPipeline(); | 972 TearDownPipeline(); |
982 } | 973 } |
983 } else { | 974 } else { |
984 NOTREACHED() << "Unexpected state: " << state_; | 975 NOTREACHED() << "Unexpected state: " << state_; |
985 } | 976 } |
986 } | 977 } |
987 | 978 |
988 void Pipeline::TeardownStateTransitionTask() { | 979 void Pipeline::TeardownStateTransitionTask() { |
989 DCHECK(IsPipelineTearingDown()); | 980 DCHECK(IsPipelineTearingDown()); |
990 DCHECK(pending_callbacks_.get()) | 981 DCHECK(pending_callbacks_.get()) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 DCHECK(message_loop_->BelongsToCurrentThread()); | 1018 DCHECK(message_loop_->BelongsToCurrentThread()); |
1028 DCHECK(IsPipelineStopped()); | 1019 DCHECK(IsPipelineStopped()); |
1029 | 1020 |
1030 audio_renderer_ = NULL; | 1021 audio_renderer_ = NULL; |
1031 video_renderer_ = NULL; | 1022 video_renderer_ = NULL; |
1032 demuxer_ = NULL; | 1023 demuxer_ = NULL; |
1033 | 1024 |
1034 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 1025 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) |
1035 error_cb_.Run(status_); | 1026 error_cb_.Run(status_); |
1036 | 1027 |
1037 if (stop_pending_) { | 1028 if (!stop_cb_.is_null()) { |
1038 stop_pending_ = false; | |
1039 { | 1029 { |
1040 base::AutoLock l(lock_); | 1030 base::AutoLock l(lock_); |
1041 running_ = false; | 1031 running_ = false; |
1042 } | 1032 } |
1043 | 1033 |
1044 // Notify the client that stopping has finished. | 1034 // Notify the client that stopping has finished. |
1045 base::ResetAndReturn(&stop_cb_).Run(); | 1035 base::ResetAndReturn(&stop_cb_).Run(); |
1046 } | 1036 } |
1047 | 1037 |
1048 tearing_down_ = false; | 1038 tearing_down_ = false; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 base::Bind(&Pipeline::SetError, this), | 1177 base::Bind(&Pipeline::SetError, this), |
1188 base::Bind(&Pipeline::GetMediaTime, this), | 1178 base::Bind(&Pipeline::GetMediaTime, this), |
1189 base::Bind(&Pipeline::GetMediaDuration, this)); | 1179 base::Bind(&Pipeline::GetMediaDuration, this)); |
1190 return true; | 1180 return true; |
1191 } | 1181 } |
1192 | 1182 |
1193 void Pipeline::TearDownPipeline() { | 1183 void Pipeline::TearDownPipeline() { |
1194 DCHECK(message_loop_->BelongsToCurrentThread()); | 1184 DCHECK(message_loop_->BelongsToCurrentThread()); |
1195 DCHECK_NE(kStopped, state_); | 1185 DCHECK_NE(kStopped, state_); |
1196 | 1186 |
1197 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1187 // We're either... |
1198 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1188 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) |
1199 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1189 // 2) ...tearing down due to an error (it does set tearing_down_) |
| 1190 // 3) ...tearing down due to an error and Stop() was called during that time |
| 1191 DCHECK(!tearing_down_ || |
| 1192 (tearing_down_ && error_caused_teardown_) || |
| 1193 (tearing_down_ && !stop_cb_.is_null())); |
1200 | 1194 |
1201 // Mark that we already start tearing down operation. | 1195 // Mark that we already start tearing down operation. |
1202 tearing_down_ = true; | 1196 tearing_down_ = true; |
1203 | 1197 |
1204 // Cancel any pending operation so we can proceed with teardown. | 1198 // Cancel any pending operation so we can proceed with teardown. |
1205 pending_callbacks_.reset(); | 1199 pending_callbacks_.reset(); |
1206 | 1200 |
1207 switch (state_) { | 1201 switch (state_) { |
1208 case kCreated: | 1202 case kCreated: |
1209 case kError: | 1203 case kError: |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1299 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1293 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1300 lock_.AssertAcquired(); | 1294 lock_.AssertAcquired(); |
1301 if (!waiting_for_clock_update_) | 1295 if (!waiting_for_clock_update_) |
1302 return; | 1296 return; |
1303 | 1297 |
1304 waiting_for_clock_update_ = false; | 1298 waiting_for_clock_update_ = false; |
1305 clock_->Play(); | 1299 clock_->Play(); |
1306 } | 1300 } |
1307 | 1301 |
1308 } // namespace media | 1302 } // namespace media |
OLD | NEW |