Refactor PipelineIntegrationTest into PipelineIntegrationTestBase.

No changes, just splits current framework out into
PipelineIntegrationTestBase.

BUG=112321
TEST=media_unittests


Review URL: http://codereview.chromium.org/9323044

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120736 0039d316-1c4b-4281-b951-d872f2087c98
parent 2fb1f080
...@@ -2,26 +2,11 @@ ...@@ -2,26 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "media/filters/pipeline_integration_test_base.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/message_loop.h"
#include "media/base/filter_collection.h"
#include "media/base/media_log.h"
#include "media/base/message_loop_factory_impl.h"
#include "media/base/pipeline.h"
#include "media/base/test_data_util.h" #include "media/base/test_data_util.h"
#include "media/filters/chunk_demuxer.h"
#include "media/filters/chunk_demuxer_client.h" #include "media/filters/chunk_demuxer_client.h"
#include "media/filters/chunk_demuxer_factory.h"
#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer_factory.h"
#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"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::AnyNumber;
namespace media { namespace media {
...@@ -90,160 +75,8 @@ class MockMediaSource : public ChunkDemuxerClient { ...@@ -90,160 +75,8 @@ class MockMediaSource : public ChunkDemuxerClient {
scoped_refptr<ChunkDemuxer> chunk_demuxer_; scoped_refptr<ChunkDemuxer> chunk_demuxer_;
}; };
// Integration tests for Pipeline. Real demuxers, real decoders, and class PipelineIntegrationTest : public PipelineIntegrationTestBase {
// base renderer implementations are used to verify pipeline functionality. The
// renderers used in these tests rely heavily on the AudioRendererBase &
// VideoRendererBase implementations which contain a majority of the code used
// in the real AudioRendererImpl & SkCanvasVideoRenderer implementations used in
// the browser. The renderers in this test don't actually write data to a
// display or audio device. Both of these devices are simulated since they have
// little effect on verifying pipeline behavior and allow tests to run faster
// than real-time.
class PipelineIntegrationTest : public testing::Test {
public: public:
PipelineIntegrationTest()
: message_loop_factory_(new MessageLoopFactoryImpl()),
pipeline_(new Pipeline(&message_loop_, new MediaLog())),
ended_(false),
pipeline_status_(PIPELINE_OK) {
EXPECT_CALL(*this, OnVideoRendererPaint()).Times(AnyNumber());
EXPECT_CALL(*this, OnSetOpaque(true)).Times(AnyNumber());
}
virtual ~PipelineIntegrationTest() {
if (!pipeline_->IsRunning())
return;
Stop();
}
void OnStatusCallback(PipelineStatus expected_status,
PipelineStatus status) {
EXPECT_EQ(status, expected_status);
pipeline_status_ = status;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
PipelineStatusCB QuitOnStatusCB(PipelineStatus expected_status) {
return base::Bind(&PipelineIntegrationTest::OnStatusCallback,
base::Unretained(this),
expected_status);
}
void OnEnded(PipelineStatus status) {
DCHECK_EQ(status, PIPELINE_OK);
DCHECK(!ended_);
ended_ = true;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
bool WaitUntilOnEnded() {
if (ended_)
return (pipeline_status_ == PIPELINE_OK);
message_loop_.Run();
EXPECT_TRUE(ended_);
return ended_ && (pipeline_status_ == PIPELINE_OK);
}
void OnError(PipelineStatus status) {
DCHECK_NE(status, PIPELINE_OK);
pipeline_status_ = status;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
bool Start(const std::string& url, PipelineStatus expected_status) {
pipeline_->Start(
CreateFilterCollection(url),
url,
base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
NetworkEventCB(),
QuitOnStatusCB(expected_status));
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
void Play() {
pipeline_->SetPlaybackRate(1);
}
void Pause() {
pipeline_->SetPlaybackRate(0);
}
bool Seek(base::TimeDelta seek_time) {
ended_ = false;
pipeline_->Seek(seek_time, QuitOnStatusCB(PIPELINE_OK));
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
void Stop() {
DCHECK(pipeline_->IsRunning());
pipeline_->Stop(QuitOnStatusCB(PIPELINE_OK));
message_loop_.Run();
}
void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time) {
if (pipeline_->GetCurrentTime() >= quit_time ||
pipeline_status_ != PIPELINE_OK) {
message_loop_.Quit();
return;
}
message_loop_.PostDelayedTask(
FROM_HERE,
base::Bind(&PipelineIntegrationTest::QuitAfterCurrentTimeTask,
base::Unretained(this), quit_time),
10);
}
bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time) {
DCHECK(pipeline_->IsRunning());
DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
DCHECK(wait_time <= pipeline_->GetMediaDuration());
message_loop_.PostDelayedTask(
FROM_HERE,
base::Bind(&PipelineIntegrationTest::QuitAfterCurrentTimeTask,
base::Unretained(this),
wait_time),
10);
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
scoped_ptr<FilterCollection> CreateFilterCollection(const std::string& url) {
scoped_refptr<FileDataSource> data_source = new FileDataSource();
CHECK_EQ(PIPELINE_OK, data_source->Initialize(url));
return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
new FFmpegDemuxerFactory(data_source, &message_loop_)));
}
scoped_ptr<FilterCollection> CreateFilterCollection(
ChunkDemuxerClient* client) {
return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
new ChunkDemuxerFactory(client)));
}
scoped_ptr<FilterCollection> CreateFilterCollection(
scoped_ptr<DemuxerFactory> demuxer_factory) {
scoped_ptr<FilterCollection> collection(new FilterCollection());
collection->SetDemuxerFactory(demuxer_factory.Pass());
collection->AddAudioDecoder(new FFmpegAudioDecoder(
message_loop_factory_->GetMessageLoop("AudioDecoderThread")));
collection->AddVideoDecoder(new FFmpegVideoDecoder(
message_loop_factory_->GetMessageLoop("VideoDecoderThread")));
collection->AddVideoRenderer(new VideoRendererBase(
base::Bind(&PipelineIntegrationTest::OnVideoRendererPaint,
base::Unretained(this)),
base::Bind(&PipelineIntegrationTest::OnSetOpaque,
base::Unretained(this))));
collection->AddAudioRenderer(new NullAudioRenderer());
return collection.Pass();
}
// Verifies that seeking works properly for ChunkDemuxer when the // Verifies that seeking works properly for ChunkDemuxer when the
// seek happens while there is a pending read on the ChunkDemuxer // seek happens while there is a pending read on the ChunkDemuxer
// and no data is available. // and no data is available.
...@@ -281,17 +114,6 @@ class PipelineIntegrationTest : public testing::Test { ...@@ -281,17 +114,6 @@ class PipelineIntegrationTest : public testing::Test {
Stop(); Stop();
return true; return true;
} }
protected:
MessageLoop message_loop_;
scoped_ptr<MessageLoopFactory> message_loop_factory_;
scoped_refptr<Pipeline> pipeline_;
bool ended_;
PipelineStatus pipeline_status_;
private:
MOCK_METHOD0(OnVideoRendererPaint, void());
MOCK_METHOD1(OnSetOpaque, void(bool));
}; };
......
// 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/filters/pipeline_integration_test_base.h"
#include "base/bind.h"
#include "media/base/media_log.h"
#include "media/filters/chunk_demuxer_factory.h"
#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer_factory.h"
#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;
namespace media {
PipelineIntegrationTestBase::PipelineIntegrationTestBase()
: message_loop_factory_(new MessageLoopFactoryImpl()),
pipeline_(new Pipeline(&message_loop_, new MediaLog())),
ended_(false),
pipeline_status_(PIPELINE_OK) {
EXPECT_CALL(*this, OnVideoRendererPaint()).Times(AnyNumber());
EXPECT_CALL(*this, OnSetOpaque(true)).Times(AnyNumber());
}
PipelineIntegrationTestBase::~PipelineIntegrationTestBase() {
if (!pipeline_->IsRunning())
return;
Stop();
}
void PipelineIntegrationTestBase::OnStatusCallback(
PipelineStatus expected_status,
PipelineStatus status) {
EXPECT_EQ(status, expected_status);
pipeline_status_ = status;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
PipelineStatusCB PipelineIntegrationTestBase::QuitOnStatusCB(
PipelineStatus expected_status) {
return base::Bind(&PipelineIntegrationTestBase::OnStatusCallback,
base::Unretained(this),
expected_status);
}
void PipelineIntegrationTestBase::OnEnded(PipelineStatus status) {
DCHECK_EQ(status, PIPELINE_OK);
DCHECK(!ended_);
ended_ = true;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
bool PipelineIntegrationTestBase::WaitUntilOnEnded() {
if (ended_)
return (pipeline_status_ == PIPELINE_OK);
message_loop_.Run();
EXPECT_TRUE(ended_);
return ended_ && (pipeline_status_ == PIPELINE_OK);
}
void PipelineIntegrationTestBase::OnError(PipelineStatus status) {
DCHECK_NE(status, PIPELINE_OK);
pipeline_status_ = status;
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
bool PipelineIntegrationTestBase::Start(const std::string& url,
PipelineStatus expected_status) {
pipeline_->Start(
CreateFilterCollection(url),
url,
base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
NetworkEventCB(),
QuitOnStatusCB(expected_status));
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
void PipelineIntegrationTestBase::Play() {
pipeline_->SetPlaybackRate(1);
}
void PipelineIntegrationTestBase::Pause() {
pipeline_->SetPlaybackRate(0);
}
bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
ended_ = false;
pipeline_->Seek(seek_time, QuitOnStatusCB(PIPELINE_OK));
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
void PipelineIntegrationTestBase::Stop() {
DCHECK(pipeline_->IsRunning());
pipeline_->Stop(QuitOnStatusCB(PIPELINE_OK));
message_loop_.Run();
}
void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
const base::TimeDelta& quit_time) {
if (pipeline_->GetCurrentTime() >= quit_time ||
pipeline_status_ != PIPELINE_OK) {
message_loop_.Quit();
return;
}
message_loop_.PostDelayedTask(
FROM_HERE,
base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
base::Unretained(this), quit_time),
10);
}
bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
const base::TimeDelta& wait_time) {
DCHECK(pipeline_->IsRunning());
DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
DCHECK(wait_time <= pipeline_->GetMediaDuration());
message_loop_.PostDelayedTask(
FROM_HERE,
base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
base::Unretained(this),
wait_time),
10);
message_loop_.Run();
return (pipeline_status_ == PIPELINE_OK);
}
scoped_ptr<FilterCollection>
PipelineIntegrationTestBase::CreateFilterCollection(const std::string& url) {
scoped_refptr<FileDataSource> data_source = new FileDataSource();
CHECK_EQ(PIPELINE_OK, data_source->Initialize(url));
return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
new FFmpegDemuxerFactory(data_source, &message_loop_)));
}
scoped_ptr<FilterCollection>
PipelineIntegrationTestBase::CreateFilterCollection(
ChunkDemuxerClient* client) {
return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
new ChunkDemuxerFactory(client)));
}
scoped_ptr<FilterCollection>
PipelineIntegrationTestBase::CreateFilterCollection(
scoped_ptr<DemuxerFactory> demuxer_factory) {
scoped_ptr<FilterCollection> collection(new FilterCollection());
collection->SetDemuxerFactory(demuxer_factory.Pass());
collection->AddAudioDecoder(new FFmpegAudioDecoder(
message_loop_factory_->GetMessageLoop("AudioDecoderThread")));
collection->AddVideoDecoder(new FFmpegVideoDecoder(
message_loop_factory_->GetMessageLoop("VideoDecoderThread")));
collection->AddVideoRenderer(new VideoRendererBase(
base::Bind(&PipelineIntegrationTestBase::OnVideoRendererPaint,
base::Unretained(this)),
base::Bind(&PipelineIntegrationTestBase::OnSetOpaque,
base::Unretained(this))));
collection->AddAudioRenderer(new NullAudioRenderer());
return collection.Pass();
}
} // namespace media
// 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_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
#define MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
#include "base/message_loop.h"
#include "media/base/filter_collection.h"
#include "media/base/message_loop_factory_impl.h"
#include "media/base/pipeline.h"
#include "media/filters/chunk_demuxer.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
// 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 &
// VideoRendererBase implementations which contain a majority of the code used
// in the real AudioRendererImpl & SkCanvasVideoRenderer implementations used in
// the browser. The renderers in this test don't actually write data to a
// display or audio device. Both of these devices are simulated since they have
// little effect on verifying pipeline behavior and allow tests to run faster
// than real-time.
class PipelineIntegrationTestBase : public testing::Test {
public:
PipelineIntegrationTestBase();
virtual ~PipelineIntegrationTestBase();
bool WaitUntilOnEnded();
void OnError(PipelineStatus status);
bool Start(const std::string& url, PipelineStatus expected_status);
void Play();
void Pause();
bool Seek(base::TimeDelta seek_time);
void Stop();
bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time);
scoped_ptr<FilterCollection> CreateFilterCollection(const std::string& url);
scoped_ptr<FilterCollection> CreateFilterCollection(
ChunkDemuxerClient* client);
protected:
MessageLoop message_loop_;
scoped_ptr<MessageLoopFactory> message_loop_factory_;
scoped_refptr<Pipeline> pipeline_;
bool ended_;
PipelineStatus pipeline_status_;
void OnStatusCallback(PipelineStatus expected_status,
PipelineStatus status);
PipelineStatusCB QuitOnStatusCB(PipelineStatus expected_status);
void OnEnded(PipelineStatus status);
void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time);
scoped_ptr<FilterCollection> CreateFilterCollection(
scoped_ptr<DemuxerFactory> demuxer_factory);
MOCK_METHOD0(OnVideoRendererPaint, void());
MOCK_METHOD1(OnSetOpaque, void(bool));
};
} // namespace media
#endif // MEDIA_FILTERS_PIPELINE_INTEGRATION_TEST_BASE_H_
...@@ -610,6 +610,7 @@ ...@@ -610,6 +610,7 @@
'filters/ffmpeg_video_decoder_unittest.cc', 'filters/ffmpeg_video_decoder_unittest.cc',
'filters/file_data_source_unittest.cc', 'filters/file_data_source_unittest.cc',
'filters/pipeline_integration_test.cc', 'filters/pipeline_integration_test.cc',
'filters/pipeline_integration_test_base.cc',
'filters/video_renderer_base_unittest.cc', 'filters/video_renderer_base_unittest.cc',
'video/capture/video_capture_device_unittest.cc', 'video/capture/video_capture_device_unittest.cc',
'webm/cluster_builder.cc', 'webm/cluster_builder.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment