Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: media/base/pipeline.cc

Issue 10825280: Merge Pipeline's kError state with kStopped: a baby step towards bringing sanity to shutdown. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: maybe this time Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 tearing_down_(false), 74 tearing_down_(false),
75 error_caused_teardown_(false),
76 playback_rate_change_pending_(false), 75 playback_rate_change_pending_(false),
77 did_loading_progress_(false), 76 did_loading_progress_(false),
78 total_bytes_(0), 77 total_bytes_(0),
79 natural_size_(0, 0), 78 natural_size_(0, 0),
80 volume_(1.0f), 79 volume_(1.0f),
81 playback_rate_(0.0f), 80 playback_rate_(0.0f),
82 pending_playback_rate_(0.0f), 81 pending_playback_rate_(0.0f),
83 clock_(new Clock(&base::Time::Now)), 82 clock_(new Clock(&base::Time::Now)),
84 waiting_for_clock_update_(false), 83 waiting_for_clock_update_(false),
85 status_(PIPELINE_OK), 84 status_(PIPELINE_OK),
(...skipping 28 matching lines...) Expand all
114 CHECK(!running_) << "Media pipeline is already running"; 113 CHECK(!running_) << "Media pipeline is already running";
115 114
116 running_ = true; 115 running_ = true;
117 message_loop_->PostTask(FROM_HERE, base::Bind( 116 message_loop_->PostTask(FROM_HERE, base::Bind(
118 &Pipeline::StartTask, this, base::Passed(&collection), 117 &Pipeline::StartTask, this, base::Passed(&collection),
119 ended_cb, error_cb, start_cb)); 118 ended_cb, error_cb, start_cb));
120 } 119 }
121 120
122 void Pipeline::Stop(const base::Closure& stop_cb) { 121 void Pipeline::Stop(const base::Closure& stop_cb) {
123 base::AutoLock auto_lock(lock_); 122 base::AutoLock auto_lock(lock_);
124 CHECK(running_) << "Media pipeline isn't running";
125
126 // Stop the pipeline, which will set |running_| to false on our behalf.
127 message_loop_->PostTask(FROM_HERE, base::Bind( 123 message_loop_->PostTask(FROM_HERE, base::Bind(
128 &Pipeline::StopTask, this, stop_cb)); 124 &Pipeline::StopTask, this, stop_cb));
129 } 125 }
130 126
131 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 127 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
132 base::AutoLock auto_lock(lock_); 128 base::AutoLock auto_lock(lock_);
133 CHECK(running_) << "Media pipeline isn't running"; 129 CHECK(running_) << "Media pipeline isn't running";
134 130
135 message_loop_->PostTask(FROM_HERE, base::Bind( 131 message_loop_->PostTask(FROM_HERE, base::Bind(
136 &Pipeline::SeekTask, this, time, seek_cb)); 132 &Pipeline::SeekTask, this, time, seek_cb));
(...skipping 18 matching lines...) Expand all
155 base::AutoLock auto_lock(lock_); 151 base::AutoLock auto_lock(lock_);
156 return playback_rate_; 152 return playback_rate_;
157 } 153 }
158 154
159 void Pipeline::SetPlaybackRate(float playback_rate) { 155 void Pipeline::SetPlaybackRate(float playback_rate) {
160 if (playback_rate < 0.0f) 156 if (playback_rate < 0.0f)
161 return; 157 return;
162 158
163 base::AutoLock auto_lock(lock_); 159 base::AutoLock auto_lock(lock_);
164 playback_rate_ = playback_rate; 160 playback_rate_ = playback_rate;
165 if (running_ && !tearing_down_) { 161 if (running_) {
166 message_loop_->PostTask(FROM_HERE, base::Bind( 162 message_loop_->PostTask(FROM_HERE, base::Bind(
167 &Pipeline::PlaybackRateChangedTask, this, playback_rate)); 163 &Pipeline::PlaybackRateChangedTask, this, playback_rate));
168 } 164 }
169 } 165 }
170 166
171 float Pipeline::GetVolume() const { 167 float Pipeline::GetVolume() const {
172 base::AutoLock auto_lock(lock_); 168 base::AutoLock auto_lock(lock_);
173 return volume_; 169 return volume_;
174 } 170 }
175 171
176 void Pipeline::SetVolume(float volume) { 172 void Pipeline::SetVolume(float volume) {
177 if (volume < 0.0f || volume > 1.0f) 173 if (volume < 0.0f || volume > 1.0f)
178 return; 174 return;
179 175
180 base::AutoLock auto_lock(lock_); 176 base::AutoLock auto_lock(lock_);
181 volume_ = volume; 177 volume_ = volume;
182 if (running_ && !tearing_down_) { 178 if (running_) {
183 message_loop_->PostTask(FROM_HERE, base::Bind( 179 message_loop_->PostTask(FROM_HERE, base::Bind(
184 &Pipeline::VolumeChangedTask, this, volume)); 180 &Pipeline::VolumeChangedTask, this, volume));
185 } 181 }
186 } 182 }
187 183
188 TimeDelta Pipeline::GetMediaTime() const { 184 TimeDelta Pipeline::GetMediaTime() const {
189 base::AutoLock auto_lock(lock_); 185 base::AutoLock auto_lock(lock_);
190 return clock_->Elapsed(); 186 return clock_->Elapsed();
191 } 187 }
192 188
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 bool ret = did_loading_progress_; 227 bool ret = did_loading_progress_;
232 did_loading_progress_ = false; 228 did_loading_progress_ = false;
233 return ret; 229 return ret;
234 } 230 }
235 231
236 PipelineStatistics Pipeline::GetStatistics() const { 232 PipelineStatistics Pipeline::GetStatistics() const {
237 base::AutoLock auto_lock(lock_); 233 base::AutoLock auto_lock(lock_);
238 return statistics_; 234 return statistics_;
239 } 235 }
240 236
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
256 void Pipeline::SetClockForTesting(Clock* clock) { 237 void Pipeline::SetClockForTesting(Clock* clock) {
257 clock_.reset(clock); 238 clock_.reset(clock);
258 } 239 }
259 240
260 void Pipeline::SetErrorForTesting(PipelineStatus status) { 241 void Pipeline::SetErrorForTesting(PipelineStatus status) {
261 SetError(status); 242 SetError(status);
262 } 243 }
263 244
264 void Pipeline::SetState(State next_state) { 245 void Pipeline::SetState(State next_state) {
265 if (state_ != kStarted && next_state == kStarted && 246 if (state_ != kStarted && next_state == kStarted &&
266 !creation_time_.is_null()) { 247 !creation_time_.is_null()) {
267 UMA_HISTOGRAM_TIMES( 248 UMA_HISTOGRAM_TIMES(
268 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_); 249 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_);
269 creation_time_ = base::Time(); 250 creation_time_ = base::Time();
270 } 251 }
271 state_ = next_state; 252 state_ = next_state;
272 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); 253 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
273 } 254 }
274 255
275 bool Pipeline::IsPipelineOk() { 256 bool Pipeline::IsPipelineOk() {
276 base::AutoLock auto_lock(lock_); 257 base::AutoLock auto_lock(lock_);
277 return status_ == PIPELINE_OK; 258 return status_ == PIPELINE_OK;
278 } 259 }
279 260
280 bool Pipeline::IsPipelineStopped() {
281 DCHECK(message_loop_->BelongsToCurrentThread());
282 return state_ == kStopped || state_ == kError;
283 }
284
285 bool Pipeline::IsPipelineTearingDown() {
286 DCHECK(message_loop_->BelongsToCurrentThread());
287 return tearing_down_;
288 }
289
290 bool Pipeline::IsPipelineSeeking() { 261 bool Pipeline::IsPipelineSeeking() {
291 DCHECK(message_loop_->BelongsToCurrentThread()); 262 DCHECK(message_loop_->BelongsToCurrentThread());
292 if (!seek_pending_) 263 if (!seek_pending_)
293 return false; 264 return false;
294 DCHECK(kSeeking == state_ || kPausing == state_ || 265 DCHECK(kSeeking == state_ || kPausing == state_ ||
295 kFlushing == state_ || kStarting == state_) 266 kFlushing == state_ || kStarting == state_)
296 << "Current state : " << state_; 267 << "Current state : " << state_;
297 return true; 268 return true;
298 } 269 }
299 270
(...skipping 28 matching lines...) Expand all
328 // static 299 // static
329 Pipeline::State Pipeline::FindNextState(State current) { 300 Pipeline::State Pipeline::FindNextState(State current) {
330 // TODO(scherkus): refactor InitializeTask() to make use of this function. 301 // TODO(scherkus): refactor InitializeTask() to make use of this function.
331 if (current == kPausing) { 302 if (current == kPausing) {
332 return kFlushing; 303 return kFlushing;
333 } else if (current == kFlushing) { 304 } else if (current == kFlushing) {
334 // We will always honor Seek() before Stop(). This is based on the 305 // We will always honor Seek() before Stop(). This is based on the
335 // assumption that we never accept Seek() after Stop(). 306 // assumption that we never accept Seek() after Stop().
336 DCHECK(IsPipelineSeeking() || 307 DCHECK(IsPipelineSeeking() ||
337 !stop_cb_.is_null() || 308 !stop_cb_.is_null() ||
338 IsPipelineTearingDown()); 309 tearing_down_);
339 return IsPipelineSeeking() ? kSeeking : kStopping; 310 return IsPipelineSeeking() ? kSeeking : kStopping;
340 } else if (current == kSeeking) { 311 } else if (current == kSeeking) {
341 return kStarting; 312 return kStarting;
342 } else if (current == kStarting) { 313 } else if (current == kStarting) {
343 return kStarted; 314 return kStarted;
344 } else if (current == kStopping) { 315 } else if (current == kStopping) {
345 return error_caused_teardown_ ? kError : kStopped; 316 return kStopped;
346 } else { 317 } else {
347 return current; 318 return current;
348 } 319 }
349 } 320 }
350 321
351 void Pipeline::OnDemuxerError(PipelineStatus error) { 322 void Pipeline::OnDemuxerError(PipelineStatus error) {
352 SetError(error); 323 SetError(error);
353 } 324 }
354 325
355 void Pipeline::SetError(PipelineStatus error) { 326 void Pipeline::SetError(PipelineStatus error) {
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 if (state_ == kInitVideoDecoder && 588 if (state_ == kInitVideoDecoder &&
618 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { 589 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) {
619 state_ = kInitAudioRenderer; 590 state_ = kInitAudioRenderer;
620 } else { 591 } else {
621 SetError(last_stage_status); 592 SetError(last_stage_status);
622 return; 593 return;
623 } 594 }
624 } 595 }
625 596
626 // If we have received the stop or error signal, return immediately. 597 // If we have received the stop or error signal, return immediately.
627 if (!stop_cb_.is_null() || IsPipelineStopped() || !IsPipelineOk()) 598 if (!stop_cb_.is_null() || state_ == kStopped || !IsPipelineOk())
628 return; 599 return;
629 600
630 DCHECK(state_ == kInitDemuxer || 601 DCHECK(state_ == kInitDemuxer ||
631 state_ == kInitAudioDecoder || 602 state_ == kInitAudioDecoder ||
632 state_ == kInitAudioRenderer || 603 state_ == kInitAudioRenderer ||
633 state_ == kInitVideoDecoder || 604 state_ == kInitVideoDecoder ||
634 state_ == kInitVideoRenderer); 605 state_ == kInitVideoRenderer);
635 606
636 // Demuxer created, create audio decoder. 607 // Demuxer created, create audio decoder.
637 if (state_ == kInitDemuxer) { 608 if (state_ == kInitDemuxer) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // This method is called as a result of the client calling Pipeline::Stop() or 670 // This method is called as a result of the client calling Pipeline::Stop() or
700 // as the result of an error condition. 671 // as the result of an error condition.
701 // We stop the filters in the reverse order. 672 // We stop the filters in the reverse order.
702 // 673 //
703 // TODO(scherkus): beware! this can get posted multiple times since we post 674 // TODO(scherkus): beware! this can get posted multiple times since we post
704 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 675 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
705 // additional calls, however most of this logic will be changing. 676 // additional calls, however most of this logic will be changing.
706 void Pipeline::StopTask(const base::Closure& stop_cb) { 677 void Pipeline::StopTask(const base::Closure& stop_cb) {
707 DCHECK(message_loop_->BelongsToCurrentThread()); 678 DCHECK(message_loop_->BelongsToCurrentThread());
708 DCHECK(stop_cb_.is_null()); 679 DCHECK(stop_cb_.is_null());
709 DCHECK_NE(state_, kStopped); 680
681 if (state_ == kStopped) {
682 stop_cb.Run();
683 return;
684 }
710 685
711 if (video_decoder_) { 686 if (video_decoder_) {
712 video_decoder_->PrepareForShutdownHack(); 687 video_decoder_->PrepareForShutdownHack();
713 video_decoder_ = NULL; 688 video_decoder_ = NULL;
714 } 689 }
715 690
716 if (IsPipelineTearingDown() && error_caused_teardown_) { 691 if (tearing_down_ && status_ != PIPELINE_OK) {
717 // If we are stopping due to SetError(), stop normally instead of 692 // If we are stopping due to SetError(), stop normally instead of
718 // going to error state and calling |error_cb_|. This converts 693 // going to error state and calling |error_cb_|. This converts
719 // the teardown in progress from an error teardown into one that acts 694 // the teardown in progress from an error teardown into one that acts
720 // like the error never occurred. 695 // like the error never occurred.
721 base::AutoLock auto_lock(lock_); 696 base::AutoLock auto_lock(lock_);
722 status_ = PIPELINE_OK; 697 status_ = PIPELINE_OK;
723 error_caused_teardown_ = false;
724 } 698 }
725 699
726 stop_cb_ = stop_cb; 700 stop_cb_ = stop_cb;
727 701
728 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { 702 if (!IsPipelineSeeking() && !tearing_down_) {
729 // We will tear down pipeline immediately when there is no seek operation 703 // We will tear down pipeline immediately when there is no seek operation
730 // pending and no teardown in progress. This should include the case where 704 // pending and no teardown in progress. This should include the case where
731 // we are partially initialized. 705 // we are partially initialized.
732 TearDownPipeline(); 706 TearDownPipeline();
733 } 707 }
734 } 708 }
735 709
736 void Pipeline::ErrorChangedTask(PipelineStatus error) { 710 void Pipeline::ErrorChangedTask(PipelineStatus error) {
737 DCHECK(message_loop_->BelongsToCurrentThread()); 711 DCHECK(message_loop_->BelongsToCurrentThread());
738 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; 712 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
739 713
740 // Suppress executing additional error logic. Note that if we are currently 714 // Suppress executing additional error logic. Note that if we are currently
741 // performing a normal stop, then we return immediately and continue the 715 // performing a normal stop, then we return immediately and continue the
742 // normal stop. 716 // normal stop.
743 if (IsPipelineStopped() || IsPipelineTearingDown()) { 717 if (state_ == kStopped || tearing_down_) {
744 return; 718 return;
745 } 719 }
746 720
747 base::AutoLock auto_lock(lock_); 721 base::AutoLock auto_lock(lock_);
748 status_ = error; 722 status_ = error;
749 723
750 error_caused_teardown_ = true;
751
752 // Posting TearDownPipeline() to message loop so that we can make sure 724 // Posting TearDownPipeline() to message loop so that we can make sure
753 // it runs after any pending callbacks that are already queued. 725 // it runs after any pending callbacks that are already queued.
754 // |tearing_down_| is set early here to make sure that pending callbacks 726 // |tearing_down_| is set early here to make sure that pending callbacks
755 // don't modify the state before TeadDownPipeline() can run. 727 // don't modify the state before TearDownPipeline() can run.
756 tearing_down_ = true; 728 tearing_down_ = true;
757 message_loop_->PostTask(FROM_HERE, base::Bind( 729 message_loop_->PostTask(FROM_HERE, base::Bind(
758 &Pipeline::TearDownPipeline, this)); 730 &Pipeline::TearDownPipeline, this));
759 } 731 }
760 732
761 void Pipeline::PlaybackRateChangedTask(float playback_rate) { 733 void Pipeline::PlaybackRateChangedTask(float playback_rate) {
762 DCHECK(message_loop_->BelongsToCurrentThread()); 734 DCHECK(message_loop_->BelongsToCurrentThread());
763 735
764 if (!running_ || tearing_down_) 736 if (state_ == kStopped || tearing_down_)
765 return; 737 return;
766 738
767 // Suppress rate change until after seeking. 739 // Suppress rate change until after seeking.
768 if (IsPipelineSeeking()) { 740 if (IsPipelineSeeking()) {
769 pending_playback_rate_ = playback_rate; 741 pending_playback_rate_ = playback_rate;
770 playback_rate_change_pending_ = true; 742 playback_rate_change_pending_ = true;
771 return; 743 return;
772 } 744 }
773 745
774 { 746 {
775 base::AutoLock auto_lock(lock_); 747 base::AutoLock auto_lock(lock_);
776 clock_->SetPlaybackRate(playback_rate); 748 clock_->SetPlaybackRate(playback_rate);
777 } 749 }
778 750
779 // These will get set after initialization completes in case playback rate is 751 // These will get set after initialization completes in case playback rate is
780 // set prior to initialization. 752 // set prior to initialization.
781 if (demuxer_) 753 if (demuxer_)
782 demuxer_->SetPlaybackRate(playback_rate); 754 demuxer_->SetPlaybackRate(playback_rate);
783 if (audio_renderer_) 755 if (audio_renderer_)
784 audio_renderer_->SetPlaybackRate(playback_rate_); 756 audio_renderer_->SetPlaybackRate(playback_rate_);
785 if (video_renderer_) 757 if (video_renderer_)
786 video_renderer_->SetPlaybackRate(playback_rate_); 758 video_renderer_->SetPlaybackRate(playback_rate_);
787 } 759 }
788 760
789 void Pipeline::VolumeChangedTask(float volume) { 761 void Pipeline::VolumeChangedTask(float volume) {
790 DCHECK(message_loop_->BelongsToCurrentThread()); 762 DCHECK(message_loop_->BelongsToCurrentThread());
791 if (!running_ || tearing_down_) 763
764 if (state_ == kStopped || tearing_down_)
792 return; 765 return;
793 766
794 if (audio_renderer_) 767 if (audio_renderer_)
795 audio_renderer_->SetVolume(volume); 768 audio_renderer_->SetVolume(volume);
796 } 769 }
797 770
798 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 771 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
799 DCHECK(message_loop_->BelongsToCurrentThread()); 772 DCHECK(message_loop_->BelongsToCurrentThread());
800 DCHECK(stop_cb_.is_null()); 773 DCHECK(stop_cb_.is_null());
801 774
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 clock_->SetMaxTime(clock_->Duration()); 869 clock_->SetMaxTime(clock_->Duration());
897 StartClockIfWaitingForTimeUpdate_Locked(); 870 StartClockIfWaitingForTimeUpdate_Locked();
898 } 871 }
899 872
900 void Pipeline::FilterStateTransitionTask() { 873 void Pipeline::FilterStateTransitionTask() {
901 DCHECK(message_loop_->BelongsToCurrentThread()); 874 DCHECK(message_loop_->BelongsToCurrentThread());
902 DCHECK(pending_callbacks_.get()) 875 DCHECK(pending_callbacks_.get())
903 << "Filter state transitions must be completed via pending_callbacks_"; 876 << "Filter state transitions must be completed via pending_callbacks_";
904 pending_callbacks_.reset(); 877 pending_callbacks_.reset();
905 878
906 // No reason transitioning if we've errored or have stopped. 879 // State transitions while tearing down are handled via
907 if (IsPipelineStopped()) { 880 // TeardownStateTransitionTask().
881 //
882 // TODO(scherkus): Merge all state machinery!
883 if (state_ == kStopped || tearing_down_) {
908 return; 884 return;
909 } 885 }
910 886
911 // If we are tearing down, don't allow any state changes. Teardown
912 // state changes will come in via TeardownStateTransitionTask().
913 if (IsPipelineTearingDown()) {
914 return;
915 }
916
917 if (!TransientState(state_)) { 887 if (!TransientState(state_)) {
918 NOTREACHED() << "Invalid current state: " << state_; 888 NOTREACHED() << "Invalid current state: " << state_;
919 SetError(PIPELINE_ERROR_ABORT); 889 SetError(PIPELINE_ERROR_ABORT);
920 return; 890 return;
921 } 891 }
922 892
923 // Decrement the number of remaining transitions, making sure to transition 893 // Decrement the number of remaining transitions, making sure to transition
924 // to the next state if needed. 894 // to the next state if needed.
925 SetState(FindNextState(state_)); 895 SetState(FindNextState(state_));
926 if (state_ == kSeeking) { 896 if (state_ == kSeeking) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 // Check if we have a pending stop request that needs to be honored. 940 // Check if we have a pending stop request that needs to be honored.
971 if (!stop_cb_.is_null()) { 941 if (!stop_cb_.is_null()) {
972 TearDownPipeline(); 942 TearDownPipeline();
973 } 943 }
974 } else { 944 } else {
975 NOTREACHED() << "Unexpected state: " << state_; 945 NOTREACHED() << "Unexpected state: " << state_;
976 } 946 }
977 } 947 }
978 948
979 void Pipeline::TeardownStateTransitionTask() { 949 void Pipeline::TeardownStateTransitionTask() {
980 DCHECK(IsPipelineTearingDown()); 950 DCHECK(tearing_down_);
981 DCHECK(pending_callbacks_.get()) 951 DCHECK(pending_callbacks_.get())
982 << "Teardown state transitions must be completed via pending_callbacks_"; 952 << "Teardown state transitions must be completed via pending_callbacks_";
983 pending_callbacks_.reset(); 953 pending_callbacks_.reset();
984 954
985 switch (state_) { 955 switch (state_) {
986 case kStopping: 956 case kStopping:
987 SetState(error_caused_teardown_ ? kError : kStopped); 957 SetState(kStopped);
988 FinishDestroyingFiltersTask(); 958 FinishDestroyingFiltersTask();
989 break; 959 break;
990 case kPausing: 960 case kPausing:
991 SetState(kFlushing); 961 SetState(kFlushing);
992 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 962 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
993 break; 963 break;
994 case kFlushing: 964 case kFlushing:
995 SetState(kStopping); 965 SetState(kStopping);
996 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 966 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
997 break; 967 break;
998 968
999 case kCreated: 969 case kCreated:
1000 case kError:
1001 case kInitDemuxer: 970 case kInitDemuxer:
1002 case kInitAudioDecoder: 971 case kInitAudioDecoder:
1003 case kInitAudioRenderer: 972 case kInitAudioRenderer:
1004 case kInitVideoDecoder: 973 case kInitVideoDecoder:
1005 case kInitVideoRenderer: 974 case kInitVideoRenderer:
1006 case kSeeking: 975 case kSeeking:
1007 case kStarting: 976 case kStarting:
1008 case kStopped: 977 case kStopped:
1009 case kStarted: 978 case kStarted:
1010 NOTREACHED() << "Unexpected state for teardown: " << state_; 979 NOTREACHED() << "Unexpected state for teardown: " << state_;
1011 break; 980 break;
1012 // default: intentionally left out to force new states to cause compiler 981 // default: intentionally left out to force new states to cause compiler
1013 // errors. 982 // errors.
1014 }; 983 };
1015 } 984 }
1016 985
1017 void Pipeline::FinishDestroyingFiltersTask() { 986 void Pipeline::FinishDestroyingFiltersTask() {
1018 DCHECK(message_loop_->BelongsToCurrentThread()); 987 DCHECK(message_loop_->BelongsToCurrentThread());
1019 DCHECK(IsPipelineStopped()); 988 DCHECK_EQ(state_, kStopped);
1020 989
1021 audio_renderer_ = NULL; 990 audio_renderer_ = NULL;
1022 video_renderer_ = NULL; 991 video_renderer_ = NULL;
1023 demuxer_ = NULL; 992 demuxer_ = NULL;
993 tearing_down_ = false;
994 {
995 base::AutoLock l(lock_);
996 running_ = false;
997 }
1024 998
1025 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) 999 if (!IsPipelineOk() && !error_cb_.is_null())
1026 error_cb_.Run(status_); 1000 error_cb_.Run(status_);
1027 1001
1028 if (!stop_cb_.is_null()) { 1002 if (!stop_cb_.is_null())
1029 {
1030 base::AutoLock l(lock_);
1031 running_ = false;
1032 }
1033
1034 // Notify the client that stopping has finished.
1035 base::ResetAndReturn(&stop_cb_).Run(); 1003 base::ResetAndReturn(&stop_cb_).Run();
1036 }
1037
1038 tearing_down_ = false;
1039 error_caused_teardown_ = false;
1040 } 1004 }
1041 1005
1042 void Pipeline::InitializeDemuxer() { 1006 void Pipeline::InitializeDemuxer() {
1043 DCHECK(message_loop_->BelongsToCurrentThread()); 1007 DCHECK(message_loop_->BelongsToCurrentThread());
1044 DCHECK(IsPipelineOk()); 1008 DCHECK(IsPipelineOk());
1045 1009
1046 demuxer_ = filter_collection_->GetDemuxer(); 1010 demuxer_ = filter_collection_->GetDemuxer();
1047 if (!demuxer_) { 1011 if (!demuxer_) {
1048 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1012 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1049 return; 1013 return;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 1146
1183 void Pipeline::TearDownPipeline() { 1147 void Pipeline::TearDownPipeline() {
1184 DCHECK(message_loop_->BelongsToCurrentThread()); 1148 DCHECK(message_loop_->BelongsToCurrentThread());
1185 DCHECK_NE(kStopped, state_); 1149 DCHECK_NE(kStopped, state_);
1186 1150
1187 // We're either... 1151 // We're either...
1188 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) 1152 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_)
1189 // 2) ...tearing down due to an error (it does set tearing_down_) 1153 // 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 1154 // 3) ...tearing down due to an error and Stop() was called during that time
1191 DCHECK(!tearing_down_ || 1155 DCHECK(!tearing_down_ ||
1192 (tearing_down_ && error_caused_teardown_) || 1156 (tearing_down_ && status_ != PIPELINE_OK) ||
1193 (tearing_down_ && !stop_cb_.is_null())); 1157 (tearing_down_ && !stop_cb_.is_null()));
1194 1158
1195 // Mark that we already start tearing down operation. 1159 // Mark that we already start tearing down operation.
1196 tearing_down_ = true; 1160 tearing_down_ = true;
1197 1161
1198 // Cancel any pending operation so we can proceed with teardown. 1162 // Cancel any pending operation so we can proceed with teardown.
1199 pending_callbacks_.reset(); 1163 pending_callbacks_.reset();
1200 1164
1201 switch (state_) { 1165 switch (state_) {
1202 case kCreated: 1166 case kCreated:
1203 case kError:
1204 SetState(kStopped); 1167 SetState(kStopped);
1205 // Need to put this in the message loop to make sure that it comes 1168 // Need to put this in the message loop to make sure that it comes
1206 // after any pending callback tasks that are already queued. 1169 // after any pending callback tasks that are already queued.
1207 message_loop_->PostTask(FROM_HERE, base::Bind( 1170 message_loop_->PostTask(FROM_HERE, base::Bind(
1208 &Pipeline::FinishDestroyingFiltersTask, this)); 1171 &Pipeline::FinishDestroyingFiltersTask, this));
1209 break; 1172 break;
1210 1173
1211 case kInitDemuxer: 1174 case kInitDemuxer:
1212 case kInitAudioDecoder: 1175 case kInitAudioDecoder:
1213 case kInitAudioRenderer: 1176 case kInitAudioRenderer:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1256 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1294 lock_.AssertAcquired(); 1257 lock_.AssertAcquired();
1295 if (!waiting_for_clock_update_) 1258 if (!waiting_for_clock_update_)
1296 return; 1259 return;
1297 1260
1298 waiting_for_clock_update_ = false; 1261 waiting_for_clock_update_ = false;
1299 clock_->Play(); 1262 clock_->Play();
1300 } 1263 }
1301 1264
1302 } // namespace media 1265 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698