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), | |
77 playback_rate_change_pending_(false), | 75 playback_rate_change_pending_(false), |
78 did_loading_progress_(false), | 76 did_loading_progress_(false), |
79 total_bytes_(0), | 77 total_bytes_(0), |
80 natural_size_(0, 0), | 78 natural_size_(0, 0), |
81 volume_(1.0f), | 79 volume_(1.0f), |
82 playback_rate_(0.0f), | 80 playback_rate_(0.0f), |
83 pending_playback_rate_(0.0f), | 81 pending_playback_rate_(0.0f), |
84 clock_(new Clock(&base::Time::Now)), | 82 clock_(new Clock(&base::Time::Now)), |
85 waiting_for_clock_update_(false), | 83 waiting_for_clock_update_(false), |
86 status_(PIPELINE_OK), | 84 status_(PIPELINE_OK), |
87 has_audio_(false), | 85 has_audio_(false), |
88 has_video_(false), | 86 has_video_(false), |
89 state_(kCreated), | 87 state_(kCreated), |
90 seek_timestamp_(kNoTimestamp()), | 88 seek_timestamp_(kNoTimestamp()), |
91 audio_disabled_(false), | 89 audio_disabled_(false), |
92 creation_time_(base::Time::Now()) { | 90 creation_time_(base::Time::Now()) { |
93 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 91 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
94 media_log_->AddEvent( | 92 media_log_->AddEvent( |
95 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 93 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
96 } | 94 } |
97 | 95 |
98 Pipeline::~Pipeline() { | 96 Pipeline::~Pipeline() { |
99 base::AutoLock auto_lock(lock_); | 97 base::AutoLock auto_lock(lock_); |
100 DCHECK(!running_) << "Stop() must complete before destroying object"; | 98 DCHECK(!running_) << "Stop() must complete before destroying object"; |
101 DCHECK(!stop_pending_); | 99 DCHECK(stop_cb_.is_null()); |
102 DCHECK(!seek_pending_); | 100 DCHECK(!seek_pending_); |
103 | 101 |
104 media_log_->AddEvent( | 102 media_log_->AddEvent( |
105 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); | 103 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); |
106 } | 104 } |
107 | 105 |
108 void Pipeline::Start(scoped_ptr<FilterCollection> collection, | 106 void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
109 const PipelineStatusCB& ended_cb, | 107 const PipelineStatusCB& ended_cb, |
110 const PipelineStatusCB& error_cb, | 108 const PipelineStatusCB& error_cb, |
111 const PipelineStatusCB& start_cb) { | 109 const PipelineStatusCB& start_cb) { |
112 base::AutoLock auto_lock(lock_); | 110 base::AutoLock auto_lock(lock_); |
113 CHECK(!running_) << "Media pipeline is already running"; | 111 CHECK(!running_) << "Media pipeline is already running"; |
114 | 112 |
115 running_ = true; | 113 running_ = true; |
116 message_loop_->PostTask(FROM_HERE, base::Bind( | 114 message_loop_->PostTask(FROM_HERE, base::Bind( |
117 &Pipeline::StartTask, this, base::Passed(&collection), | 115 &Pipeline::StartTask, this, base::Passed(&collection), |
118 ended_cb, error_cb, start_cb)); | 116 ended_cb, error_cb, start_cb)); |
119 } | 117 } |
120 | 118 |
121 void Pipeline::Stop(const base::Closure& stop_cb) { | 119 void Pipeline::Stop(const base::Closure& stop_cb) { |
122 base::AutoLock auto_lock(lock_); | |
123 CHECK(running_) << "Media pipeline isn't running"; | |
124 | |
125 // Stop the pipeline, which will set |running_| to false on our behalf. | |
126 message_loop_->PostTask(FROM_HERE, base::Bind( | 120 message_loop_->PostTask(FROM_HERE, base::Bind( |
127 &Pipeline::StopTask, this, stop_cb)); | 121 &Pipeline::StopTask, this, stop_cb)); |
128 } | 122 } |
129 | 123 |
130 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { | 124 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { |
131 base::AutoLock auto_lock(lock_); | 125 base::AutoLock auto_lock(lock_); |
132 CHECK(running_) << "Media pipeline isn't running"; | 126 CHECK(running_) << "Media pipeline isn't running"; |
133 | 127 |
134 message_loop_->PostTask(FROM_HERE, base::Bind( | 128 message_loop_->PostTask(FROM_HERE, base::Bind( |
135 &Pipeline::SeekTask, this, time, seek_cb)); | 129 &Pipeline::SeekTask, this, time, seek_cb)); |
136 } | 130 } |
137 | 131 |
138 bool Pipeline::IsRunning() const { | 132 bool Pipeline::IsRunning() const { |
139 base::AutoLock auto_lock(lock_); | 133 base::AutoLock auto_lock(lock_); |
140 return running_; | 134 return running_; |
141 } | 135 } |
142 | 136 |
143 bool Pipeline::IsInitialized() const { | |
144 // TODO(scherkus): perhaps replace this with a bool that is set/get under the | |
145 // lock, because this is breaching the contract that |state_| is only accessed | |
146 // on |message_loop_|. | |
147 base::AutoLock auto_lock(lock_); | |
148 switch (state_) { | |
149 case kPausing: | |
150 case kFlushing: | |
151 case kSeeking: | |
152 case kStarting: | |
153 case kStarted: | |
154 return true; | |
155 default: | |
156 return false; | |
157 } | |
158 } | |
159 | |
160 bool Pipeline::HasAudio() const { | 137 bool Pipeline::HasAudio() const { |
161 base::AutoLock auto_lock(lock_); | 138 base::AutoLock auto_lock(lock_); |
162 return has_audio_; | 139 return has_audio_; |
163 } | 140 } |
164 | 141 |
165 bool Pipeline::HasVideo() const { | 142 bool Pipeline::HasVideo() const { |
166 base::AutoLock auto_lock(lock_); | 143 base::AutoLock auto_lock(lock_); |
167 return has_video_; | 144 return has_video_; |
168 } | 145 } |
169 | 146 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); | 246 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); |
270 } | 247 } |
271 | 248 |
272 bool Pipeline::IsPipelineOk() { | 249 bool Pipeline::IsPipelineOk() { |
273 base::AutoLock auto_lock(lock_); | 250 base::AutoLock auto_lock(lock_); |
274 return status_ == PIPELINE_OK; | 251 return status_ == PIPELINE_OK; |
275 } | 252 } |
276 | 253 |
277 bool Pipeline::IsPipelineStopped() { | 254 bool Pipeline::IsPipelineStopped() { |
278 DCHECK(message_loop_->BelongsToCurrentThread()); | 255 DCHECK(message_loop_->BelongsToCurrentThread()); |
279 return state_ == kStopped || state_ == kError; | 256 return state_ == kStopped; |
280 } | 257 } |
281 | 258 |
282 bool Pipeline::IsPipelineTearingDown() { | 259 bool Pipeline::IsPipelineTearingDown() { |
283 DCHECK(message_loop_->BelongsToCurrentThread()); | 260 DCHECK(message_loop_->BelongsToCurrentThread()); |
284 return tearing_down_; | 261 return tearing_down_; |
285 } | 262 } |
286 | 263 |
287 bool Pipeline::IsPipelineStopPending() { | 264 bool Pipeline::IsPipelineStopPending() { |
288 DCHECK(message_loop_->BelongsToCurrentThread()); | 265 DCHECK(message_loop_->BelongsToCurrentThread()); |
289 return stop_pending_; | 266 return !stop_cb_.is_null(); |
290 } | 267 } |
291 | 268 |
292 bool Pipeline::IsPipelineSeeking() { | 269 bool Pipeline::IsPipelineSeeking() { |
293 DCHECK(message_loop_->BelongsToCurrentThread()); | 270 DCHECK(message_loop_->BelongsToCurrentThread()); |
294 if (!seek_pending_) | 271 if (!seek_pending_) |
295 return false; | 272 return false; |
296 DCHECK(kSeeking == state_ || kPausing == state_ || | 273 DCHECK(kSeeking == state_ || kPausing == state_ || |
297 kFlushing == state_ || kStarting == state_) | 274 kFlushing == state_ || kStarting == state_) |
298 << "Current state : " << state_; | 275 << "Current state : " << state_; |
299 return true; | 276 return true; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 // assumption that we never accept Seek() after Stop(). | 313 // assumption that we never accept Seek() after Stop(). |
337 DCHECK(IsPipelineSeeking() || | 314 DCHECK(IsPipelineSeeking() || |
338 IsPipelineStopPending() || | 315 IsPipelineStopPending() || |
339 IsPipelineTearingDown()); | 316 IsPipelineTearingDown()); |
340 return IsPipelineSeeking() ? kSeeking : kStopping; | 317 return IsPipelineSeeking() ? kSeeking : kStopping; |
341 } else if (current == kSeeking) { | 318 } else if (current == kSeeking) { |
342 return kStarting; | 319 return kStarting; |
343 } else if (current == kStarting) { | 320 } else if (current == kStarting) { |
344 return kStarted; | 321 return kStarted; |
345 } else if (current == kStopping) { | 322 } else if (current == kStopping) { |
346 return error_caused_teardown_ ? kError : kStopped; | 323 return kStopped; |
347 } else { | 324 } else { |
348 return current; | 325 return current; |
349 } | 326 } |
350 } | 327 } |
351 | 328 |
352 void Pipeline::OnDemuxerError(PipelineStatus error) { | 329 void Pipeline::OnDemuxerError(PipelineStatus error) { |
353 SetError(error); | 330 SetError(error); |
354 } | 331 } |
355 | 332 |
356 void Pipeline::SetError(PipelineStatus error) { | 333 void Pipeline::SetError(PipelineStatus error) { |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 // Fire a seek request to get the renderers to preroll. We can skip a seek | 659 // Fire a seek request to get the renderers to preroll. We can skip a seek |
683 // here as the demuxer should be at the start of the stream. | 660 // here as the demuxer should be at the start of the stream. |
684 seek_pending_ = true; | 661 seek_pending_ = true; |
685 SetState(kSeeking); | 662 SetState(kSeeking); |
686 seek_timestamp_ = demuxer_->GetStartTime(); | 663 seek_timestamp_ = demuxer_->GetStartTime(); |
687 DoSeek(seek_timestamp_, true, | 664 DoSeek(seek_timestamp_, true, |
688 base::Bind(&Pipeline::OnFilterStateTransition, this)); | 665 base::Bind(&Pipeline::OnFilterStateTransition, this)); |
689 } | 666 } |
690 } | 667 } |
691 | 668 |
692 // This method is called as a result of the client calling Pipeline::Stop() or | |
693 // as the result of an error condition. | |
694 // We stop the filters in the reverse order. | |
695 // | |
696 // TODO(scherkus): beware! this can get posted multiple times since we post | |
697 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | |
698 // additional calls, however most of this logic will be changing. | |
699 void Pipeline::StopTask(const base::Closure& stop_cb) { | 669 void Pipeline::StopTask(const base::Closure& stop_cb) { |
700 DCHECK(message_loop_->BelongsToCurrentThread()); | 670 DCHECK(message_loop_->BelongsToCurrentThread()); |
701 DCHECK(!IsPipelineStopPending()); | 671 DCHECK(!IsPipelineStopPending()); |
702 DCHECK_NE(state_, kStopped); | 672 DCHECK(!stop_cb.is_null()); |
| 673 |
| 674 if (state_ == kStopped) { |
| 675 stop_cb.Run(); |
| 676 return; |
| 677 } |
703 | 678 |
704 if (video_decoder_) { | 679 if (video_decoder_) { |
705 video_decoder_->PrepareForShutdownHack(); | 680 video_decoder_->PrepareForShutdownHack(); |
706 video_decoder_ = NULL; | 681 video_decoder_ = NULL; |
707 } | 682 } |
708 | 683 |
709 if (IsPipelineTearingDown() && error_caused_teardown_) { | 684 if (IsPipelineTearingDown() && status_ != PIPELINE_OK) { |
710 // If we are stopping due to SetError(), stop normally instead of | 685 // If we are stopping due to SetError(), stop normally instead of |
711 // going to error state and calling |error_cb_|. This converts | 686 // going to error state and calling |error_cb_|. This converts |
712 // the teardown in progress from an error teardown into one that acts | 687 // the teardown in progress from an error teardown into one that acts |
713 // like the error never occurred. | 688 // like the error never occurred. |
714 base::AutoLock auto_lock(lock_); | 689 base::AutoLock auto_lock(lock_); |
715 status_ = PIPELINE_OK; | 690 status_ = PIPELINE_OK; |
716 error_caused_teardown_ = false; | |
717 } | 691 } |
718 | 692 |
719 stop_cb_ = stop_cb; | 693 stop_cb_ = stop_cb; |
720 | 694 |
721 stop_pending_ = true; | |
722 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { | 695 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { |
723 // We will tear down pipeline immediately when there is no seek operation | 696 // We will tear down pipeline immediately when there is no seek operation |
724 // pending and no teardown in progress. This should include the case where | 697 // pending and no teardown in progress. This should include the case where |
725 // we are partially initialized. | 698 // we are partially initialized. |
726 TearDownPipeline(); | 699 TearDownPipeline(); |
727 } | 700 } |
728 } | 701 } |
729 | 702 |
730 void Pipeline::ErrorChangedTask(PipelineStatus error) { | 703 void Pipeline::ErrorChangedTask(PipelineStatus error) { |
731 DCHECK(message_loop_->BelongsToCurrentThread()); | 704 DCHECK(message_loop_->BelongsToCurrentThread()); |
732 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 705 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
733 | 706 |
734 // Suppress executing additional error logic. Note that if we are currently | 707 // Suppress executing additional error logic. Note that if we are currently |
735 // performing a normal stop, then we return immediately and continue the | 708 // performing a normal stop, then we return immediately and continue the |
736 // normal stop. | 709 // normal stop. |
737 if (IsPipelineStopped() || IsPipelineTearingDown()) { | 710 if (IsPipelineStopped() || IsPipelineTearingDown()) { |
738 return; | 711 return; |
739 } | 712 } |
740 | 713 |
741 base::AutoLock auto_lock(lock_); | 714 base::AutoLock auto_lock(lock_); |
742 status_ = error; | 715 status_ = error; |
743 | 716 |
744 error_caused_teardown_ = true; | |
745 | |
746 // Posting TearDownPipeline() to message loop so that we can make sure | 717 // Posting TearDownPipeline() to message loop so that we can make sure |
747 // it runs after any pending callbacks that are already queued. | 718 // it runs after any pending callbacks that are already queued. |
748 // |tearing_down_| is set early here to make sure that pending callbacks | 719 // |tearing_down_| is set early here to make sure that pending callbacks |
749 // don't modify the state before TeadDownPipeline() can run. | 720 // don't modify the state before TeadDownPipeline() can run. |
750 tearing_down_ = true; | 721 tearing_down_ = true; |
751 message_loop_->PostTask(FROM_HERE, base::Bind( | 722 message_loop_->PostTask(FROM_HERE, base::Bind( |
752 &Pipeline::TearDownPipeline, this)); | 723 &Pipeline::TearDownPipeline, this)); |
753 } | 724 } |
754 | 725 |
755 void Pipeline::PlaybackRateChangedTask(float playback_rate) { | 726 void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 } | 926 } |
956 | 927 |
957 void Pipeline::TeardownStateTransitionTask() { | 928 void Pipeline::TeardownStateTransitionTask() { |
958 DCHECK(IsPipelineTearingDown()); | 929 DCHECK(IsPipelineTearingDown()); |
959 DCHECK(pending_callbacks_.get()) | 930 DCHECK(pending_callbacks_.get()) |
960 << "Teardown state transitions must be completed via pending_callbacks_"; | 931 << "Teardown state transitions must be completed via pending_callbacks_"; |
961 pending_callbacks_.reset(); | 932 pending_callbacks_.reset(); |
962 | 933 |
963 switch (state_) { | 934 switch (state_) { |
964 case kStopping: | 935 case kStopping: |
965 SetState(error_caused_teardown_ ? kError : kStopped); | 936 SetState(kStopped); |
966 FinishDestroyingFiltersTask(); | 937 FinishDestroyingFiltersTask(); |
967 break; | 938 break; |
968 case kPausing: | 939 case kPausing: |
969 SetState(kFlushing); | 940 SetState(kFlushing); |
970 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 941 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
971 break; | 942 break; |
972 case kFlushing: | 943 case kFlushing: |
973 SetState(kStopping); | 944 SetState(kStopping); |
974 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 945 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
975 break; | 946 break; |
976 | 947 |
977 case kCreated: | 948 case kCreated: |
978 case kError: | |
979 case kInitDemuxer: | 949 case kInitDemuxer: |
980 case kInitAudioDecoder: | 950 case kInitAudioDecoder: |
981 case kInitAudioRenderer: | 951 case kInitAudioRenderer: |
982 case kInitVideoDecoder: | 952 case kInitVideoDecoder: |
983 case kInitVideoRenderer: | 953 case kInitVideoRenderer: |
984 case kSeeking: | 954 case kSeeking: |
985 case kStarting: | 955 case kStarting: |
986 case kStopped: | 956 case kStopped: |
987 case kStarted: | 957 case kStarted: |
988 NOTREACHED() << "Unexpected state for teardown: " << state_; | 958 NOTREACHED() << "Unexpected state for teardown: " << state_; |
989 break; | 959 break; |
990 // default: intentionally left out to force new states to cause compiler | 960 // default: intentionally left out to force new states to cause compiler |
991 // errors. | 961 // errors. |
992 }; | 962 }; |
993 } | 963 } |
994 | 964 |
995 void Pipeline::FinishDestroyingFiltersTask() { | 965 void Pipeline::FinishDestroyingFiltersTask() { |
996 DCHECK(message_loop_->BelongsToCurrentThread()); | 966 DCHECK(message_loop_->BelongsToCurrentThread()); |
997 DCHECK(IsPipelineStopped()); | 967 DCHECK(IsPipelineStopped()); |
998 | 968 |
999 audio_renderer_ = NULL; | 969 audio_renderer_ = NULL; |
1000 video_renderer_ = NULL; | 970 video_renderer_ = NULL; |
1001 demuxer_ = NULL; | 971 demuxer_ = NULL; |
| 972 { |
| 973 base::AutoLock l(lock_); |
| 974 running_ = false; |
| 975 } |
1002 | 976 |
1003 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 977 // We prioritize executing stop callbacks over error callbacks if they're |
| 978 // present. |
| 979 if (!stop_cb_.is_null()) { |
| 980 base::ResetAndReturn(&stop_cb_).Run(); |
| 981 } else if (!error_cb_.is_null() && status_ != PIPELINE_OK) { |
1004 error_cb_.Run(status_); | 982 error_cb_.Run(status_); |
1005 | |
1006 if (stop_pending_) { | |
1007 stop_pending_ = false; | |
1008 { | |
1009 base::AutoLock l(lock_); | |
1010 running_ = false; | |
1011 } | |
1012 | |
1013 // Notify the client that stopping has finished. | |
1014 base::ResetAndReturn(&stop_cb_).Run(); | |
1015 } | 983 } |
1016 | 984 |
1017 tearing_down_ = false; | 985 tearing_down_ = false; |
1018 error_caused_teardown_ = false; | |
1019 } | 986 } |
1020 | 987 |
1021 void Pipeline::InitializeDemuxer() { | 988 void Pipeline::InitializeDemuxer() { |
1022 DCHECK(message_loop_->BelongsToCurrentThread()); | 989 DCHECK(message_loop_->BelongsToCurrentThread()); |
1023 DCHECK(IsPipelineOk()); | 990 DCHECK(IsPipelineOk()); |
1024 | 991 |
1025 demuxer_ = filter_collection_->GetDemuxer(); | 992 demuxer_ = filter_collection_->GetDemuxer(); |
1026 if (!demuxer_) { | 993 if (!demuxer_) { |
1027 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 994 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1028 return; | 995 return; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 base::Bind(&Pipeline::SetError, this), | 1123 base::Bind(&Pipeline::SetError, this), |
1157 base::Bind(&Pipeline::GetMediaTime, this), | 1124 base::Bind(&Pipeline::GetMediaTime, this), |
1158 base::Bind(&Pipeline::GetMediaDuration, this)); | 1125 base::Bind(&Pipeline::GetMediaDuration, this)); |
1159 return true; | 1126 return true; |
1160 } | 1127 } |
1161 | 1128 |
1162 void Pipeline::TearDownPipeline() { | 1129 void Pipeline::TearDownPipeline() { |
1163 DCHECK(message_loop_->BelongsToCurrentThread()); | 1130 DCHECK(message_loop_->BelongsToCurrentThread()); |
1164 DCHECK_NE(kStopped, state_); | 1131 DCHECK_NE(kStopped, state_); |
1165 | 1132 |
1166 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1133 // We're either... |
1167 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1134 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) |
1168 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1135 // 2) ...tearing down due to an error (it does set tearing_down_) |
| 1136 // 3) ...tearing down due to an error and Stop() was called |
| 1137 DCHECK(!tearing_down_ && !stop_cb_.is_null() || |
| 1138 (tearing_down_ && status_ != PIPELINE_OK) || |
| 1139 (tearing_down_ && !stop_cb_.is_null())); |
1169 | 1140 |
1170 // Mark that we already start tearing down operation. | 1141 // Mark that we already start tearing down operation. |
1171 tearing_down_ = true; | 1142 tearing_down_ = true; |
1172 | 1143 |
1173 // Cancel any pending operation so we can proceed with teardown. | 1144 // Cancel any pending operation so we can proceed with teardown. |
1174 pending_callbacks_.reset(); | 1145 pending_callbacks_.reset(); |
1175 | 1146 |
1176 switch (state_) { | 1147 switch (state_) { |
1177 case kCreated: | 1148 case kCreated: |
1178 case kError: | |
1179 SetState(kStopped); | 1149 SetState(kStopped); |
1180 // Need to put this in the message loop to make sure that it comes | 1150 // Need to put this in the message loop to make sure that it comes |
1181 // after any pending callback tasks that are already queued. | 1151 // after any pending callback tasks that are already queued. |
1182 message_loop_->PostTask(FROM_HERE, base::Bind( | 1152 message_loop_->PostTask(FROM_HERE, base::Bind( |
1183 &Pipeline::FinishDestroyingFiltersTask, this)); | 1153 &Pipeline::FinishDestroyingFiltersTask, this)); |
1184 break; | 1154 break; |
1185 | 1155 |
1186 case kInitDemuxer: | 1156 case kInitDemuxer: |
1187 case kInitAudioDecoder: | 1157 case kInitAudioDecoder: |
1188 case kInitAudioRenderer: | 1158 case kInitAudioRenderer: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1238 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1269 lock_.AssertAcquired(); | 1239 lock_.AssertAcquired(); |
1270 if (!waiting_for_clock_update_) | 1240 if (!waiting_for_clock_update_) |
1271 return; | 1241 return; |
1272 | 1242 |
1273 waiting_for_clock_update_ = false; | 1243 waiting_for_clock_update_ = false; |
1274 clock_->Play(); | 1244 clock_->Play(); |
1275 } | 1245 } |
1276 | 1246 |
1277 } // namespace media | 1247 } // namespace media |
OLD | NEW |