diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-06 06:58:38 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-06 06:58:38 +0000 |
commit | 1848da07b207f323d31883e565cdf1229137a075 (patch) | |
tree | 5240eecce5de5266f3a70e49fbedaaa49fd130fc /media | |
parent | 300ba0c4a5d7fc82c0ab0952ff3d5596f727f611 (diff) | |
download | chromium_src-1848da07b207f323d31883e565cdf1229137a075.zip chromium_src-1848da07b207f323d31883e565cdf1229137a075.tar.gz chromium_src-1848da07b207f323d31883e565cdf1229137a075.tar.bz2 |
Replace WaitableEvents and ConditionalVariables in VideoRendererBase tests with MessageLoop.
Review URL: https://chromiumcodereview.appspot.com/11316293
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171438 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/mock_callback.cc | 43 | ||||
-rw-r--r-- | media/base/mock_callback.h | 36 | ||||
-rw-r--r-- | media/base/pipeline_unittest.cc | 2 | ||||
-rw-r--r-- | media/base/test_helpers.cc | 99 | ||||
-rw-r--r-- | media/base/test_helpers.h | 57 | ||||
-rw-r--r-- | media/filters/audio_renderer_impl_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/chunk_demuxer_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/decrypting_audio_decoder_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/decrypting_demuxer_stream_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/decrypting_video_decoder_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/ffmpeg_audio_decoder_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer_unittest.cc | 44 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/file_data_source_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/video_renderer_base_unittest.cc | 566 | ||||
-rw-r--r-- | media/media.gyp | 4 |
16 files changed, 432 insertions, 435 deletions
diff --git a/media/base/mock_callback.cc b/media/base/mock_callback.cc deleted file mode 100644 index e9d2da3..0000000 --- a/media/base/mock_callback.cc +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -#include "media/base/mock_callback.h" - -#include "base/bind.h" - -using ::testing::_; -using ::testing::StrictMock; - -namespace media { - -MockClosure::MockClosure() {} -MockClosure::~MockClosure() {} - -base::Closure NewExpectedClosure() { - StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); - EXPECT_CALL(*callback, Run()); - return base::Bind(&MockClosure::Run, callback); -} - -class MockStatusCB : public base::RefCountedThreadSafe<MockStatusCB> { - public: - MockStatusCB() {} - MOCK_METHOD1(Run, void(PipelineStatus)); - - protected: - friend class base::RefCountedThreadSafe<MockStatusCB>; - virtual ~MockStatusCB() {} - - private: - DISALLOW_COPY_AND_ASSIGN(MockStatusCB); -}; - -base::Callback<void(PipelineStatus)> NewExpectedStatusCB( - PipelineStatus status) { - StrictMock<MockStatusCB>* callback = new StrictMock<MockStatusCB>(); - EXPECT_CALL(*callback, Run(status)); - return base::Bind(&MockStatusCB::Run, callback); -} - -} // namespace media diff --git a/media/base/mock_callback.h b/media/base/mock_callback.h deleted file mode 100644 index 00d8276..0000000 --- a/media/base/mock_callback.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -#ifndef MEDIA_BASE_MOCK_CALLBACK_H_ -#define MEDIA_BASE_MOCK_CALLBACK_H_ - -#include "base/callback.h" -#include "media/base/pipeline_status.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace media { - -// Utility mock for testing methods expecting Closures. See -// NewExpectedClosure() below for a helper suitable when expectation order is -// not checked (or when the expectation can be set at mock construction time). -class MockClosure : public base::RefCountedThreadSafe<MockClosure> { - public: - MockClosure(); - MOCK_METHOD0(Run, void()); - - protected: - friend class base::RefCountedThreadSafe<MockClosure>; - virtual ~MockClosure(); - - private: - DISALLOW_COPY_AND_ASSIGN(MockClosure); -}; - -// Return a callback that expects to be run once. -base::Closure NewExpectedClosure(); -base::Callback<void(PipelineStatus)> NewExpectedStatusCB(PipelineStatus status); - -} // namespace media - -#endif // MEDIA_BASE_MOCK_CALLBACK_H_ diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index 085aa8a..a12f91c 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -11,9 +11,9 @@ #include "media/base/clock.h" #include "media/base/gmock_callback_support.h" #include "media/base/media_log.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" #include "media/base/pipeline.h" +#include "media/base/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/size.h" diff --git a/media/base/test_helpers.cc b/media/base/test_helpers.cc new file mode 100644 index 0000000..862c9d4 --- /dev/null +++ b/media/base/test_helpers.cc @@ -0,0 +1,99 @@ +// 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. + +#include "media/base/test_helpers.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "base/test/test_timeouts.h" +#include "base/timer.h" +#include "media/base/bind_to_loop.h" + +using ::testing::_; +using ::testing::StrictMock; + +namespace media { + +// Utility mock for testing methods expecting Closures and PipelineStatusCBs. +class MockCallback : public base::RefCountedThreadSafe<MockCallback> { + public: + MockCallback(); + MOCK_METHOD0(Run, void()); + MOCK_METHOD1(RunWithStatus, void(PipelineStatus)); + + protected: + friend class base::RefCountedThreadSafe<MockCallback>; + virtual ~MockCallback(); + + private: + DISALLOW_COPY_AND_ASSIGN(MockCallback); +}; + +MockCallback::MockCallback() {} +MockCallback::~MockCallback() {} + +base::Closure NewExpectedClosure() { + StrictMock<MockCallback>* callback = new StrictMock<MockCallback>(); + EXPECT_CALL(*callback, Run()); + return base::Bind(&MockCallback::Run, callback); +} + +PipelineStatusCB NewExpectedStatusCB(PipelineStatus status) { + StrictMock<MockCallback>* callback = new StrictMock<MockCallback>(); + EXPECT_CALL(*callback, RunWithStatus(status)); + return base::Bind(&MockCallback::RunWithStatus, callback); +} + +WaitableMessageLoopEvent::WaitableMessageLoopEvent() + : message_loop_(MessageLoop::current()), + signaled_(false), + status_(PIPELINE_OK) { + DCHECK(message_loop_); +} + +WaitableMessageLoopEvent::~WaitableMessageLoopEvent() {} + +base::Closure WaitableMessageLoopEvent::GetClosure() { + DCHECK_EQ(message_loop_, MessageLoop::current()); + return BindToLoop(message_loop_->message_loop_proxy(), base::Bind( + &WaitableMessageLoopEvent::OnCallback, base::Unretained(this), + PIPELINE_OK)); +} + +PipelineStatusCB WaitableMessageLoopEvent::GetPipelineStatusCB() { + DCHECK_EQ(message_loop_, MessageLoop::current()); + return BindToLoop(message_loop_->message_loop_proxy(), base::Bind( + &WaitableMessageLoopEvent::OnCallback, base::Unretained(this))); +} + +void WaitableMessageLoopEvent::RunAndWait() { + RunAndWaitForStatus(PIPELINE_OK); +} + +void WaitableMessageLoopEvent::RunAndWaitForStatus(PipelineStatus expected) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + base::Timer timer(false, false); + timer.Start(FROM_HERE, TestTimeouts::action_timeout(), base::Bind( + &WaitableMessageLoopEvent::OnTimeout, base::Unretained(this))); + + DCHECK(!signaled_) << "Already signaled"; + message_loop_->Run(); + EXPECT_TRUE(signaled_); + EXPECT_EQ(expected, status_); +} + +void WaitableMessageLoopEvent::OnCallback(PipelineStatus status) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + signaled_ = true; + status_ = status; + message_loop_->QuitWhenIdle(); +} + +void WaitableMessageLoopEvent::OnTimeout() { + DCHECK_EQ(message_loop_, MessageLoop::current()); + ADD_FAILURE() << "Timed out waiting for message loop to quit"; + message_loop_->QuitWhenIdle(); +} + +} // namespace media diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h new file mode 100644 index 0000000..1c38694 --- /dev/null +++ b/media/base/test_helpers.h @@ -0,0 +1,57 @@ +// 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. + +#ifndef MEDIA_BASE_TEST_HELPERS_H_ +#define MEDIA_BASE_TEST_HELPERS_H_ + +#include "base/callback.h" +#include "media/base/pipeline_status.h" +#include "testing/gmock/include/gmock/gmock.h" + +class MessageLoop; + +namespace media { + +// Return a callback that expects to be run once. +base::Closure NewExpectedClosure(); +PipelineStatusCB NewExpectedStatusCB(PipelineStatus status); + +// Helper class for running a message loop until a callback has run. Useful for +// testing classes that run on more than a single thread. +// +// Events are intended for single use and cannot be reset. +class WaitableMessageLoopEvent { + public: + WaitableMessageLoopEvent(); + ~WaitableMessageLoopEvent(); + + // Returns a thread-safe closure that will signal |this| when executed. + base::Closure GetClosure(); + PipelineStatusCB GetPipelineStatusCB(); + + // Runs the current message loop until |this| has been signaled. + // + // Fails the test if the timeout is reached. + void RunAndWait(); + + // Runs the current message loop until |this| has been signaled and asserts + // that the |expected| status was received. + // + // Fails the test if the timeout is reached. + void RunAndWaitForStatus(PipelineStatus expected); + + private: + void OnCallback(PipelineStatus status); + void OnTimeout(); + + MessageLoop* message_loop_; + bool signaled_; + PipelineStatus status_; + + DISALLOW_COPY_AND_ASSIGN(WaitableMessageLoopEvent); +}; + +} // namespace media + +#endif // MEDIA_BASE_TEST_HELPERS_H_ diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc index 4f741d9..23f2078 100644 --- a/media/filters/audio_renderer_impl_unittest.cc +++ b/media/filters/audio_renderer_impl_unittest.cc @@ -11,8 +11,8 @@ #include "media/base/data_buffer.h" #include "media/base/gmock_callback_support.h" #include "media/base/mock_audio_renderer_sink.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" #include "media/filters/audio_renderer_impl.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index 8f4fa4e..3fbfa6b 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -6,9 +6,9 @@ #include "base/message_loop.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" -#include "media/base/mock_callback.h" #include "media/base/mock_demuxer_host.h" #include "media/base/test_data_util.h" +#include "media/base/test_helpers.h" #include "media/filters/chunk_demuxer.h" #include "media/webm/cluster_builder.h" #include "media/webm/webm_constants.h" diff --git a/media/filters/decrypting_audio_decoder_unittest.cc b/media/filters/decrypting_audio_decoder_unittest.cc index b4c2a7b..a6a897f 100644 --- a/media/filters/decrypting_audio_decoder_unittest.cc +++ b/media/filters/decrypting_audio_decoder_unittest.cc @@ -13,8 +13,8 @@ #include "media/base/decoder_buffer.h" #include "media/base/decrypt_config.h" #include "media/base/gmock_callback_support.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" #include "media/filters/decrypting_audio_decoder.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/media/filters/decrypting_demuxer_stream_unittest.cc b/media/filters/decrypting_demuxer_stream_unittest.cc index f952d82..3e85d7f 100644 --- a/media/filters/decrypting_demuxer_stream_unittest.cc +++ b/media/filters/decrypting_demuxer_stream_unittest.cc @@ -11,8 +11,8 @@ #include "media/base/decoder_buffer.h" #include "media/base/decrypt_config.h" #include "media/base/gmock_callback_support.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" #include "media/filters/decrypting_demuxer_stream.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/media/filters/decrypting_video_decoder_unittest.cc b/media/filters/decrypting_video_decoder_unittest.cc index efaf4d8..3007637 100644 --- a/media/filters/decrypting_video_decoder_unittest.cc +++ b/media/filters/decrypting_video_decoder_unittest.cc @@ -11,8 +11,8 @@ #include "media/base/decoder_buffer.h" #include "media/base/decrypt_config.h" #include "media/base/gmock_callback_support.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" #include "media/base/video_frame.h" #include "media/filters/decrypting_video_decoder.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/media/filters/ffmpeg_audio_decoder_unittest.cc b/media/filters/ffmpeg_audio_decoder_unittest.cc index 2ad7ab8..ead293d 100644 --- a/media/filters/ffmpeg_audio_decoder_unittest.cc +++ b/media/filters/ffmpeg_audio_decoder_unittest.cc @@ -8,9 +8,9 @@ #include "base/message_loop.h" #include "base/stringprintf.h" #include "media/base/decoder_buffer.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" #include "media/base/test_data_util.h" +#include "media/base/test_helpers.h" #include "media/ffmpeg/ffmpeg_common.h" #include "media/filters/ffmpeg_audio_decoder.h" #include "media/filters/ffmpeg_glue.h" diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 9ce8659..e0dc371 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -11,8 +11,8 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/threading/thread.h" -#include "media/base/mock_callback.h" #include "media/base/mock_demuxer_host.h" +#include "media/base/test_helpers.h" #include "media/ffmpeg/ffmpeg_common.h" #include "media/filters/ffmpeg_demuxer.h" #include "media/filters/file_data_source.h" @@ -87,8 +87,9 @@ class FFmpegDemuxerTest : public testing::Test { void InitializeDemuxer() { EXPECT_CALL(host_, SetDuration(_)); - demuxer_->Initialize(&host_, NewStatusCB(PIPELINE_OK)); - message_loop_.Run(); + WaitableMessageLoopEvent event; + demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(PIPELINE_OK); } MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); @@ -122,18 +123,6 @@ class FFmpegDemuxerTest : public testing::Test { location, size, timestampInMicroseconds); } - PipelineStatusCB NewStatusCB(PipelineStatus expected) { - return base::Bind(&FFmpegDemuxerTest::OnStatusDone, - base::Unretained(this), expected); - } - - void OnStatusDone(PipelineStatus expected, PipelineStatus status) { - EXPECT_EQ(expected, status); - - DCHECK_EQ(&message_loop_, MessageLoop::current()); - message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); - } - // Accessor to demuxer internals. void set_duration_known(bool duration_known) { demuxer_->duration_known_ = duration_known; @@ -192,8 +181,9 @@ class FFmpegDemuxerTest : public testing::Test { TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { // Simulate avformat_open_input() failing. CreateDemuxer("ten_byte_file"); - demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); - message_loop_.Run(); + WaitableMessageLoopEvent event; + demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN); } // TODO(acolwell): Uncomment this test when we discover a file that passes @@ -209,15 +199,17 @@ TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { // Open a file with no streams whatsoever. CreateDemuxer("no_streams.webm"); - demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); - message_loop_.Run(); + WaitableMessageLoopEvent event; + demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); } TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { // Open a file containing streams but none of which are audio/video streams. CreateDemuxer("no_audio_video.webm"); - demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); - message_loop_.Run(); + WaitableMessageLoopEvent event; + demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); } TEST_F(FFmpegDemuxerTest, Initialize_Successful) { @@ -380,9 +372,10 @@ TEST_F(FFmpegDemuxerTest, Seek) { message_loop_.Run(); // Issue a simple forward seek, which should discard queued packets. + WaitableMessageLoopEvent event; demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000), - NewStatusCB(PIPELINE_OK)); - message_loop_.Run(); + event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(PIPELINE_OK); // Audio read #1. audio->Read(NewReadCB(FROM_HERE, 145, 803000)); @@ -553,9 +546,10 @@ TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) { message_loop_.Run(); // Issue a simple forward seek, which should discard queued packets. + WaitableMessageLoopEvent event; demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000), - NewStatusCB(PIPELINE_OK)); - message_loop_.Run(); + event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(PIPELINE_OK); // Audio read #1. audio->Read(NewReadCB(FROM_HERE, 40, 2403000)); diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index ba6e114..309f08f 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -14,9 +14,9 @@ #include "media/base/decrypt_config.h" #include "media/base/gmock_callback_support.h" #include "media/base/limits.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" #include "media/base/test_data_util.h" +#include "media/base/test_helpers.h" #include "media/base/video_decoder.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" diff --git a/media/filters/file_data_source_unittest.cc b/media/filters/file_data_source_unittest.cc index ac170a7..d7eaad0 100644 --- a/media/filters/file_data_source_unittest.cc +++ b/media/filters/file_data_source_unittest.cc @@ -9,8 +9,8 @@ #include "base/file_path.h" #include "base/path_service.h" #include "base/utf_string_conversions.h" -#include "media/base/mock_callback.h" #include "media/base/mock_data_source_host.h" +#include "media/base/test_helpers.h" #include "media/filters/file_data_source.h" using ::testing::NiceMock; diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc index 2e6cc12..90f42fe 100644 --- a/media/filters/video_renderer_base_unittest.cc +++ b/media/filters/video_renderer_base_unittest.cc @@ -2,21 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <algorithm> - #include "base/bind.h" #include "base/callback.h" +#include "base/callback_helpers.h" +#include "base/message_loop.h" #include "base/stl_util.h" #include "base/stringprintf.h" -#include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" +#include "base/timer.h" #include "media/base/data_buffer.h" #include "media/base/gmock_callback_support.h" #include "media/base/limits.h" -#include "media/base/mock_callback.h" #include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" #include "media/base/video_frame.h" #include "media/filters/video_renderer_base.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,26 +30,17 @@ using ::testing::StrictMock; namespace media { -static const int kFrameDuration = 10; -static const int kVideoDuration = kFrameDuration * 100; -static const int kEndOfStream = -1; +static const int kFrameDurationInMs = 10; +static const int kVideoDurationInMs = kFrameDurationInMs * 100; static const gfx::Size kNaturalSize(16u, 16u); class VideoRendererBaseTest : public ::testing::Test { public: VideoRendererBaseTest() : decoder_(new MockVideoDecoder()), - demuxer_stream_(new MockDemuxerStream()), - cv_(&lock_), - event_(false, false), - timeout_(TestTimeouts::action_timeout()), - prerolling_(false), - next_frame_timestamp_(0), - paint_cv_(&lock_), - paint_was_called_(false), - should_queue_read_cb_(false) { + demuxer_stream_(new MockDemuxerStream()) { renderer_ = new VideoRendererBase( - base::Bind(&VideoRendererBaseTest::Paint, base::Unretained(this)), + base::Bind(&VideoRendererBaseTest::OnPaint, base::Unretained(this)), base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)), true); @@ -65,36 +54,28 @@ class VideoRendererBaseTest : public ::testing::Test { .Times(AnyNumber()); EXPECT_CALL(*this, OnTimeUpdate(_)) .Times(AnyNumber()); + EXPECT_CALL(*this, OnPaint()) + .Times(AnyNumber()); EXPECT_CALL(*this, OnSetOpaque(_)) .Times(AnyNumber()); } - virtual ~VideoRendererBaseTest() { - read_queue_.clear(); - - if (renderer_) { - Stop(); - } - } + virtual ~VideoRendererBaseTest() {} // Callbacks passed into VideoRendererBase(). + MOCK_CONST_METHOD0(OnPaint, void()); MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); // Callbacks passed into Initialize(). MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); - MOCK_METHOD0(OnEnded, void()); - MOCK_METHOD1(OnError, void(PipelineStatus)); void Initialize() { - Initialize(kVideoDuration); + InitializeWithDuration(kVideoDurationInMs); } - void Initialize(int duration) { - duration_ = duration; - - // TODO(scherkus): really, really, really need to inject a thread into - // VideoRendererBase... it makes mocking much harder. + void InitializeWithDuration(int duration_ms) { + duration_ = base::TimeDelta::FromMilliseconds(duration_ms); // Monitor reads from the decoder. EXPECT_CALL(*decoder_, Read(_)) @@ -118,87 +99,69 @@ class VideoRendererBaseTest : public ::testing::Test { EXPECT_CALL(*this, OnNaturalSizeChanged(kNaturalSize)); // Start prerolling. - Preroll(0); + QueuePrerollFrames(0); + Preroll(0, PIPELINE_OK); } - void InitializeRenderer(PipelineStatus expected_status) { + void InitializeRenderer(PipelineStatus expected) { + SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected)); VideoRendererBase::VideoDecoderList decoders; decoders.push_back(decoder_); + + WaitableMessageLoopEvent event; renderer_->Initialize( demuxer_stream_, decoders, - NewExpectedStatusCB(expected_status), + event.GetPipelineStatusCB(), base::Bind(&MockStatisticsCB::OnStatistics, base::Unretained(&statistics_cb_object_)), base::Bind(&VideoRendererBaseTest::OnTimeUpdate, base::Unretained(this)), base::Bind(&VideoRendererBaseTest::OnNaturalSizeChanged, base::Unretained(this)), - base::Bind(&VideoRendererBaseTest::OnEnded, base::Unretained(this)), - base::Bind(&VideoRendererBaseTest::OnError, base::Unretained(this)), + ended_event_.GetClosure(), + error_event_.GetPipelineStatusCB(), base::Bind(&VideoRendererBaseTest::GetTime, base::Unretained(this)), base::Bind(&VideoRendererBaseTest::GetDuration, base::Unretained(this))); - } - - // Instead of immediately satisfying a decoder Read request, queue it up. - void QueueReadCB() { - should_queue_read_cb_ = true; - } - - void SatisfyQueuedReadCB() { - base::AutoLock l(lock_); - CHECK(should_queue_read_cb_ && !queued_read_cb_.is_null()); - should_queue_read_cb_ = false; - VideoDecoder::ReadCB read_cb(queued_read_cb_); - queued_read_cb_.Reset(); - base::AutoUnlock u(lock_); - read_cb.Run(VideoDecoder::kOk, VideoFrame::CreateEmptyFrame()); - } - - void StartPrerolling(int timestamp, PipelineStatus expected_status) { - EXPECT_FALSE(prerolling_); - - next_frame_timestamp_ = 0; - prerolling_ = true; - renderer_->Preroll(base::TimeDelta::FromMilliseconds(timestamp), - base::Bind(&VideoRendererBaseTest::OnPrerollComplete, - base::Unretained(this), expected_status)); + event.RunAndWaitForStatus(expected); } void Play() { SCOPED_TRACE("Play()"); - renderer_->Play(NewWaitableClosure()); - WaitForClosure(); + WaitableMessageLoopEvent event; + renderer_->Play(event.GetClosure()); + event.RunAndWait(); } - // Preroll to the given timestamp. - // - // Use |kEndOfStream| to preroll end of stream frames. - void Preroll(int timestamp) { - SCOPED_TRACE(base::StringPrintf("Preroll(%d)", timestamp)); - bool end_of_stream = (timestamp == kEndOfStream); - int preroll_timestamp = end_of_stream ? 0 : timestamp; - StartPrerolling(preroll_timestamp, PIPELINE_OK); - FinishPrerolling(end_of_stream); + void Preroll(int timestamp_ms, PipelineStatus expected) { + SCOPED_TRACE(base::StringPrintf("Preroll(%d, %d)", timestamp_ms, expected)); + WaitableMessageLoopEvent event; + renderer_->Preroll( + base::TimeDelta::FromMilliseconds(timestamp_ms), + event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(expected); } void Pause() { SCOPED_TRACE("Pause()"); - renderer_->Pause(NewWaitableClosure()); - WaitForClosure(); + WaitableMessageLoopEvent event; + renderer_->Pause(event.GetClosure()); + event.RunAndWait(); } void Flush() { SCOPED_TRACE("Flush()"); - renderer_->Flush(NewWaitableClosure()); - WaitForClosure(); + WaitableMessageLoopEvent event; + renderer_->Flush(event.GetClosure()); + event.RunAndWait(); } void Stop() { SCOPED_TRACE("Stop()"); - renderer_->Stop(NewWaitableClosure()); - WaitForClosure(); + WaitableMessageLoopEvent event; + renderer_->Stop(event.GetClosure()); + event.RunAndWait(); } void Shutdown() { @@ -207,122 +170,113 @@ class VideoRendererBaseTest : public ::testing::Test { Stop(); } - void DeliverNextFrame(bool end_of_stream) { - base::AutoLock l(lock_); - DeliverNextFrame_Locked(end_of_stream); + // Queues a VideoFrame with |next_frame_timestamp_|. + void QueueNextFrame() { + DCHECK_EQ(&message_loop_, MessageLoop::current()); + DCHECK_LT(next_frame_timestamp_.InMicroseconds(), + duration_.InMicroseconds()); + + scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( + VideoFrame::RGB32, kNaturalSize, gfx::Rect(kNaturalSize), kNaturalSize, + next_frame_timestamp_); + decode_results_.push_back(std::make_pair( + VideoDecoder::kOk, frame)); + next_frame_timestamp_ += + base::TimeDelta::FromMilliseconds(kFrameDurationInMs); } - // Delivers the next frame to the video renderer. If |end_of_stream| - // is true then an "end or stream" frame will be returned. Otherwise - // A frame with |next_frame_timestamp_| will be returned. - void DeliverNextFrame_Locked(bool end_of_stream) { - lock_.AssertAcquired(); - - VideoDecoder::ReadCB read_cb; - std::swap(read_cb, read_cb_); - - DCHECK_LT(next_frame_timestamp_, duration_); - int timestamp = next_frame_timestamp_; - next_frame_timestamp_ += kFrameDuration; - - // Unlock to deliver the frame to avoid re-entrancy issues. - base::AutoUnlock ul(lock_); - if (end_of_stream) { - read_cb.Run(VideoDecoder::kOk, VideoFrame::CreateEmptyFrame()); - } else { - read_cb.Run(VideoDecoder::kOk, CreateFrame(timestamp)); - } + void QueueEndOfStream() { + DCHECK_EQ(&message_loop_, MessageLoop::current()); + decode_results_.push_back(std::make_pair( + VideoDecoder::kOk, VideoFrame::CreateEmptyFrame())); } - void DecoderError() { - // Lock+swap to avoid re-entrancy issues. - VideoDecoder::ReadCB read_cb; - { - base::AutoLock l(lock_); - std::swap(read_cb, read_cb_); - } + void QueueDecodeError() { + DCHECK_EQ(&message_loop_, MessageLoop::current()); + scoped_refptr<VideoFrame> null_frame; + decode_results_.push_back(std::make_pair( + VideoDecoder::kDecodeError, null_frame)); + } - read_cb.Run(VideoDecoder::kDecodeError, NULL); + void QueueAbortedRead() { + DCHECK_EQ(&message_loop_, MessageLoop::current()); + scoped_refptr<VideoFrame> null_frame; + decode_results_.push_back(std::make_pair( + VideoDecoder::kOk, null_frame)); } - void AbortRead() { - // Lock+swap to avoid re-entrancy issues. - VideoDecoder::ReadCB read_cb; - { - base::AutoLock l(lock_); - std::swap(read_cb, read_cb_); + void QueuePrerollFrames(int timestamp_ms) { + DCHECK_EQ(&message_loop_, MessageLoop::current()); + next_frame_timestamp_ = base::TimeDelta(); + base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(timestamp_ms); + while (next_frame_timestamp_ < timestamp) { + QueueNextFrame(); } - read_cb.Run(VideoDecoder::kOk, NULL); - } - - void ExpectCurrentFrame(bool present) { - scoped_refptr<VideoFrame> frame; - renderer_->GetCurrentFrame(&frame); - if (present) { - EXPECT_TRUE(frame); - } else { - EXPECT_FALSE(frame); + // Queue the frame at |timestamp| plus additional ones for prerolling. + for (int i = 0; i < limits::kMaxVideoFrames; ++i) { + QueueNextFrame(); } - renderer_->PutCurrentFrame(frame); } - void ExpectCurrentTimestamp(int timestamp) { + scoped_refptr<VideoFrame> GetCurrentFrame() { scoped_refptr<VideoFrame> frame; renderer_->GetCurrentFrame(&frame); - EXPECT_EQ(timestamp, frame->GetTimestamp().InMilliseconds()); renderer_->PutCurrentFrame(frame); + return frame; } - base::Closure NewWaitableClosure() { - return base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)); + int GetCurrentTimestampInMs() { + scoped_refptr<VideoFrame> frame = GetCurrentFrame(); + if (!frame) + return -1; + return frame->GetTimestamp().InMilliseconds(); } - void WaitForClosure() { - ASSERT_TRUE(event_.TimedWait(timeout_)); - event_.Reset(); + void WaitForError(PipelineStatus expected) { + SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); + error_event_.RunAndWaitForStatus(expected); } - // Creates a frame with given timestamp. - scoped_refptr<VideoFrame> CreateFrame(int timestamp) { - scoped_refptr<VideoFrame> frame = - VideoFrame::CreateFrame(VideoFrame::RGB32, kNaturalSize, - gfx::Rect(kNaturalSize), kNaturalSize, - base::TimeDelta::FromMilliseconds(timestamp)); - return frame; + void WaitForEnded() { + SCOPED_TRACE("WaitForEnded()"); + ended_event_.RunAndWait(); } - // Advances clock to |timestamp| and waits for the frame at |timestamp| to get - // rendered using |read_cb_| as the signal that the frame has rendered. - void RenderFrame(int timestamp) { - base::AutoLock l(lock_); - time_ = base::TimeDelta::FromMilliseconds(timestamp); - paint_was_called_ = false; - if (read_cb_.is_null()) { - cv_.TimedWait(timeout_); - CHECK(!read_cb_.is_null()) << "Timed out waiting for read to occur."; - } - WaitForPaint_Locked(); - } + void WaitForPendingRead() { + SCOPED_TRACE("WaitForPendingRead()"); + if (!read_cb_.is_null()) + return; - // Advances clock to |timestamp| (which should be the timestamp of the last - // frame plus duration) and waits for the ended signal before returning. - void RenderLastFrame(int timestamp) { - EXPECT_CALL(*this, OnEnded()) - .WillOnce(Invoke(&event_, &base::WaitableEvent::Signal)); - { - base::AutoLock l(lock_); - time_ = base::TimeDelta::FromMilliseconds(timestamp); - } - CHECK(event_.TimedWait(timeout_)) << "Timed out waiting for ended signal."; + DCHECK(pending_read_cb_.is_null()); + + WaitableMessageLoopEvent event; + pending_read_cb_ = event.GetClosure(); + event.RunAndWait(); + + DCHECK(!read_cb_.is_null()); + DCHECK(pending_read_cb_.is_null()); } - base::WaitableEvent* event() { return &event_; } - const base::TimeDelta& timeout() { return timeout_; } + void SatisfyPendingRead() { + CHECK(!read_cb_.is_null()); + CHECK(!decode_results_.empty()); + + base::Closure closure = base::Bind( + read_cb_, decode_results_.front().first, + decode_results_.front().second); - void VerifyNotPrerolling() { + read_cb_.Reset(); + decode_results_.pop_front(); + + message_loop_.PostTask(FROM_HERE, closure); + } + + void AdvanceTimeInMs(int time_ms) { + DCHECK_EQ(&message_loop_, MessageLoop::current()); base::AutoLock l(lock_); - ASSERT_FALSE(prerolling_); + time_ += base::TimeDelta::FromMilliseconds(time_ms); + DCHECK_LE(time_.InMicroseconds(), duration_.InMicroseconds()); } protected: @@ -332,119 +286,80 @@ class VideoRendererBaseTest : public ::testing::Test { scoped_refptr<MockDemuxerStream> demuxer_stream_; MockStatisticsCB statistics_cb_object_; - // Receives all the buffers that renderer had provided to |decoder_|. - std::deque<scoped_refptr<VideoFrame> > read_queue_; - private: - // Called by VideoRendererBase for accessing the current time. base::TimeDelta GetTime() { base::AutoLock l(lock_); return time_; } base::TimeDelta GetDuration() { - return base::TimeDelta::FromMilliseconds(duration_); + return duration_; } - // Called by VideoRendererBase when it wants a frame. - void FrameRequested(const VideoDecoder::ReadCB& callback) { - base::AutoLock l(lock_); - if (should_queue_read_cb_) { - CHECK(queued_read_cb_.is_null()); - queued_read_cb_ = callback; + void FrameRequested(const VideoDecoder::ReadCB& read_cb) { + // TODO(scherkus): Make VideoRendererBase call on right thread. + if (&message_loop_ != MessageLoop::current()) { + message_loop_.PostTask(FROM_HERE, base::Bind( + &VideoRendererBaseTest::FrameRequested, base::Unretained(this), + read_cb)); return; } - CHECK(read_cb_.is_null()); - read_cb_ = callback; - cv_.Signal(); - } - void FlushRequested(const base::Closure& callback) { - // Lock+swap to avoid re-entrancy issues. - VideoDecoder::ReadCB read_cb; - { - base::AutoLock l(lock_); - std::swap(read_cb, read_cb_); - } + CHECK(read_cb_.is_null()); + read_cb_ = read_cb; - // Abort pending read. - if (!read_cb.is_null()) - read_cb.Run(VideoDecoder::kOk, NULL); + // Wake up WaitForPendingRead() if needed. + if (!pending_read_cb_.is_null()) + base::ResetAndReturn(&pending_read_cb_).Run(); - callback.Run(); - } + if (decode_results_.empty()) + return; - void OnPrerollComplete(PipelineStatus expected_status, - PipelineStatus status) { - base::AutoLock l(lock_); - EXPECT_EQ(status, expected_status); - EXPECT_TRUE(prerolling_); - prerolling_ = false; - cv_.Signal(); + SatisfyPendingRead(); } - void FinishPrerolling(bool end_of_stream) { - // Satisfy the read requests. The callback must be executed in order - // to exit the loop since VideoRendererBase can read a few extra frames - // after |timestamp| in order to preroll. - base::AutoLock l(lock_); - EXPECT_TRUE(prerolling_); - paint_was_called_ = false; - while (prerolling_) { - if (!read_cb_.is_null()) { - DeliverNextFrame_Locked(end_of_stream); - } else { - // We want to wait iff we're still prerolling but have no pending read. - cv_.TimedWait(timeout_); - CHECK(!prerolling_ || !read_cb_.is_null()) - << "Timed out waiting for preroll or read to occur."; - } + void FlushRequested(const base::Closure& callback) { + // TODO(scherkus): Make VideoRendererBase call on right thread. + if (&message_loop_ != MessageLoop::current()) { + message_loop_.PostTask(FROM_HERE, base::Bind( + &VideoRendererBaseTest::FlushRequested, base::Unretained(this), + callback)); + return; } - EXPECT_TRUE(read_cb_.is_null()); - WaitForPaint_Locked(); - } + decode_results_.clear(); + if (!read_cb_.is_null()) { + QueueAbortedRead(); + SatisfyPendingRead(); + } - void Paint() { - base::AutoLock l(lock_); - paint_was_called_ = true; - paint_cv_.Signal(); + message_loop_.PostTask(FROM_HERE, callback); } - void WaitForPaint_Locked() { - lock_.AssertAcquired(); - if (paint_was_called_) - return; - paint_cv_.TimedWait(timeout_); - EXPECT_TRUE(paint_was_called_); - } + MessageLoop message_loop_; + // Used to protect |time_|. base::Lock lock_; - base::ConditionVariable cv_; - base::WaitableEvent event_; - base::TimeDelta timeout_; + base::TimeDelta time_; - // Used in conjunction with |lock_| and |cv_| for satisfying reads. - bool prerolling_; + // Used for satisfying reads. VideoDecoder::ReadCB read_cb_; - int next_frame_timestamp_; - int duration_; - base::TimeDelta time_; + base::TimeDelta next_frame_timestamp_; + base::TimeDelta duration_; - // Used in conjunction with |lock_| to wait for Paint() calls. - base::ConditionVariable paint_cv_; - bool paint_was_called_; + WaitableMessageLoopEvent error_event_; + WaitableMessageLoopEvent ended_event_; + base::Closure pending_read_cb_; - // Holding queue for Read callbacks for exercising delayed demux/decode. - bool should_queue_read_cb_; - VideoDecoder::ReadCB queued_read_cb_; + std::deque<std::pair< + VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest); }; TEST_F(VideoRendererBaseTest, Initialize) { Initialize(); - ExpectCurrentTimestamp(0); + EXPECT_EQ(0, GetCurrentTimestampInMs()); Shutdown(); } @@ -458,68 +373,61 @@ TEST_F(VideoRendererBaseTest, EndOfStream_DefaultFrameDuration) { Initialize(); Play(); - // Finish rendering up to the next-to-last frame. - int timestamp = kFrameDuration; - for (int i = 1; i < limits::kMaxVideoFrames; ++i) { - RenderFrame(timestamp); - timestamp += kFrameDuration; - } - - // Deliver the end of stream frame. - DeliverNextFrame(true); - // Verify that the ended callback fires when the default last frame duration // has elapsed. - int end_timestamp = - timestamp + VideoRendererBase::kMaxLastFrameDuration().InMilliseconds(); - EXPECT_LT(end_timestamp, kVideoDuration); - RenderLastFrame(end_timestamp); + int end_timestamp = kFrameDurationInMs * limits::kMaxVideoFrames + + VideoRendererBase::kMaxLastFrameDuration().InMilliseconds(); + EXPECT_LT(end_timestamp, kVideoDurationInMs); + + QueueEndOfStream(); + AdvanceTimeInMs(end_timestamp); + WaitForEnded(); Shutdown(); } TEST_F(VideoRendererBaseTest, EndOfStream_ClipDuration) { - int duration = kVideoDuration + kFrameDuration / 2; - Initialize(duration); + int duration = kVideoDurationInMs + kFrameDurationInMs / 2; + InitializeWithDuration(duration); Play(); // Render all frames except for the last |limits::kMaxVideoFrames| frames // and deliver all the frames between the start and |duration|. The preroll // inside Initialize() makes this a little confusing, but |timestamp| is - // the current render time and DeliverNextFrame() delivers a frame with a - // timestamp that is |timestamp| + limits::kMaxVideoFrames * kFrameDuration. - int timestamp = kFrameDuration; - int end_timestamp = duration - limits::kMaxVideoFrames * kFrameDuration; - for (; timestamp < end_timestamp; timestamp += kFrameDuration) { - RenderFrame(timestamp); - DeliverNextFrame(false); + // the current render time and QueueNextFrame() delivers a frame with a + // timestamp that is |timestamp| + limits::kMaxVideoFrames * + // kFrameDurationInMs. + int timestamp = kFrameDurationInMs; + int end_timestamp = duration - limits::kMaxVideoFrames * kFrameDurationInMs; + for (; timestamp < end_timestamp; timestamp += kFrameDurationInMs) { + QueueNextFrame(); } - // Render the next frame so that a Read() will get requested. - RenderFrame(timestamp); - - // Deliver the end of stream frame and wait for the last frame to be rendered. - DeliverNextFrame(true); - RenderLastFrame(duration); + // Queue the end of stream frame and wait for the last frame to be rendered. + QueueEndOfStream(); + AdvanceTimeInMs(duration); + WaitForEnded(); Shutdown(); } -TEST_F(VideoRendererBaseTest, DecoderError) { +TEST_F(VideoRendererBaseTest, DecodeError_Playing) { Initialize(); Play(); - RenderFrame(kFrameDuration); - EXPECT_CALL(*this, OnError(PIPELINE_ERROR_DECODE)); - DecoderError(); + + QueueDecodeError(); + AdvanceTimeInMs(kVideoDurationInMs); + WaitForError(PIPELINE_ERROR_DECODE); Shutdown(); } -TEST_F(VideoRendererBaseTest, DecoderErrorDuringPreroll) { +TEST_F(VideoRendererBaseTest, DecodeError_DuringPreroll) { Initialize(); Pause(); Flush(); - StartPrerolling(kFrameDuration * 6, PIPELINE_ERROR_DECODE); - DecoderError(); + + QueueDecodeError(); + Preroll(kFrameDurationInMs * 6, PIPELINE_ERROR_DECODE); Shutdown(); } @@ -527,8 +435,10 @@ TEST_F(VideoRendererBaseTest, Preroll_Exact) { Initialize(); Pause(); Flush(); - Preroll(kFrameDuration * 6); - ExpectCurrentTimestamp(kFrameDuration * 6); + QueuePrerollFrames(kFrameDurationInMs * 6); + + Preroll(kFrameDurationInMs * 6, PIPELINE_OK); + EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); Shutdown(); } @@ -536,8 +446,10 @@ TEST_F(VideoRendererBaseTest, Preroll_RightBefore) { Initialize(); Pause(); Flush(); - Preroll(kFrameDuration * 6 - 1); - ExpectCurrentTimestamp(kFrameDuration * 5); + QueuePrerollFrames(kFrameDurationInMs * 6); + + Preroll(kFrameDurationInMs * 6 - 1, PIPELINE_OK); + EXPECT_EQ(kFrameDurationInMs * 5, GetCurrentTimestampInMs()); Shutdown(); } @@ -545,21 +457,23 @@ TEST_F(VideoRendererBaseTest, Preroll_RightAfter) { Initialize(); Pause(); Flush(); - Preroll(kFrameDuration * 6 + 1); - ExpectCurrentTimestamp(kFrameDuration * 6); + QueuePrerollFrames(kFrameDurationInMs * 6); + + Preroll(kFrameDurationInMs * 6 + 1, PIPELINE_OK); + EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); Shutdown(); } TEST_F(VideoRendererBaseTest, GetCurrentFrame_Initialized) { Initialize(); - ExpectCurrentFrame(true); // Due to prerolling. + EXPECT_TRUE(GetCurrentFrame()); // Due to prerolling. Shutdown(); } TEST_F(VideoRendererBaseTest, GetCurrentFrame_Playing) { Initialize(); Play(); - ExpectCurrentFrame(true); + EXPECT_TRUE(GetCurrentFrame()); Shutdown(); } @@ -567,7 +481,7 @@ TEST_F(VideoRendererBaseTest, GetCurrentFrame_Paused) { Initialize(); Play(); Pause(); - ExpectCurrentFrame(true); + EXPECT_TRUE(GetCurrentFrame()); Shutdown(); } @@ -576,7 +490,7 @@ TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { Play(); Pause(); Flush(); - ExpectCurrentFrame(false); + EXPECT_FALSE(GetCurrentFrame()); Shutdown(); } @@ -593,14 +507,13 @@ TEST_F(VideoRendererBaseTest, MAYBE_GetCurrentFrame_EndOfStream) { Flush(); // Preroll only end of stream frames. - Preroll(kEndOfStream); - ExpectCurrentFrame(false); + QueueEndOfStream(); + Preroll(0, PIPELINE_OK); + EXPECT_FALSE(GetCurrentFrame()); // Start playing, we should immediately get notified of end of stream. - EXPECT_CALL(*this, OnEnded()) - .WillOnce(Invoke(event(), &base::WaitableEvent::Signal)); Play(); - CHECK(event()->TimedWait(timeout())) << "Timed out waiting for ended signal."; + WaitForEnded(); Shutdown(); } @@ -608,14 +521,14 @@ TEST_F(VideoRendererBaseTest, MAYBE_GetCurrentFrame_EndOfStream) { TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { Initialize(); Shutdown(); - ExpectCurrentFrame(false); + EXPECT_FALSE(GetCurrentFrame()); } // Stop() is called immediately during an error. TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { Initialize(); Stop(); - ExpectCurrentFrame(false); + EXPECT_FALSE(GetCurrentFrame()); } // Verify that shutdown can only proceed after we return the current frame. @@ -631,11 +544,12 @@ TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) { Pause(); // Start flushing -- it won't complete until we return the frame. - renderer_->Flush(NewWaitableClosure()); + WaitableMessageLoopEvent event; + renderer_->Flush(event.GetClosure()); // Return the frame and wait. renderer_->PutCurrentFrame(frame); - WaitForClosure(); + event.RunAndWait(); Stop(); } @@ -643,28 +557,37 @@ TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) { // Verify that a late decoder response doesn't break invariants in the renderer. TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { Initialize(); - Pause(); - Flush(); - QueueReadCB(); - StartPrerolling(kFrameDuration * 6, PIPELINE_OK); // Force-decode some more. - renderer_->Stop(NewWaitableClosure()); - SatisfyQueuedReadCB(); - WaitForClosure(); // Finish the Stop(). + Play(); + + // Advance time a bit to trigger a Read(). + AdvanceTimeInMs(kFrameDurationInMs); + WaitForPendingRead(); + + WaitableMessageLoopEvent event; + renderer_->Stop(event.GetClosure()); + + QueueEndOfStream(); + SatisfyPendingRead(); + + event.RunAndWait(); } TEST_F(VideoRendererBaseTest, AbortPendingRead_Playing) { Initialize(); Play(); - // Render a frame to trigger a Read(). - RenderFrame(kFrameDuration); + // Advance time a bit to trigger a Read(). + AdvanceTimeInMs(kFrameDurationInMs); + WaitForPendingRead(); - AbortRead(); + QueueAbortedRead(); + SatisfyPendingRead(); Pause(); Flush(); - Preroll(kFrameDuration * 6); - ExpectCurrentTimestamp(kFrameDuration * 6); + QueuePrerollFrames(kFrameDurationInMs * 6); + Preroll(kFrameDurationInMs * 6, PIPELINE_OK); + EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); Shutdown(); } @@ -672,8 +595,9 @@ TEST_F(VideoRendererBaseTest, AbortPendingRead_Flush) { Initialize(); Play(); - // Render a frame to trigger a Read(). - RenderFrame(kFrameDuration); + // Advance time a bit to trigger a Read(). + AdvanceTimeInMs(kFrameDurationInMs); + WaitForPendingRead(); Pause(); Flush(); @@ -684,9 +608,9 @@ TEST_F(VideoRendererBaseTest, AbortPendingRead_Preroll) { Initialize(); Pause(); Flush(); - StartPrerolling(kFrameDuration * 6, PIPELINE_OK); - AbortRead(); - VerifyNotPrerolling(); + + QueueAbortedRead(); + Preroll(kFrameDurationInMs * 6, PIPELINE_OK); Shutdown(); } @@ -696,6 +620,8 @@ TEST_F(VideoRendererBaseTest, VideoDecoder_InitFailure) { EXPECT_CALL(*decoder_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_ERROR_DECODE)); InitializeRenderer(PIPELINE_ERROR_DECODE); + + Stop(); } } // namespace media diff --git a/media/media.gyp b/media/media.gyp index 963ee56..b061d7a 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -841,14 +841,14 @@ 'base/gmock_callback_support.h', 'base/mock_audio_renderer_sink.cc', 'base/mock_audio_renderer_sink.h', - 'base/mock_callback.cc', - 'base/mock_callback.h', 'base/mock_data_source_host.cc', 'base/mock_data_source_host.h', 'base/mock_demuxer_host.cc', 'base/mock_demuxer_host.h', 'base/mock_filters.cc', 'base/mock_filters.h', + 'base/test_helpers.cc', + 'base/test_helpers.h', ], }, ], |