diff options
author | kylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-30 18:51:52 +0000 |
---|---|---|
committer | kylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-30 18:51:52 +0000 |
commit | db190487d2bc37ef9a2852d948bd8dd4548a98bd (patch) | |
tree | bba60ce128d4e214663cbd45e6620224e2cf3ae4 | |
parent | 66f16b11638993ead4028e853d5565a74b9acba3 (diff) | |
download | chromium_src-db190487d2bc37ef9a2852d948bd8dd4548a98bd.zip chromium_src-db190487d2bc37ef9a2852d948bd8dd4548a98bd.tar.gz chromium_src-db190487d2bc37ef9a2852d948bd8dd4548a98bd.tar.bz2 |
Pipeline will execute a callback whenever an run-time error has happened.
BUG=16738
TEST=pipeline_impl_unittest.cc
Review URL: http://codereview.chromium.org/160298
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22075 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/base/pipeline_impl.cc | 10 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 8 | ||||
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 7 | ||||
-rw-r--r-- | webkit/glue/webmediaplayer_impl.cc | 53 | ||||
-rw-r--r-- | webkit/glue/webmediaplayer_impl.h | 6 |
5 files changed, 81 insertions, 3 deletions
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 10ab9a3..05ee62e 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -247,6 +247,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_); const base::TimeDelta kZero; @@ -551,6 +555,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 e83822d..aee1f59 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -7,9 +7,9 @@ #ifndef MEDIA_BASE_PIPELINE_IMPL_H_ #define MEDIA_BASE_PIPELINE_IMPL_H_ +#include <set> #include <string> #include <vector> -#include <set> #include "base/message_loop.h" #include "base/ref_counted.h" @@ -84,6 +84,11 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual bool IsStreaming() 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 { @@ -323,6 +328,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 7e69ce5..068b095 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() { @@ -234,6 +238,7 @@ TEST_F(PipelineImplTest, NeverInitializes) { } TEST_F(PipelineImplTest, RequiredFilterMissing) { + EXPECT_CALL(callbacks_, OnError()); mocks_->set_creation_successful(false); InitializePipeline(); @@ -247,6 +252,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(); @@ -266,6 +272,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 e31139a..8ab1f29 100644 --- a/webkit/glue/webmediaplayer_impl.cc +++ b/webkit/glue/webmediaplayer_impl.cc @@ -93,6 +93,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_); { @@ -119,6 +124,13 @@ void WebMediaPlayerImpl::Proxy::PipelineSeekTask() { } } +void WebMediaPlayerImpl::Proxy::PipelineErrorTask() { + DCHECK(MessageLoop::current() == render_loop_); + if (webmediaplayer_) { + webmediaplayer_->OnPipelineError(); + } +} + ///////////////////////////////////////////////////////////////////////////// // WebMediaPlayerImpl implementation @@ -139,16 +151,21 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, // Create the pipeline and its thread. if (!pipeline_thread_.Start()) { NOTREACHED() << "Could not start PipelineThread"; - } else { - pipeline_ = new media::PipelineImpl(pipeline_thread_.message_loop()); + return; } + pipeline_ = new media::PipelineImpl(pipeline_thread_.message_loop()); + // Also we want to be notified of |main_loop_| destruction. main_loop_->AddDestructionObserver(this); // Creates the proxy. proxy_ = new Proxy(main_loop_, this); + // Sets the pipeline's error reporting callback. + pipeline_->SetPipelineErrorCallback(NewCallback(proxy_.get(), + &WebMediaPlayerImpl::Proxy::PipelineErrorCallback)); + // Add in the default filter factories. filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); @@ -404,6 +421,38 @@ void WebMediaPlayerImpl::OnPipelineSeek() { } } +void WebMediaPlayerImpl::OnPipelineError() { + DCHECK(MessageLoop::current() == main_loop_); + switch (pipeline_->GetError()) { + case media::PIPELINE_OK: + case media::PIPELINE_STOPPING: + NOTREACHED() << "We shouldn't get called with these non-errors"; + 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 3fd44fe..187c753 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_; @@ -216,6 +220,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. |