diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-17 01:34:26 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-17 01:34:26 +0000 |
commit | b3c4717987eb4a42ed2c24cf38df21ad1afbb7ed (patch) | |
tree | 8ac0e971649f0adf6caa787bbed29fbdc39aeb73 | |
parent | 9a491bd864f97e71a6f978477eedefc242621d8f (diff) | |
download | chromium_src-b3c4717987eb4a42ed2c24cf38df21ad1afbb7ed.zip chromium_src-b3c4717987eb4a42ed2c24cf38df21ad1afbb7ed.tar.gz chromium_src-b3c4717987eb4a42ed2c24cf38df21ad1afbb7ed.tar.bz2 |
Add frame hashing to PipelineIntegrationTests.
Also adds support for disabling frame dropping in the video renderer so
we can be sure we've seen every frame coming out.
Testing shows that there are issues with threading in the FFmpeg H264
decoder. Running with --video-threads=1 will yield different results
than running multithreaded.
We should probably increase the breadth of our basic playback testing
once we've got a better handle on threaded decoding in FFmpeg.
BUG=118688
TEST=media_unittests, ffmpeg_regression_tests.
Review URL: http://codereview.chromium.org/9716008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127320 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/ffmpeg/ffmpeg_regression_tests.cc | 152 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test.cc | 1 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test_base.cc | 29 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test_base.h | 14 | ||||
-rw-r--r-- | media/filters/video_renderer_base.cc | 7 | ||||
-rw-r--r-- | media/filters/video_renderer_base.h | 7 | ||||
-rw-r--r-- | media/filters/video_renderer_base_unittest.cc | 3 | ||||
-rw-r--r-- | media/tools/player_wtl/view.h | 10 | ||||
-rw-r--r-- | media/tools/player_x11/player_x11.cc | 3 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.cc | 3 |
10 files changed, 153 insertions, 76 deletions
diff --git a/media/ffmpeg/ffmpeg_regression_tests.cc b/media/ffmpeg/ffmpeg_regression_tests.cc index a145bdd..ae17dac 100644 --- a/media/ffmpeg/ffmpeg_regression_tests.cc +++ b/media/ffmpeg/ffmpeg_regression_tests.cc @@ -29,12 +29,14 @@ namespace media { struct RegressionTestData { RegressionTestData(const char* filename, PipelineStatus init_status, - PipelineStatus end_status) - : filename(filename), + PipelineStatus end_status, const char *md5) + : md5(md5), + filename(filename), init_status(init_status), end_status(end_status) { } + const char* md5; const char* filename; PipelineStatus init_status; PipelineStatus end_status; @@ -45,119 +47,146 @@ class FFmpegRegressionTest public PipelineIntegrationTestBase { }; -#define FFMPEG_TEST_CASE(name, fn, init_status, end_status) \ +#define FFMPEG_TEST_CASE(name, fn, init_status, end_status, md5) \ INSTANTIATE_TEST_CASE_P(name, FFmpegRegressionTest, \ testing::Values(RegressionTestData(fn, \ init_status, \ - end_status))); + end_status, \ + md5))); // Test cases from issues. -FFMPEG_TEST_CASE(Cr47325, "security/47325.mp4", PIPELINE_OK, PIPELINE_OK); -FFMPEG_TEST_CASE(Cr93620, "security/93620.ogg", PIPELINE_OK, PIPELINE_OK); +FFMPEG_TEST_CASE(Cr47325, "security/47325.mp4", PIPELINE_OK, PIPELINE_OK, + "bdb3976d86c531b43a4c9d43fa5e7dc2"); +FFMPEG_TEST_CASE(Cr93620, "security/93620.ogg", PIPELINE_OK, PIPELINE_OK, + kNullVideoHash); FFMPEG_TEST_CASE(Cr100492, "security/100492.webm", DECODER_ERROR_NOT_SUPPORTED, - DECODER_ERROR_NOT_SUPPORTED); -FFMPEG_TEST_CASE(Cr100543, "security/100543.webm", PIPELINE_OK, PIPELINE_OK); + DECODER_ERROR_NOT_SUPPORTED, kNullVideoHash); +FFMPEG_TEST_CASE(Cr100543, "security/100543.webm", PIPELINE_OK, PIPELINE_OK, + "17d7079458ef351b813c100ce87afbe6"); FFMPEG_TEST_CASE(Cr101458, "security/101458.webm", DECODER_ERROR_NOT_SUPPORTED, - DECODER_ERROR_NOT_SUPPORTED); -FFMPEG_TEST_CASE(Cr108416, "security/108416.webm", PIPELINE_OK, PIPELINE_OK); + DECODER_ERROR_NOT_SUPPORTED, kNullVideoHash); +FFMPEG_TEST_CASE(Cr108416, "security/108416.webm", PIPELINE_OK, PIPELINE_OK, + "d5559b43d7406aac33bfeafceaf86fe9"); FFMPEG_TEST_CASE(Cr110849, "security/110849.mkv", DEMUXER_ERROR_COULD_NOT_PARSE, - DEMUXER_ERROR_COULD_NOT_PARSE); + DEMUXER_ERROR_COULD_NOT_PARSE, kNullVideoHash); FFMPEG_TEST_CASE(Cr112384, "security/112384.webm", - DEMUXER_ERROR_COULD_NOT_PARSE, DEMUXER_ERROR_COULD_NOT_PARSE); + DEMUXER_ERROR_COULD_NOT_PARSE, DEMUXER_ERROR_COULD_NOT_PARSE, + kNullVideoHash); FFMPEG_TEST_CASE(Cr112670, "security/112670.mp4", PIPELINE_ERROR_DECODE, - PIPELINE_ERROR_DECODE); -FFMPEG_TEST_CASE(Cr112976, "security/112976.ogg", PIPELINE_OK, PIPELINE_OK); + PIPELINE_ERROR_DECODE, kNullVideoHash); +FFMPEG_TEST_CASE(Cr112976, "security/112976.ogg", PIPELINE_OK, PIPELINE_OK, + kNullVideoHash); FFMPEG_TEST_CASE(Cr116927, "security/116927.ogv", PIPELINE_ERROR_DECODE, - PIPELINE_ERROR_DECODE); + PIPELINE_ERROR_DECODE, kNullVideoHash); // General MKV test cases. FFMPEG_TEST_CASE(MKV_0, "security/nested_tags_lang.mka.627.628", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, kNullVideoHash); FFMPEG_TEST_CASE(MKV_1, "security/nested_tags_lang.mka.667.628", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, kNullVideoHash); // General MP4 test cases. -FFMPEG_TEST_CASE(MP4_0, "security/aac.10419.mp4", PIPELINE_OK, PIPELINE_OK); +FFMPEG_TEST_CASE(MP4_0, "security/aac.10419.mp4", PIPELINE_OK, PIPELINE_OK, + kNullVideoHash); FFMPEG_TEST_CASE(MP4_1, "security/clockh264aac_200021889.mp4", - DEMUXER_ERROR_COULD_NOT_OPEN, DEMUXER_ERROR_COULD_NOT_OPEN); + DEMUXER_ERROR_COULD_NOT_OPEN, DEMUXER_ERROR_COULD_NOT_OPEN, + kNullVideoHash); FFMPEG_TEST_CASE(MP4_2, "security/clockh264aac_200701257.mp4", PIPELINE_OK, - PIPELINE_OK); -FFMPEG_TEST_CASE(MP4_4, "security/clockh264aac_301350139.mp4", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, kNullVideoHash); FFMPEG_TEST_CASE(MP4_5, "security/clockh264aac_3022500.mp4", DEMUXER_ERROR_NO_SUPPORTED_STREAMS, - DEMUXER_ERROR_NO_SUPPORTED_STREAMS); + DEMUXER_ERROR_NO_SUPPORTED_STREAMS, kNullVideoHash); FFMPEG_TEST_CASE(MP4_6, "security/clockh264aac_344289.mp4", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, kNullVideoHash); FFMPEG_TEST_CASE(MP4_7, "security/clockh264mp3_187697.mp4", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, kNullVideoHash); FFMPEG_TEST_CASE(MP4_8, "security/h264.705767.mp4", PIPELINE_ERROR_DECODE, - PIPELINE_ERROR_DECODE); + PIPELINE_ERROR_DECODE, kNullVideoHash); FFMPEG_TEST_CASE(MP4_9, "security/smclockmp4aac_1_0.mp4", - DEMUXER_ERROR_COULD_NOT_OPEN, DEMUXER_ERROR_COULD_NOT_OPEN); + DEMUXER_ERROR_COULD_NOT_OPEN, DEMUXER_ERROR_COULD_NOT_OPEN, + kNullVideoHash); // General OGV test cases. FFMPEG_TEST_CASE(OGV_1, "security/out.163.ogv", DECODER_ERROR_NOT_SUPPORTED, - DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, kNullVideoHash); FFMPEG_TEST_CASE(OGV_2, "security/out.391.ogv", DECODER_ERROR_NOT_SUPPORTED, - DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, kNullVideoHash); FFMPEG_TEST_CASE(OGV_5, "security/smclocktheora_1_0.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_7, "security/smclocktheora_1_102.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_8, "security/smclocktheora_1_104.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_9, "security/smclocktheora_1_110.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_10, "security/smclocktheora_1_179.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_11, "security/smclocktheora_1_20.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_12, "security/smclocktheora_1_723.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_14, "security/smclocktheora_2_10405.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_15, "security/smclocktheora_2_10619.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_16, "security/smclocktheora_2_1075.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_17, "security/vorbis.482086.ogv", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(OGV_18, "security/wav.711.ogv", DECODER_ERROR_NOT_SUPPORTED, - DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, kNullVideoHash); // General WebM test cases. -FFMPEG_TEST_CASE(WEBM_1, "security/no-bug.webm", PIPELINE_OK, PIPELINE_OK); +FFMPEG_TEST_CASE(WEBM_1, "security/no-bug.webm", PIPELINE_OK, PIPELINE_OK, + "20536f9ce571c5830bb7c782584223fd"); FFMPEG_TEST_CASE(WEBM_2, "security/uninitialize.webm", PIPELINE_ERROR_DECODE, - PIPELINE_ERROR_DECODE); + PIPELINE_ERROR_DECODE, kNullVideoHash); FFMPEG_TEST_CASE(WEBM_3, "security/out.webm.139771.2965", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(WEBM_4, "security/out.webm.68798.1929", - DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED); + DECODER_ERROR_NOT_SUPPORTED, DECODER_ERROR_NOT_SUPPORTED, + kNullVideoHash); FFMPEG_TEST_CASE(WEBM_5, "content/frame_size_change.webm", PIPELINE_OK, - PIPELINE_OK); + PIPELINE_OK, "0e89c98da281067d58f8459eca0f35ba"); FFMPEG_TEST_CASE(WEBM_6, "security/117912.webm", DEMUXER_ERROR_COULD_NOT_OPEN, - DEMUXER_ERROR_COULD_NOT_OPEN); + DEMUXER_ERROR_COULD_NOT_OPEN, kNullVideoHash); -// Flaky, maybe larger issues. All eventually fail in the browser. +// Flaky under threading, maybe larger issues. Values were set with +// --video-threads=1 under the hope that they may one day pass with threading. FFMPEG_TEST_CASE(FLAKY_Cr99652, "security/99652.webm", PIPELINE_OK, - PIPELINE_ERROR_DECODE); + PIPELINE_ERROR_DECODE, "43db203056009b7ff3ac145a3488807a"); FFMPEG_TEST_CASE(FLAKY_Cr100464, "security/100464.webm", PIPELINE_OK, - PIPELINE_ERROR_DECODE); + PIPELINE_OK, "985cff66e292f3064bf853e8943fd8c8"); +FFMPEG_TEST_CASE(FLAKY_OGV_3, "security/smclock_1_0.ogv", PIPELINE_OK, + PIPELINE_OK, "6923c1e1c6354d8e00cd57b7b66c9b02"); +FFMPEG_TEST_CASE(FLAKY_OGV_4, "security/smclock.ogv.1.0.ogv", + PIPELINE_OK, PIPELINE_OK, "6923c1e1c6354d8e00cd57b7b66c9b02"); +FFMPEG_TEST_CASE(FLAKY_OGV_13, "security/smclocktheora_1_790.ogv", + PIPELINE_OK, PIPELINE_OK, "6923c1e1c6354d8e00cd57b7b66c9b02"); +FFMPEG_TEST_CASE(FLAKY_MP4_4, "security/clockh264aac_301350139.mp4", + PIPELINE_OK, PIPELINE_OK, "87c110e9d0bbaf7a2d9757dc8e2ce9d7"); + +// Flaky due to other non-threading related reasons: FFMPEG_TEST_CASE(FLAKY_Cr111342, "security/111342.ogm", PIPELINE_OK, - PIPELINE_ERROR_DECODE); -FFMPEG_TEST_CASE(FLAKY_MP4_3, "security/clockh264aac_300413969.mp4", - PIPELINE_OK, PIPELINE_ERROR_DECODE); + PIPELINE_ERROR_DECODE, "a79faa6f4ccb1734e2143d5d37482448"); FFMPEG_TEST_CASE(FLAKY_OGV_0, "security/big_dims.ogv", PIPELINE_OK, - PIPELINE_ERROR_DECODE); -FFMPEG_TEST_CASE(FLAKY_OGV_3, "security/smclock_1_0.ogv", PIPELINE_ERROR_DECODE, - PIPELINE_ERROR_DECODE); -FFMPEG_TEST_CASE(FLAKY_OGV_4, "security/smclock.ogv.1.0.ogv", - PIPELINE_OK, PIPELINE_ERROR_DECODE); + PIPELINE_OK, "c5c23c1e0958a4a4756c35d045f94e0e"); FFMPEG_TEST_CASE(FLAKY_OGV_6, "security/smclocktheora_1_10000.ogv", - PIPELINE_OK, PIPELINE_ERROR_DECODE); -FFMPEG_TEST_CASE(FLAKY_OGV_13, "security/smclocktheora_1_790.ogv", - PIPELINE_ERROR_DECODE, PIPELINE_ERROR_DECODE); + PIPELINE_OK, PIPELINE_OK, "cdce61e17a8058c6ac5fca92cd3e4a86"); +FFMPEG_TEST_CASE(FLAKY_MP4_3, "security/clockh264aac_300413969.mp4", + PIPELINE_OK, PIPELINE_OK, "3781a90401195dfb6ad3e4dbc4888f4f"); // Hangs. http://crbug.com/117038 // FFMPEG_TEST_CASE(WEBM_0, "security/memcpy.webm", PIPELINE_OK, PIPELINE_OK); @@ -176,6 +205,7 @@ TEST_P(FFmpegRegressionTest, BasicPlayback) { ASSERT_FALSE(Start(GetTestDataURL(GetParam().filename), GetParam().init_status)); } + ASSERT_EQ(GetVideoHash(), GetParam().md5); } } // namespace media diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc index e954b9f..d8d5f72 100644 --- a/media/filters/pipeline_integration_test.cc +++ b/media/filters/pipeline_integration_test.cc @@ -127,6 +127,7 @@ TEST_F(PipelineIntegrationTest, BasicPlayback) { Play(); ASSERT_TRUE(WaitUntilOnEnded()); + ASSERT_EQ(GetVideoHash(), "923ce08df753797b642df55a46a1dcfb"); } // TODO(xhwang): Enable this test when AddKey is integrated into pipeline. diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc index eeb5cb1..e421963 100644 --- a/media/filters/pipeline_integration_test_base.cc +++ b/media/filters/pipeline_integration_test_base.cc @@ -5,6 +5,7 @@ #include "media/filters/pipeline_integration_test_base.h" #include "base/bind.h" +#include "base/string_piece.h" #include "media/base/media_log.h" #include "media/filters/chunk_demuxer_factory.h" #include "media/filters/ffmpeg_audio_decoder.h" @@ -12,7 +13,6 @@ #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source.h" #include "media/filters/null_audio_renderer.h" -#include "media/filters/video_renderer_base.h" using ::testing::AnyNumber; @@ -23,7 +23,7 @@ PipelineIntegrationTestBase::PipelineIntegrationTestBase() pipeline_(new Pipeline(&message_loop_, new MediaLog())), ended_(false), pipeline_status_(PIPELINE_OK) { - EXPECT_CALL(*this, OnVideoRendererPaint()).Times(AnyNumber()); + base::MD5Init(&md5_context_); EXPECT_CALL(*this, OnSetOpaque(true)).Times(AnyNumber()); } @@ -170,13 +170,34 @@ PipelineIntegrationTestBase::CreateFilterCollection( base::Bind(&MessageLoopFactory::GetMessageLoop, base::Unretained(message_loop_factory_.get()), "VideoDecoderThread"))); - collection->AddVideoRenderer(new VideoRendererBase( + renderer_ = new VideoRendererBase( base::Bind(&PipelineIntegrationTestBase::OnVideoRendererPaint, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnSetOpaque, - base::Unretained(this)))); + base::Unretained(this)), + false); + collection->AddVideoRenderer(renderer_); collection->AddAudioRenderer(new NullAudioRenderer()); return collection.Pass(); } +void PipelineIntegrationTestBase::OnVideoRendererPaint() { + scoped_refptr<VideoFrame> frame; + renderer_->GetCurrentFrame(&frame); + if (frame) + base::MD5Update( + &md5_context_, + base::StringPiece( + reinterpret_cast<char*>(frame->data(VideoFrame::kRGBPlane)), + (frame->rows(VideoFrame::kRGBPlane) * + frame->row_bytes(VideoFrame::kRGBPlane)))); + renderer_->PutCurrentFrame(frame); +} + +std::string PipelineIntegrationTestBase::GetVideoHash() { + base::MD5Digest digest; + base::MD5Final(&digest, &md5_context_); + return base::MD5DigestToBase16(digest); +} + } // namespace media diff --git a/media/filters/pipeline_integration_test_base.h b/media/filters/pipeline_integration_test_base.h index 06e6bf1..dfa231b 100644 --- a/media/filters/pipeline_integration_test_base.h +++ b/media/filters/pipeline_integration_test_base.h @@ -6,14 +6,19 @@ #define MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_ #include "base/message_loop.h" +#include "base/md5.h" #include "media/base/filter_collection.h" #include "media/base/message_loop_factory.h" #include "media/base/pipeline.h" #include "media/filters/chunk_demuxer.h" +#include "media/filters/video_renderer_base.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { +// Empty MD5 hash string. Used to verify videos which have decoded no frames. +static const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e"; + // Integration tests for Pipeline. Real demuxers, real decoders, and // base renderer implementations are used to verify pipeline functionality. The // renderers used in these tests rely heavily on the AudioRendererBase & @@ -40,10 +45,17 @@ class PipelineIntegrationTestBase { scoped_ptr<FilterCollection> CreateFilterCollection( ChunkDemuxerClient* client); + // Returns the MD5 hash of all video frames seen. Should only be called once + // after playback completes. First time hashes should be generated with + // --video-threads=1 to ensure correctness. + std::string GetVideoHash(); + protected: MessageLoop message_loop_; + base::MD5Context md5_context_; scoped_ptr<MessageLoopFactory> message_loop_factory_; scoped_refptr<Pipeline> pipeline_; + scoped_refptr<VideoRendererBase> renderer_; bool ended_; PipelineStatus pipeline_status_; @@ -55,8 +67,8 @@ class PipelineIntegrationTestBase { void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time); scoped_ptr<FilterCollection> CreateFilterCollection( scoped_ptr<DemuxerFactory> demuxer_factory); + void OnVideoRendererPaint(); - MOCK_METHOD0(OnVideoRendererPaint, void()); MOCK_METHOD1(OnSetOpaque, void(bool)); }; diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index b4c2568..0ecb586 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -15,13 +15,15 @@ namespace media { VideoRendererBase::VideoRendererBase(const base::Closure& paint_cb, - const SetOpaqueCB& set_opaque_cb) + const SetOpaqueCB& set_opaque_cb, + bool drop_frames) : frame_available_(&lock_), state_(kUninitialized), thread_(base::kNullThreadHandle), pending_read_(false), pending_paint_(false), pending_paint_with_last_available_(false), + drop_frames_(drop_frames), playback_rate_(0), read_cb_(base::Bind(&VideoRendererBase::FrameReady, base::Unretained(this))), @@ -259,6 +261,9 @@ void VideoRendererBase::ThreadMain() { if (remaining_time.InMicroseconds() > 0) break; + if (!drop_frames_) + break; + // Frame dropped: read again. ++frames_dropped; ready_frames_.pop_front(); diff --git a/media/filters/video_renderer_base.h b/media/filters/video_renderer_base.h index fe69571..13e344a 100644 --- a/media/filters/video_renderer_base.h +++ b/media/filters/video_renderer_base.h @@ -37,10 +37,13 @@ class MEDIA_EXPORT VideoRendererBase // instead post a task to a common/worker thread to handle rendering. Slowing // down the video thread may result in losing synchronization with audio. // + // Setting |drop_frames_| to true causes the renderer to drop expired frames. + // // TODO(scherkus): pass the VideoFrame* to this callback and remove // Get/PutCurrentFrame() http://crbug.com/108435 VideoRendererBase(const base::Closure& paint_cb, - const SetOpaqueCB& set_opaque_cb); + const SetOpaqueCB& set_opaque_cb, + bool drop_frames); virtual ~VideoRendererBase(); // Filter implementation. @@ -179,6 +182,8 @@ class MEDIA_EXPORT VideoRendererBase bool pending_paint_; bool pending_paint_with_last_available_; + bool drop_frames_; + float playback_rate_; // Filter callbacks. diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc index 30c804b..40e0d6a 100644 --- a/media/filters/video_renderer_base_unittest.cc +++ b/media/filters/video_renderer_base_unittest.cc @@ -54,7 +54,8 @@ class VideoRendererBaseTest : public ::testing::Test { renderer_ = new VideoRendererBase( base::Bind(&VideoRendererBaseTest::Paint, base::Unretained(this)), base::Bind(&VideoRendererBaseTest::SetOpaqueCBWasCalled, - base::Unretained(this))); + base::Unretained(this)), + true); renderer_->set_host(&host_); EXPECT_CALL(*decoder_, natural_size()) diff --git a/media/tools/player_wtl/view.h b/media/tools/player_wtl/view.h index c4ad454..7519b09 100644 --- a/media/tools/player_wtl/view.h +++ b/media/tools/player_wtl/view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -43,10 +43,10 @@ class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> { view_size_ = 2; // Normal size. view_rotate_ = media::ROTATE_0; view_filter_ = media::FILTER_NONE; - renderer_ = new media::VideoRendererBase(base::Bind( - &WtlVideoWindow::InvalidateWrapper, base::Unretained(this)), - base::Bind( - &WtlVideoWindow::SetOpaque, base::Unretained(this))); + renderer_ = new media::VideoRendererBase( + base::Bind(&WtlVideoWindow::InvalidateWrapper, base::Unretained(this)), + base::Bind(&WtlVideoWindow::SetOpaque, base::Unretained(this)), + true); last_frame_ = NULL; hbmp_ = NULL; } diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 5220fd5..8da75de 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -135,7 +135,8 @@ bool InitPipeline(MessageLoop* message_loop, // Create our video renderer and save a reference to it for painting. g_video_renderer = new media::VideoRendererBase( base::Bind(&Paint, paint_message_loop, paint_cb), - base::Bind(&SetOpaque)); + base::Bind(&SetOpaque), + true); collection->AddVideoRenderer(g_video_renderer); collection->AddAudioRenderer(new media::NullAudioRenderer()); diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 84d7766..c988faa 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -149,7 +149,8 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( scoped_refptr<media::VideoRendererBase> video_renderer = new media::VideoRendererBase( base::Bind(&WebMediaPlayerProxy::Repaint, proxy_), - base::Bind(&WebMediaPlayerProxy::SetOpaque, proxy_.get())); + base::Bind(&WebMediaPlayerProxy::SetOpaque, proxy_.get()), + true); filter_collection_->AddVideoRenderer(video_renderer); proxy_->set_frame_provider(video_renderer); |