diff options
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/filter_host.h | 4 | ||||
-rw-r--r-- | media/base/filters.h | 12 | ||||
-rw-r--r-- | media/base/mock_filter_host.h | 1 | ||||
-rw-r--r-- | media/base/mock_filters.h | 12 | ||||
-rw-r--r-- | media/base/pipeline_impl.cc | 20 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 4 | ||||
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 41 |
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 |