Chromium Code Reviews| Index: media/base/pipeline_impl.cc |
| diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc |
| index d071d58db9a08feb4f21669bafc07fa608117188..bd0b550ea2c9afc0b8c678e88a72f5b3e3d2f85f 100644 |
| --- a/media/base/pipeline_impl.cc |
| +++ b/media/base/pipeline_impl.cc |
| @@ -300,6 +300,7 @@ void PipelineImpl::ResetState() { |
| stop_pending_ = false; |
| seek_pending_ = false; |
| tearing_down_ = false; |
| + error_caused_teardown_ = false; |
| duration_ = kZero; |
| buffered_time_ = kZero; |
| buffered_bytes_ = 0; |
| @@ -393,7 +394,7 @@ PipelineImpl::State PipelineImpl::FindNextState(State current) { |
| } else if (current == kStarting) { |
| return kStarted; |
| } else if (current == kStopping) { |
| - return kStopped; |
| + return error_caused_teardown_ ? kError : kStopped; |
| } else { |
| return current; |
| } |
| @@ -670,28 +671,33 @@ void PipelineImpl::InitializeTask() { |
| // additional calls, however most of this logic will be changing. |
| void PipelineImpl::StopTask(PipelineCallback* stop_callback) { |
| DCHECK_EQ(MessageLoop::current(), message_loop_); |
| - PipelineError error = GetError(); |
| + DCHECK(!IsPipelineStopPending()); |
| + DCHECK_NE(state_, kStopped); |
| - if (state_ == kStopped || (IsPipelineStopPending() && error == PIPELINE_OK)) { |
| - // If we are already stopped or stopping normally, return immediately. |
| + if (state_ == kStopped) { |
| + // Already stopped so just run callback. |
| + stop_callback->Run(); |
| delete stop_callback; |
| return; |
| - } else if (state_ == kError || |
| - (IsPipelineStopPending() && error != PIPELINE_OK)) { |
| + } |
| + |
| + if (IsPipelineTearingDown() && error_caused_teardown_) { |
|
scherkus (not reviewing)
2011/01/13 00:47:38
to confirm: this happens in the case someone calls
acolwell GONE FROM CHROMIUM
2011/01/13 01:39:16
This happens in the case where an error occurs tha
|
| // If we are stopping due to SetError(), stop normally instead of |
| - // going to error state. |
| + // going to error state and calling |error_callback_|. This converts |
| + // the teardown in progress from an error teardown into one that acts |
| + // like the error never occurred. |
| AutoLock auto_lock(lock_); |
| error_ = PIPELINE_OK; |
| + error_caused_teardown_ = false; |
| } |
| stop_callback_.reset(stop_callback); |
| stop_pending_ = true; |
| - if (!IsPipelineSeeking()) { |
| + if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { |
| // We will tear down pipeline immediately when there is no seek operation |
| - // pending. This should include the case where we are partially initialized. |
| - // Ideally this case should use SetError() rather than Stop() to tear down. |
| - DCHECK(!IsPipelineTearingDown()); |
| + // pending and no teardown in progress. This should include the case where |
| + // we are partially initialized. |
| TearDownPipeline(); |
| } |
| } |
| @@ -710,6 +716,7 @@ void PipelineImpl::ErrorChangedTask(PipelineError error) { |
| AutoLock auto_lock(lock_); |
| error_ = error; |
| + error_caused_teardown_ = true; |
| TearDownPipeline(); |
| } |
| @@ -915,11 +922,12 @@ void PipelineImpl::FinishDestroyingFiltersTask() { |
| pipeline_filter_ = NULL; |
| - stop_pending_ = false; |
| - tearing_down_ = false; |
| + if (error_caused_teardown_ && GetError() != PIPELINE_OK && |
|
scherkus (not reviewing)
2011/01/13 00:47:38
nit: get rid of extra space between error_caused_t
acolwell GONE FROM CHROMIUM
2011/01/13 01:39:16
Done.
|
| + error_callback_.get()) { |
| + error_callback_->Run(); |
| + } |
| - if (PIPELINE_OK == GetError()) { |
| - // Destroying filters due to Stop(). |
| + if (stop_pending_) { |
| ResetState(); |
| // Notify the client that stopping has finished. |
| @@ -927,14 +935,11 @@ void PipelineImpl::FinishDestroyingFiltersTask() { |
| stop_callback_->Run(); |
| stop_callback_.reset(); |
| } |
| - } else { |
| - // Destroying filters due to SetError(). |
| - set_state(kError); |
| - // If our owner has requested to be notified of an error. |
| - if (error_callback_.get()) { |
| - error_callback_->Run(); |
| - } |
| } |
| + |
| + stop_pending_ = false; |
| + tearing_down_ = false; |
| + error_caused_teardown_ = false; |
| } |
| bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { |
| @@ -1119,25 +1124,54 @@ void PipelineImpl::TearDownPipeline() { |
| // Mark that we already start tearing down operation. |
| tearing_down_ = true; |
| - if (IsPipelineInitializing()) { |
| - // Make it look like initialization was successful. |
| - pipeline_filter_ = pipeline_init_state_->composite_; |
| - pipeline_init_state_.reset(); |
| + switch(state_) { |
| + case kCreated: |
| + case kError: |
| + set_state(kStopped); |
| + message_loop_->PostTask(FROM_HERE, |
| + NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); |
| + break; |
| - set_state(kStopping); |
| - pipeline_filter_->Stop(NewCallback( |
| - this, &PipelineImpl::OnFilterStateTransition)); |
| + case kInitDataSource: |
| + case kInitDemuxer: |
| + case kInitAudioDecoder: |
| + case kInitAudioRenderer: |
| + case kInitVideoDecoder: |
| + case kInitVideoRenderer: |
| + // Make it look like initialization was successful. |
| + pipeline_filter_ = pipeline_init_state_->composite_; |
| + pipeline_init_state_.reset(); |
| + |
| + set_state(kStopping); |
| + pipeline_filter_->Stop( |
| + NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| - FinishInitialization(); |
| - } else if (pipeline_filter_.get()) { |
| - set_state(kPausing); |
| - pipeline_filter_->Pause(NewCallback( |
| - this, &PipelineImpl::OnFilterStateTransition)); |
| - } else { |
| - set_state(kStopped); |
| - message_loop_->PostTask(FROM_HERE, |
| - NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); |
| - } |
| + FinishInitialization(); |
| + break; |
| + |
| + case kPausing: |
| + case kSeeking: |
| + case kFlushing: |
| + case kStarting: |
| + set_state(kStopping); |
| + pipeline_filter_->Stop(NewCallback( |
|
scherkus (not reviewing)
2011/01/13 00:47:38
drop NewCallback to next line
acolwell GONE FROM CHROMIUM
2011/01/13 01:39:16
Done.
|
| + this, &PipelineImpl::OnFilterStateTransition)); |
| + break; |
| + |
| + case kStarted: |
| + case kEnded: |
| + set_state(kPausing); |
| + pipeline_filter_->Pause(NewCallback( |
|
scherkus (not reviewing)
2011/01/13 00:47:38
drop NewCallback to next line
acolwell GONE FROM CHROMIUM
2011/01/13 01:39:16
Done.
|
| + this, &PipelineImpl::OnFilterStateTransition)); |
| + break; |
| + |
| + case kStopping: |
| + case kStopped: |
| + NOTREACHED() << "Unexpected state for teardown: " << state_; |
| + break; |
| + // default: intentionally left out to force new states to cause compiler |
| + // errors. |
| + }; |
| } |
| } // namespace media |