summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 05:40:13 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 05:40:13 +0000
commit9e166974e33f359467458af13987c3d87663c163 (patch)
tree63ddfaa99458d1d06b120ec99383f6ff814933da /media
parentbcc26067bf9a0bb7fe1600119a5b034b36b86da4 (diff)
downloadchromium_src-9e166974e33f359467458af13987c3d87663c163.zip
chromium_src-9e166974e33f359467458af13987c3d87663c163.tar.gz
chromium_src-9e166974e33f359467458af13987c3d87663c163.tar.bz2
Move MediaFilterCollection code into a class.
Refactored FilterType usage a bit to remove the need to manually associate FilterType values to filter base classes. Patch by acolwell@chromium.org: http://codereview.chromium.org/4176006/show BUG=60778 TEST=media_unittests git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64885 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/filters.cc12
-rw-r--r--media/base/filters.h12
-rw-r--r--media/base/media_filter_collection.cc41
-rw-r--r--media/base/media_filter_collection.h54
-rw-r--r--media/base/media_filter_collection_unittest.cc99
-rw-r--r--media/base/mock_filters.h24
-rw-r--r--media/base/pipeline.h3
-rw-r--r--media/base/pipeline_impl.cc178
-rw-r--r--media/base/pipeline_impl.h18
-rw-r--r--media/base/pipeline_impl_unittest.cc3
-rw-r--r--media/media.gyp3
-rw-r--r--media/tools/player_wtl/movie.cc18
-rw-r--r--media/tools/player_x11/player_x11.cc21
13 files changed, 328 insertions, 158 deletions
diff --git a/media/base/filters.cc b/media/base/filters.cc
index 4c9ab4f..fb8f66a 100644
--- a/media/base/filters.cc
+++ b/media/base/filters.cc
@@ -86,15 +86,15 @@ bool DataSource::IsUrlSupported(const std::string& url) {
}
FilterType DataSource::filter_type() const {
- return FILTER_DATA_SOURCE;
+ return static_filter_type();
}
FilterType Demuxer::filter_type() const {
- return FILTER_DEMUXER;
+ return static_filter_type();
}
FilterType AudioDecoder::filter_type() const {
- return FILTER_AUDIO_DECODER;
+ return static_filter_type();
}
const char* AudioDecoder::major_mime_type() const {
@@ -102,7 +102,7 @@ const char* AudioDecoder::major_mime_type() const {
}
FilterType AudioRenderer::filter_type() const {
- return FILTER_AUDIO_RENDERER;
+ return static_filter_type();
}
const char* AudioRenderer::major_mime_type() const {
@@ -110,7 +110,7 @@ const char* AudioRenderer::major_mime_type() const {
}
FilterType VideoDecoder::filter_type() const {
- return FILTER_VIDEO_DECODER;
+ return static_filter_type();
}
const char* VideoDecoder::major_mime_type() const {
@@ -118,7 +118,7 @@ const char* VideoDecoder::major_mime_type() const {
}
FilterType VideoRenderer::filter_type() const {
- return FILTER_VIDEO_RENDERER;
+ return static_filter_type();
}
const char* VideoRenderer::major_mime_type() const {
diff --git a/media/base/filters.h b/media/base/filters.h
index 02bc596..f386111 100644
--- a/media/base/filters.h
+++ b/media/base/filters.h
@@ -24,7 +24,6 @@
#define MEDIA_BASE_FILTERS_H_
#include <limits>
-#include <list>
#include <string>
#include "base/callback.h"
@@ -60,11 +59,6 @@ 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();
@@ -147,6 +141,7 @@ class DataSource : public MediaFilter {
virtual bool IsUrlSupported(const std::string& url);
+ static FilterType static_filter_type() { return FILTER_DATA_SOURCE; }
virtual FilterType filter_type() const;
// Initialize a DataSource for the given URL, executing the callback upon
@@ -173,6 +168,7 @@ class DataSource : public MediaFilter {
class Demuxer : public MediaFilter {
public:
+ static FilterType static_filter_type() { return FILTER_DEMUXER; }
virtual FilterType filter_type() const;
// Initialize a Demuxer with the given DataSource, executing the callback upon
@@ -228,6 +224,7 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> {
class VideoDecoder : public MediaFilter {
public:
+ static FilterType static_filter_type() { return FILTER_VIDEO_DECODER; }
virtual FilterType filter_type() const;
virtual const char* major_mime_type() const;
@@ -272,6 +269,7 @@ class VideoDecoder : public MediaFilter {
class AudioDecoder : public MediaFilter {
public:
+ static FilterType static_filter_type() { return FILTER_AUDIO_DECODER; }
virtual FilterType filter_type() const;
virtual const char* major_mime_type() const;
@@ -311,6 +309,7 @@ class AudioDecoder : public MediaFilter {
class VideoRenderer : public MediaFilter {
public:
+ static FilterType static_filter_type() { return FILTER_VIDEO_RENDERER; }
virtual FilterType filter_type() const;
virtual const char* major_mime_type() const;
@@ -327,6 +326,7 @@ class VideoRenderer : public MediaFilter {
class AudioRenderer : public MediaFilter {
public:
+ static FilterType static_filter_type() { return FILTER_AUDIO_RENDERER; }
virtual FilterType filter_type() const;
virtual const char* major_mime_type() const;
diff --git a/media/base/media_filter_collection.cc b/media/base/media_filter_collection.cc
new file mode 100644
index 0000000..2c90412
--- /dev/null
+++ b/media/base/media_filter_collection.cc
@@ -0,0 +1,41 @@
+// 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/media_filter_collection.h"
+
+namespace media {
+
+MediaFilterCollection::MediaFilterCollection() {
+}
+
+void MediaFilterCollection::AddFilter(MediaFilter* filter) {
+ filters_.push_back(filter);
+}
+
+bool MediaFilterCollection::IsEmpty() const {
+ return filters_.empty();
+}
+
+void MediaFilterCollection::Clear() {
+ filters_.clear();
+}
+
+void MediaFilterCollection::SelectFilter(
+ FilterType filter_type,
+ scoped_refptr<MediaFilter>* filter_out) {
+
+ std::list<scoped_refptr<MediaFilter> >::iterator it = filters_.begin();
+ while (it != filters_.end()) {
+ if ((*it)->filter_type() == filter_type)
+ break;
+ ++it;
+ }
+
+ if (it != filters_.end()) {
+ *filter_out = it->get();
+ filters_.erase(it);
+ }
+}
+
+} // namespace media
diff --git a/media/base/media_filter_collection.h b/media/base/media_filter_collection.h
new file mode 100644
index 0000000..31ea69c
--- /dev/null
+++ b/media/base/media_filter_collection.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef MEDIA_BASE_MEDIA_FILTER_COLLECTION_H_
+#define MEDIA_BASE_MEDIA_FILTER_COLLECTION_H_
+
+#include <list>
+
+#include "base/ref_counted.h"
+#include "media/base/filters.h"
+
+namespace media {
+
+// This is a collection of MediaFilter objects used to form a media playback
+// pipeline. See src/media/base/pipeline.h for more information.
+class MediaFilterCollection {
+ public:
+ MediaFilterCollection();
+
+ // Adds a filter to the collection.
+ void AddFilter(MediaFilter* filter);
+
+ // Is the collection empty?
+ bool IsEmpty() const;
+
+ // Remove remaining filters.
+ void Clear();
+
+ // Selects a filter of the specified type from the collection.
+ // If the required filter cannot be found, NULL is returned.
+ // If a filter is returned it is removed from the collection.
+ template <class Filter>
+ void SelectFilter(scoped_refptr<Filter>* filter_out) {
+ scoped_refptr<MediaFilter> filter;
+ SelectFilter(Filter::static_filter_type(), &filter);
+ *filter_out = reinterpret_cast<Filter*>(filter.get());
+ }
+
+ private:
+ // List of filters managed by this collection.
+ std::list<scoped_refptr<MediaFilter> > filters_;
+
+ // Helper function that searches the filters list for a specific
+ // filter type.
+ void SelectFilter(FilterType filter_type,
+ scoped_refptr<MediaFilter>* filter_out);
+
+ DISALLOW_COPY_AND_ASSIGN(MediaFilterCollection);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_MEDIA_FILTER_COLLECTION_H_
diff --git a/media/base/media_filter_collection_unittest.cc b/media/base/media_filter_collection_unittest.cc
new file mode 100644
index 0000000..d974b4f
--- /dev/null
+++ b/media/base/media_filter_collection_unittest.cc
@@ -0,0 +1,99 @@
+// 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/media_filter_collection.h"
+#include "media/base/mock_filters.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+class MediaFilterCollectionTest : public ::testing::Test {
+ public:
+ MediaFilterCollectionTest() {}
+ virtual ~MediaFilterCollectionTest() {}
+
+ protected:
+ MediaFilterCollection collection_;
+ MockFilterCollection mock_filters_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaFilterCollectionTest);
+};
+
+TEST_F(MediaFilterCollectionTest, TestIsEmptyAndClear) {
+ EXPECT_TRUE(collection_.IsEmpty());
+
+ collection_.AddFilter(mock_filters_.data_source());
+
+ EXPECT_FALSE(collection_.IsEmpty());
+
+ collection_.Clear();
+
+ EXPECT_TRUE(collection_.IsEmpty());
+}
+
+TEST_F(MediaFilterCollectionTest, SelectFilter) {
+ scoped_refptr<AudioDecoder> audio_decoder;
+ scoped_refptr<DataSource> data_source;
+
+ collection_.AddFilter(mock_filters_.data_source());
+ EXPECT_FALSE(collection_.IsEmpty());
+
+ // Verify that the data source will not be returned if we
+ // ask for a different type.
+ collection_.SelectFilter(&audio_decoder);
+ EXPECT_FALSE(audio_decoder);
+ EXPECT_FALSE(collection_.IsEmpty());
+
+ // Verify that we can actually retrieve the data source
+ // and that it is removed from the collection.
+ collection_.SelectFilter(&data_source);
+ EXPECT_TRUE(data_source);
+ EXPECT_TRUE(collection_.IsEmpty());
+
+ // Add a data source and audio decoder.
+ collection_.AddFilter(mock_filters_.data_source());
+ collection_.AddFilter(mock_filters_.audio_decoder());
+
+ // Verify that we can select the audio decoder.
+ collection_.SelectFilter(&audio_decoder);
+ EXPECT_TRUE(audio_decoder);
+ EXPECT_FALSE(collection_.IsEmpty());
+
+ // Verify that we can't select it again since only one has been added.
+ collection_.SelectFilter(&audio_decoder);
+ EXPECT_FALSE(audio_decoder);
+
+ // Verify that we can select the data source and that doing so will
+ // empty the collection again.
+ collection_.SelectFilter(&data_source);
+ EXPECT_TRUE(collection_.IsEmpty());
+}
+
+TEST_F(MediaFilterCollectionTest, MultipleFiltersOfSameType) {
+ scoped_refptr<DataSource> data_source_a(new MockDataSource());
+ scoped_refptr<DataSource> data_source_b(new MockDataSource());
+
+ scoped_refptr<DataSource> data_source;
+
+ collection_.AddFilter(data_source_a.get());
+ collection_.AddFilter(data_source_b.get());
+
+ // Verify that first SelectFilter() returns data_source_a.
+ collection_.SelectFilter(&data_source);
+ EXPECT_TRUE(data_source);
+ EXPECT_EQ(data_source, data_source_a);
+ EXPECT_FALSE(collection_.IsEmpty());
+
+ // Verify that second SelectFilter() returns data_source_b.
+ collection_.SelectFilter(&data_source);
+ EXPECT_TRUE(data_source);
+ EXPECT_EQ(data_source, data_source_b);
+ EXPECT_TRUE(collection_.IsEmpty());
+
+ // Verify that third SelectFilter returns nothing.
+ collection_.SelectFilter(&data_source);
+ EXPECT_FALSE(data_source);
+}
+
+} // namespace media
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index 97710fe..ba15293 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -17,6 +17,7 @@
#include "base/callback.h"
#include "media/base/filters.h"
+#include "media/base/media_filter_collection.h"
#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -284,14 +285,21 @@ class MockFilterCollection {
MockVideoRenderer* video_renderer() const { return video_renderer_; }
MockAudioRenderer* audio_renderer() const { return audio_renderer_; }
- 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_);
+ MediaFilterCollection* filter_collection() const {
+ return filter_collection(true);
+ }
+
+ MediaFilterCollection* filter_collection(bool include_data_source) const {
+ MediaFilterCollection* collection = new MediaFilterCollection();
+
+ if (include_data_source) {
+ collection->AddFilter(data_source_);
+ }
+ collection->AddFilter(demuxer_);
+ collection->AddFilter(video_decoder_);
+ collection->AddFilter(audio_decoder_);
+ collection->AddFilter(video_renderer_);
+ collection->AddFilter(audio_renderer_);
return collection;
}
diff --git a/media/base/pipeline.h b/media/base/pipeline.h
index 0519b35..ab08cc4 100644
--- a/media/base/pipeline.h
+++ b/media/base/pipeline.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "media/base/filters.h"
+#include "media/base/media_filter_collection.h"
namespace base {
class TimeDelta;
@@ -59,7 +60,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(const MediaFilterCollection& filter_collection,
+ virtual bool Start(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 214be7d0..2493f3b 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -75,18 +75,21 @@ PipelineImpl::~PipelineImpl() {
}
// Creates the PipelineInternal and calls it's start method.
-bool PipelineImpl::Start(const MediaFilterCollection& collection,
+bool PipelineImpl::Start(MediaFilterCollection* collection,
const std::string& url,
PipelineCallback* start_callback) {
AutoLock auto_lock(lock_);
scoped_ptr<PipelineCallback> callback(start_callback);
+ scoped_ptr<MediaFilterCollection> filter_collection(collection);
+
if (running_) {
VLOG(1) << "Media pipeline is already running";
return false;
}
- if (collection.empty())
+ if (collection->IsEmpty()) {
return false;
+ }
// Kick off initialization!
running_ = true;
@@ -94,7 +97,7 @@ bool PipelineImpl::Start(const MediaFilterCollection& collection,
FROM_HERE,
NewRunnableMethod(this,
&PipelineImpl::StartTask,
- collection,
+ filter_collection.release(),
url,
callback.release()));
return true;
@@ -566,12 +569,12 @@ void PipelineImpl::OnFilterStateTransition() {
NewRunnableMethod(this, &PipelineImpl::FilterStateTransitionTask));
}
-void PipelineImpl::StartTask(const MediaFilterCollection& filter_collection,
+void PipelineImpl::StartTask(MediaFilterCollection* filter_collection,
const std::string& url,
PipelineCallback* start_callback) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
DCHECK_EQ(kCreated, state_);
- filter_collection_ = filter_collection;
+ filter_collection_.reset(filter_collection);
url_ = url;
seek_callback_.reset(start_callback);
@@ -664,7 +667,7 @@ void PipelineImpl::InitializeTask() {
}
// Clear the collection of filters.
- filter_collection_.clear();
+ filter_collection_->Clear();
// Initialization was successful, we are now considered paused, so it's safe
// to set the initial playback rate and volume.
@@ -750,7 +753,7 @@ void PipelineImpl::VolumeChangedTask(float volume) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
scoped_refptr<AudioRenderer> audio_renderer;
- GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer);
+ GetInitializedFilter(&audio_renderer);
if (audio_renderer) {
audio_renderer->SetVolume(volume);
}
@@ -808,8 +811,8 @@ void PipelineImpl::NotifyEndedTask() {
// Grab the renderers, if they exist.
scoped_refptr<AudioRenderer> audio_renderer;
scoped_refptr<VideoRenderer> video_renderer;
- GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer);
- GetInitializedFilter(FILTER_VIDEO_RENDERER, &video_renderer);
+ GetInitializedFilter(&audio_renderer);
+ GetInitializedFilter(&video_renderer);
DCHECK(audio_renderer || video_renderer);
// Make sure every extant renderer has ended.
@@ -972,38 +975,6 @@ void PipelineImpl::FinishDestroyingFiltersTask() {
}
}
-template <class Filter>
-void PipelineImpl::SelectFilter(
- FilterType filter_type, scoped_refptr<Filter>* filter_out) const {
- DCHECK_EQ(MessageLoop::current(), message_loop_);
-
- 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());
@@ -1037,10 +1008,9 @@ void PipelineImpl::InitializeDataSource() {
scoped_refptr<DataSource> data_source;
while (true) {
- SelectFilter(FILTER_DATA_SOURCE, &data_source);
+ filter_collection_->SelectFilter(&data_source);
if (!data_source || data_source->IsUrlSupported(url_))
break;
- RemoveFilter(data_source);
}
if (!data_source) {
@@ -1048,7 +1018,6 @@ void PipelineImpl::InitializeDataSource() {
return;
}
- RemoveFilter(data_source);
PrepareFilter(data_source);
data_source->Initialize(
url_, NewCallback(this, &PipelineImpl::OnFilterInitialize));
@@ -1061,16 +1030,15 @@ void PipelineImpl::InitializeDemuxer() {
scoped_refptr<DataSource> data_source;
scoped_refptr<Demuxer> demuxer;
- GetInitializedFilter(FILTER_DATA_SOURCE, &data_source);
+ GetInitializedFilter(&data_source);
CHECK(data_source);
- SelectFilter(FILTER_DEMUXER, &demuxer);
+ filter_collection_->SelectFilter(&demuxer);
if (!demuxer) {
SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
return;
}
- RemoveFilter(demuxer);
PrepareFilter(demuxer);
demuxer->Initialize(data_source,
NewCallback(this, &PipelineImpl::OnFilterInitialize));
@@ -1082,21 +1050,23 @@ bool PipelineImpl::InitializeAudioDecoder() {
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;
+ if (stream) {
+ scoped_refptr<AudioDecoder> audio_decoder;
+ filter_collection_->SelectFilter(&audio_decoder);
- RemoveFilter(audio_decoder);
- PrepareFilter(audio_decoder);
- audio_decoder->Initialize(
- stream,
- NewCallback(this, &PipelineImpl::OnFilterInitialize));
- return true;
+ if (audio_decoder) {
+ PrepareFilter(audio_decoder);
+ audio_decoder->Initialize(
+ stream,
+ NewCallback(this, &PipelineImpl::OnFilterInitialize));
+ return true;
+ } else {
+ SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
+ }
+ }
+
+ return false;
}
bool PipelineImpl::InitializeVideoDecoder() {
@@ -1105,21 +1075,22 @@ bool PipelineImpl::InitializeVideoDecoder() {
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;
+ if (stream) {
+ scoped_refptr<VideoDecoder> video_decoder;
+ filter_collection_->SelectFilter(&video_decoder);
- RemoveFilter(video_decoder);
- PrepareFilter(video_decoder);
- video_decoder->Initialize(
- stream,
- NewCallback(this, &PipelineImpl::OnFilterInitialize));
- return true;
+ if (video_decoder) {
+ PrepareFilter(video_decoder);
+ video_decoder->Initialize(
+ stream,
+ NewCallback(this, &PipelineImpl::OnFilterInitialize));
+ return true;
+ } else {
+ SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
+ }
+ }
+ return false;
}
bool PipelineImpl::InitializeAudioRenderer() {
@@ -1127,21 +1098,22 @@ bool PipelineImpl::InitializeAudioRenderer() {
DCHECK(IsPipelineOk());
scoped_refptr<AudioDecoder> decoder;
- GetInitializedFilter(FILTER_AUDIO_DECODER, &decoder);
- scoped_refptr<AudioRenderer> audio_renderer;
- SelectFilter(FILTER_AUDIO_RENDERER, &audio_renderer);
+ GetInitializedFilter(&decoder);
- // 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;
+ if (decoder) {
+ scoped_refptr<AudioRenderer> audio_renderer;
+ filter_collection_->SelectFilter(&audio_renderer);
- RemoveFilter(audio_renderer);
- PrepareFilter(audio_renderer);
- audio_renderer->Initialize(
- decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize));
- return true;
+ if (audio_renderer) {
+ PrepareFilter(audio_renderer);
+ audio_renderer->Initialize(
+ decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize));
+ return true;
+ } else {
+ SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
+ }
+ }
+ return false;
}
bool PipelineImpl::InitializeVideoRenderer() {
@@ -1149,27 +1121,28 @@ bool PipelineImpl::InitializeVideoRenderer() {
DCHECK(IsPipelineOk());
scoped_refptr<VideoDecoder> decoder;
- GetInitializedFilter(FILTER_VIDEO_DECODER, &decoder);
- scoped_refptr<VideoRenderer> video_renderer;
- SelectFilter(FILTER_VIDEO_RENDERER, &video_renderer);
+ GetInitializedFilter(&decoder);
- // 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;
+ if (decoder) {
+ scoped_refptr<VideoRenderer> video_renderer;
+ filter_collection_->SelectFilter(&video_renderer);
- RemoveFilter(video_renderer);
- PrepareFilter(video_renderer);
- video_renderer->Initialize(
- decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize));
- return true;
+ if (video_renderer) {
+ PrepareFilter(video_renderer);
+ video_renderer->Initialize(
+ decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize));
+ return true;
+ } else {
+ SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
+ }
+ }
+ return false;
}
scoped_refptr<DemuxerStream> PipelineImpl::FindDemuxerStream(
std::string major_mime_type) {
scoped_refptr<Demuxer> demuxer;
- GetInitializedFilter(FILTER_DEMUXER, &demuxer);
+ GetInitializedFilter(&demuxer);
DCHECK(demuxer);
const int num_outputs = demuxer->GetNumberOfStreams();
@@ -1186,10 +1159,11 @@ scoped_refptr<DemuxerStream> PipelineImpl::FindDemuxerStream(
template <class Filter>
void PipelineImpl::GetInitializedFilter(
- FilterType filter_type, scoped_refptr<Filter>* filter_out) const {
+ scoped_refptr<Filter>* filter_out) const {
DCHECK_EQ(MessageLoop::current(), message_loop_);
- FilterTypeMap::const_iterator ft = filter_types_.find(filter_type);
+ FilterTypeMap::const_iterator ft =
+ filter_types_.find(Filter::static_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 0370fd5..c03f8c5 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(const MediaFilterCollection& filter_collection,
+ virtual bool Start(MediaFilterCollection* filter_collection,
const std::string& uri,
PipelineCallback* start_callback);
virtual void Stop(PipelineCallback* stop_callback);
@@ -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(const MediaFilterCollection& filter_collection,
+ void StartTask(MediaFilterCollection* filter_collection,
const std::string& url,
PipelineCallback* start_callback);
@@ -241,15 +241,6 @@ 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.
- // 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);
@@ -280,8 +271,7 @@ class PipelineImpl : public Pipeline, public FilterHost {
// specified filter type. If one exists, the |filter_out| will contain
// the filter, |*filter_out| will be NULL.
template <class Filter>
- void GetInitializedFilter(FilterType filter_type,
- scoped_refptr<Filter>* filter_out) const;
+ void GetInitializedFilter(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:
@@ -400,7 +390,7 @@ class PipelineImpl : public Pipeline, public FilterHost {
base::TimeDelta max_buffered_time_;
// Filter collection as passed in by Start().
- MediaFilterCollection filter_collection_;
+ scoped_ptr<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 eef63566..02d1165 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -351,8 +351,7 @@ TEST_F(PipelineImplTest, RequiredFilterMissing) {
EXPECT_CALL(callbacks_, OnStart());
// Create a filter collection with missing filter.
- MediaFilterCollection collection = mocks_->filter_collection();
- collection.pop_front();
+ MediaFilterCollection* collection = mocks_->filter_collection(false);
pipeline_->Start(collection, "",
NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_),
&CallbackHelper::OnStart));
diff --git a/media/media.gyp b/media/media.gyp
index f844f12..53c59f4 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -80,6 +80,8 @@
'base/filters.cc',
'base/filters.h',
'base/media.h',
+ 'base/media_filter_collection.cc',
+ 'base/media_filter_collection.h',
'base/media_format.cc',
'base/media_format.h',
'base/media_posix.cc',
@@ -262,6 +264,7 @@
'base/clock_impl_unittest.cc',
'base/data_buffer_unittest.cc',
'base/djb2_unittest.cc',
+ 'base/media_filter_collection_unittest.cc',
'base/mock_ffmpeg.cc',
'base/mock_ffmpeg.h',
'base/mock_filter_host.h',
diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc
index 90dae4f..c12d724 100644
--- a/media/tools/player_wtl/movie.cc
+++ b/media/tools/player_wtl/movie.cc
@@ -54,25 +54,25 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) {
}
// 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));
+ scoped_ptr<MediaFilterCollection> collection(new MediaFilterCollection());
+ collection->AddFilter(new FileDataSource());
+ collection->AddFilter(new FFmpegAudioDecoder());
+ collection->AddFilter(new FFmpegDemuxer());
+ collection->AddFilter(new FFmpegVideoDecoder(NULL));
if (enable_audio_) {
- collection.push_back(new AudioRendererImpl());
+ collection->AddFilter(new AudioRendererImpl());
} else {
- collection.push_back(new media::NullAudioRenderer());
+ collection->AddFilter(new media::NullAudioRenderer());
}
- collection.push_back(video_renderer);
+ collection->AddFilter(video_renderer);
thread_.reset(new base::Thread("PipelineThread"));
thread_->Start();
pipeline_ = new PipelineImpl(thread_->message_loop());
// Create and start our pipeline.
- pipeline_->Start(collection, WideToUTF8(std::wstring(url)), NULL);
+ pipeline_->Start(collection.release(), WideToUTF8(std::wstring(url)), NULL);
while (true) {
PlatformThread::Sleep(100);
if (pipeline_->IsInitialized())
diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc
index d1a7ffe..ad307c4 100644
--- a/media/tools/player_x11/player_x11.cc
+++ b/media/tools/player_x11/player_x11.cc
@@ -97,26 +97,27 @@ bool InitPipeline(MessageLoop* message_loop,
}
// Create our filter factories.
- media::MediaFilterCollection collection;
- collection.push_back(new media::FileDataSource());
- collection.push_back(new media::FFmpegDemuxer());
- collection.push_back(new media::FFmpegAudioDecoder());
+ scoped_ptr<media::MediaFilterCollection> collection(
+ new media::MediaFilterCollection());
+ collection->AddFilter(new media::FileDataSource());
+ collection->AddFilter(new media::FFmpegDemuxer());
+ collection->AddFilter(new media::FFmpegAudioDecoder());
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableOpenMax)) {
- collection.push_back(new media::OmxVideoDecoder(NULL));
+ collection->AddFilter(new media::OmxVideoDecoder(NULL));
} else {
- collection.push_back(new media::FFmpegVideoDecoder(NULL));
+ collection->AddFilter(new media::FFmpegVideoDecoder(NULL));
}
- collection.push_back(new Renderer(g_display, g_window, paint_message_loop));
+ collection->AddFilter(new Renderer(g_display, g_window, paint_message_loop));
if (enable_audio)
- collection.push_back(new media::AudioRendererImpl());
+ collection->AddFilter(new media::AudioRendererImpl());
else
- collection.push_back(new media::NullAudioRenderer());
+ collection->AddFilter(new media::NullAudioRenderer());
// Creates the pipeline and start it.
*pipeline = new media::PipelineImpl(message_loop);
- (*pipeline)->Start(collection, filename, NULL);
+ (*pipeline)->Start(collection.release(), filename, NULL);
// Wait until the pipeline is fully initialized.
while (true) {