diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-16 02:03:16 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-16 02:03:16 +0000 |
commit | 4c51bc66e6496234d5a3a7cbdfb1cf07cca2167e (patch) | |
tree | 03e28346b7752cec02e91ba925694548b49b8184 /media/base | |
parent | 9cadfb34adaf42ad30e398b24ab06e5bc587e57a (diff) | |
download | chromium_src-4c51bc66e6496234d5a3a7cbdfb1cf07cca2167e.zip chromium_src-4c51bc66e6496234d5a3a7cbdfb1cf07cca2167e.tar.gz chromium_src-4c51bc66e6496234d5a3a7cbdfb1cf07cca2167e.tar.bz2 |
Implement webkit media metrics in chromium.
This implements the chromium side of the webkit media statistics
feature.
A followup cl (in webkit) will wire the two sides together.
Patch by sjl@chromium.org:
http://codereview.chromium.org/6246091/
BUG=71255
TEST=media_unittests
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75050 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/filters.h | 16 | ||||
-rw-r--r-- | media/base/mock_filters.cc | 6 | ||||
-rw-r--r-- | media/base/mock_filters.h | 26 | ||||
-rw-r--r-- | media/base/pipeline.h | 17 | ||||
-rw-r--r-- | media/base/pipeline_impl.cc | 24 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 7 | ||||
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 14 |
7 files changed, 91 insertions, 19 deletions
diff --git a/media/base/filters.h b/media/base/filters.h index 84c466d..06f44c2 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -41,9 +41,14 @@ class DemuxerStream; class Filter; class FilterHost; +struct PipelineStatistics; + // Used for completing asynchronous methods. typedef Callback0::Type FilterCallback; +// Used for updating pipeline statistics. +typedef Callback1<const PipelineStatistics&>::Type StatisticsCallback; + class Filter : public base::RefCountedThreadSafe<Filter> { public: Filter(); @@ -193,7 +198,9 @@ class VideoDecoder : public Filter { // Initialize a VideoDecoder with the given DemuxerStream, executing the // callback upon completion. - virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; + // stats_callback is used to update global pipeline statistics. + virtual void Initialize(DemuxerStream* stream, FilterCallback* callback, + StatisticsCallback* stats_callback) = 0; // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver video frames at @@ -235,7 +242,9 @@ class AudioDecoder : public Filter { // Initialize a AudioDecoder with the given DemuxerStream, executing the // callback upon completion. - virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; + // stats_callback is used to update global pipeline statistics. + virtual void Initialize(DemuxerStream* stream, FilterCallback* callback, + StatisticsCallback* stats_callback) = 0; // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver buffers at @@ -272,7 +281,8 @@ class VideoRenderer : public Filter { // Initialize a VideoRenderer with the given VideoDecoder, executing the // callback upon completion. - virtual void Initialize(VideoDecoder* decoder, FilterCallback* callback) = 0; + virtual void Initialize(VideoDecoder* decoder, FilterCallback* callback, + StatisticsCallback* stats_callback) = 0; // Returns true if this filter has received and processed an end-of-stream // buffer. diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index 8aa5458..ebfa90c 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc @@ -65,6 +65,12 @@ void RunFilterCallback(::testing::Unused, FilterCallback* callback) { delete callback; } +void RunFilterCallback3(::testing::Unused, FilterCallback* callback, + ::testing::Unused) { + callback->Run(); + delete callback; +} + void DestroyFilterCallback(::testing::Unused, FilterCallback* callback) { delete callback; } diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 3439597..22eba74 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -17,6 +17,7 @@ #include "media/base/filters.h" #include "media/base/filter_collection.h" +#include "media/base/pipeline.h" #include "media/base/video_frame.h" #include "testing/gmock/include/gmock/gmock.h" @@ -143,8 +144,9 @@ class MockVideoDecoder : public VideoDecoder { MOCK_METHOD0(OnAudioRendererDisabled, void()); // VideoDecoder implementation. - MOCK_METHOD2(Initialize, void(DemuxerStream* stream, - FilterCallback* callback)); + MOCK_METHOD3(Initialize, void(DemuxerStream* stream, + FilterCallback* callback, + StatisticsCallback* stats_callback)); MOCK_METHOD0(media_format, const MediaFormat&()); MOCK_METHOD1(ProduceVideoFrame, void(scoped_refptr<VideoFrame>)); MOCK_METHOD0(ProvidesBuffer, bool()); @@ -172,8 +174,9 @@ class MockAudioDecoder : public AudioDecoder { MOCK_METHOD0(OnAudioRendererDisabled, void()); // AudioDecoder implementation. - MOCK_METHOD2(Initialize, void(DemuxerStream* stream, - FilterCallback* callback)); + MOCK_METHOD3(Initialize, void(DemuxerStream* stream, + FilterCallback* callback, + StatisticsCallback* stats_callback)); MOCK_METHOD0(media_format, const MediaFormat&()); MOCK_METHOD1(ProduceAudioSamples, void(scoped_refptr<Buffer>)); @@ -200,8 +203,9 @@ class MockVideoRenderer : public VideoRenderer { MOCK_METHOD0(OnAudioRendererDisabled, void()); // VideoRenderer implementation. - MOCK_METHOD2(Initialize, void(VideoDecoder* decoder, - FilterCallback* callback)); + MOCK_METHOD3(Initialize, void(VideoDecoder* decoder, + FilterCallback* callback, + StatisticsCallback* stats_callback)); MOCK_METHOD0(HasEnded, bool()); MOCK_METHOD1(ConsumeVideoFrame, void(scoped_refptr<VideoFrame> frame)); @@ -267,10 +271,12 @@ class MockFilterCollection { DISALLOW_COPY_AND_ASSIGN(MockFilterCollection); }; -// Helper gmock function that immediately executes and destroys the +// Helper gmock functions that immediately executes and destroys the // FilterCallback on behalf of the provided filter. Can be used when mocking // the Initialize() and Seek() methods. void RunFilterCallback(::testing::Unused, FilterCallback* callback); +void RunFilterCallback3(::testing::Unused, FilterCallback* callback, + ::testing::Unused); // Helper gmock function that immediately destroys the FilterCallback on behalf // of the provided filter. Can be used when mocking the Initialize() and Seek() @@ -311,6 +317,12 @@ ACTION_P(DisableAudioRenderer, filter) { filter->host()->DisableAudioRenderer(); } +// Helper mock statistics callback. +class MockStatisticsCallback { + public: + MOCK_METHOD1(OnStatistics, void(const media::PipelineStatistics& statistics)); +}; + } // namespace media #endif // MEDIA_BASE_MOCK_FILTERS_H_ diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 61a1110..0b87d29 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -42,6 +42,20 @@ enum PipelineError { DEMUXER_ERROR_COULD_NOT_CREATE_THREAD, }; +struct PipelineStatistics { + PipelineStatistics() : + audio_bytes_decoded(0), + video_bytes_decoded(0), + video_frames_decoded(0), + video_frames_dropped(0) { + } + + uint32 audio_bytes_decoded; // Should be uint64? + uint32 video_bytes_decoded; // Should be uint64? + uint32 video_frames_decoded; + uint32 video_frames_dropped; +}; + class FilterCollection; // Client-provided callbacks for various pipeline operations. Clients should @@ -172,6 +186,9 @@ class Pipeline : public base::RefCountedThreadSafe<Pipeline> { // operating correctly, this will return OK. virtual PipelineError GetError() const = 0; + // Gets the current pipeline statistics. + virtual PipelineStatistics GetStatistics() const = 0; + protected: // Only allow ourselves to be deleted by reference counting. friend class base::RefCountedThreadSafe<Pipeline>; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index a0fda64..76a07cd 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -274,6 +274,11 @@ PipelineError PipelineImpl::GetError() const { return error_; } +PipelineStatistics PipelineImpl::GetStatistics() const { + base::AutoLock auto_lock(lock_); + return statistics_; +} + void PipelineImpl::SetCurrentReadPosition(int64 offset) { base::AutoLock auto_lock(lock_); @@ -530,6 +535,15 @@ void PipelineImpl::OnTeardownStateTransition() { NewRunnableMethod(this, &PipelineImpl::TeardownStateTransitionTask)); } +// Called from any thread. +void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats) { + base::AutoLock auto_lock(lock_); + statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; + statistics_.video_bytes_decoded += stats.video_bytes_decoded; + statistics_.video_frames_decoded += stats.video_frames_decoded; + statistics_.video_frames_dropped += stats.video_frames_dropped; +} + void PipelineImpl::StartTask(FilterCollection* filter_collection, const std::string& url, PipelineCallback* start_callback) { @@ -1074,7 +1088,8 @@ bool PipelineImpl::InitializeAudioDecoder( pipeline_init_state_->audio_decoder_ = audio_decoder; audio_decoder->Initialize( stream, - NewCallback(this, &PipelineImpl::OnFilterInitialize)); + NewCallback(this, &PipelineImpl::OnFilterInitialize), + NewCallback(this, &PipelineImpl::OnUpdateStatistics)); return true; } @@ -1103,7 +1118,8 @@ bool PipelineImpl::InitializeVideoDecoder( pipeline_init_state_->video_decoder_ = video_decoder; video_decoder->Initialize( stream, - NewCallback(this, &PipelineImpl::OnFilterInitialize)); + NewCallback(this, &PipelineImpl::OnFilterInitialize), + NewCallback(this, &PipelineImpl::OnUpdateStatistics)); return true; } @@ -1147,7 +1163,9 @@ bool PipelineImpl::InitializeVideoRenderer( return false; video_renderer_->Initialize( - decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + decoder, + NewCallback(this, &PipelineImpl::OnFilterInitialize), + NewCallback(this, &PipelineImpl::OnUpdateStatistics)); return true; } diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 3611416..128e350 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -92,6 +92,7 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual bool IsStreaming() const; virtual bool IsLoaded() const; virtual PipelineError GetError() const; + virtual PipelineStatistics GetStatistics() const; private: // Pipeline states, as described above. @@ -186,6 +187,9 @@ class PipelineImpl : public Pipeline, public FilterHost { // Callback executed by filters when completing teardown operations. void OnTeardownStateTransition(); + // Callback executed by filters to update statistics. + void OnUpdateStatistics(const PipelineStatistics& stats); + // 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. @@ -405,6 +409,9 @@ class PipelineImpl : public Pipeline, public FilterHost { class PipelineInitState; scoped_ptr<PipelineInitState> pipeline_init_state_; + // Statistics. + PipelineStatistics statistics_; + FRIEND_TEST_ALL_PREFIXES(PipelineImplTest, GetBufferedTime); FRIEND_TEST_ALL_PREFIXES(PipelineImplTest, AudioStreamShorterThanVideo); diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 54e4dbf..45caef8 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -148,8 +148,9 @@ class PipelineImplTest : public ::testing::Test { // Sets up expectations to allow the video decoder to initialize. void InitializeVideoDecoder(MockDemuxerStream* stream) { - EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream, NotNull())) - .WillOnce(Invoke(&RunFilterCallback)); + EXPECT_CALL(*mocks_->video_decoder(), + Initialize(stream, NotNull(), NotNull())) + .WillOnce(Invoke(&RunFilterCallback3)); EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->video_decoder(), Seek(base::TimeDelta(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); @@ -159,8 +160,9 @@ class PipelineImplTest : public ::testing::Test { // Sets up expectations to allow the audio decoder to initialize. void InitializeAudioDecoder(MockDemuxerStream* stream) { - EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, NotNull())) - .WillOnce(Invoke(&RunFilterCallback)); + EXPECT_CALL(*mocks_->audio_decoder(), + Initialize(stream, NotNull(), NotNull())) + .WillOnce(Invoke(&RunFilterCallback3)); EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->audio_decoder(), Seek(base::TimeDelta(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); @@ -171,8 +173,8 @@ class PipelineImplTest : public ::testing::Test { // Sets up expectations to allow the video renderer to initialize. void InitializeVideoRenderer() { EXPECT_CALL(*mocks_->video_renderer(), - Initialize(mocks_->video_decoder(), NotNull())) - .WillOnce(Invoke(&RunFilterCallback)); + Initialize(mocks_->video_decoder(), NotNull(), NotNull())) + .WillOnce(Invoke(&RunFilterCallback3)); EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->video_renderer(), Seek(base::TimeDelta(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); |