diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-15 07:09:27 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-15 07:09:27 +0000 |
commit | f78d1dfc8d92a6667a355e90da7f2f100c89b832 (patch) | |
tree | bcba6d266d612b0df072cf32241c83d1ba6b897a | |
parent | 4e425be43fae960cad4dc81be0181bf99f2f7080 (diff) | |
download | chromium_src-f78d1dfc8d92a6667a355e90da7f2f100c89b832.zip chromium_src-f78d1dfc8d92a6667a355e90da7f2f100c89b832.tar.gz chromium_src-f78d1dfc8d92a6667a355e90da7f2f100c89b832.tar.bz2 |
Remove MessageLoop methods from Filter interface to
separate Filter management from MessageLoop management.
This sets the stage for filters to share threads in the
future which will reduce resource consumption when
multiple <video> tags are on the same page.
BUG=69451
TEST=None
Review URL: http://codereview.chromium.org/6171009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71548 0039d316-1c4b-4281-b951-d872f2087c98
35 files changed, 361 insertions, 347 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl_unittest.cc b/chrome/renderer/media/audio_renderer_impl_unittest.cc index b5f80e6..249c987 100644 --- a/chrome/renderer/media/audio_renderer_impl_unittest.cc +++ b/chrome/renderer/media/audio_renderer_impl_unittest.cc @@ -46,7 +46,6 @@ class AudioRendererImplTest : public ::testing::Test { // Create and initialize audio renderer. renderer_ = new AudioRendererImpl(filter_); renderer_->set_host(&host_); - renderer_->set_message_loop(message_loop_.get()); renderer_->Initialize(decoder_, media::NewExpectedCallback()); // Run pending tasks and simulate responding with a created audio stream. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 9395eca..f16ae6f 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -106,6 +106,7 @@ #include "grit/renderer_resources.h" #include "media/base/filter_collection.h" #include "media/base/media_switches.h" +#include "media/base/message_loop_factory_impl.h" #include "net/base/data_url.h" #include "net/base/escape.h" #include "net/base/net_errors.h" @@ -2811,6 +2812,8 @@ WebSharedWorker* RenderView::createSharedWorker( WebMediaPlayer* RenderView::createMediaPlayer( WebFrame* frame, WebMediaPlayerClient* client) { + scoped_ptr<media::MessageLoopFactory> message_loop_factory( + new media::MessageLoopFactoryImpl()); scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); @@ -2846,7 +2849,9 @@ WebMediaPlayer* RenderView::createMediaPlayer( video_renderer = renderer; scoped_ptr<webkit_glue::WebMediaPlayerImpl> result( - new webkit_glue::WebMediaPlayerImpl(client, collection.release())); + new webkit_glue::WebMediaPlayerImpl(client, + collection.release(), + message_loop_factory.release())); if (!result->Initialize(frame, cmd_line->HasSwitch(switches::kSimpleDataSource), video_renderer)) { diff --git a/media/base/composite_filter.cc b/media/base/composite_filter.cc index 94665fd..41eb31c 100644 --- a/media/base/composite_filter.cc +++ b/media/base/composite_filter.cc @@ -4,6 +4,7 @@ #include "media/base/composite_filter.h" +#include "base/message_loop.h" #include "base/stl_util-inl.h" #include "media/base/callback.h" @@ -40,46 +41,21 @@ class CompositeFilter::FilterHostImpl : public FilterHost { DISALLOW_COPY_AND_ASSIGN(FilterHostImpl); }; -CompositeFilter::CompositeFilter(MessageLoop* message_loop) { - Init(message_loop, NULL); -} - -CompositeFilter::CompositeFilter(MessageLoop* message_loop, - ThreadFactoryFunction thread_factory) { - DCHECK(thread_factory); - Init(message_loop, thread_factory); -} - -void CompositeFilter::Init(MessageLoop* message_loop, - ThreadFactoryFunction thread_factory) { +CompositeFilter::CompositeFilter(MessageLoop* message_loop) + : state_(kCreated), + sequence_index_(0), + message_loop_(message_loop), + error_(PIPELINE_OK) { DCHECK(message_loop); - message_loop_ = message_loop; - thread_factory_ = thread_factory; runnable_factory_.reset( new ScopedRunnableMethodFactory<CompositeFilter>(this)); - - if (!thread_factory_) { - thread_factory_ = &CompositeFilter::DefaultThreadFactory; - } - - state_ = kCreated; - sequence_index_ = 0; - error_ = PIPELINE_OK; } CompositeFilter::~CompositeFilter() { DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK(state_ == kCreated || state_ == kStopped); - // Stop every running filter thread. - for (FilterThreadVector::iterator iter = filter_threads_.begin(); - iter != filter_threads_.end(); - ++iter) { - (*iter)->Stop(); - } - filters_.clear(); - STLDeleteElements(&filter_threads_); } bool CompositeFilter::AddFilter(scoped_refptr<Filter> filter) { @@ -87,19 +63,6 @@ bool CompositeFilter::AddFilter(scoped_refptr<Filter> filter) { if (!filter.get() || state_ != kCreated || !host()) return false; - // Create a dedicated thread for this filter if applicable. - if (filter->requires_message_loop()) { - scoped_ptr<base::Thread> thread( - thread_factory_(filter->message_loop_name())); - - if (!thread.get() || !thread->Start()) { - return false; - } - - filter->set_message_loop(thread->message_loop()); - filter_threads_.push_back(thread.release()); - } - // Register ourselves as the filter's host. filter->set_host(host_impl_.get()); filters_.push_back(make_scoped_refptr(filter.get())); @@ -121,22 +84,6 @@ FilterHost* CompositeFilter::host() { return host_impl_.get() ? host_impl_->host() : NULL; } -bool CompositeFilter::requires_message_loop() const { - return false; -} - -const char* CompositeFilter::message_loop_name() const { - return "CompositeFilter"; -} - -void CompositeFilter::set_message_loop(MessageLoop* message_loop) { - NOTREACHED() << "Message loop should not be set."; -} - -MessageLoop* CompositeFilter::message_loop() { - return NULL; -} - void CompositeFilter::Play(FilterCallback* play_callback) { DCHECK_EQ(message_loop_, MessageLoop::current()); scoped_ptr<FilterCallback> callback(play_callback); @@ -278,11 +225,6 @@ void CompositeFilter::OnAudioRendererDisabled() { } } -base::Thread* CompositeFilter::DefaultThreadFactory( - const char* thread_name) { - return new base::Thread(thread_name); -} - void CompositeFilter::ChangeState(State new_state) { DCHECK_EQ(message_loop_, MessageLoop::current()); state_ = new_state; @@ -529,9 +471,9 @@ void CompositeFilter::SetError(PipelineError error) { } CompositeFilter::FilterHostImpl::FilterHostImpl(CompositeFilter* parent, - FilterHost* host) : - parent_(parent), - host_(host) { + FilterHost* host) + : parent_(parent), + host_(host) { } FilterHost* CompositeFilter::FilterHostImpl::host() { diff --git a/media/base/composite_filter.h b/media/base/composite_filter.h index c1bd8c0..daac421 100644 --- a/media/base/composite_filter.h +++ b/media/base/composite_filter.h @@ -5,39 +5,29 @@ #ifndef MEDIA_BASE_COMPOSITE_FILTER_H_ #define MEDIA_BASE_COMPOSITE_FILTER_H_ -#include "base/threading/thread.h" +#include "base/task.h" #include "media/base/filter_host.h" #include "media/base/filters.h" +class MessageLoop; + namespace media { class CompositeFilter : public Filter { public: - typedef base::Thread* (*ThreadFactoryFunction)(const char* thread_name); - - CompositeFilter(MessageLoop* message_loop); - - // Constructor that allows the default thread creation strategy to be - // overridden. - CompositeFilter(MessageLoop* message_loop, - ThreadFactoryFunction thread_factory); + explicit CompositeFilter(MessageLoop* message_loop); // Adds a filter to the composite. This is only allowed after set_host() // is called and before the first state changing operation such as Play(), // Flush(), Stop(), or Seek(). True is returned if the filter was successfully // added to the composite. False is returned if the filter couldn't be added - // because the composite is in the wrong state or the filter needed a thread - // and the composite was unable to create one. + // because the composite is in the wrong state. bool AddFilter(scoped_refptr<Filter> filter); // media::Filter methods. virtual const char* major_mime_type() const; virtual void set_host(FilterHost* host); virtual FilterHost* host(); - virtual bool requires_message_loop() const; - virtual const char* message_loop_name() const; - virtual void set_message_loop(MessageLoop* message_loop); - virtual MessageLoop* message_loop(); virtual void Play(FilterCallback* play_callback); virtual void Pause(FilterCallback* pause_callback); virtual void Flush(FilterCallback* flush_callback); @@ -49,9 +39,6 @@ class CompositeFilter : public Filter { protected: virtual ~CompositeFilter(); - /// Default thread factory strategy. - static base::Thread* DefaultThreadFactory(const char* thread_name); - void SetError(PipelineError error); private: @@ -75,9 +62,6 @@ class CompositeFilter : public Filter { kError }; - // Initialization method called by constructors. - void Init(MessageLoop* message_loop, ThreadFactoryFunction thread_factory); - // Transition to a new state. void ChangeState(State new_state); @@ -124,17 +108,10 @@ class CompositeFilter : public Filter { // to the host of this filter. bool CanForwardError(); - // Vector of threads owned by the composite and used by filters in |filters_|. - typedef std::vector<base::Thread*> FilterThreadVector; - FilterThreadVector filter_threads_; - // Vector of the filters added to the composite. typedef std::vector<scoped_refptr<Filter> > FilterVector; FilterVector filters_; - // Factory function used to create filter threads. - ThreadFactoryFunction thread_factory_; - // Callback for the pending request. scoped_ptr<FilterCallback> callback_; diff --git a/media/base/composite_filter_unittest.cc b/media/base/composite_filter_unittest.cc index 4ce96c1..0be2185 100644 --- a/media/base/composite_filter_unittest.cc +++ b/media/base/composite_filter_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/message_loop.h" #include "media/base/composite_filter.h" #include "media/base/mock_callback.h" #include "media/base/mock_filter_host.h" @@ -297,56 +298,29 @@ void CompositeFilterTest::RunFilter2Callback() { delete callback; } -static base::Thread* NullThreadFactory(const char* thread_name) { - return NULL; -} - // Test AddFilter() failure cases. TEST_F(CompositeFilterTest, TestAddFilterFailCases) { // Test adding a null pointer. EXPECT_FALSE(composite_->AddFilter(NULL)); - scoped_refptr<StrictMock<MockFilter> > filter = - new StrictMock<MockFilter>(true); + scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>(); EXPECT_EQ(NULL, filter->host()); - EXPECT_EQ(NULL, filter->message_loop()); // Test failing because set_host() hasn't been called yet. EXPECT_FALSE(composite_->AddFilter(filter)); - - // Test thread creation failure. - composite_ = new CompositeFilter(&message_loop_, &NullThreadFactory); - composite_->set_host(mock_filter_host_.get()); - EXPECT_FALSE(composite_->AddFilter(filter)); - EXPECT_EQ(NULL, filter->host()); - EXPECT_EQ(NULL, filter->message_loop()); } // Test successful AddFilter() cases. TEST_F(CompositeFilterTest, TestAddFilter) { composite_->set_host(mock_filter_host_.get()); - // Add a filter that doesn't require a message loop. + // Add a filter. scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>(); EXPECT_EQ(NULL, filter->host()); - EXPECT_EQ(NULL, filter->message_loop()); EXPECT_TRUE(composite_->AddFilter(filter)); EXPECT_TRUE(filter->host() != NULL); - EXPECT_EQ(NULL, filter->message_loop()); - - // Add a filter that requires a message loop. - scoped_refptr<StrictMock<MockFilter> > filter_2 = - new StrictMock<MockFilter>(true); - - EXPECT_EQ(NULL, filter_2->host()); - EXPECT_EQ(NULL, filter_2->message_loop()); - - EXPECT_TRUE(composite_->AddFilter(filter_2)); - - EXPECT_TRUE(filter_2->host() != NULL); - EXPECT_TRUE(filter_2->message_loop() != NULL); } TEST_F(CompositeFilterTest, TestPlay) { diff --git a/media/base/filters.cc b/media/base/filters.cc index d3d3bcb..eff50b4 100644 --- a/media/base/filters.cc +++ b/media/base/filters.cc @@ -5,11 +5,10 @@ #include "media/base/filters.h" #include "base/logging.h" -#include "base/message_loop.h" namespace media { -Filter::Filter() : host_(NULL), message_loop_(NULL) {} +Filter::Filter() : host_(NULL) {} Filter::~Filter() {} @@ -27,24 +26,6 @@ FilterHost* Filter::host() { return host_; } -bool Filter::requires_message_loop() const { - return false; -} - -const char* Filter::message_loop_name() const { - return "FilterThread"; -} - -void Filter::set_message_loop(MessageLoop* message_loop) { - DCHECK(message_loop); - DCHECK(!message_loop_); - message_loop_ = message_loop; -} - -MessageLoop* Filter::message_loop() { - return message_loop_; -} - void Filter::Play(FilterCallback* callback) { DCHECK(callback); if (callback) { @@ -93,26 +74,10 @@ bool DataSource::IsUrlSupported(const std::string& url) { return true; } -bool Demuxer::requires_message_loop() const { - return true; -} - -const char* Demuxer::message_loop_name() const { - return "DemuxerThread"; -} - const char* AudioDecoder::major_mime_type() const { return mime_type::kMajorTypeAudio; } -bool AudioDecoder::requires_message_loop() const { - return true; -} - -const char* AudioDecoder::message_loop_name() const { - return "AudioDecoderThread"; -} - const char* AudioRenderer::major_mime_type() const { return mime_type::kMajorTypeAudio; } @@ -121,14 +86,6 @@ const char* VideoDecoder::major_mime_type() const { return mime_type::kMajorTypeVideo; } -bool VideoDecoder::requires_message_loop() const { - return true; -} - -const char* VideoDecoder::message_loop_name() const { - return "VideoDecoderThread"; -} - const char* VideoRenderer::major_mime_type() const { return mime_type::kMajorTypeVideo; } diff --git a/media/base/filters.h b/media/base/filters.h index 49fa347..84c466d 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -33,8 +33,6 @@ #include "media/base/media_format.h" #include "media/base/video_frame.h" -class MessageLoop; - namespace media { class Buffer; @@ -61,20 +59,6 @@ class Filter : public base::RefCountedThreadSafe<Filter> { virtual FilterHost* host(); - // Indicates whether this filter requires a message loop to operate. - virtual bool requires_message_loop() const; - - // The name to associate with this filter's message loop. - virtual const char* message_loop_name() const; - - // Sets the private member |message_loop_|, which is used by filters for - // processing asynchronous tasks and maintaining synchronized access to - // internal data members. The message loop should be running and exceed the - // lifetime of the filter. - virtual void set_message_loop(MessageLoop* message_loop); - - virtual MessageLoop* message_loop(); - // The pipeline has resumed playback. Filters can continue requesting reads. // Filters may implement this method if they need to respond to this call. // TODO(boliu): Check that callback is not NULL in subclasses. @@ -114,11 +98,9 @@ class Filter : public base::RefCountedThreadSafe<Filter> { virtual ~Filter(); FilterHost* host() const { return host_; } - MessageLoop* message_loop() const { return message_loop_; } private: FilterHost* host_; - MessageLoop* message_loop_; DISALLOW_COPY_AND_ASSIGN(Filter); }; @@ -154,9 +136,6 @@ class DataSource : public Filter { class Demuxer : public Filter { public: - virtual bool requires_message_loop() const; - virtual const char* message_loop_name() const; - // Initialize a Demuxer with the given DataSource, executing the callback upon // completion. virtual void Initialize(DataSource* data_source, @@ -211,9 +190,6 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { class VideoDecoder : public Filter { public: virtual const char* major_mime_type() const; - virtual bool requires_message_loop() const; - virtual const char* message_loop_name() const; - // Initialize a VideoDecoder with the given DemuxerStream, executing the // callback upon completion. @@ -256,8 +232,6 @@ class VideoDecoder : public Filter { class AudioDecoder : public Filter { public: virtual const char* major_mime_type() const; - virtual bool requires_message_loop() const; - virtual const char* message_loop_name() const; // Initialize a AudioDecoder with the given DemuxerStream, executing the // callback upon completion. diff --git a/media/base/message_loop_factory.cc b/media/base/message_loop_factory.cc new file mode 100644 index 0000000..e5b1d33 --- /dev/null +++ b/media/base/message_loop_factory.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/message_loop_factory.h" + +namespace media { + +MessageLoopFactory::~MessageLoopFactory() {} + +} // namespace media diff --git a/media/base/message_loop_factory.h b/media/base/message_loop_factory.h new file mode 100644 index 0000000..dacfab2 --- /dev/null +++ b/media/base/message_loop_factory.h @@ -0,0 +1,34 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_MESSAGE_LOOP_FACTORY_H_ +#define MEDIA_BASE_MESSAGE_LOOP_FACTORY_H_ + +#include <string> + +#include "base/scoped_ptr.h" + +class MessageLoop; + +namespace media { + +// Factory object that manages named MessageLoops. +class MessageLoopFactory { + public: + // Get the message loop associated with |name|. A new MessageLoop + // is created if the factory doesn't have one associated with |name|. + // NULL is returned if |name| is an empty string, or a new + // MessageLoop needs to be created and a failure occurs during the + // creation process. + virtual MessageLoop* GetMessageLoop(const std::string& name) = 0; + + protected: + // Only allow scoped_ptr<> to delete factory. + friend class scoped_ptr<MessageLoopFactory>; + virtual ~MessageLoopFactory(); +}; + +} // namespace media + +#endif // MEDIA_BASE_MESSAGE_LOOP_FACTORY_H_ diff --git a/media/base/message_loop_factory_impl.cc b/media/base/message_loop_factory_impl.cc new file mode 100644 index 0000000..bcf3bf8 --- /dev/null +++ b/media/base/message_loop_factory_impl.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/message_loop_factory_impl.h" + +namespace media { + +MessageLoopFactoryImpl::MessageLoopFactoryImpl() {} + +MessageLoopFactoryImpl::~MessageLoopFactoryImpl() { + AutoLock auto_lock(lock_); + + for (ThreadMap::iterator iter = thread_map_.begin(); + iter != thread_map_.end(); + ++iter) { + base::Thread* thread = (*iter).second; + + if (thread) { + thread->Stop(); + delete thread; + } + } + thread_map_.clear(); +} + +// MessageLoopFactory methods. +MessageLoop* MessageLoopFactoryImpl::GetMessageLoop(const std::string& name) { + if (name.empty()) { + return NULL; + } + + AutoLock auto_lock(lock_); + + ThreadMap::iterator it = thread_map_.find(name); + if (it != thread_map_.end()) + return (*it).second->message_loop(); + + scoped_ptr<base::Thread> thread(new base::Thread(name.c_str())); + + if (thread->Start()) { + MessageLoop* message_loop = thread->message_loop(); + thread_map_[name] = thread.release(); + return message_loop; + } + + LOG(ERROR) << "Failed to start '" << name << "' thread!"; + return NULL; +} + +} // namespace media diff --git a/media/base/message_loop_factory_impl.h b/media/base/message_loop_factory_impl.h new file mode 100644 index 0000000..1c8a61a --- /dev/null +++ b/media/base/message_loop_factory_impl.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_MESSAGE_LOOP_FACTORY_IMPL_H_ +#define MEDIA_BASE_MESSAGE_LOOP_FACTORY_IMPL_H_ + +#include <map> +#include <string> + +#include "base/threading/thread.h" +#include "media/base/message_loop_factory.h" + +namespace media { + +class MessageLoopFactoryImpl : public MessageLoopFactory { + public: + MessageLoopFactoryImpl(); + + // MessageLoopFactory methods. + virtual MessageLoop* GetMessageLoop(const std::string& name); + + protected: + virtual ~MessageLoopFactoryImpl(); + + private: + // Lock used to serialize access for the following data members. + Lock lock_; + + typedef std::map<std::string, base::Thread*> ThreadMap; + ThreadMap thread_map_; + + DISALLOW_COPY_AND_ASSIGN(MessageLoopFactoryImpl); +}; + +} // namespace media + +#endif // MEDIA_BASE_MESSAGE_LOOP_FACTORY_IMPL_H_ diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index 90df69b..8aa5458 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc @@ -74,23 +74,9 @@ void RunStopFilterCallback(FilterCallback* callback) { delete callback; } -MockFilter::MockFilter() : - requires_message_loop_(false) { -} - -MockFilter::MockFilter(bool requires_message_loop) : - requires_message_loop_(requires_message_loop) { +MockFilter::MockFilter() { } MockFilter::~MockFilter() {} -bool MockFilter::requires_message_loop() const { - return requires_message_loop_; -} - -const char* MockFilter::message_loop_name() const { - return "MockFilter"; -} - - } // namespace media diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 45c1e29..3439597 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -46,12 +46,8 @@ class Destroyable : public MockClass { class MockFilter : public Filter { public: MockFilter(); - MockFilter(bool requires_message_loop); // Filter implementation. - virtual bool requires_message_loop() const; - virtual const char* message_loop_name() const; - MOCK_METHOD1(Play, void(FilterCallback* callback)); MOCK_METHOD1(Pause, void(FilterCallback* callback)); MOCK_METHOD1(Flush, void(FilterCallback* callback)); @@ -64,9 +60,6 @@ class MockFilter : public Filter { virtual ~MockFilter(); private: - - bool requires_message_loop_; - DISALLOW_COPY_AND_ASSIGN(MockFilter); }; diff --git a/media/filters/decoder_base.h b/media/filters/decoder_base.h index f8b26ab..7ddd16e 100644 --- a/media/filters/decoder_base.h +++ b/media/filters/decoder_base.h @@ -26,17 +26,16 @@ namespace media { template <class Decoder, class Output> class DecoderBase : public Decoder { public: - // Filter implementation. virtual void Stop(FilterCallback* callback) { - this->message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &DecoderBase::StopTask, callback)); } virtual void Seek(base::TimeDelta time, FilterCallback* callback) { - this->message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &DecoderBase::SeekTask, time, callback)); } @@ -44,7 +43,7 @@ class DecoderBase : public Decoder { // Decoder implementation. virtual void Initialize(DemuxerStream* demuxer_stream, FilterCallback* callback) { - this->message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &DecoderBase::InitializeTask, @@ -58,13 +57,14 @@ class DecoderBase : public Decoder { // Note that this class is only used by the audio decoder, this will // eventually be merged into FFmpegAudioDecoder. virtual void ProduceAudioSamples(scoped_refptr<Output> output) { - this->message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &DecoderBase::ReadTask, output)); } protected: - DecoderBase() - : pending_reads_(0), + explicit DecoderBase(MessageLoop* message_loop) + : message_loop_(message_loop), + pending_reads_(0), pending_requests_(0), state_(kUninitialized) { } @@ -78,7 +78,7 @@ class DecoderBase : public Decoder { // It places an output buffer in the result queue. It must be called from // within the OnDecode method. void EnqueueResult(Output* output) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); if (!IsStopped()) { result_queue_.push_back(output); } @@ -136,6 +136,9 @@ class DecoderBase : public Decoder { } } + // Provide access to subclasses. + MessageLoop* message_loop() { return message_loop_; } + private: bool IsStopped() { return state_ == kStopped; } @@ -146,12 +149,12 @@ class DecoderBase : public Decoder { // TODO(scherkus): change the callback format to pass a scoped_refptr<> or // better yet see if we can get away with not using reference counting. scoped_refptr<Buffer> buffer_ref = buffer; - this->message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &DecoderBase::ReadCompleteTask, buffer_ref)); } void StopTask(FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // Delegate to the subclass first. DoStop(NewRunnableMethod(this, &DecoderBase::OnStopComplete, callback)); @@ -169,7 +172,7 @@ class DecoderBase : public Decoder { } void SeekTask(base::TimeDelta time, FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; DCHECK_EQ(0u, pending_requests_) << "Pending requests should be empty"; @@ -190,7 +193,7 @@ class DecoderBase : public Decoder { } void InitializeTask(DemuxerStream* demuxer_stream, FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); CHECK(kUninitialized == state_); CHECK(!demuxer_stream_); demuxer_stream_ = demuxer_stream; @@ -208,7 +211,7 @@ class DecoderBase : public Decoder { scoped_ptr<bool> success_deleter(success); AutoCallbackRunner done_runner(done_cb); - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // Delegate to subclass first. if (!*success) { this->host()->SetError(PIPELINE_ERROR_DECODE); @@ -220,7 +223,7 @@ class DecoderBase : public Decoder { } void ReadTask(scoped_refptr<Output> output) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // TODO(scherkus): should reply with a null operation (empty buffer). if (IsStopped()) @@ -239,7 +242,7 @@ class DecoderBase : public Decoder { } void ReadCompleteTask(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_GT(pending_reads_, 0u); --pending_reads_; if (IsStopped()) { @@ -255,7 +258,7 @@ class DecoderBase : public Decoder { // // Return true if one read request is fulfilled. bool FulfillPendingRead() { - DCHECK_EQ(MessageLoop::current(), this->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); if (!pending_requests_ || result_queue_.empty()) { return false; } @@ -274,6 +277,8 @@ class DecoderBase : public Decoder { return true; } + MessageLoop* message_loop_; + // Tracks the number of asynchronous reads issued to |demuxer_stream_|. // Using size_t since it is always compared against deque::size(). size_t pending_reads_; diff --git a/media/filters/decoder_base_unittest.cc b/media/filters/decoder_base_unittest.cc index 2fefb56..661ba4e 100644 --- a/media/filters/decoder_base_unittest.cc +++ b/media/filters/decoder_base_unittest.cc @@ -62,7 +62,8 @@ class MockDecoderCallback { class MockDecoderImpl : public media::DecoderBase< MockDecoder, MockDecoderOutput> { public: - MockDecoderImpl() { + explicit MockDecoderImpl(MessageLoop* message_loop) + : media::DecoderBase<MockDecoder, MockDecoderOutput>(message_loop) { media_format_.SetAsString(media::MediaFormat::kMimeType, "mock"); } @@ -117,12 +118,11 @@ ACTION(CompleteDemuxRequest) { // \ ReadCallback() -> client TEST(DecoderBaseTest, FlowControl) { MessageLoop message_loop; - scoped_refptr<MockDecoderImpl> decoder(new MockDecoderImpl()); + scoped_refptr<MockDecoderImpl> decoder(new MockDecoderImpl(&message_loop)); MockDecoderCallback read_callback; decoder->set_consume_audio_samples_callback( NewCallback(&read_callback, &MockDecoderCallback::OnReadComplete)); scoped_refptr<MockDemuxerStream> demuxer_stream(new MockDemuxerStream()); - decoder->set_message_loop(&message_loop); // Initailize. EXPECT_CALL(*decoder, DoInitialize(NotNull(), NotNull(), NotNull())) diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index 2e8e9ad..030149a 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc @@ -27,8 +27,9 @@ namespace media { const size_t FFmpegAudioDecoder::kOutputBufferSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; -FFmpegAudioDecoder::FFmpegAudioDecoder() - : codec_context_(NULL), +FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop) + : DecoderBase<AudioDecoder, Buffer>(message_loop), + codec_context_(NULL), estimated_next_timestamp_(kNoTimestamp) { } diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h index 0a7a915..20bc22e 100644 --- a/media/filters/ffmpeg_audio_decoder.h +++ b/media/filters/ffmpeg_audio_decoder.h @@ -1,6 +1,6 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this -// source code is governed by a BSD-style license that can be found in the -// LICENSE file. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ #define MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ @@ -16,7 +16,7 @@ class ScopedPtrAVFree; class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { public: - FFmpegAudioDecoder(); + explicit FFmpegAudioDecoder(MessageLoop* message_loop); virtual ~FFmpegAudioDecoder(); protected: diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 7c4f763..17248c6 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -239,12 +239,14 @@ base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( // // FFmpegDemuxer // -FFmpegDemuxer::FFmpegDemuxer() - : format_context_(NULL), +FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop) + : message_loop_(message_loop), + format_context_(NULL), read_event_(false, false), read_has_failed_(false), last_read_bytes_(0), read_position_(0) { + DCHECK(message_loop_); } FFmpegDemuxer::~FFmpegDemuxer() { @@ -279,13 +281,13 @@ FFmpegDemuxer::~FFmpegDemuxer() { } void FFmpegDemuxer::PostDemuxTask() { - message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegDemuxer::DemuxTask)); } void FFmpegDemuxer::Stop(FilterCallback* callback) { // Post a task to notify the streams to stop as well. - message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegDemuxer::StopTask, callback)); // Then wakes up the thread from reading. @@ -297,18 +299,18 @@ void FFmpegDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { // operation is completed and filters behind the demuxer is good to issue // more reads, but we are posting a task here, which makes the seek operation // asynchronous, should change how seek works to make it fully asynchronous. - message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegDemuxer::SeekTask, time, callback)); } void FFmpegDemuxer::OnAudioRendererDisabled() { - message_loop()->PostTask(FROM_HERE, + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegDemuxer::DisableAudioStreamTask)); } void FFmpegDemuxer::Initialize(DataSource* data_source, FilterCallback* callback) { - message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &FFmpegDemuxer::InitializeTask, @@ -391,9 +393,13 @@ bool FFmpegDemuxer::IsStreaming() { return data_source_->IsStreaming(); } +MessageLoop* FFmpegDemuxer::message_loop() { + return message_loop_; +} + void FFmpegDemuxer::InitializeTask(DataSource* data_source, FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); scoped_ptr<FilterCallback> c(callback); data_source_ = data_source; @@ -477,7 +483,7 @@ void FFmpegDemuxer::InitializeTask(DataSource* data_source, } void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); scoped_ptr<FilterCallback> c(callback); // Tell streams to flush buffers due to seeking. @@ -504,7 +510,7 @@ void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) { } void FFmpegDemuxer::DemuxTask() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // Make sure we have work to do before demuxing. if (!StreamsHavePendingReads()) { @@ -556,7 +562,7 @@ void FFmpegDemuxer::DemuxTask() { } void FFmpegDemuxer::StopTask(FilterCallback* callback) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); StreamVector::iterator iter; for (iter = streams_.begin(); iter != streams_.end(); ++iter) { (*iter)->Stop(); @@ -568,7 +574,7 @@ void FFmpegDemuxer::StopTask(FilterCallback* callback) { } void FFmpegDemuxer::DisableAudioStreamTask() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); StreamVector::iterator iter; for (size_t i = 0; i < packet_streams_.size(); ++i) { @@ -586,7 +592,7 @@ void FFmpegDemuxer::DisableAudioStreamTask() { } bool FFmpegDemuxer::StreamsHavePendingReads() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); StreamVector::iterator iter; for (iter = streams_.begin(); iter != streams_.end(); ++iter) { if ((*iter)->HasPendingReads()) { @@ -597,7 +603,7 @@ bool FFmpegDemuxer::StreamsHavePendingReads() { } void FFmpegDemuxer::StreamHasEnded() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); StreamVector::iterator iter; for (iter = streams_.begin(); iter != streams_.end(); ++iter) { AVPacket* packet = new AVPacket(); diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index e5355203..2123563 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -121,7 +121,7 @@ class FFmpegDemuxerStream : public DemuxerStream, public AVStreamProvider { class FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { public: - FFmpegDemuxer(); + explicit FFmpegDemuxer(MessageLoop* message_loop); virtual ~FFmpegDemuxer(); // Posts a task to perform additional demuxing. @@ -144,6 +144,9 @@ class FFmpegDemuxer : public Demuxer, virtual bool GetSize(int64* size_out); virtual bool IsStreaming(); + // Provide access to FFmpegDemuxerStream. + MessageLoop* message_loop(); + private: // Only allow a factory to create this class. friend class MockFFmpegDemuxer; @@ -187,6 +190,8 @@ class FFmpegDemuxer : public Demuxer, // Signal that read has completed, and |size| bytes have been read. virtual void SignalReadCompleted(size_t size); + MessageLoop* message_loop_; + // FFmpeg context handle. AVFormatContext* format_context_; diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 0bb21c0..5ba6fd3 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -65,12 +65,11 @@ class FFmpegDemuxerTest : public testing::Test { FFmpegDemuxerTest() { // Create an FFmpegDemuxer. - demuxer_ = new FFmpegDemuxer(); + demuxer_ = new FFmpegDemuxer(&message_loop_); DCHECK(demuxer_); // Inject a filter host and message loop and prepare a data source. demuxer_->set_host(&host_); - demuxer_->set_message_loop(&message_loop_); data_source_ = new StrictMock<MockDataSource>(); // Initialize FFmpeg fixtures. @@ -619,7 +618,9 @@ TEST_F(FFmpegDemuxerTest, DisableAudioStream) { class MockFFmpegDemuxer : public FFmpegDemuxer { public: - MockFFmpegDemuxer() {} + explicit MockFFmpegDemuxer(MessageLoop* message_loop) + : FFmpegDemuxer(message_loop) { + } virtual ~MockFFmpegDemuxer() {} MOCK_METHOD0(WaitForRead, size_t()); @@ -638,10 +639,10 @@ void RunCallback(size_t size, DataSource::ReadCallback* callback) { TEST_F(FFmpegDemuxerTest, ProtocolRead) { // Creates a demuxer. - scoped_refptr<MockFFmpegDemuxer> demuxer(new MockFFmpegDemuxer()); + scoped_refptr<MockFFmpegDemuxer> demuxer( + new MockFFmpegDemuxer(&message_loop_)); ASSERT_TRUE(demuxer); demuxer->set_host(&host_); - demuxer->set_message_loop(&message_loop_); demuxer->data_source_ = data_source_; uint8 kBuffer[1]; diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index bdaee8c..13b26b2 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -21,8 +21,10 @@ namespace media { -FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeContext* decode_context) - : width_(0), +FFmpegVideoDecoder::FFmpegVideoDecoder(MessageLoop* message_loop, + VideoDecodeContext* decode_context) + : message_loop_(message_loop), + width_(0), height_(0), time_base_(new AVRational()), state_(kUnInitialized), @@ -36,8 +38,8 @@ FFmpegVideoDecoder::~FFmpegVideoDecoder() { void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask( + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::Initialize, @@ -46,7 +48,7 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!demuxer_stream_); DCHECK(!initialize_callback_.get()); @@ -98,11 +100,11 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, config.width = width_; config.height = height_; state_ = kInitializing; - decode_engine_->Initialize(message_loop(), this, NULL, config); + decode_engine_->Initialize(message_loop_, this, NULL, config); } void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(initialize_callback_.get()); info_ = info; // Save a copy. @@ -128,15 +130,15 @@ void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { } void FFmpegVideoDecoder::Stop(FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::Stop, callback)); return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!uninitialize_callback_.get()); uninitialize_callback_.reset(callback); @@ -147,7 +149,7 @@ void FFmpegVideoDecoder::Stop(FilterCallback* callback) { } void FFmpegVideoDecoder::OnUninitializeComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(uninitialize_callback_.get()); AutoCallbackRunner done_runner(uninitialize_callback_.release()); @@ -157,8 +159,8 @@ void FFmpegVideoDecoder::OnUninitializeComplete() { } void FFmpegVideoDecoder::Pause(FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::Pause, callback)); @@ -170,15 +172,15 @@ void FFmpegVideoDecoder::Pause(FilterCallback* callback) { } void FFmpegVideoDecoder::Flush(FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::Flush, callback)); return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!flush_callback_.get()); state_ = kFlushing; @@ -191,7 +193,7 @@ void FFmpegVideoDecoder::Flush(FilterCallback* callback) { } void FFmpegVideoDecoder::OnFlushComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(flush_callback_.get()); AutoCallbackRunner done_runner(flush_callback_.release()); @@ -206,8 +208,8 @@ void FFmpegVideoDecoder::OnFlushComplete() { void FFmpegVideoDecoder::Seek(base::TimeDelta time, FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::Seek, time, @@ -215,7 +217,7 @@ void FFmpegVideoDecoder::Seek(base::TimeDelta time, return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!seek_callback_.get()); seek_callback_.reset(callback); @@ -223,7 +225,7 @@ void FFmpegVideoDecoder::Seek(base::TimeDelta time, } void FFmpegVideoDecoder::OnSeekComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(seek_callback_.get()); AutoCallbackRunner done_runner(seek_callback_.release()); @@ -239,7 +241,7 @@ void FFmpegVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) { scoped_refptr<Buffer> buffer(buffer_in); - message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::OnReadCompleteTask, @@ -247,7 +249,7 @@ void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) { } void FFmpegVideoDecoder::OnReadCompleteTask(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_NE(state_, kStopped); // because of Flush() before Stop(). // During decode, because reads are issued asynchronously, it is possible to @@ -301,15 +303,15 @@ const MediaFormat& FFmpegVideoDecoder::media_format() { void FFmpegVideoDecoder::ProduceVideoFrame( scoped_refptr<VideoFrame> video_frame) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask( + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &FFmpegVideoDecoder::ProduceVideoFrame, video_frame)); return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // Synchronized flushing before stop should prevent this. DCHECK_NE(state_, kStopped); @@ -330,7 +332,7 @@ void FFmpegVideoDecoder::ProduceVideoFrame( void FFmpegVideoDecoder::ConsumeVideoFrame( scoped_refptr<VideoFrame> video_frame) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_NE(state_, kStopped); if (video_frame.get()) { @@ -365,7 +367,7 @@ void FFmpegVideoDecoder::ConsumeVideoFrame( void FFmpegVideoDecoder::ProduceVideoSample( scoped_refptr<Buffer> buffer) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_NE(state_, kStopped); demuxer_stream_->Read( diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index 76e60e8..82e5a8c 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -25,7 +25,8 @@ class VideoDecodeEngine; class FFmpegVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - explicit FFmpegVideoDecoder(VideoDecodeContext* decode_context); + FFmpegVideoDecoder(MessageLoop* message_loop, + VideoDecodeContext* decode_context); virtual ~FFmpegVideoDecoder(); // Filter implementation. @@ -109,6 +110,7 @@ class FFmpegVideoDecoder : public VideoDecoder, // the provided engine. virtual void SetVideoDecodeEngineForTest(VideoDecodeEngine* engine); + MessageLoop* message_loop_; size_t width_; size_t height_; MediaFormat media_format_; diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index 3db54c0..128e531 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -71,8 +71,9 @@ class MockVideoDecodeEngine : public VideoDecodeEngine { // Class that just mocks the private functions. class DecoderPrivateMock : public FFmpegVideoDecoder { public: - explicit DecoderPrivateMock(VideoDecodeContext* context) - : FFmpegVideoDecoder(context) { + DecoderPrivateMock(MessageLoop* message_loop, + VideoDecodeContext* context) + : FFmpegVideoDecoder(message_loop, context) { } // change access qualifier for test: used in actions. @@ -125,7 +126,7 @@ class FFmpegVideoDecoderTest : public testing::Test { // Create an FFmpegVideoDecoder, and MockVideoDecodeEngine. // // TODO(ajwong): Break the test's dependency on FFmpegVideoDecoder. - decoder_ = new DecoderPrivateMock(NULL); + decoder_ = new DecoderPrivateMock(&message_loop_, NULL); renderer_ = new MockVideoRenderer(); engine_ = new StrictMock<MockVideoDecodeEngine>(); @@ -133,7 +134,6 @@ class FFmpegVideoDecoderTest : public testing::Test { // Inject mocks and prepare a demuxer stream. decoder_->set_host(&host_); - decoder_->set_message_loop(&message_loop_); decoder_->SetVideoDecodeEngineForTest(engine_); demuxer_ = new StrictMock<MockFFmpegDemuxerStream>(); diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc index 15ba4f1..3a31bf7 100644 --- a/media/filters/omx_video_decoder.cc +++ b/media/filters/omx_video_decoder.cc @@ -16,8 +16,10 @@ namespace media { OmxVideoDecoder::OmxVideoDecoder( + MessageLoop* message_loop, VideoDecodeContext* context) - : decode_engine_(new OmxVideoDecodeEngine()), + : message_loop_(message_loop), + decode_engine_(new OmxVideoDecodeEngine()), decode_context_(context), width_(0), height_(0) { DCHECK(decode_engine_.get()); @@ -30,8 +32,8 @@ OmxVideoDecoder::~OmxVideoDecoder() { void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask( + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &OmxVideoDecoder::Initialize, @@ -40,7 +42,7 @@ void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, return; } - DCHECK_EQ(message_loop(), MessageLoop::current()); + DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK(!demuxer_stream_); DCHECK(!initialize_callback_.get()); @@ -88,11 +90,11 @@ void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, config.opaque_context = NULL; config.width = width_; config.height = height_; - decode_engine_->Initialize(message_loop(), this, NULL, config); + decode_engine_->Initialize(message_loop_, this, NULL, config); } void OmxVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(initialize_callback_.get()); info_ = info; // Save a copy. @@ -115,15 +117,15 @@ void OmxVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { } void OmxVideoDecoder::Stop(FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &OmxVideoDecoder::Stop, callback)); return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!uninitialize_callback_.get()); uninitialize_callback_.reset(callback); @@ -131,7 +133,7 @@ void OmxVideoDecoder::Stop(FilterCallback* callback) { } void OmxVideoDecoder::OnUninitializeComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(uninitialize_callback_.get()); AutoCallbackRunner done_runner(uninitialize_callback_.release()); @@ -140,15 +142,15 @@ void OmxVideoDecoder::OnUninitializeComplete() { } void OmxVideoDecoder::Flush(FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &OmxVideoDecoder::Flush, callback)); return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!flush_callback_.get()); flush_callback_.reset(callback); @@ -165,8 +167,8 @@ void OmxVideoDecoder::OnFlushComplete() { void OmxVideoDecoder::Seek(base::TimeDelta time, FilterCallback* callback) { - if (MessageLoop::current() != message_loop()) { - message_loop()->PostTask(FROM_HERE, + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &OmxVideoDecoder::Seek, time, @@ -174,7 +176,7 @@ void OmxVideoDecoder::Seek(base::TimeDelta time, return; } - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(!seek_callback_.get()); seek_callback_.reset(callback); @@ -182,7 +184,7 @@ void OmxVideoDecoder::Seek(base::TimeDelta time, } void OmxVideoDecoder::OnSeekComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(seek_callback_.get()); AutoCallbackRunner done_runner(seek_callback_.release()); @@ -196,20 +198,20 @@ void OmxVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { } void OmxVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(message_loop(), MessageLoop::current()); + DCHECK_EQ(message_loop_, MessageLoop::current()); // Issue more demux. demuxer_stream_->Read(NewCallback(this, &OmxVideoDecoder::DemuxCompleteTask)); } void OmxVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { - DCHECK_EQ(message_loop(), MessageLoop::current()); + DCHECK_EQ(message_loop_, MessageLoop::current()); VideoFrameReady(frame); } void OmxVideoDecoder::ProduceVideoFrame(scoped_refptr<VideoFrame> frame) { DCHECK(decode_engine_.get()); - message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(decode_engine_.get(), &VideoDecodeEngine::ProduceVideoFrame, frame)); @@ -228,7 +230,7 @@ void OmxVideoDecoder::DemuxCompleteTask(Buffer* buffer) { // We simply delicate the buffer to the right message loop. scoped_refptr<Buffer> ref_buffer = buffer; DCHECK(decode_engine_.get()); - message_loop()->PostTask( + message_loop_->PostTask( FROM_HERE, NewRunnableMethod(decode_engine_.get(), &VideoDecodeEngine::ConsumeVideoSample, ref_buffer)); diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h index 7eb8504..ddec99f 100644 --- a/media/filters/omx_video_decoder.h +++ b/media/filters/omx_video_decoder.h @@ -23,7 +23,8 @@ class VideoFrame; class OmxVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - explicit OmxVideoDecoder(VideoDecodeContext* decode_context); + OmxVideoDecoder(MessageLoop* message_loop, + VideoDecodeContext* decode_context); virtual ~OmxVideoDecoder(); // Filter implementations. @@ -50,6 +51,8 @@ class OmxVideoDecoder : public VideoDecoder, // scoped_refptr. void DemuxCompleteTask(Buffer* buffer); + MessageLoop* message_loop_; + // Pointer to the demuxer stream that will feed us compressed buffers. scoped_refptr<DemuxerStream> demuxer_stream_; scoped_ptr<VideoDecodeEngine> decode_engine_; diff --git a/media/media.gyp b/media/media.gyp index 259a7a1..660898b 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -94,6 +94,10 @@ 'base/media_switches.cc', 'base/media_switches.h', 'base/media_win.cc', + 'base/message_loop_factory.cc', + 'base/message_loop_factory.h', + 'base/message_loop_factory_impl.cc', + 'base/message_loop_factory_impl.h', 'base/pipeline.h', 'base/pipeline_impl.cc', 'base/pipeline_impl.h', diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc index 2efd715..fe73490 100644 --- a/media/tools/player_wtl/movie.cc +++ b/media/tools/player_wtl/movie.cc @@ -8,6 +8,7 @@ #include "base/threading/platform_thread.h" #include "base/utf_string_conversions.h" #include "media/base/filter_collection.h" +#include "media/base/message_loop_factory_impl.h" #include "media/base/pipeline_impl.h" #include "media/filters/audio_renderer_impl.h" #include "media/filters/ffmpeg_audio_decoder.h" @@ -60,12 +61,17 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) { Close(); } + message_loop_factory_.reset(new media::MessageLoopFactoryImpl()); + // Create filter collection. scoped_ptr<FilterCollection> collection(new FilterCollection()); collection->AddDataSource(new FileDataSource()); - collection->AddAudioDecoder(new FFmpegAudioDecoder()); - collection->AddDemuxer(new FFmpegDemuxer()); - collection->AddVideoDecoder(new FFmpegVideoDecoder(NULL)); + collection->AddAudioDecoder(new FFmpegAudioDecoder( + message_loop_factory_->GetMessageLoop("AudioDecoderThread"))); + collection->AddDemuxer(new FFmpegDemuxer( + message_loop_factory_->GetMessageLoop("DemuxThread"))); + collection->AddVideoDecoder(new FFmpegVideoDecoder( + message_loop_factory_->GetMessageLoop("VideoDecoderThread"), NULL)); if (enable_audio_) { collection->AddAudioRenderer(new AudioRendererImpl()); @@ -74,9 +80,8 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) { } collection->AddVideoRenderer(video_renderer); - thread_.reset(new base::Thread("PipelineThread")); - thread_->Start(); - pipeline_ = new PipelineImpl(thread_->message_loop()); + pipeline_ = new PipelineImpl( + message_loop_factory_->GetMessageLoop("PipelineThread")); // Create and start our pipeline. pipeline_->Start(collection.release(), WideToUTF8(std::wstring(url)), NULL); @@ -168,10 +173,10 @@ bool Movie::GetDumpYuvFileEnable() { void Movie::Close() { if (pipeline_) { pipeline_->Stop(NULL); - thread_->Stop(); pipeline_ = NULL; - thread_.reset(); } + + message_loop_factory_.reset(); } } // namespace media diff --git a/media/tools/player_wtl/movie.h b/media/tools/player_wtl/movie.h index ea81b09..00708f9 100644 --- a/media/tools/player_wtl/movie.h +++ b/media/tools/player_wtl/movie.h @@ -11,7 +11,7 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" -#include "base/threading/thread.h" +#include "media/base/message_loop_factory.h" template <typename T> struct DefaultSingletonTraits; class WtlVideoRenderer; @@ -83,7 +83,7 @@ class Movie { virtual ~Movie(); scoped_refptr<PipelineImpl> pipeline_; - scoped_ptr<base::Thread> thread_; + scoped_ptr<media::MessageLoopFactory> message_loop_factory_; bool enable_audio_; bool enable_draw_; diff --git a/media/tools/player_wtl/view.h b/media/tools/player_wtl/view.h index cbb0a48..5273cd5 100644 --- a/media/tools/player_wtl/view.h +++ b/media/tools/player_wtl/view.h @@ -9,6 +9,7 @@ #include <process.h> #include <string.h> +#include "base/logging.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" #include "media/tools/player_wtl/movie.h" diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index df9bd619..2e75994 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -17,6 +17,7 @@ #include "media/base/filter_collection.h" #include "media/base/media.h" #include "media/base/media_switches.h" +#include "media/base/message_loop_factory_impl.h" #include "media/base/pipeline_impl.h" #include "media/filters/audio_renderer_impl.h" #include "media/filters/ffmpeg_audio_decoder.h" @@ -83,7 +84,8 @@ bool InitX11() { bool InitPipeline(MessageLoop* message_loop, const char* filename, bool enable_audio, scoped_refptr<media::PipelineImpl>* pipeline, - MessageLoop* paint_message_loop) { + MessageLoop* paint_message_loop, + media::MessageLoopFactory* message_loop_factory) { // Initialize OpenMAX. if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableOpenMax) && @@ -102,13 +104,19 @@ bool InitPipeline(MessageLoop* message_loop, scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); collection->AddDataSource(new media::FileDataSource()); - collection->AddDemuxer(new media::FFmpegDemuxer()); - collection->AddAudioDecoder(new media::FFmpegAudioDecoder()); + collection->AddDemuxer(new media::FFmpegDemuxer( + message_loop_factory->GetMessageLoop("DemuxThread"))); + collection->AddAudioDecoder(new media::FFmpegAudioDecoder( + message_loop_factory->GetMessageLoop("AudioDecoderThread"))); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableOpenMax)) { - collection->AddVideoDecoder(new media::OmxVideoDecoder(NULL)); + collection->AddVideoDecoder(new media::OmxVideoDecoder( + message_loop_factory->GetMessageLoop("VideoDecoderThread"), + NULL)); } else { - collection->AddVideoDecoder(new media::FFmpegVideoDecoder(NULL)); + collection->AddVideoDecoder(new media::FFmpegVideoDecoder( + message_loop_factory->GetMessageLoop("VideoDecoderThread"), + NULL)); } collection->AddVideoRenderer(new Renderer(g_display, g_window, @@ -244,13 +252,16 @@ int main(int argc, char** argv) { // Initialize the pipeline thread and the pipeline. base::AtExitManager at_exit; + scoped_ptr<media::MessageLoopFactory> message_loop_factory( + new media::MessageLoopFactoryImpl()); scoped_ptr<base::Thread> thread; scoped_refptr<media::PipelineImpl> pipeline; MessageLoop message_loop; thread.reset(new base::Thread("PipelineThread")); thread->Start(); if (InitPipeline(thread->message_loop(), filename.c_str(), - enable_audio, &pipeline, &message_loop)) { + enable_audio, &pipeline, &message_loop, + message_loop_factory.get())) { // Main loop of the application. g_running = true; @@ -266,6 +277,8 @@ int main(int argc, char** argv) { } // Cleanup tasks. + message_loop_factory.reset(); + thread->Stop(); XDestroyWindow(g_display, g_window); XCloseDisplay(g_display); diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index 0129b60..fd5c12e 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -11,6 +11,8 @@ #include "media/base/filters.h" #include "media/filters/video_renderer_base.h" +class MessageLoop; + class X11VideoRenderer : public media::VideoRendererBase { public: X11VideoRenderer(Display* display, Window window, MessageLoop* message_loop); diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc index 005c7cf..3bfb6a9 100644 --- a/webkit/glue/webmediaplayer_impl.cc +++ b/webkit/glue/webmediaplayer_impl.cc @@ -225,13 +225,14 @@ void WebMediaPlayerImpl::Proxy::PutCurrentFrame( WebMediaPlayerImpl::WebMediaPlayerImpl( WebKit::WebMediaPlayerClient* client, - media::FilterCollection* collection) + media::FilterCollection* collection, + media::MessageLoopFactory* message_loop_factory) : network_state_(WebKit::WebMediaPlayer::Empty), ready_state_(WebKit::WebMediaPlayer::HaveNothing), main_loop_(NULL), filter_collection_(collection), pipeline_(NULL), - pipeline_thread_("PipelineThread"), + message_loop_factory_(message_loop_factory), paused_(true), seeking_(false), playback_rate_(0.0f), @@ -247,13 +248,14 @@ bool WebMediaPlayerImpl::Initialize( WebKit::WebFrame* frame, bool use_simple_data_source, scoped_refptr<WebVideoRenderer> web_video_renderer) { - // Create the pipeline and its thread. - if (!pipeline_thread_.Start()) { + MessageLoop* pipeline_message_loop = + message_loop_factory_->GetMessageLoop("PipelineThread"); + if (!pipeline_message_loop) { NOTREACHED() << "Could not start PipelineThread"; return false; } - pipeline_ = new media::PipelineImpl(pipeline_thread_.message_loop()); + pipeline_ = new media::PipelineImpl(pipeline_message_loop); // Also we want to be notified of |main_loop_| destruction. main_loop_->AddDestructionObserver(this); @@ -290,9 +292,12 @@ bool WebMediaPlayerImpl::Initialize( } // Add in the default filter factories. - filter_collection_->AddDemuxer(new media::FFmpegDemuxer()); - filter_collection_->AddAudioDecoder(new media::FFmpegAudioDecoder()); - filter_collection_->AddVideoDecoder(new media::FFmpegVideoDecoder(NULL)); + filter_collection_->AddDemuxer(new media::FFmpegDemuxer( + message_loop_factory_->GetMessageLoop("DemuxThread"))); + filter_collection_->AddAudioDecoder(new media::FFmpegAudioDecoder( + message_loop_factory_->GetMessageLoop("AudioDecoderThread"))); + filter_collection_->AddVideoDecoder(new media::FFmpegVideoDecoder( + message_loop_factory_->GetMessageLoop("VideoDecoderThread"), NULL)); filter_collection_->AddAudioRenderer(new media::NullAudioRenderer()); return true; @@ -794,9 +799,10 @@ void WebMediaPlayerImpl::Destroy() { pipeline_->Stop(NewCallback(this, &WebMediaPlayerImpl::PipelineStoppedCallback)); pipeline_stopped_.Wait(); - pipeline_thread_.Stop(); } + message_loop_factory_.reset(); + // And then detach the proxy, it may live on the render thread for a little // longer until all the tasks are finished. if (proxy_) { diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h index abb1c60..9f2db64 100644 --- a/webkit/glue/webmediaplayer_impl.h +++ b/webkit/glue/webmediaplayer_impl.h @@ -62,6 +62,7 @@ #include "gfx/rect.h" #include "gfx/size.h" #include "media/base/filters.h" +#include "media/base/message_loop_factory.h" #include "media/base/pipeline.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h" @@ -175,7 +176,8 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // // Callers must call |Initialize()| before they can use the object. WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, - media::FilterCollection* collection); + media::FilterCollection* collection, + media::MessageLoopFactory* message_loop_factory); virtual ~WebMediaPlayerImpl(); // Finalizes initialization of the object. @@ -288,7 +290,8 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // The actual pipeline and the thread it runs on. scoped_refptr<media::Pipeline> pipeline_; - base::Thread pipeline_thread_; + + scoped_ptr<media::MessageLoopFactory> message_loop_factory_; // Playback state. // diff --git a/webkit/support/webkit_support.cc b/webkit/support/webkit_support.cc index 8a76c1f..f043c82 100644 --- a/webkit/support/webkit_support.cc +++ b/webkit/support/webkit_support.cc @@ -26,6 +26,7 @@ #include "base/weak_ptr.h" #include "grit/webkit_chromium_resources.h" #include "media/base/filter_collection.h" +#include "media/base/message_loop_factory_impl.h" #include "net/base/escape.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" @@ -266,6 +267,9 @@ WebPlugin* CreateWebPlugin(WebFrame* frame, WebKit::WebMediaPlayer* CreateMediaPlayer(WebFrame* frame, WebMediaPlayerClient* client) { + scoped_ptr<media::MessageLoopFactory> message_loop_factory( + new media::MessageLoopFactoryImpl()); + scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); @@ -274,7 +278,9 @@ WebKit::WebMediaPlayer* CreateMediaPlayer(WebFrame* frame, collection->AddVideoRenderer(video_renderer); scoped_ptr<webkit_glue::WebMediaPlayerImpl> result( - new webkit_glue::WebMediaPlayerImpl(client, collection.release())); + new webkit_glue::WebMediaPlayerImpl(client, + collection.release(), + message_loop_factory.release())); if (!result->Initialize(frame, false, video_renderer)) { return NULL; } diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc index 305fa1f..0d61350 100644 --- a/webkit/tools/test_shell/test_webview_delegate.cc +++ b/webkit/tools/test_shell/test_webview_delegate.cc @@ -19,6 +19,7 @@ #include "gfx/native_widget_types.h" #include "gfx/point.h" #include "media/base/filter_collection.h" +#include "media/base/message_loop_factory_impl.h" #include "net/base/net_errors.h" #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h" #include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h" @@ -732,6 +733,9 @@ WebWorker* TestWebViewDelegate::createWorker(WebFrame* frame, WebMediaPlayer* TestWebViewDelegate::createMediaPlayer( WebFrame* frame, WebMediaPlayerClient* client) { + scoped_ptr<media::MessageLoopFactory> message_loop_factory( + new media::MessageLoopFactoryImpl()); + scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); @@ -740,7 +744,9 @@ WebMediaPlayer* TestWebViewDelegate::createMediaPlayer( collection->AddVideoRenderer(video_renderer); scoped_ptr<webkit_glue::WebMediaPlayerImpl> result( - new webkit_glue::WebMediaPlayerImpl(client, collection.release())); + new webkit_glue::WebMediaPlayerImpl(client, + collection.release(), + message_loop_factory.release())); if (!result->Initialize(frame, false, video_renderer)) { return NULL; } |