summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 02:03:16 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 02:03:16 +0000
commit4c51bc66e6496234d5a3a7cbdfb1cf07cca2167e (patch)
tree03e28346b7752cec02e91ba925694548b49b8184 /media/base
parent9cadfb34adaf42ad30e398b24ab06e5bc587e57a (diff)
downloadchromium_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.h16
-rw-r--r--media/base/mock_filters.cc6
-rw-r--r--media/base/mock_filters.h26
-rw-r--r--media/base/pipeline.h17
-rw-r--r--media/base/pipeline_impl.cc24
-rw-r--r--media/base/pipeline_impl.h7
-rw-r--r--media/base/pipeline_impl_unittest.cc14
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));