diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 01:20:37 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 01:20:37 +0000 |
commit | 457d83467c00c236e806bb150796a2efdc88bfcf (patch) | |
tree | 36c58186b34d36300374b232fb79540457307b23 /media | |
parent | 77a397cc5cf8106e559aa87a5228478afc28cec1 (diff) | |
download | chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.zip chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.tar.gz chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.tar.bz2 |
Terminate FilterFactory and his nasty friends
FilterFactory, IsMediaFormatSupported and CreateFactory are the source
of evil. They also have have a gang of template functions. This patch
terminate them all and make the world a better place.
BUG=28207
TEST=<video> runs
Review URL: http://codereview.chromium.org/3878001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63609 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
36 files changed, 423 insertions, 829 deletions
diff --git a/media/base/factory.cc b/media/base/factory.cc deleted file mode 100644 index 685d1e7..0000000 --- a/media/base/factory.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2010 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/factory.h" - -namespace media { - -FilterFactory::FilterFactory() {} - -FilterFactory::~FilterFactory() {} - -FilterFactoryCollection::FilterFactoryCollection() {} - -void FilterFactoryCollection::AddFactory(FilterFactory* factory) { - factories_.push_back(factory); -} - -MediaFilter* FilterFactoryCollection::Create(FilterType filter_type, - const MediaFormat& media_format) { - MediaFilter* filter = NULL; - for (FactoryVector::iterator factory = factories_.begin(); - !filter && factory != factories_.end(); - ++factory) { - filter = (*factory)->Create(filter_type, media_format); - } - return filter; -} - -FilterFactoryCollection::~FilterFactoryCollection() {} - - -} // namespace media diff --git a/media/base/factory.h b/media/base/factory.h deleted file mode 100644 index d5dd9a7..0000000 --- a/media/base/factory.h +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) 2006-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. - -// A filter factory handles the creation of filters given a FilterType (i.e., -// FILTER_AUDIO_DECODER) and a MediaFormat. Generally a filter factory handles -// creating a single type of filter, with multiple factories combined into a -// FilterFactoryCollection. We use some template tricks to enforce type-safety -// and eliminate casting for callers. -// -// The majority of applications will only use FilterFactoryCollection since -// filter factory classes can be created from templates: -// FilterFactoryCollection filter_factory = new FilterFactoryCollection(); -// filter_factory->AddFactory(new TypeFilterFactory<YourAudioDecoder>()); -// filter_factory->AddFactory(new TypeFilterFactory<YourAudioRenderer>()); -// etc... -// AudioDecoder* filter; -// if (filter_factory->Create<AudioDecoder>(media_format, &filter) { -// do stuff with the filter... -// } -// -// The only requirement is that your filter implementation provide a static -// Create method with the following signature: -// -// Returns true and assigns |filter_out| if the filter was created, false -// and assigns NULL otherwise. -// static bool Create(MediaFormat& media_format, YourFilterType** filter_out); -// - -#ifndef MEDIA_BASE_FACTORY_H_ -#define MEDIA_BASE_FACTORY_H_ - -#include <vector> - -#include "base/logging.h" -#include "base/ref_counted.h" -#include "media/base/filters.h" - -namespace media { - -class FilterFactoryCollection; - -class FilterFactory : public base::RefCountedThreadSafe<FilterFactory> { - public: - // Creates a filter implementing the specified interface. Hides the casting - // and FilterType constants from the callers and produces cleaner code: - // socped_refptr<MyAudioDecoder> d = Create<MyAudioDecoder>(media_format); - // If the factory does not support the specific filter type or does not - // support the |media_format| then NULL is returned. - template <class Filter> - Filter* Create(const MediaFormat& media_format) { - return reinterpret_cast<Filter*>(Create(Filter::filter_type(), - media_format)); - } - - protected: - // For accessing the protected version of Create. - friend class FilterFactoryCollection; - - // Attempt to create a filter of the given type using the information stored - // in |media_format|. If successful, the filter is returned. If the filter - // cannot be created for any reason, NULL is returned. - // - // It is assumed that the MediaFilter interface can be safely cast to the - // corresponding interface type (i.e., FILTER_AUDIO_DECODER -> AudioDecoder). - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) = 0; - - friend class base::RefCountedThreadSafe<FilterFactory>; - FilterFactory(); - virtual ~FilterFactory(); -}; - - -// Maintains a collection of FilterFactories. -class FilterFactoryCollection : public FilterFactory { - public: - FilterFactoryCollection(); - - // Adds a factory to the end of the collection. - void AddFactory(FilterFactory* factory); - - protected: - // Attempts to create a filter by walking down the list of filter factories. - MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format); - - private: - ~FilterFactoryCollection(); - - typedef std::vector< scoped_refptr<FilterFactory> > FactoryVector; - FactoryVector factories_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryCollection); -}; - -//----------------------------------------------------------------------------- - -// This template is used by classes to implement a type-safe filter factory. -// If the derived class needs to examine the |media_format| passed to the -// Create method then they should implement the static method -// IsMediaFormatSupported. Classes should implement their contructor as private -// and make FilterFactoryImpl<MyClass> a friend class. -template <class Filter> -class FilterFactoryImpl0 : public FilterFactory { - public: - FilterFactoryImpl0() {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(); - } - return filter; - } - - private: - ~FilterFactoryImpl0() {} - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl0); -}; - -// This template can be used by classes that need to be constructed with a -// parameter that needs to be used in the construction of the actual filter. -// This would usually be a "parent" object which the instantiated filter needs -// to communicate with. The class's CreateFactory method would look like: -// static FilterFactory* CreateFactory(MyRequiredParentClass* parent) { -// return new FilterFactoryImpl1<MyClass>(parent); -// } -// The class would be constructed with the same pointer passed to the -// CreateFactory method. -template <class Filter, class A> -class FilterFactoryImpl1 : public FilterFactory { - public: - explicit FilterFactoryImpl1(A a) : a_(a) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_); - } - return filter; - } - - private: - ~FilterFactoryImpl1() {} - - A const a_; - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl1); -}; - -template <class Filter, class A, class B> -class FilterFactoryImpl2 : public FilterFactory { - public: - FilterFactoryImpl2(A a, B b) : a_(a), b_(b) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_, b_); - } - return filter; - } - - private: - ~FilterFactoryImpl2() {} - - A const a_; - B const b_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl2); -}; - -template <class Filter, class A, class B, class C> -class FilterFactoryImpl3 : public FilterFactory { - public: - FilterFactoryImpl3(A a, B b, C c) : a_(a), b_(b), c_(c) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_, b_, c_); - } - return filter; - } - - private: - ~FilterFactoryImpl3() {} - - A const a_; - B const b_; - C const c_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl3); -}; - -//------------------------------------------------------------------------------ - -// This specialized factory is typically used by test programs that create -// a filter instance, and want to return that specific instance of the test -// filter to the pipeline. It takes an already created filter in the -// constructor, and then hands that instance out when the Create method is -// called. The factory makes sure to only return a single copy of the -// filter. The normal patern of use for this factory is: -// scoped_refptr<MyTestFilter> my_test_filter = new MyTestFilter(); -// filter_factory_collection->AddFactory( -// new InstanceFilterFactory<MyTestFilter>(my_test_filter)); -template <class Filter> -class InstanceFilterFactory : public FilterFactory { - public: - explicit InstanceFilterFactory(Filter* filter) - : filter_(filter), - create_called_(false) { - } - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - if (!create_called_) { - create_called_ = true; - return filter_; - } else { - NOTREACHED(); - } - } - return NULL; - } - - private: - ~InstanceFilterFactory() {} - - scoped_refptr<Filter> filter_; - bool create_called_; - - DISALLOW_COPY_AND_ASSIGN(InstanceFilterFactory); -}; - -} // namespace media - -#endif // MEDIA_BASE_FACTORY_H_ diff --git a/media/base/filters.cc b/media/base/filters.cc index 2ade8d2..4c9ab4f 100644 --- a/media/base/filters.cc +++ b/media/base/filters.cc @@ -11,6 +11,10 @@ namespace media { MediaFilter::MediaFilter() : host_(NULL), message_loop_(NULL) {} +const char* MediaFilter::major_mime_type() const { + return ""; +} + void MediaFilter::set_host(FilterHost* host) { DCHECK(host); DCHECK(!host_); @@ -77,6 +81,50 @@ void MediaFilter::OnAudioRendererDisabled() { MediaFilter::~MediaFilter() {} +bool DataSource::IsUrlSupported(const std::string& url) { + return true; +} + +FilterType DataSource::filter_type() const { + return FILTER_DATA_SOURCE; +} + +FilterType Demuxer::filter_type() const { + return FILTER_DEMUXER; +} + +FilterType AudioDecoder::filter_type() const { + return FILTER_AUDIO_DECODER; +} + +const char* AudioDecoder::major_mime_type() const { + return mime_type::kMajorTypeAudio; +} + +FilterType AudioRenderer::filter_type() const { + return FILTER_AUDIO_RENDERER; +} + +const char* AudioRenderer::major_mime_type() const { + return mime_type::kMajorTypeAudio; +} + +FilterType VideoDecoder::filter_type() const { + return FILTER_VIDEO_DECODER; +} + +const char* VideoDecoder::major_mime_type() const { + return mime_type::kMajorTypeVideo; +} + +FilterType VideoRenderer::filter_type() const { + return FILTER_VIDEO_RENDERER; +} + +const char* VideoRenderer::major_mime_type() const { + return mime_type::kMajorTypeVideo; +} + DemuxerStream::~DemuxerStream() {} VideoDecoder::VideoDecoder() {} diff --git a/media/base/filters.h b/media/base/filters.h index d9edfc1..02bc596 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -24,6 +24,7 @@ #define MEDIA_BASE_FILTERS_H_ #include <limits> +#include <list> #include <string> #include "base/callback.h" @@ -41,11 +42,12 @@ class Buffer; class Decoder; class DemuxerStream; class FilterHost; +class MediaFilter; class WritableBuffer; -// Identifies the type of filter implementation. Used in conjunction with some -// template wizardry to enforce strongly typed operations. More or less a -// knock off of MSVC's __uuidof() operator. +// Identifies the type of filter implementation. Each filter has to be one of +// the following types. This is used to identify filter object during +// initialization of pipeline. enum FilterType { FILTER_DATA_SOURCE, FILTER_DEMUXER, @@ -58,10 +60,22 @@ enum FilterType { // Used for completing asynchronous methods. typedef Callback0::Type FilterCallback; +// This is a list of MediaFilter objects. Objects in this list is used to +// form a media playback pipeline. See src/media/base/pipeline.h for more +// information. +typedef std::list<scoped_refptr<MediaFilter> > MediaFilterCollection; + class MediaFilter : public base::RefCountedThreadSafe<MediaFilter> { public: MediaFilter(); + // Return the type of this filter. All implementor has to provide this + // method. + virtual FilterType filter_type() const = 0; + + // Return the major mime type for this filter. + virtual const char* major_mime_type() const; + // Sets the private member |host_|. This is the first method called by // the FilterHost after a filter is created. The host holds a strong // reference to the filter. The reference held by the host is guaranteed @@ -126,29 +140,19 @@ class MediaFilter : public base::RefCountedThreadSafe<MediaFilter> { DISALLOW_COPY_AND_ASSIGN(MediaFilter); }; - class DataSource : public MediaFilter { public: typedef Callback1<size_t>::Type ReadCallback; static const size_t kReadError = static_cast<size_t>(-1); - static FilterType filter_type() { - return FILTER_DATA_SOURCE; - } + virtual bool IsUrlSupported(const std::string& url); - static bool IsMediaFormatSupported(const MediaFormat& media_format) { - std::string mime_type; - return (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type == mime_type::kURL); - } + virtual FilterType filter_type() const; // Initialize a DataSource for the given URL, executing the callback upon // completion. virtual void Initialize(const std::string& url, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // Reads |size| bytes from |position| into |data|. And when the read is done // or failed, |read_callback| is called with the number of bytes read or // kReadError in case of error. @@ -169,15 +173,7 @@ class DataSource : public MediaFilter { class Demuxer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_DEMUXER; - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format) { - std::string mime_type; - return (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type == mime_type::kApplicationOctetStream); - } + virtual FilterType filter_type() const; // Initialize a Demuxer with the given DataSource, executing the callback upon // completion. @@ -194,9 +190,6 @@ class Demuxer : public MediaFilter { class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { public: - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // Schedules a read. When the |read_callback| is called, the downstream // filter takes ownership of the buffer by AddRef()'ing the buffer. // @@ -214,6 +207,9 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { return (NULL != i); }; + // Returns the media format of this stream. + virtual const MediaFormat& media_format() = 0; + virtual void EnableBitstreamConverter() = 0; protected: @@ -232,21 +228,14 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { class VideoDecoder : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_VIDEO_DECODER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeVideo; - } + virtual const char* major_mime_type() const; // Initialize a VideoDecoder with the given DemuxerStream, executing the // callback upon completion. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver video frames at // runtime to downstream filter @@ -263,6 +252,9 @@ class VideoDecoder : public MediaFilter { // Indicate whether decoder provides its own output buffers virtual bool ProvidesBuffer() = 0; + // Returns the media format produced by this decoder. + virtual const MediaFormat& media_format() = 0; + protected: // A video frame is ready to be consumed. This method invoke // |consume_video_frame_callback_| internally. @@ -280,21 +272,14 @@ class VideoDecoder : public MediaFilter { class AudioDecoder : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_AUDIO_DECODER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeAudio; - } + virtual const char* major_mime_type() const; // Initialize a AudioDecoder with the given DemuxerStream, executing the // callback upon completion. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver buffers at // runtime to downstream filter. @@ -312,6 +297,9 @@ class AudioDecoder : public MediaFilter { // We could also pass empty pointer here to let decoder provide buffers pool. virtual void ProduceAudioSamples(scoped_refptr<Buffer> buffer) = 0; + // Returns the media format produced by this decoder. + virtual const MediaFormat& media_format() = 0; + protected: AudioDecoder(); ~AudioDecoder(); @@ -323,13 +311,9 @@ class AudioDecoder : public MediaFilter { class VideoRenderer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_VIDEO_RENDERER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeVideo; - } + virtual const char* major_mime_type() const; // Initialize a VideoRenderer with the given VideoDecoder, executing the // callback upon completion. @@ -343,13 +327,9 @@ class VideoRenderer : public MediaFilter { class AudioRenderer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_AUDIO_RENDERER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeAudio; - } + virtual const char* major_mime_type() const; // Initialize a AudioRenderer with the given AudioDecoder, executing the // callback upon completion. diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h index 5868333..9043854 100644 --- a/media/base/mock_filter_host.h +++ b/media/base/mock_filter_host.h @@ -12,12 +12,8 @@ #include <string> #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" -#include "media/base/filters.h" -#include "media/base/media_format.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace media { diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index fe5a58d..97710fe 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -16,7 +16,6 @@ #include <string> #include "base/callback.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/video_frame.h" #include "testing/gmock/include/gmock/gmock.h" @@ -101,6 +100,7 @@ class MockDataSource : public DataSource { MOCK_METHOD0(OnAudioRendererDisabled, void()); // DataSource implementation. + MOCK_METHOD1(IsUrlSupported, bool(const std::string& url)); MOCK_METHOD2(Initialize, void(const std::string& url, FilterCallback* callback)); MOCK_METHOD0(media_format, const MediaFormat&()); @@ -262,12 +262,11 @@ class MockAudioRenderer : public AudioRenderer { }; // FilterFactory that returns canned instances of mock filters. You can set -// expectations on the filters and then pass the factory into a pipeline. -class MockFilterFactory : public FilterFactory { +// expectations on the filters and then pass the collection into a pipeline. +class MockFilterCollection { public: - MockFilterFactory() - : creation_successful_(true), - data_source_(new MockDataSource()), + MockFilterCollection() + : data_source_(new MockDataSource()), demuxer_(new MockDemuxer()), video_decoder_(new MockVideoDecoder()), audio_decoder_(new MockAudioDecoder()), @@ -275,12 +274,7 @@ class MockFilterFactory : public FilterFactory { audio_renderer_(new MockAudioRenderer()) { } - virtual ~MockFilterFactory() {} - - // Controls whether the Create() method is successful or not. - void set_creation_successful(bool creation_successful) { - creation_successful_ = creation_successful; - } + virtual ~MockFilterCollection() {} // Mock accessors. MockDataSource* data_source() const { return data_source_; } @@ -290,33 +284,18 @@ class MockFilterFactory : public FilterFactory { MockVideoRenderer* video_renderer() const { return video_renderer_; } MockAudioRenderer* audio_renderer() const { return audio_renderer_; } - protected: - MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format) { - if (!creation_successful_) { - return NULL; - } - - switch (filter_type) { - case FILTER_DATA_SOURCE: - return data_source_; - case FILTER_DEMUXER: - return demuxer_; - case FILTER_VIDEO_DECODER: - return video_decoder_; - case FILTER_AUDIO_DECODER: - return audio_decoder_; - case FILTER_VIDEO_RENDERER: - return video_renderer_; - case FILTER_AUDIO_RENDERER: - return audio_renderer_; - default: - NOTREACHED() << "Unknown filter type: " << filter_type; - } - return NULL; + MediaFilterCollection filter_collection() const { + MediaFilterCollection collection; + collection.push_back(data_source_); + collection.push_back(demuxer_); + collection.push_back(video_decoder_); + collection.push_back(audio_decoder_); + collection.push_back(video_renderer_); + collection.push_back(audio_renderer_); + return collection; } private: - bool creation_successful_; scoped_refptr<MockDataSource> data_source_; scoped_refptr<MockDemuxer> demuxer_; scoped_refptr<MockVideoDecoder> video_decoder_; @@ -324,7 +303,7 @@ class MockFilterFactory : public FilterFactory { scoped_refptr<MockVideoRenderer> video_renderer_; scoped_refptr<MockAudioRenderer> audio_renderer_; - DISALLOW_COPY_AND_ASSIGN(MockFilterFactory); + DISALLOW_COPY_AND_ASSIGN(MockFilterCollection); }; // Helper gmock function that immediately executes and destroys the diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 4af77db..0519b35 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -3,7 +3,7 @@ // found in the LICENSE file. // The pipeline is the public API clients use for playing back media. Clients -// provide a filter factory containing the filters they want the pipeline to +// provide a filter collection containing the filters they want the pipeline to // use to render media. #ifndef MEDIA_BASE_PIPELINE_H_ @@ -12,7 +12,7 @@ #include <string> #include "base/callback.h" -#include "media/base/factory.h" +#include "media/base/filters.h" namespace base { class TimeDelta; @@ -47,8 +47,8 @@ typedef Callback0::Type PipelineCallback; class Pipeline : public base::RefCountedThreadSafe<Pipeline> { public: - // Build a pipeline to render the given URL using the given filter factory to - // construct a filter chain. Returns true if successful, false otherwise + // Build a pipeline to render the given URL using the given filter collection + // to construct a filter chain. Returns true if successful, false otherwise // (i.e., pipeline already started). Note that a return value of true // only indicates that the initialization process has started successfully. // Pipeline initialization is an inherently asynchronous process. Clients can @@ -59,7 +59,7 @@ class Pipeline : public base::RefCountedThreadSafe<Pipeline> { // If the caller provides a |start_callback|, it will be called when the // pipeline initialization completes. Clients are expected to call GetError() // to check whether initialization succeeded. - virtual bool Start(FilterFactory* filter_factory, + virtual bool Start(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback) = 0; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index bc825f6..2128c34 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -19,9 +19,8 @@ namespace { // Small helper function to help us transition over to injected message loops. // // TODO(scherkus): have every filter support injected message loops. -template <class Filter> -bool SupportsSetMessageLoop() { - switch (Filter::filter_type()) { +bool SupportsSetMessageLoop(FilterType type) { + switch (type) { case FILTER_DEMUXER: case FILTER_AUDIO_DECODER: case FILTER_VIDEO_DECODER: @@ -35,17 +34,16 @@ bool SupportsSetMessageLoop() { // Skipping default case so compiler will warn on a missed enumeration. } - NOTREACHED() << "Unexpected filter type " << Filter::filter_type(); + NOTREACHED() << "Unexpected filter type " << type; return false; } // Small helper function to help us name filter threads for debugging. // // TODO(scherkus): figure out a cleaner way to derive the filter thread name. -template <class Filter> -const char* GetThreadName() { - DCHECK(SupportsSetMessageLoop<Filter>()); - switch (Filter::filter_type()) { +const char* GetThreadName(FilterType type) { + DCHECK(SupportsSetMessageLoop(type)); + switch (type) { case FILTER_DEMUXER: return "DemuxerThread"; case FILTER_AUDIO_DECODER: @@ -77,17 +75,17 @@ PipelineImpl::~PipelineImpl() { } // Creates the PipelineInternal and calls it's start method. -bool PipelineImpl::Start(FilterFactory* factory, +bool PipelineImpl::Start(const MediaFilterCollection& collection, const std::string& url, PipelineCallback* start_callback) { AutoLock auto_lock(lock_); - DCHECK(factory); scoped_ptr<PipelineCallback> callback(start_callback); if (running_) { VLOG(1) << "Media pipeline is already running"; return false; } - if (!factory) + + if (collection.empty()) return false; // Kick off initialization! @@ -96,7 +94,7 @@ bool PipelineImpl::Start(FilterFactory* factory, FROM_HERE, NewRunnableMethod(this, &PipelineImpl::StartTask, - make_scoped_refptr(factory), + collection, url, callback.release())); return true; @@ -403,7 +401,6 @@ void PipelineImpl::FinishInitialization() { seek_callback_->Run(); seek_callback_.reset(); } - filter_factory_ = NULL; } // static @@ -569,12 +566,12 @@ void PipelineImpl::OnFilterStateTransition() { NewRunnableMethod(this, &PipelineImpl::FilterStateTransitionTask)); } -void PipelineImpl::StartTask(FilterFactory* filter_factory, +void PipelineImpl::StartTask(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback) { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_EQ(kCreated, state_); - filter_factory_ = filter_factory; + filter_collection_ = filter_collection; url_ = url; seek_callback_.reset(start_callback); @@ -614,14 +611,14 @@ void PipelineImpl::InitializeTask() { // Just created, create data source. if (state_ == kCreated) { state_ = kInitDataSource; - CreateDataSource(); + InitializeDataSource(); return; } // Data source created, create demuxer. if (state_ == kInitDataSource) { state_ = kInitDemuxer; - CreateDemuxer(); + InitializeDemuxer(); return; } @@ -629,7 +626,7 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitDemuxer) { state_ = kInitAudioDecoder; // If this method returns false, then there's no audio stream. - if (CreateDecoder<AudioDecoder>()) + if (InitializeAudioDecoder()) return; } @@ -637,8 +634,8 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitAudioDecoder) { state_ = kInitAudioRenderer; // Returns false if there's no audio stream. - if (CreateRenderer<AudioDecoder, AudioRenderer>()) { - InsertRenderedMimeType(AudioDecoder::major_mime_type()); + if (InitializeAudioRenderer()) { + InsertRenderedMimeType(mime_type::kMajorTypeAudio); return; } } @@ -647,15 +644,15 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitAudioRenderer) { // Then perform the stage of initialization, i.e. initialize video decoder. state_ = kInitVideoDecoder; - if (CreateDecoder<VideoDecoder>()) + if (InitializeVideoDecoder()) return; } // Assuming video decoder was created, create video renderer. if (state_ == kInitVideoDecoder) { state_ = kInitVideoRenderer; - if (CreateRenderer<VideoDecoder, VideoRenderer>()) { - InsertRenderedMimeType(VideoDecoder::major_mime_type()); + if (InitializeVideoRenderer()) { + InsertRenderedMimeType(mime_type::kMajorTypeVideo); return; } } @@ -666,6 +663,9 @@ void PipelineImpl::InitializeTask() { return; } + // Clear the collection of filters. + filter_collection_.clear(); + // Initialization was successful, we are now considered paused, so it's safe // to set the initial playback rate and volume. PlaybackRateChangedTask(GetPlaybackRate()); @@ -750,7 +750,7 @@ void PipelineImpl::VolumeChangedTask(float volume) { DCHECK_EQ(MessageLoop::current(), message_loop_); scoped_refptr<AudioRenderer> audio_renderer; - GetFilter(&audio_renderer); + GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer); if (audio_renderer) { audio_renderer->SetVolume(volume); } @@ -808,8 +808,8 @@ void PipelineImpl::NotifyEndedTask() { // Grab the renderers, if they exist. scoped_refptr<AudioRenderer> audio_renderer; scoped_refptr<VideoRenderer> video_renderer; - GetFilter(&audio_renderer); - GetFilter(&video_renderer); + GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer); + GetInitializedFilter(FILTER_VIDEO_RENDERER, &video_renderer); DCHECK(audio_renderer || video_renderer); // Make sure every extant renderer has ended. @@ -972,23 +972,46 @@ void PipelineImpl::FinishDestroyingFiltersTask() { } } -template <class Filter, class Source> -void PipelineImpl::CreateFilter(FilterFactory* filter_factory, - Source source, - const MediaFormat& media_format) { +template <class Filter> +void PipelineImpl::SelectFilter( + FilterType filter_type, scoped_refptr<Filter>* filter_out) const { DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(IsPipelineOk()); - // Create the filter. - scoped_refptr<Filter> filter = filter_factory->Create<Filter>(media_format); - if (!filter) { - SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + MediaFilterCollection::const_iterator it = filter_collection_.begin(); + while (it != filter_collection_.end()) { + if ((*it)->filter_type() == filter_type) + break; + ++it; + } + + if (it == filter_collection_.end()) + *filter_out = NULL; + else + *filter_out = reinterpret_cast<Filter*>(it->get()); +} + +void PipelineImpl::RemoveFilter(scoped_refptr<MediaFilter> filter) { + MediaFilterCollection::iterator it = filter_collection_.begin(); + while (it != filter_collection_.end()) { + if (*it == filter) + break; + ++it; + } + if (it == filter_collection_.end()) { + NOTREACHED() << "Removing a filter that doesn't exist"; return; } + filter_collection_.erase(it); +} + +void PipelineImpl::PrepareFilter(scoped_refptr<MediaFilter> filter) { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); // Create a dedicated thread for this filter if applicable. - if (SupportsSetMessageLoop<Filter>()) { - scoped_ptr<base::Thread> thread(new base::Thread(GetThreadName<Filter>())); + if (SupportsSetMessageLoop(filter->filter_type())) { + scoped_ptr<base::Thread> thread( + new base::Thread(GetThreadName(filter->filter_type()))); if (!thread.get() || !thread->Start()) { NOTREACHED() << "Could not start filter thread"; SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); @@ -1001,82 +1024,172 @@ void PipelineImpl::CreateFilter(FilterFactory* filter_factory, // Register ourselves as the filter's host. DCHECK(IsPipelineOk()); - DCHECK(filter_types_.find(Filter::filter_type()) == filter_types_.end()) - << "Filter type " << Filter::filter_type() << " already exists"; + DCHECK(filter_types_.find(filter->filter_type()) == filter_types_.end()) + << "Filter type " << filter->filter_type() << " already exists"; filter->set_host(this); filters_.push_back(filter.get()); - filter_types_[Filter::filter_type()] = filter.get(); + filter_types_[filter->filter_type()] = filter.get(); +} + +void PipelineImpl::InitializeDataSource() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DataSource> data_source; + while (true) { + SelectFilter(FILTER_DATA_SOURCE, &data_source); + if (!data_source || data_source->IsUrlSupported(url_)) + break; + RemoveFilter(data_source); + } + + if (!data_source) { + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + return; + } + + RemoveFilter(data_source); + PrepareFilter(data_source); + data_source->Initialize( + url_, NewCallback(this, &PipelineImpl::OnFilterInitialize)); +} + +void PipelineImpl::InitializeDemuxer() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DataSource> data_source; + scoped_refptr<Demuxer> demuxer; + + GetInitializedFilter(FILTER_DATA_SOURCE, &data_source); + CHECK(data_source); + + SelectFilter(FILTER_DEMUXER, &demuxer); + if (!demuxer) { + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + return; + } - // Now initialize the filter. - filter->Initialize(source, + RemoveFilter(demuxer); + PrepareFilter(demuxer); + demuxer->Initialize(data_source, + NewCallback(this, &PipelineImpl::OnFilterInitialize)); +} + +bool PipelineImpl::InitializeAudioDecoder() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DemuxerStream> stream = + FindDemuxerStream(mime_type::kMajorTypeAudio); + scoped_refptr<AudioDecoder> audio_decoder; + SelectFilter(FILTER_AUDIO_DECODER, &audio_decoder); + + // If there is such stream but audio decoder is not found. + if (stream && !audio_decoder) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!stream || !audio_decoder) + return false; + + RemoveFilter(audio_decoder); + PrepareFilter(audio_decoder); + audio_decoder->Initialize( + stream, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -void PipelineImpl::CreateDataSource() { +bool PipelineImpl::InitializeVideoDecoder() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); - MediaFormat url_format; - url_format.SetAsString(MediaFormat::kMimeType, mime_type::kURL); - url_format.SetAsString(MediaFormat::kURL, url_); - CreateFilter<DataSource>(filter_factory_, url_, url_format); + scoped_refptr<DemuxerStream> stream = + FindDemuxerStream(mime_type::kMajorTypeVideo); + scoped_refptr<VideoDecoder> video_decoder; + SelectFilter(FILTER_VIDEO_DECODER, &video_decoder); + + // If there is such stream but video decoder is not found. + if (stream && !video_decoder) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!stream || !video_decoder) + return false; + + RemoveFilter(video_decoder); + PrepareFilter(video_decoder); + video_decoder->Initialize( + stream, + NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -void PipelineImpl::CreateDemuxer() { +bool PipelineImpl::InitializeAudioRenderer() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); - scoped_refptr<DataSource> data_source; - GetFilter(&data_source); - DCHECK(data_source); - CreateFilter<Demuxer, DataSource>(filter_factory_, data_source); + scoped_refptr<AudioDecoder> decoder; + GetInitializedFilter(FILTER_AUDIO_DECODER, &decoder); + scoped_refptr<AudioRenderer> audio_renderer; + SelectFilter(FILTER_AUDIO_RENDERER, &audio_renderer); + + // If there is such decoder but renderer is not found. + if (decoder && !audio_renderer) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!decoder || !audio_renderer) + return false; + + RemoveFilter(audio_renderer); + PrepareFilter(audio_renderer); + audio_renderer->Initialize( + decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -template <class Decoder> -bool PipelineImpl::CreateDecoder() { +bool PipelineImpl::InitializeVideoRenderer() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); + scoped_refptr<VideoDecoder> decoder; + GetInitializedFilter(FILTER_VIDEO_DECODER, &decoder); + scoped_refptr<VideoRenderer> video_renderer; + SelectFilter(FILTER_VIDEO_RENDERER, &video_renderer); + + // If there is such decoder but renderer is not found. + if (decoder && !video_renderer) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!decoder || !video_renderer) + return false; + + RemoveFilter(video_renderer); + PrepareFilter(video_renderer); + video_renderer->Initialize( + decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; +} + +scoped_refptr<DemuxerStream> PipelineImpl::FindDemuxerStream( + std::string major_mime_type) { scoped_refptr<Demuxer> demuxer; - GetFilter(&demuxer); + GetInitializedFilter(FILTER_DEMUXER, &demuxer); DCHECK(demuxer); - const std::string major_mime_type = Decoder::major_mime_type(); const int num_outputs = demuxer->GetNumberOfStreams(); for (int i = 0; i < num_outputs; ++i) { - scoped_refptr<DemuxerStream> stream = demuxer->GetStream(i); std::string value; - if (stream->media_format().GetAsString(MediaFormat::kMimeType, &value) && - 0 == value.compare(0, major_mime_type.length(), major_mime_type)) { - CreateFilter<Decoder, DemuxerStream>(filter_factory_, stream); - return true; + if (demuxer->GetStream(i)->media_format().GetAsString( + MediaFormat::kMimeType, &value) && + !value.compare(0, major_mime_type.length(), major_mime_type)) { + return demuxer->GetStream(i); } } - return false; -} - -template <class Decoder, class Renderer> -bool PipelineImpl::CreateRenderer() { - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(IsPipelineOk()); - - scoped_refptr<Decoder> decoder; - GetFilter(&decoder); - - if (decoder) { - // If the decoder was created. - const std::string major_mime_type = Decoder::major_mime_type(); - CreateFilter<Renderer, Decoder>(filter_factory_, decoder); - return true; - } - return false; + return NULL; } template <class Filter> -void PipelineImpl::GetFilter(scoped_refptr<Filter>* filter_out) const { +void PipelineImpl::GetInitializedFilter( + FilterType filter_type, scoped_refptr<Filter>* filter_out) const { DCHECK_EQ(MessageLoop::current(), message_loop_); - FilterTypeMap::const_iterator ft = filter_types_.find(Filter::filter_type()); + FilterTypeMap::const_iterator ft = filter_types_.find(filter_type); if (ft == filter_types_.end()) { *filter_out = NULL; } else { diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 2060cef..0370fd5 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -66,7 +66,7 @@ class PipelineImpl : public Pipeline, public FilterHost { explicit PipelineImpl(MessageLoop* message_loop); // Pipeline implementation. - virtual bool Start(FilterFactory* filter_factory, + virtual bool Start(const MediaFilterCollection& filter_collection, const std::string& uri, PipelineCallback* start_callback); virtual void Stop(PipelineCallback* stop_callback); @@ -147,7 +147,7 @@ class PipelineImpl : public Pipeline, public FilterHost { bool IsPipelineSeeking(); // Helper method to execute callback from Start() and reset - // |filter_factory_|. Called when initialization completes + // |filter_collection_|. Called when initialization completes // normally or when pipeline is stopped or error occurs during // initialization. void FinishInitialization(); @@ -194,7 +194,7 @@ class PipelineImpl : public Pipeline, public FilterHost { // The following "task" methods correspond to the public methods, but these // methods are run as the result of posting a task to the PipelineInternal's // message loop. - void StartTask(FilterFactory* filter_factory, + void StartTask(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback); @@ -241,64 +241,47 @@ class PipelineImpl : public Pipeline, public FilterHost { // Internal methods used in the implementation of the pipeline thread. All // of these methods are only called on the pipeline thread. - // The following template functions make use of the fact that media filter - // derived interfaces are self-describing in the sense that they all contain - // the static method filter_type() which returns a FilterType enum that - // uniquely identifies the filter's interface. In addition, filters that are - // specific to audio or video also support a static method major_mime_type() - // which returns a string of "audio/" or "video/". - // - // Uses the FilterFactory to create a new filter of the Filter class, and - // initializes it using the Source object. The source may be another filter - // or it could be a string in the case of a DataSource. - // - // The CreateFilter() method actually does much more than simply creating the - // filter. It also creates the filter's thread and injects a FilterHost and - // MessageLoop. Finally, it calls the filter's type-specific Initialize() - // method to initialize the filter. If the required filter cannot be created, - // PIPELINE_ERROR_REQUIRED_FILTER_MISSING is raised, initialization is halted - // and this object will remain in the "Error" state. - template <class Filter, class Source> - void CreateFilter(FilterFactory* filter_factory, - Source source, - const MediaFormat& source_media_format); - - // Creates a Filter and initializes it with the given |source|. If a Filter - // could not be created or an error occurred, this method returns NULL and the - // pipeline's |error_| member will contain a specific error code. Note that - // the Source could be a filter or a DemuxerStream, but it must support the - // GetMediaFormat() method. - template <class Filter, class Source> - void CreateFilter(FilterFactory* filter_factory, Source* source) { - CreateFilter<Filter, Source*>(filter_factory, - source, - source->media_format()); - } - - // Creates a DataSource (the first filter in a pipeline). - void CreateDataSource(); - - // Creates a Demuxer. - void CreateDemuxer(); - - // Creates a decoder of type Decoder. Returns true if the asynchronous action - // of creating decoder has started. Returns false if this method did nothing - // because the corresponding audio/video stream does not exist. - template <class Decoder> - bool CreateDecoder(); - - // Creates a renderer of type Renderer and connects it with Decoder. Returns - // true if the asynchronous action of creating renderer has started. Returns + // Uses the MediaFilterCollection to return a filter of |filter_type|. + // If the required filter cannot be found, NULL is returned. + template <class Filter> + void SelectFilter(FilterType filter_type, + scoped_refptr<Filter>* filter_out) const; + + // Remove a filer from MediaFilterCollection. + void RemoveFilter(scoped_refptr<MediaFilter> filter); + + // PrepareFilter() creates the filter's thread and injects a FilterHost and + // MessageLoop. + void PrepareFilter(scoped_refptr<MediaFilter> filter); + + // The following initialize methods are used to select a specific type of + // MediaFilter object from MediaFilterCollection and initialize it + // asynchronously. + void InitializeDataSource(); + void InitializeDemuxer(); + + // Returns true if the asynchronous action of creating decoder has started. + // Returns false if this method did nothing because the corresponding + // audio/video stream does not exist. + bool InitializeAudioDecoder(); + bool InitializeVideoDecoder(); + + // Initializes a renderer and connects it with decoder. Returns true if the + // asynchronous action of creating renderer has started. Returns // false if this method did nothing because the corresponding audio/video // stream does not exist. - template <class Decoder, class Renderer> - bool CreateRenderer(); + bool InitializeAudioRenderer(); + bool InitializeVideoRenderer(); + + // Helper to find the demuxer of |major_mime_type| from Demuxer. + scoped_refptr<DemuxerStream> FindDemuxerStream(std::string major_mime_type); - // Examine the list of existing filters to find one that supports the - // specified Filter interface. If one exists, the |filter_out| will contain + // Examine the list of initialized filters to find one that matches the + // specified filter type. If one exists, the |filter_out| will contain // the filter, |*filter_out| will be NULL. template <class Filter> - void GetFilter(scoped_refptr<Filter>* filter_out) const; + void GetInitializedFilter(FilterType filter_type, + scoped_refptr<Filter>* filter_out) const; // Kicks off destroying filters. Called by StopTask() and ErrorChangedTask(). // When we start to tear down the pipeline, we will consider two cases: @@ -416,8 +399,8 @@ class PipelineImpl : public Pipeline, public FilterHost { // TODO(vrk): This is a hack. base::TimeDelta max_buffered_time_; - // Filter factory as passed in by Start(). - scoped_refptr<FilterFactory> filter_factory_; + // Filter collection as passed in by Start(). + MediaFilterCollection filter_collection_; // URL for the data source as passed in by Start(). std::string url_; diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index dc5783f..544e000 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -9,12 +9,11 @@ #include "media/base/pipeline_impl.h" #include "media/base/media_format.h" #include "media/base/filters.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" #include "media/base/mock_filters.h" #include "testing/gtest/include/gtest/gtest.h" -using ::testing::DoAll; +using ::testing::_; using ::testing::InSequence; using ::testing::Invoke; using ::testing::Mock; @@ -61,11 +60,11 @@ class CallbackHelper { class PipelineImplTest : public ::testing::Test { public: PipelineImplTest() - : pipeline_(new PipelineImpl(&message_loop_)), - mocks_(new MockFilterFactory()) { + : pipeline_(new PipelineImpl(&message_loop_)) { pipeline_->SetPipelineErrorCallback(NewCallback( reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnError)); + mocks_.reset(new MockFilterCollection()); } virtual ~PipelineImplTest() { @@ -82,9 +81,7 @@ class PipelineImplTest : public ::testing::Test { // Free allocated media formats (if any). STLDeleteElements(&stream_media_formats_); - // Release the filter factory to workaround a gMock bug. - // See: http://code.google.com/p/googlemock/issues/detail?id=79 - mocks_ = NULL; + mocks_.reset(); } protected: @@ -95,12 +92,12 @@ class PipelineImplTest : public ::testing::Test { SetBufferedBytes(mocks_->data_source(), kBufferedBytes), Invoke(&RunFilterCallback))); EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(0.0f)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Seek(base::TimeDelta(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->data_source(), media_format()) - .WillOnce(ReturnRef(data_source_media_format_)); } // Sets up expectations to allow the demuxer to initialize. @@ -152,8 +149,6 @@ class PipelineImplTest : public ::testing::Test { .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->video_decoder(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->video_decoder(), media_format()) - .WillOnce(ReturnRef(video_decoder_media_format_)); } // Sets up expectations to allow the audio decoder to initialize. @@ -165,8 +160,6 @@ class PipelineImplTest : public ::testing::Test { .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->audio_decoder(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->audio_decoder(), media_format()) - .WillOnce(ReturnRef(audio_decoder_media_format_)); } // Sets up expectations to allow the video renderer to initialize. @@ -199,7 +192,7 @@ class PipelineImplTest : public ::testing::Test { void InitializePipeline() { // Expect an initialization callback. EXPECT_CALL(callbacks_, OnStart()); - pipeline_->Start(mocks_, "", + pipeline_->Start(mocks_->filter_collection(), "", NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnStart)); message_loop_.RunAllPending(); @@ -262,14 +255,10 @@ class PipelineImplTest : public ::testing::Test { StrictMock<CallbackHelper> callbacks_; MessageLoop message_loop_; scoped_refptr<PipelineImpl> pipeline_; - scoped_refptr<media::MockFilterFactory> mocks_; + scoped_ptr<media::MockFilterCollection> mocks_; scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream_; scoped_refptr<StrictMock<MockDemuxerStream> > video_stream_; - MediaFormat data_source_media_format_; - MediaFormat audio_decoder_media_format_; - MediaFormat video_decoder_media_format_; - typedef std::vector<MediaFormat*> MediaFormatVector; MediaFormatVector stream_media_formats_; @@ -293,8 +282,8 @@ TEST_F(PipelineImplTest, NotStarted) { EXPECT_FALSE(pipeline_->IsRunning()); EXPECT_FALSE(pipeline_->IsInitialized()); EXPECT_FALSE(pipeline_->IsRendered("")); - EXPECT_FALSE(pipeline_->IsRendered(AudioDecoder::major_mime_type())); - EXPECT_FALSE(pipeline_->IsRendered(VideoDecoder::major_mime_type())); + EXPECT_FALSE(pipeline_->IsRendered(mime_type::kMajorTypeAudio)); + EXPECT_FALSE(pipeline_->IsRendered(mime_type::kMajorTypeVideo)); // Setting should still work. EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); @@ -330,13 +319,15 @@ TEST_F(PipelineImplTest, NotStarted) { TEST_F(PipelineImplTest, NeverInitializes) { EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull())) .WillOnce(Invoke(&DestroyFilterCallback)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); // This test hangs during initialization by never calling // InitializationComplete(). StrictMock<> will ensure that the callback is // never executed. - pipeline_->Start(mocks_, "", + pipeline_->Start(mocks_->filter_collection(), "", NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnStart)); message_loop_.RunAllPending(); @@ -353,9 +344,20 @@ TEST_F(PipelineImplTest, NeverInitializes) { TEST_F(PipelineImplTest, RequiredFilterMissing) { EXPECT_CALL(callbacks_, OnError()); - mocks_->set_creation_successful(false); - InitializePipeline(); + // Sets up expectations on the callback and initializes the pipeline. Called + // after tests have set expectations any filters they wish to use. + // Expect an initialization callback. + EXPECT_CALL(callbacks_, OnStart()); + + // Create a filter collection with missing filter. + MediaFilterCollection collection = mocks_->filter_collection(); + collection.pop_front(); + pipeline_->Start(collection, "", + NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), + &CallbackHelper::OnStart)); + message_loop_.RunAllPending(); + EXPECT_FALSE(pipeline_->IsInitialized()); EXPECT_EQ(PIPELINE_ERROR_REQUIRED_FILTER_MISSING, pipeline_->GetError()); @@ -366,6 +368,8 @@ TEST_F(PipelineImplTest, URLNotFound) { .WillOnce(DoAll(SetError(mocks_->data_source(), PIPELINE_ERROR_URL_NOT_FOUND), Invoke(&RunFilterCallback))); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(callbacks_, OnError()); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); @@ -380,10 +384,10 @@ TEST_F(PipelineImplTest, NoStreams) { // we cannot fully initialize the pipeline. EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull())) .WillOnce(Invoke(&RunFilterCallback)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->data_source(), media_format()) - .WillOnce(ReturnRef(data_source_media_format_)); EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); diff --git a/media/filters/audio_renderer_base.h b/media/filters/audio_renderer_base.h index 36a90f0..f9b7aee 100644 --- a/media/filters/audio_renderer_base.h +++ b/media/filters/audio_renderer_base.h @@ -22,7 +22,6 @@ #include "base/lock.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_algorithm_base.h" @@ -30,6 +29,9 @@ namespace media { class AudioRendererBase : public AudioRenderer { public: + AudioRendererBase(); + virtual ~AudioRendererBase(); + // MediaFilter implementation. virtual void Play(FilterCallback* callback); virtual void Pause(FilterCallback* callback); @@ -42,10 +44,6 @@ class AudioRendererBase : public AudioRenderer { virtual bool HasEnded(); protected: - // Only allow a factory to create this class. - AudioRendererBase(); - virtual ~AudioRendererBase(); - // Called by Initialize(). |media_format| is the format of the AudioDecoder. // Subclasses should return true if they were able to initialize, false // otherwise. diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc index 69188b3..5634ab2 100644 --- a/media/filters/audio_renderer_impl.cc +++ b/media/filters/audio_renderer_impl.cc @@ -29,15 +29,6 @@ AudioRendererImpl::~AudioRendererImpl() { } } -bool AudioRendererImpl::IsMediaFormatSupported( - const MediaFormat& media_format) { - int channels; - int sample_rate; - int sample_bits; - return AudioManager::GetAudioManager()->HasAudioOutputDevices() && - ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits); -} - void AudioRendererImpl::SetPlaybackRate(float rate) { // TODO(fbarchard): limit rate to reasonable values AudioRendererBase::SetPlaybackRate(rate); diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h index fc61f80..1e18a41 100644 --- a/media/filters/audio_renderer_impl.h +++ b/media/filters/audio_renderer_impl.h @@ -20,7 +20,6 @@ #include "base/lock.h" #include "media/audio/audio_io.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" @@ -29,12 +28,8 @@ namespace media { class AudioRendererImpl : public AudioRendererBase, public AudioOutputStream::AudioSourceCallback { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<AudioRendererImpl>(); - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format); + AudioRendererImpl(); + virtual ~AudioRendererImpl(); // MediaFilter implementation. virtual void SetPlaybackRate(float playback_rate); @@ -49,11 +44,6 @@ class AudioRendererImpl : public AudioRendererBase, virtual void OnError(AudioOutputStream* stream, int code); protected: - // Only allow a factory to create this class. - friend class FilterFactoryImpl0<AudioRendererImpl>; - AudioRendererImpl(); - virtual ~AudioRendererImpl(); - // AudioRendererBase implementation. virtual bool OnInitialize(const MediaFormat& media_format); virtual void OnStop(); diff --git a/media/filters/decoder_base_unittest.cc b/media/filters/decoder_base_unittest.cc index ec80915..41dcf9a 100644 --- a/media/filters/decoder_base_unittest.cc +++ b/media/filters/decoder_base_unittest.cc @@ -67,6 +67,10 @@ class MockDecoderImpl : public media::DecoderBase< virtual ~MockDecoderImpl() {} + virtual media::FilterType filter_type() const { + return media::FILTER_VIDEO_DECODER; + } + // DecoderBase Implementations. MOCK_METHOD3(DoInitialize, void(media::DemuxerStream* demuxer_stream, diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index e8abeac..1895221 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc @@ -35,13 +35,6 @@ FFmpegAudioDecoder::FFmpegAudioDecoder() FFmpegAudioDecoder::~FFmpegAudioDecoder() { } -// static -bool FFmpegAudioDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - return format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type::kFFmpegAudio == mime_type; -} - void FFmpegAudioDecoder::DoInitialize(DemuxerStream* demuxer_stream, bool* success, Task* done_cb) { diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h index d0ad27f..0a7a915 100644 --- a/media/filters/ffmpeg_audio_decoder.h +++ b/media/filters/ffmpeg_audio_decoder.h @@ -5,7 +5,6 @@ #ifndef MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ #define MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ -#include "media/base/factory.h" #include "media/filters/decoder_base.h" struct AVCodecContext; @@ -17,11 +16,8 @@ class ScopedPtrAVFree; class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { public: - static FilterFactory* CreateFactory() { - return new FilterFactoryImpl0<FFmpegAudioDecoder>(); - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format); + FFmpegAudioDecoder(); + virtual ~FFmpegAudioDecoder(); protected: virtual void DoInitialize(DemuxerStream* demuxer_stream, bool* success, @@ -32,10 +28,6 @@ class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { virtual void DoDecode(Buffer* input); private: - friend class FilterFactoryImpl0<FFmpegAudioDecoder>; - FFmpegAudioDecoder(); - virtual ~FFmpegAudioDecoder(); - // Calculates the duration of an audio buffer based on the sample rate, // channels and bits per sample given the size in bytes. base::TimeDelta CalculateDuration(size_t size); diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index ef74abe..a1f921d 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -29,7 +29,6 @@ #include "base/gtest_prod_util.h" #include "base/waitable_event.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/media_format.h" #include "media/filters/ffmpeg_glue.h" @@ -122,10 +121,8 @@ class FFmpegDemuxerStream : public DemuxerStream, public AVStreamProvider { class FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<FFmpegDemuxer>(); - } + FFmpegDemuxer(); + virtual ~FFmpegDemuxer(); // Posts a task to perform additional demuxing. virtual void PostDemuxTask(); @@ -149,13 +146,9 @@ class FFmpegDemuxer : public Demuxer, private: // Only allow a factory to create this class. - friend class FilterFactoryImpl0<FFmpegDemuxer>; friend class MockFFmpegDemuxer; FRIEND_TEST_ALL_PREFIXES(FFmpegDemuxerTest, ProtocolRead); - FFmpegDemuxer(); - virtual ~FFmpegDemuxer(); - // Carries out initialization on the demuxer thread. void InitializeTask(DataSource* data_source, FilterCallback* callback); diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 5ac1cbd..ecf87b5 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -65,11 +65,7 @@ class FFmpegDemuxerTest : public testing::Test { FFmpegDemuxerTest() { // Create an FFmpegDemuxer. - factory_ = FFmpegDemuxer::CreateFilterFactory(); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kApplicationOctetStream); - demuxer_ = factory_->Create<FFmpegDemuxer>(media_format); + demuxer_ = new FFmpegDemuxer(); DCHECK(demuxer_); // Inject a filter host and message loop and prepare a data source. @@ -159,7 +155,6 @@ class FFmpegDemuxerTest : public testing::Test { } // Fixture members. - scoped_refptr<FilterFactory> factory_; scoped_refptr<FFmpegDemuxer> demuxer_; scoped_refptr<StrictMock<MockDataSource> > data_source_; StrictMock<MockFilterHost> host_; @@ -190,22 +185,6 @@ const uint8 FFmpegDemuxerTest::kAudioData[kDataSize] = {0, 1, 2, 3}; const uint8 FFmpegDemuxerTest::kVideoData[kDataSize] = {4, 5, 6, 7}; const uint8* FFmpegDemuxerTest::kNullData = NULL; -TEST(FFmpegDemuxerFactoryTest, Create) { - // Should only accept application/octet-stream type. - scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); - scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format)); - ASSERT_FALSE(demuxer); - - // Try again with application/octet-stream mime type. - media_format.Clear(); - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kApplicationOctetStream); - demuxer = factory->Create<Demuxer>(media_format); - ASSERT_TRUE(demuxer); -} - TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { // Simulate av_open_input_file() failing. EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) diff --git a/media/filters/ffmpeg_glue_unittest.cc b/media/filters/ffmpeg_glue_unittest.cc index c2f0f6b..d217f9c 100644 --- a/media/filters/ffmpeg_glue_unittest.cc +++ b/media/filters/ffmpeg_glue_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/logging.h" #include "base/scoped_ptr.h" #include "media/base/mock_ffmpeg.h" #include "media/base/mock_filters.h" diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 68d2046..45357f2 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -18,17 +18,15 @@ #include "media/filters/ffmpeg_interfaces.h" #include "media/video/ffmpeg_video_decode_engine.h" #include "media/video/video_decode_context.h" -#include "media/video/video_decode_engine.h" namespace media { -FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context) +FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeContext* decode_context) : width_(0), height_(0), time_base_(new AVRational()), state_(kUnInitialized), - decode_engine_(decode_engine), + decode_engine_(new FFmpegVideoDecodeEngine()), decode_context_(decode_context) { memset(&info_, 0, sizeof(info_)); } @@ -440,20 +438,4 @@ void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( decode_engine_.reset(engine); } -// static -FilterFactory* FFmpegVideoDecoder::CreateFactory( - VideoDecodeContext* decode_context) { - return new FilterFactoryImpl2<FFmpegVideoDecoder, - VideoDecodeEngine*, - VideoDecodeContext*>( - new FFmpegVideoDecodeEngine(), decode_context); -} - -// static -bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - return format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type::kFFmpegVideo == mime_type; -} - } // namespace media diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index 150a0e1..415ab7d 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -9,7 +9,6 @@ #include "base/gtest_prod_util.h" #include "base/time.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/pts_heap.h" #include "media/base/video_frame.h" @@ -26,13 +25,9 @@ class VideoDecodeEngine; class FFmpegVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - FFmpegVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context); + explicit FFmpegVideoDecoder(VideoDecodeContext* decode_context); virtual ~FFmpegVideoDecoder(); - static FilterFactory* CreateFactory(VideoDecodeContext* decode_context); - static bool IsMediaFormatSupported(const MediaFormat& media_format); - // MediaFilter implementation. virtual void Stop(FilterCallback* callback); virtual void Seek(base::TimeDelta time, FilterCallback* callback); @@ -57,7 +52,6 @@ class FFmpegVideoDecoder : public VideoDecoder, virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer); virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame); - friend class FilterFactoryImpl1<FFmpegVideoDecoder, VideoDecodeEngine*>; friend class DecoderPrivateMock; friend class FFmpegVideoDecoderTest; FRIEND_TEST_ALL_PREFIXES(FFmpegVideoDecoderTest, FindPtsAndDuration); diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index a81125d..d94e90e 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -71,8 +71,8 @@ class MockVideoDecodeEngine : public VideoDecodeEngine { // Class that just mocks the private functions. class DecoderPrivateMock : public FFmpegVideoDecoder { public: - DecoderPrivateMock(VideoDecodeEngine* engine, VideoDecodeContext* context) - : FFmpegVideoDecoder(engine, context) { + explicit DecoderPrivateMock(VideoDecodeContext* context) + : FFmpegVideoDecoder(context) { } // change access qualifier for test: used in actions. @@ -125,8 +125,7 @@ class FFmpegVideoDecoderTest : public testing::Test { // Create an FFmpegVideoDecoder, and MockVideoDecodeEngine. // // TODO(ajwong): Break the test's dependency on FFmpegVideoDecoder. - factory_ = FFmpegVideoDecoder::CreateFactory(NULL); - decoder_ = factory_->Create<DecoderPrivateMock>(media_format); + decoder_ = new DecoderPrivateMock(NULL); renderer_ = new MockVideoRenderer(); engine_ = new StrictMock<MockVideoDecodeEngine>(); @@ -194,7 +193,6 @@ class FFmpegVideoDecoderTest : public testing::Test { message_loop_.RunAllPending(); } // Fixture members. - scoped_refptr<FilterFactory> factory_; MockVideoDecodeEngine* engine_; // Owned by |decoder_|. scoped_refptr<DecoderPrivateMock> decoder_; scoped_refptr<MockVideoRenderer> renderer_; @@ -229,24 +227,6 @@ const FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoderTest::kTestPts3 = { base::TimeDelta::FromMicroseconds(789), base::TimeDelta::FromMicroseconds(60) }; -TEST(FFmpegVideoDecoderFactoryTest, Create) { - // Should only accept video/x-ffmpeg mime type. - scoped_refptr<FilterFactory> factory = - FFmpegVideoDecoder::CreateFactory(NULL); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); - scoped_refptr<VideoDecoder> decoder = - factory->Create<VideoDecoder>(media_format); - ASSERT_FALSE(decoder); - - // Try again with video/x-ffmpeg mime type. - media_format.Clear(); - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kFFmpegVideo); - decoder = factory->Create<VideoDecoder>(media_format); - ASSERT_TRUE(decoder); -} - TEST_F(FFmpegVideoDecoderTest, Initialize_QueryInterfaceFails) { // Test QueryInterface returning NULL. EXPECT_CALL(*demuxer_, QueryInterface(AVStreamProvider::interface_id())) diff --git a/media/filters/file_data_source.h b/media/filters/file_data_source.h index 4457890..584663a 100644 --- a/media/filters/file_data_source.h +++ b/media/filters/file_data_source.h @@ -17,10 +17,8 @@ namespace media { // system to read data for a media pipeline. class FileDataSource : public DataSource { public: - // Public method to get a filter factory for the FileDataSource. - static FilterFactory* CreateFactory() { - return new FilterFactoryImpl0<FileDataSource>(); - } + FileDataSource(); + virtual ~FileDataSource(); // Implementation of MediaFilter. virtual void Stop(FilterCallback* callback); @@ -41,9 +39,6 @@ class FileDataSource : public DataSource { FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, OpenFile); FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, ReadData); FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, Seek); - friend class FilterFactoryImpl0<FileDataSource>; - FileDataSource(); - virtual ~FileDataSource(); // File handle. NULL if not initialized or an error occurs. FILE* file_; diff --git a/media/filters/null_audio_renderer.cc b/media/filters/null_audio_renderer.cc index 55c4013..7c3c039 100644 --- a/media/filters/null_audio_renderer.cc +++ b/media/filters/null_audio_renderer.cc @@ -26,15 +26,6 @@ NullAudioRenderer::~NullAudioRenderer() { DCHECK_EQ(kNullThreadHandle, thread_); } -// static -bool NullAudioRenderer::IsMediaFormatSupported( - const MediaFormat& media_format) { - int channels; - int sample_rate; - int sample_bits; - return ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits); -} - void NullAudioRenderer::SetVolume(float volume) { // Do nothing. } diff --git a/media/filters/null_audio_renderer.h b/media/filters/null_audio_renderer.h index e6f2e85..afbb098 100644 --- a/media/filters/null_audio_renderer.h +++ b/media/filters/null_audio_renderer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -23,7 +23,6 @@ #include "base/platform_thread.h" #include "base/scoped_ptr.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" @@ -31,13 +30,8 @@ namespace media { class NullAudioRenderer : public AudioRendererBase, PlatformThread::Delegate { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<NullAudioRenderer>(); - } - - // Compatible with any audio/x-uncompressed MediaFormat. - static bool IsMediaFormatSupported(const MediaFormat& media_format); + NullAudioRenderer(); + virtual ~NullAudioRenderer(); // AudioRenderer implementation. virtual void SetVolume(float volume); @@ -46,11 +40,6 @@ class NullAudioRenderer : public AudioRendererBase, PlatformThread::Delegate { virtual void ThreadMain(); protected: - // Only allow a factory to create this class. - friend class FilterFactoryImpl0<NullAudioRenderer>; - NullAudioRenderer(); - virtual ~NullAudioRenderer(); - // AudioRendererBase implementation. virtual bool OnInitialize(const MediaFormat& media_format); virtual void OnStop(); diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc index ba122e5..d8fbf04 100644 --- a/media/filters/omx_video_decoder.cc +++ b/media/filters/omx_video_decoder.cc @@ -7,7 +7,6 @@ #include "base/callback.h" #include "base/message_loop.h" #include "media/base/callback.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" #include "media/base/limits.h" #include "media/ffmpeg/ffmpeg_common.h" @@ -16,38 +15,9 @@ namespace media { -// static -FilterFactory* OmxVideoDecoder::CreateFactory( - VideoDecodeContext* decode_context) { - return new FilterFactoryImpl2<OmxVideoDecoder, - VideoDecodeEngine*, - VideoDecodeContext*>( - new OmxVideoDecodeEngine(), decode_context); -} - -// static -bool OmxVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - if (!format.GetAsString(MediaFormat::kMimeType, &mime_type) || - mime_type::kFFmpegVideo != mime_type) { - return false; - } - - // TODO(ajwong): Find a good way to white-list formats that OpenMAX can - // handle. - int codec_id; - if (format.GetAsInteger(MediaFormat::kFFmpegCodecID, &codec_id) && - codec_id == CODEC_ID_H264) { - return true; - } - - return false; -} - OmxVideoDecoder::OmxVideoDecoder( - VideoDecodeEngine* engine, VideoDecodeContext* context) - : decode_engine_(engine), + : decode_engine_(new OmxVideoDecodeEngine()), decode_context_(context), width_(0), height_(0) { DCHECK(decode_engine_.get()); diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h index f025554..e5861af 100644 --- a/media/filters/omx_video_decoder.h +++ b/media/filters/omx_video_decoder.h @@ -7,7 +7,6 @@ #include <queue> -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/media_format.h" #include "media/video/video_decode_context.h" @@ -24,13 +23,10 @@ class VideoFrame; class OmxVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - static FilterFactory* CreateFactory(VideoDecodeContext* decode_context); - static bool IsMediaFormatSupported(const MediaFormat& media_format); - - OmxVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context); + explicit OmxVideoDecoder(VideoDecodeContext* decode_context); virtual ~OmxVideoDecoder(); + // MediaFilter implementations. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback); virtual void Stop(FilterCallback* callback); virtual void Flush(FilterCallback* callback); diff --git a/media/media.gyp b/media/media.gyp index 111962a..f844f12 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -76,8 +76,6 @@ 'base/data_buffer.h', 'base/djb2.cc', 'base/djb2.h', - 'base/factory.cc', - 'base/factory.h', 'base/filter_host.h', 'base/filters.cc', 'base/filters.h', diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc index be97097..90dae4f 100644 --- a/media/tools/player_wtl/movie.cc +++ b/media/tools/player_wtl/movie.cc @@ -19,7 +19,7 @@ using media::FFmpegAudioDecoder; using media::FFmpegDemuxer; using media::FFmpegVideoDecoder; using media::FileDataSource; -using media::FilterFactoryCollection; +using media::MediaFilterCollection; using media::PipelineImpl; namespace media { @@ -53,28 +53,26 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) { Close(); } - // Create our filter factories. - scoped_refptr<FilterFactoryCollection> factories = - new FilterFactoryCollection(); - factories->AddFactory(FileDataSource::CreateFactory()); - factories->AddFactory(FFmpegAudioDecoder::CreateFactory()); - factories->AddFactory(FFmpegDemuxer::CreateFilterFactory()); - factories->AddFactory(FFmpegVideoDecoder::CreateFactory(NULL)); + // Create filter collection. + MediaFilterCollection collection; + collection.push_back(new FileDataSource()); + collection.push_back(new FFmpegAudioDecoder()); + collection.push_back(new FFmpegDemuxer()); + collection.push_back(new FFmpegVideoDecoder(NULL)); if (enable_audio_) { - factories->AddFactory(AudioRendererImpl::CreateFilterFactory()); + collection.push_back(new AudioRendererImpl()); } else { - factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); + collection.push_back(new media::NullAudioRenderer()); } - factories->AddFactory( - new media::InstanceFilterFactory<WtlVideoRenderer>(video_renderer)); + collection.push_back(video_renderer); thread_.reset(new base::Thread("PipelineThread")); thread_->Start(); pipeline_ = new PipelineImpl(thread_->message_loop()); // Create and start our pipeline. - pipeline_->Start(factories, WideToUTF8(std::wstring(url)), NULL); + pipeline_->Start(collection, WideToUTF8(std::wstring(url)), NULL); while (true) { PlatformThread::Sleep(100); if (pipeline_->IsInitialized()) diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc index 29b4f38..eef1a25 100644 --- a/media/tools/player_x11/gl_video_renderer.cc +++ b/media/tools/player_x11/gl_video_renderer.cc @@ -24,12 +24,6 @@ GlVideoRenderer::GlVideoRenderer(Display* display, Window window, GlVideoRenderer::~GlVideoRenderer() { } -// static -bool GlVideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void GlVideoRenderer::OnStop(media::FilterCallback* callback) { glXMakeCurrent(display_, 0, NULL); glXDestroyContext(display_, gl_context_); diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h index 71f8d77..c6ce45e 100644 --- a/media/tools/player_x11/gl_video_renderer.h +++ b/media/tools/player_x11/gl_video_renderer.h @@ -8,29 +8,17 @@ #include "app/gfx/gl/gl_bindings.h" #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class GlVideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - GlVideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - GlVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static GlVideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc index d3b8051..8bd8b3e 100644 --- a/media/tools/player_x11/gles_video_renderer.cc +++ b/media/tools/player_x11/gles_video_renderer.cc @@ -33,12 +33,6 @@ GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window, GlesVideoRenderer::~GlesVideoRenderer() { } -// static -bool GlesVideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void GlesVideoRenderer::OnStop(media::FilterCallback* callback) { if (glx_thread_message_loop()) { glx_thread_message_loop()->PostTask(FROM_HERE, diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h index 27780b6..ead864f 100644 --- a/media/tools/player_x11/gles_video_renderer.h +++ b/media/tools/player_x11/gles_video_renderer.h @@ -12,30 +12,18 @@ #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/video_frame.h" #include "media/filters/video_renderer_base.h" class GlesVideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - GlesVideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - GlesVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static GlesVideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 11b8b5f..d1a7ffe 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -97,29 +97,26 @@ bool InitPipeline(MessageLoop* message_loop, } // Create our filter factories. - scoped_refptr<media::FilterFactoryCollection> factories = - new media::FilterFactoryCollection(); - factories->AddFactory(media::FileDataSource::CreateFactory()); - factories->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); - factories->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); + media::MediaFilterCollection collection; + collection.push_back(new media::FileDataSource()); + collection.push_back(new media::FFmpegDemuxer()); + collection.push_back(new media::FFmpegAudioDecoder()); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableOpenMax)) { - factories->AddFactory(media::OmxVideoDecoder::CreateFactory(NULL)); + collection.push_back(new media::OmxVideoDecoder(NULL)); } else { - factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory(NULL)); + collection.push_back(new media::FFmpegVideoDecoder(NULL)); } - factories->AddFactory(Renderer::CreateFactory(g_display, g_window, - paint_message_loop)); + collection.push_back(new Renderer(g_display, g_window, paint_message_loop)); - if (enable_audio) { - factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory()); - } else { - factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); - } + if (enable_audio) + collection.push_back(new media::AudioRendererImpl()); + else + collection.push_back(new media::NullAudioRenderer()); // Creates the pipeline and start it. *pipeline = new media::PipelineImpl(message_loop); - (*pipeline)->Start(factories, filename, NULL); + (*pipeline)->Start(collection, filename, NULL); // Wait until the pipeline is fully initialized. while (true) { diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc index 6819468..2c50e50 100644 --- a/media/tools/player_x11/x11_video_renderer.cc +++ b/media/tools/player_x11/x11_video_renderer.cc @@ -67,12 +67,6 @@ X11VideoRenderer::X11VideoRenderer(Display* display, Window window, X11VideoRenderer::~X11VideoRenderer() { } -// static -bool X11VideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void X11VideoRenderer::OnStop(media::FilterCallback* callback) { if (image_) { XDestroyImage(image_); diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index 2bd9dc4..5076ef8 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -9,29 +9,17 @@ #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class X11VideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - X11VideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - X11VideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static X11VideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { |