summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-23 01:20:37 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-23 01:20:37 +0000
commit457d83467c00c236e806bb150796a2efdc88bfcf (patch)
tree36c58186b34d36300374b232fb79540457307b23 /media
parent77a397cc5cf8106e559aa87a5228478afc28cec1 (diff)
downloadchromium_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')
-rw-r--r--media/base/factory.cc33
-rw-r--r--media/base/factory.h253
-rw-r--r--media/base/filters.cc48
-rw-r--r--media/base/filters.h94
-rw-r--r--media/base/mock_filter_host.h4
-rw-r--r--media/base/mock_filters.h53
-rw-r--r--media/base/pipeline.h10
-rw-r--r--media/base/pipeline_impl.cc275
-rw-r--r--media/base/pipeline_impl.h99
-rw-r--r--media/base/pipeline_impl_unittest.cc56
-rw-r--r--media/filters/audio_renderer_base.h8
-rw-r--r--media/filters/audio_renderer_impl.cc9
-rw-r--r--media/filters/audio_renderer_impl.h14
-rw-r--r--media/filters/decoder_base_unittest.cc4
-rw-r--r--media/filters/ffmpeg_audio_decoder.cc7
-rw-r--r--media/filters/ffmpeg_audio_decoder.h12
-rw-r--r--media/filters/ffmpeg_demuxer.h11
-rw-r--r--media/filters/ffmpeg_demuxer_unittest.cc23
-rw-r--r--media/filters/ffmpeg_glue_unittest.cc1
-rw-r--r--media/filters/ffmpeg_video_decoder.cc22
-rw-r--r--media/filters/ffmpeg_video_decoder.h8
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc26
-rw-r--r--media/filters/file_data_source.h9
-rw-r--r--media/filters/null_audio_renderer.cc9
-rw-r--r--media/filters/null_audio_renderer.h17
-rw-r--r--media/filters/omx_video_decoder.cc32
-rw-r--r--media/filters/omx_video_decoder.h8
-rw-r--r--media/media.gyp2
-rw-r--r--media/tools/player_wtl/movie.cc24
-rw-r--r--media/tools/player_x11/gl_video_renderer.cc6
-rw-r--r--media/tools/player_x11/gl_video_renderer.h12
-rw-r--r--media/tools/player_x11/gles_video_renderer.cc6
-rw-r--r--media/tools/player_x11/gles_video_renderer.h12
-rw-r--r--media/tools/player_x11/player_x11.cc27
-rw-r--r--media/tools/player_x11/x11_video_renderer.cc6
-rw-r--r--media/tools/player_x11/x11_video_renderer.h12
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() {