diff options
-rw-r--r-- | media/base/pipeline_impl.cc | 10 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 9 | ||||
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 7 | ||||
-rw-r--r-- | webkit/glue/webmediaplayer_impl.cc | 46 | ||||
-rw-r--r-- | webkit/glue/webmediaplayer_impl.h | 6 |
5 files changed, 77 insertions, 1 deletions
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 9b482f8..20bd4cb 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -237,6 +237,10 @@ PipelineError PipelineImpl::GetError() const { return error_; } +void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { + error_callback_.reset(error_callback); +} + void PipelineImpl::ResetState() { AutoLock auto_lock(lock_); running_ = false; @@ -533,6 +537,12 @@ void PipelineImpl::ErrorChangedTask(PipelineError error) { // Destroy every filter and reset the pipeline as well. DestroyFilters(); + + // If our owner has requested to be notified of an error, execute + // |error_callback_| unless we have a "good" error. + if (error_callback_.get() && error != PIPELINE_STOPPING) { + error_callback_->Run(); + } } void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 4eed436..be3ad28 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -7,9 +7,10 @@ #ifndef MEDIA_BASE_PIPELINE_IMPL_H_ #define MEDIA_BASE_PIPELINE_IMPL_H_ +#include <map> +#include <set> #include <string> #include <vector> -#include <set> #include "base/message_loop.h" #include "base/ref_counted.h" @@ -82,6 +83,11 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; virtual PipelineError GetError() const; + // |error_callback_| will be executed upon an error in the pipeline. If + // |error_callback_| is NULL, it is ignored. The pipeline takes ownernship + // of |error_callback|. + virtual void SetPipelineErrorCallback(PipelineCallback* error_callback); + private: // Pipeline states, as described above. enum State { @@ -314,6 +320,7 @@ class PipelineImpl : public Pipeline, public FilterHost { // Callbacks for various pipeline operations. scoped_ptr<PipelineCallback> seek_callback_; scoped_ptr<PipelineCallback> stop_callback_; + scoped_ptr<PipelineCallback> error_callback_; // Vector of our filters and map maintaining the relationship between the // FilterType and the filter itself. diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index e745761..6913cdc 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -32,6 +32,7 @@ class CallbackHelper { MOCK_METHOD0(OnStart, void()); MOCK_METHOD0(OnSeek, void()); MOCK_METHOD0(OnStop, void()); + MOCK_METHOD0(OnError, void()); private: DISALLOW_COPY_AND_ASSIGN(CallbackHelper); @@ -48,6 +49,9 @@ class PipelineImplTest : public ::testing::Test { PipelineImplTest() : pipeline_(new PipelineImpl(&message_loop_)), mocks_(new MockFilterFactory()) { + pipeline_->SetPipelineErrorCallback(NewCallback( + reinterpret_cast<CallbackHelper*>(&callbacks_), + &CallbackHelper::OnError)); } virtual ~PipelineImplTest() { @@ -232,6 +236,7 @@ TEST_F(PipelineImplTest, NeverInitializes) { } TEST_F(PipelineImplTest, RequiredFilterMissing) { + EXPECT_CALL(callbacks_, OnError()); mocks_->set_creation_successful(false); InitializePipeline(); @@ -245,6 +250,7 @@ TEST_F(PipelineImplTest, URLNotFound) { .WillOnce(DoAll(SetError(mocks_->data_source(), PIPELINE_ERROR_URL_NOT_FOUND), Invoke(&RunFilterCallback))); + EXPECT_CALL(callbacks_, OnError()); EXPECT_CALL(*mocks_->data_source(), Stop()); InitializePipeline(); @@ -264,6 +270,7 @@ TEST_F(PipelineImplTest, NoStreams) { EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams()) .WillRepeatedly(Return(0)); EXPECT_CALL(*mocks_->demuxer(), Stop()); + EXPECT_CALL(callbacks_, OnError()); InitializePipeline(); EXPECT_FALSE(pipeline_->IsInitialized()); diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc index d8bad19..14a9524 100644 --- a/webkit/glue/webmediaplayer_impl.cc +++ b/webkit/glue/webmediaplayer_impl.cc @@ -92,6 +92,11 @@ void WebMediaPlayerImpl::Proxy::PipelineSeekCallback() { &WebMediaPlayerImpl::Proxy::PipelineSeekTask)); } +void WebMediaPlayerImpl::Proxy::PipelineErrorCallback() { + render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, + &WebMediaPlayerImpl::Proxy::PipelineErrorTask)); +} + void WebMediaPlayerImpl::Proxy::RepaintTask() { DCHECK(MessageLoop::current() == render_loop_); { @@ -118,6 +123,13 @@ void WebMediaPlayerImpl::Proxy::PipelineSeekTask() { } } +void WebMediaPlayerImpl::Proxy::PipelineErrorTask() { + DCHECK(MessageLoop::current() == render_loop_); + if (webmediaplayer_) { + webmediaplayer_->OnPipelineError(); + } +} + ///////////////////////////////////////////////////////////////////////////// // WebMediaPlayerImpl implementation @@ -140,6 +152,8 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, NOTREACHED() << "Could not start PipelineThread"; } else { pipeline_ = new media::PipelineImpl(pipeline_thread_.message_loop()); + pipeline_->SetPipelineErrorCallback(NewCallback(proxy_.get(), + &WebMediaPlayerImpl::Proxy::PipelineErrorCallback)); } // Also we want to be notified of |main_loop_| destruction. @@ -389,6 +403,38 @@ void WebMediaPlayerImpl::OnPipelineSeek() { } } +void WebMediaPlayerImpl::OnPipelineError() { + DCHECK(MessageLoop::current() == main_loop_); + switch (pipeline_->GetError()) { + case media::PIPELINE_OK: + case media::PIPELINE_STOPPING: + // We're in a good state. Do nothing. + break; + + case media::PIPELINE_ERROR_INITIALIZATION_FAILED: + case media::PIPELINE_ERROR_REQUIRED_FILTER_MISSING: + case media::PIPELINE_ERROR_COULD_NOT_RENDER: + // Format error. + SetNetworkState(WebMediaPlayer::FormatError); + break; + + case media::PIPELINE_ERROR_URL_NOT_FOUND: + case media::PIPELINE_ERROR_NETWORK: + case media::PIPELINE_ERROR_DECODE: + case media::PIPELINE_ERROR_ABORT: + case media::PIPELINE_ERROR_OUT_OF_MEMORY: + case media::PIPELINE_ERROR_READ: + case media::PIPELINE_ERROR_AUDIO_HARDWARE: + case media::DEMUXER_ERROR_COULD_NOT_OPEN: + case media::DEMUXER_ERROR_COULD_NOT_PARSE: + case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS: + case media::DEMUXER_ERROR_COULD_NOT_CREATE_THREAD: + // Decode error. + SetNetworkState(WebMediaPlayer::DecodeError); + break; + } +} + void WebMediaPlayerImpl::SetNetworkState( WebKit::WebMediaPlayer::NetworkState state) { DCHECK(MessageLoop::current() == main_loop_); diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h index a73ea71..841e9bf 100644 --- a/webkit/glue/webmediaplayer_impl.h +++ b/webkit/glue/webmediaplayer_impl.h @@ -106,6 +106,7 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // WebMediaPlayerImpl. void PipelineInitializationCallback(); void PipelineSeekCallback(); + void PipelineErrorCallback(); private: // Invoke |webmediaplayer_| to perform a repaint. @@ -117,6 +118,9 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // Notify |webmediaplayer_| that a seek has finished. void PipelineSeekTask(); + // Notify |webmediaplayer_| that a pipeline error has been set. + void PipelineErrorTask(); + // The render message loop where WebKit lives. MessageLoop* render_loop_; WebMediaPlayerImpl* webmediaplayer_; @@ -213,6 +217,8 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, void OnPipelineSeek(); + void OnPipelineError(); + private: // Helpers that set the network/ready state and notifies the client if // they've changed. |