summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
Diffstat (limited to 'media/base')
-rw-r--r--media/base/filter_host.h4
-rw-r--r--media/base/filters.h12
-rw-r--r--media/base/mock_filter_host.h1
-rw-r--r--media/base/mock_filters.h12
-rw-r--r--media/base/pipeline_impl.cc20
-rw-r--r--media/base/pipeline_impl.h4
-rw-r--r--media/base/pipeline_impl_unittest.cc41
7 files changed, 94 insertions, 0 deletions
diff --git a/media/base/filter_host.h b/media/base/filter_host.h
index 65aeebb..17e7631 100644
--- a/media/base/filter_host.h
+++ b/media/base/filter_host.h
@@ -18,6 +18,7 @@
#define MEDIA_BASE_FILTER_HOST_H_
#include "base/task.h"
+#include "media/base/filters.h"
#include "media/base/pipeline.h"
namespace media {
@@ -56,6 +57,9 @@ class FilterHost {
// Sets the flag to indicate that we are doing streaming.
virtual void SetStreaming(bool streaming) = 0;
+ // Broadcast a message of type |message| to all other filters from |source|.
+ virtual void BroadcastMessage(FilterMessage message) = 0;
+
protected:
virtual ~FilterHost() {}
};
diff --git a/media/base/filters.h b/media/base/filters.h
index 3faede5..9a63763 100644
--- a/media/base/filters.h
+++ b/media/base/filters.h
@@ -53,6 +53,12 @@ enum FilterType {
FILTER_VIDEO_RENDERER
};
+// A filter can broadcast messages to all other filters. This identifies
+// the type of message to be broadcasted.
+enum FilterMessage {
+ kMsgDisableAudio,
+};
+
// Used for completing asynchronous methods.
typedef Callback0::Type FilterCallback;
@@ -124,6 +130,12 @@ class MediaFilter : public base::RefCountedThreadSafe<MediaFilter> {
}
}
+ // This method is called from the pipeline when a message of type |message|
+ // is broadcasted from |source|. Filters can ignore the message if they do
+ // not need to react to events raised from another filter.
+ virtual void OnReceivedMessage(FilterMessage message) {
+ }
+
protected:
// Only allow scoped_refptr<> to delete filters.
friend class base::RefCountedThreadSafe<MediaFilter>;
diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h
index a7150c2..c463541 100644
--- a/media/base/mock_filter_host.h
+++ b/media/base/mock_filter_host.h
@@ -37,6 +37,7 @@ class MockFilterHost : public FilterHost {
MOCK_METHOD1(SetBufferedBytes, void(int64 buffered_bytes));
MOCK_METHOD2(SetVideoSize, void(size_t width, size_t height));
MOCK_METHOD1(SetStreaming, void(bool streamed));
+ MOCK_METHOD1(BroadcastMessage, void(FilterMessage message));
private:
DISALLOW_COPY_AND_ASSIGN(MockFilterHost);
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index cf5d2d5..affc0fa 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -96,6 +96,7 @@ class MockDataSource : public DataSource {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// DataSource implementation.
MOCK_METHOD2(Initialize, void(const std::string& url,
@@ -123,6 +124,7 @@ class MockDemuxer : public Demuxer {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// Demuxer implementation.
MOCK_METHOD2(Initialize, void(DataSource* data_source,
@@ -176,6 +178,7 @@ class MockVideoDecoder : public VideoDecoder {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// VideoDecoder implementation.
MOCK_METHOD2(Initialize, void(DemuxerStream* stream,
@@ -209,6 +212,7 @@ class MockAudioDecoder : public AudioDecoder {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// AudioDecoder implementation.
MOCK_METHOD2(Initialize, void(DemuxerStream* stream,
@@ -233,6 +237,7 @@ class MockVideoRenderer : public VideoRenderer {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// VideoRenderer implementation.
MOCK_METHOD2(Initialize, void(VideoDecoder* decoder,
@@ -253,6 +258,7 @@ class MockAudioRenderer : public AudioRenderer {
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, FilterCallback* callback));
+ MOCK_METHOD1(OnReceivedMessage, void(FilterMessage message));
// AudioRenderer implementation.
MOCK_METHOD2(Initialize, void(AudioDecoder* decoder,
@@ -365,6 +371,12 @@ ACTION_P2(SetBufferedBytes, filter, bytes) {
filter->host()->SetBufferedBytes(bytes);
}
+// Helper gmock action that calls BroadcastMessage() on behalf of the provided
+// filter.
+ACTION_P2(BroadcastMessage, filter, message) {
+ filter->host()->BroadcastMessage(message);
+}
+
} // namespace media
#endif // MEDIA_BASE_MOCK_FILTERS_H_
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index cc1c3b2..ccfce70 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -374,6 +374,15 @@ void PipelineImpl::SetStreaming(bool streaming) {
streaming_ = streaming;
}
+void PipelineImpl::BroadcastMessage(FilterMessage message) {
+ DCHECK(IsRunning());
+
+ // Broadcast the message on the message loop.
+ message_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &PipelineImpl::BroadcastMessageTask,
+ message));
+}
+
void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) {
DCHECK(IsRunning());
AutoLock auto_lock(lock_);
@@ -630,6 +639,17 @@ void PipelineImpl::SeekTask(base::TimeDelta time,
NewCallback(this, &PipelineImpl::OnFilterStateTransition));
}
+void PipelineImpl::BroadcastMessageTask(FilterMessage message) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
+ // Broadcast the message to all filters.
+ for (FilterVector::iterator iter = filters_.begin();
+ iter != filters_.end();
+ ++iter) {
+ (*iter)->OnReceivedMessage(message);
+ }
+}
+
void PipelineImpl::FilterStateTransitionTask() {
DCHECK_EQ(MessageLoop::current(), message_loop_);
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h
index aee1f59..4332cba 100644
--- a/media/base/pipeline_impl.h
+++ b/media/base/pipeline_impl.h
@@ -136,6 +136,7 @@ class PipelineImpl : public Pipeline, public FilterHost {
virtual void SetBufferedBytes(int64 buffered_bytes);
virtual void SetVideoSize(size_t width, size_t height);
virtual void SetStreaming(bool streamed);
+ virtual void BroadcastMessage(FilterMessage message);
// Method called during initialization to insert a mime type into the
// |rendered_mime_types_| set.
@@ -180,6 +181,9 @@ class PipelineImpl : public Pipeline, public FilterHost {
// Carries out notifying filters that we are seeking to a new timestamp.
void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback);
+ // Carries out message broadcasting on the message loop.
+ void BroadcastMessageTask(FilterMessage message);
+
// Carries out advancing to the next filter during Play()/Pause()/Seek().
void FilterStateTransitionTask();
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index 6400049..f3c0297 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -439,4 +439,45 @@ TEST_F(PipelineImplTest, Properties) {
pipeline_->GetBufferedTime().ToInternalValue());
}
+TEST_F(PipelineImplTest, BroadcastMessage) {
+ scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream =
+ new StrictMock<MockDemuxerStream>("audio/x-foo");
+ scoped_refptr<StrictMock<MockDemuxerStream> > video_stream =
+ new StrictMock<MockDemuxerStream>("video/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(audio_stream);
+ streams.push_back(video_stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams, base::TimeDelta());
+ InitializeAudioDecoder(audio_stream);
+ InitializeAudioRenderer();
+ InitializeVideoDecoder(video_stream);
+ InitializeVideoRenderer();
+
+ InitializePipeline();
+ EXPECT_TRUE(pipeline_->IsInitialized());
+ EXPECT_EQ(PIPELINE_OK, pipeline_->GetError());
+ EXPECT_TRUE(pipeline_->IsRendered(mime_type::kMajorTypeAudio));
+ EXPECT_TRUE(pipeline_->IsRendered(mime_type::kMajorTypeVideo));
+
+ EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(1.0f))
+ .WillOnce(BroadcastMessage(mocks_->audio_renderer(),
+ kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->data_source(),
+ OnReceivedMessage(kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->demuxer(),
+ OnReceivedMessage(kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->audio_decoder(),
+ OnReceivedMessage(kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->audio_renderer(),
+ OnReceivedMessage(kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->video_decoder(),
+ OnReceivedMessage(kMsgDisableAudio));
+ EXPECT_CALL(*mocks_->video_renderer(),
+ OnReceivedMessage(kMsgDisableAudio));
+
+ mocks_->audio_renderer()->SetPlaybackRate(1.0f);
+}
+
} // namespace media