Index: media/base/pipeline.cc |
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc |
index 44ffdf6d86cf38fcade38e66477e75d65cbc67d7..462c44dd57d04e027f6b589554f16d9d5d39724d 100644 |
--- a/media/base/pipeline.cc |
+++ b/media/base/pipeline.cc |
@@ -72,7 +72,6 @@ Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
running_(false), |
seek_pending_(false), |
tearing_down_(false), |
- error_caused_teardown_(false), |
playback_rate_change_pending_(false), |
did_loading_progress_(false), |
total_bytes_(0), |
@@ -121,9 +120,6 @@ void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
void Pipeline::Stop(const base::Closure& stop_cb) { |
base::AutoLock auto_lock(lock_); |
- CHECK(running_) << "Media pipeline isn't running"; |
- |
- // Stop the pipeline, which will set |running_| to false on our behalf. |
message_loop_->PostTask(FROM_HERE, base::Bind( |
&Pipeline::StopTask, this, stop_cb)); |
} |
@@ -162,7 +158,7 @@ void Pipeline::SetPlaybackRate(float playback_rate) { |
base::AutoLock auto_lock(lock_); |
playback_rate_ = playback_rate; |
- if (running_ && !tearing_down_) { |
+ if (running_) { |
message_loop_->PostTask(FROM_HERE, base::Bind( |
&Pipeline::PlaybackRateChangedTask, this, playback_rate)); |
} |
@@ -179,7 +175,7 @@ void Pipeline::SetVolume(float volume) { |
base::AutoLock auto_lock(lock_); |
volume_ = volume; |
- if (running_ && !tearing_down_) { |
+ if (running_) { |
message_loop_->PostTask(FROM_HERE, base::Bind( |
&Pipeline::VolumeChangedTask, this, volume)); |
} |
@@ -238,21 +234,6 @@ PipelineStatistics Pipeline::GetStatistics() const { |
return statistics_; |
} |
-bool Pipeline::IsInitializedForTesting() { |
- DCHECK(message_loop_->BelongsToCurrentThread()) |
- << "Tests should run on the same thread as Pipeline"; |
- switch (state_) { |
- case kPausing: |
- case kFlushing: |
- case kSeeking: |
- case kStarting: |
- case kStarted: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
void Pipeline::SetClockForTesting(Clock* clock) { |
clock_.reset(clock); |
} |
@@ -277,16 +258,6 @@ bool Pipeline::IsPipelineOk() { |
return status_ == PIPELINE_OK; |
} |
-bool Pipeline::IsPipelineStopped() { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
- return state_ == kStopped || state_ == kError; |
-} |
- |
-bool Pipeline::IsPipelineTearingDown() { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
- return tearing_down_; |
-} |
- |
bool Pipeline::IsPipelineSeeking() { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
if (!seek_pending_) |
@@ -335,14 +306,14 @@ Pipeline::State Pipeline::FindNextState(State current) { |
// assumption that we never accept Seek() after Stop(). |
DCHECK(IsPipelineSeeking() || |
!stop_cb_.is_null() || |
- IsPipelineTearingDown()); |
+ tearing_down_); |
return IsPipelineSeeking() ? kSeeking : kStopping; |
} else if (current == kSeeking) { |
return kStarting; |
} else if (current == kStarting) { |
return kStarted; |
} else if (current == kStopping) { |
- return error_caused_teardown_ ? kError : kStopped; |
+ return kStopped; |
} else { |
return current; |
} |
@@ -624,7 +595,7 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) { |
} |
// If we have received the stop or error signal, return immediately. |
- if (!stop_cb_.is_null() || IsPipelineStopped() || !IsPipelineOk()) |
+ if (!stop_cb_.is_null() || state_ == kStopped || !IsPipelineOk()) |
return; |
DCHECK(state_ == kInitDemuxer || |
@@ -706,26 +677,29 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) { |
void Pipeline::StopTask(const base::Closure& stop_cb) { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
DCHECK(stop_cb_.is_null()); |
- DCHECK_NE(state_, kStopped); |
+ |
+ if (state_ == kStopped) { |
+ stop_cb.Run(); |
+ return; |
+ } |
if (video_decoder_) { |
video_decoder_->PrepareForShutdownHack(); |
video_decoder_ = NULL; |
} |
- if (IsPipelineTearingDown() && error_caused_teardown_) { |
+ if (tearing_down_ && status_ != PIPELINE_OK) { |
// If we are stopping due to SetError(), stop normally instead of |
// going to error state and calling |error_cb_|. This converts |
// the teardown in progress from an error teardown into one that acts |
// like the error never occurred. |
base::AutoLock auto_lock(lock_); |
status_ = PIPELINE_OK; |
- error_caused_teardown_ = false; |
} |
stop_cb_ = stop_cb; |
- if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { |
+ if (!IsPipelineSeeking() && !tearing_down_) { |
// We will tear down pipeline immediately when there is no seek operation |
// pending and no teardown in progress. This should include the case where |
// we are partially initialized. |
@@ -740,19 +714,17 @@ void Pipeline::ErrorChangedTask(PipelineStatus error) { |
// Suppress executing additional error logic. Note that if we are currently |
// performing a normal stop, then we return immediately and continue the |
// normal stop. |
- if (IsPipelineStopped() || IsPipelineTearingDown()) { |
+ if (state_ == kStopped || tearing_down_) { |
return; |
} |
base::AutoLock auto_lock(lock_); |
status_ = error; |
- error_caused_teardown_ = true; |
- |
// Posting TearDownPipeline() to message loop so that we can make sure |
// it runs after any pending callbacks that are already queued. |
// |tearing_down_| is set early here to make sure that pending callbacks |
- // don't modify the state before TeadDownPipeline() can run. |
+ // don't modify the state before TearDownPipeline() can run. |
tearing_down_ = true; |
message_loop_->PostTask(FROM_HERE, base::Bind( |
&Pipeline::TearDownPipeline, this)); |
@@ -761,7 +733,7 @@ void Pipeline::ErrorChangedTask(PipelineStatus error) { |
void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
- if (!running_ || tearing_down_) |
+ if (state_ == kStopped || tearing_down_) |
return; |
// Suppress rate change until after seeking. |
@@ -788,7 +760,8 @@ void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
void Pipeline::VolumeChangedTask(float volume) { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
- if (!running_ || tearing_down_) |
+ |
+ if (state_ == kStopped || tearing_down_) |
return; |
if (audio_renderer_) |
@@ -903,14 +876,11 @@ void Pipeline::FilterStateTransitionTask() { |
<< "Filter state transitions must be completed via pending_callbacks_"; |
pending_callbacks_.reset(); |
- // No reason transitioning if we've errored or have stopped. |
- if (IsPipelineStopped()) { |
- return; |
- } |
- |
- // If we are tearing down, don't allow any state changes. Teardown |
- // state changes will come in via TeardownStateTransitionTask(). |
- if (IsPipelineTearingDown()) { |
+ // State transitions while tearing down are handled via |
+ // TeardownStateTransitionTask(). |
+ // |
+ // TODO(scherkus): Merge all state machinery! |
+ if (state_ == kStopped || tearing_down_) { |
return; |
} |
@@ -977,14 +947,14 @@ void Pipeline::FilterStateTransitionTask() { |
} |
void Pipeline::TeardownStateTransitionTask() { |
- DCHECK(IsPipelineTearingDown()); |
+ DCHECK(tearing_down_); |
DCHECK(pending_callbacks_.get()) |
<< "Teardown state transitions must be completed via pending_callbacks_"; |
pending_callbacks_.reset(); |
switch (state_) { |
case kStopping: |
- SetState(error_caused_teardown_ ? kError : kStopped); |
+ SetState(kStopped); |
FinishDestroyingFiltersTask(); |
break; |
case kPausing: |
@@ -997,7 +967,6 @@ void Pipeline::TeardownStateTransitionTask() { |
break; |
case kCreated: |
- case kError: |
case kInitDemuxer: |
case kInitAudioDecoder: |
case kInitAudioRenderer: |
@@ -1016,27 +985,22 @@ void Pipeline::TeardownStateTransitionTask() { |
void Pipeline::FinishDestroyingFiltersTask() { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
- DCHECK(IsPipelineStopped()); |
+ DCHECK_EQ(state_, kStopped); |
audio_renderer_ = NULL; |
video_renderer_ = NULL; |
demuxer_ = NULL; |
+ tearing_down_ = false; |
+ { |
+ base::AutoLock l(lock_); |
+ running_ = false; |
+ } |
- if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) |
+ if (!IsPipelineOk() && !error_cb_.is_null()) |
error_cb_.Run(status_); |
- if (!stop_cb_.is_null()) { |
- { |
- base::AutoLock l(lock_); |
- running_ = false; |
- } |
- |
- // Notify the client that stopping has finished. |
+ if (!stop_cb_.is_null()) |
base::ResetAndReturn(&stop_cb_).Run(); |
- } |
- |
- tearing_down_ = false; |
- error_caused_teardown_ = false; |
} |
void Pipeline::InitializeDemuxer() { |
@@ -1189,7 +1153,7 @@ void Pipeline::TearDownPipeline() { |
// 2) ...tearing down due to an error (it does set tearing_down_) |
// 3) ...tearing down due to an error and Stop() was called during that time |
DCHECK(!tearing_down_ || |
- (tearing_down_ && error_caused_teardown_) || |
+ (tearing_down_ && status_ != PIPELINE_OK) || |
(tearing_down_ && !stop_cb_.is_null())); |
// Mark that we already start tearing down operation. |
@@ -1200,7 +1164,6 @@ void Pipeline::TearDownPipeline() { |
switch (state_) { |
case kCreated: |
- case kError: |
SetState(kStopped); |
// Need to put this in the message loop to make sure that it comes |
// after any pending callback tasks that are already queued. |