Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: media/filters/pipeline_integration_test.cc

Issue 9323044: Refactor PipelineIntegrationTest into PipelineIntegrationTestBase. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Try fixes. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | media/filters/pipeline_integration_test_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/pipeline_integration_test_base.h"
6
5 #include "base/bind.h" 7 #include "base/bind.h"
6 #include "base/message_loop.h"
7 #include "media/base/filter_collection.h"
8 #include "media/base/media_log.h"
9 #include "media/base/message_loop_factory_impl.h"
10 #include "media/base/pipeline.h"
11 #include "media/base/test_data_util.h" 8 #include "media/base/test_data_util.h"
12 #include "media/filters/chunk_demuxer.h"
13 #include "media/filters/chunk_demuxer_client.h" 9 #include "media/filters/chunk_demuxer_client.h"
14 #include "media/filters/chunk_demuxer_factory.h"
15 #include "media/filters/ffmpeg_audio_decoder.h"
16 #include "media/filters/ffmpeg_demuxer_factory.h"
17 #include "media/filters/ffmpeg_video_decoder.h"
18 #include "media/filters/file_data_source.h"
19 #include "media/filters/null_audio_renderer.h"
20 #include "media/filters/video_renderer_base.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using ::testing::AnyNumber;
25 10
26 namespace media { 11 namespace media {
27 12
28 // Helper class that emulates calls made on the ChunkDemuxer by the 13 // Helper class that emulates calls made on the ChunkDemuxer by the
29 // Media Source API. 14 // Media Source API.
30 class MockMediaSource : public ChunkDemuxerClient { 15 class MockMediaSource : public ChunkDemuxerClient {
31 public: 16 public:
32 MockMediaSource(const std::string& filename, int initial_append_size) 17 MockMediaSource(const std::string& filename, int initial_append_size)
33 : url_(GetTestDataURL(filename)), 18 : url_(GetTestDataURL(filename)),
34 current_position_(0), 19 current_position_(0),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 68
84 private: 69 private:
85 std::string url_; 70 std::string url_;
86 scoped_array<uint8> file_data_; 71 scoped_array<uint8> file_data_;
87 int file_data_size_; 72 int file_data_size_;
88 int current_position_; 73 int current_position_;
89 int initial_append_size_; 74 int initial_append_size_;
90 scoped_refptr<ChunkDemuxer> chunk_demuxer_; 75 scoped_refptr<ChunkDemuxer> chunk_demuxer_;
91 }; 76 };
92 77
93 // Integration tests for Pipeline. Real demuxers, real decoders, and 78 class PipelineIntegrationTest : public PipelineIntegrationTestBase {
94 // base renderer implementations are used to verify pipeline functionality. The
95 // renderers used in these tests rely heavily on the AudioRendererBase &
96 // VideoRendererBase implementations which contain a majority of the code used
97 // in the real AudioRendererImpl & SkCanvasVideoRenderer implementations used in
98 // the browser. The renderers in this test don't actually write data to a
99 // display or audio device. Both of these devices are simulated since they have
100 // little effect on verifying pipeline behavior and allow tests to run faster
101 // than real-time.
102 class PipelineIntegrationTest : public testing::Test {
103 public: 79 public:
104 PipelineIntegrationTest()
105 : message_loop_factory_(new MessageLoopFactoryImpl()),
106 pipeline_(new Pipeline(&message_loop_, new MediaLog())),
107 ended_(false),
108 pipeline_status_(PIPELINE_OK) {
109 EXPECT_CALL(*this, OnVideoRendererPaint()).Times(AnyNumber());
110 EXPECT_CALL(*this, OnSetOpaque(true)).Times(AnyNumber());
111 }
112
113 virtual ~PipelineIntegrationTest() {
114 if (!pipeline_->IsRunning())
115 return;
116
117 Stop();
118 }
119
120 void OnStatusCallback(PipelineStatus expected_status,
121 PipelineStatus status) {
122 EXPECT_EQ(status, expected_status);
123 pipeline_status_ = status;
124 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
125 }
126
127 PipelineStatusCB QuitOnStatusCB(PipelineStatus expected_status) {
128 return base::Bind(&PipelineIntegrationTest::OnStatusCallback,
129 base::Unretained(this),
130 expected_status);
131 }
132
133 void OnEnded(PipelineStatus status) {
134 DCHECK_EQ(status, PIPELINE_OK);
135 DCHECK(!ended_);
136 ended_ = true;
137 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
138 }
139
140 bool WaitUntilOnEnded() {
141 if (ended_)
142 return (pipeline_status_ == PIPELINE_OK);
143 message_loop_.Run();
144 EXPECT_TRUE(ended_);
145 return ended_ && (pipeline_status_ == PIPELINE_OK);
146 }
147
148 void OnError(PipelineStatus status) {
149 DCHECK_NE(status, PIPELINE_OK);
150 pipeline_status_ = status;
151 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
152 }
153
154 bool Start(const std::string& url, PipelineStatus expected_status) {
155 pipeline_->Start(
156 CreateFilterCollection(url),
157 url,
158 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
159 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
160 NetworkEventCB(),
161 QuitOnStatusCB(expected_status));
162 message_loop_.Run();
163 return (pipeline_status_ == PIPELINE_OK);
164 }
165
166 void Play() {
167 pipeline_->SetPlaybackRate(1);
168 }
169
170 void Pause() {
171 pipeline_->SetPlaybackRate(0);
172 }
173
174 bool Seek(base::TimeDelta seek_time) {
175 ended_ = false;
176
177 pipeline_->Seek(seek_time, QuitOnStatusCB(PIPELINE_OK));
178 message_loop_.Run();
179 return (pipeline_status_ == PIPELINE_OK);
180 }
181
182 void Stop() {
183 DCHECK(pipeline_->IsRunning());
184 pipeline_->Stop(QuitOnStatusCB(PIPELINE_OK));
185 message_loop_.Run();
186 }
187
188 void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time) {
189 if (pipeline_->GetCurrentTime() >= quit_time ||
190 pipeline_status_ != PIPELINE_OK) {
191 message_loop_.Quit();
192 return;
193 }
194
195 message_loop_.PostDelayedTask(
196 FROM_HERE,
197 base::Bind(&PipelineIntegrationTest::QuitAfterCurrentTimeTask,
198 base::Unretained(this), quit_time),
199 10);
200 }
201
202 bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time) {
203 DCHECK(pipeline_->IsRunning());
204 DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
205 DCHECK(wait_time <= pipeline_->GetMediaDuration());
206
207 message_loop_.PostDelayedTask(
208 FROM_HERE,
209 base::Bind(&PipelineIntegrationTest::QuitAfterCurrentTimeTask,
210 base::Unretained(this),
211 wait_time),
212 10);
213 message_loop_.Run();
214 return (pipeline_status_ == PIPELINE_OK);
215 }
216
217 scoped_ptr<FilterCollection> CreateFilterCollection(const std::string& url) {
218 scoped_refptr<FileDataSource> data_source = new FileDataSource();
219 CHECK_EQ(PIPELINE_OK, data_source->Initialize(url));
220 return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
221 new FFmpegDemuxerFactory(data_source, &message_loop_)));
222 }
223
224 scoped_ptr<FilterCollection> CreateFilterCollection(
225 ChunkDemuxerClient* client) {
226 return CreateFilterCollection(scoped_ptr<DemuxerFactory>(
227 new ChunkDemuxerFactory(client)));
228 }
229
230 scoped_ptr<FilterCollection> CreateFilterCollection(
231 scoped_ptr<DemuxerFactory> demuxer_factory) {
232 scoped_ptr<FilterCollection> collection(new FilterCollection());
233 collection->SetDemuxerFactory(demuxer_factory.Pass());
234 collection->AddAudioDecoder(new FFmpegAudioDecoder(
235 message_loop_factory_->GetMessageLoop("AudioDecoderThread")));
236 collection->AddVideoDecoder(new FFmpegVideoDecoder(
237 message_loop_factory_->GetMessageLoop("VideoDecoderThread")));
238 collection->AddVideoRenderer(new VideoRendererBase(
239 base::Bind(&PipelineIntegrationTest::OnVideoRendererPaint,
240 base::Unretained(this)),
241 base::Bind(&PipelineIntegrationTest::OnSetOpaque,
242 base::Unretained(this))));
243 collection->AddAudioRenderer(new NullAudioRenderer());
244 return collection.Pass();
245 }
246
247 // Verifies that seeking works properly for ChunkDemuxer when the 80 // Verifies that seeking works properly for ChunkDemuxer when the
248 // seek happens while there is a pending read on the ChunkDemuxer 81 // seek happens while there is a pending read on the ChunkDemuxer
249 // and no data is available. 82 // and no data is available.
250 bool TestSeekDuringRead(const std::string& filename, 83 bool TestSeekDuringRead(const std::string& filename,
251 int initial_append_size, 84 int initial_append_size,
252 base::TimeDelta start_seek_time, 85 base::TimeDelta start_seek_time,
253 base::TimeDelta seek_time, 86 base::TimeDelta seek_time,
254 int seek_file_position, 87 int seek_file_position,
255 int seek_append_size) { 88 int seek_append_size) {
256 MockMediaSource source(filename, initial_append_size); 89 MockMediaSource source(filename, initial_append_size);
(...skipping 17 matching lines...) Expand all
274 source.Seek(seek_file_position, seek_append_size); 107 source.Seek(seek_file_position, seek_append_size);
275 if (!Seek(seek_time)) 108 if (!Seek(seek_time))
276 return false; 109 return false;
277 110
278 source.EndOfStream(); 111 source.EndOfStream();
279 112
280 source.Abort(); 113 source.Abort();
281 Stop(); 114 Stop();
282 return true; 115 return true;
283 } 116 }
284
285 protected:
286 MessageLoop message_loop_;
287 scoped_ptr<MessageLoopFactory> message_loop_factory_;
288 scoped_refptr<Pipeline> pipeline_;
289 bool ended_;
290 PipelineStatus pipeline_status_;
291
292 private:
293 MOCK_METHOD0(OnVideoRendererPaint, void());
294 MOCK_METHOD1(OnSetOpaque, void(bool));
295 }; 117 };
296 118
297 119
298 TEST_F(PipelineIntegrationTest, BasicPlayback) { 120 TEST_F(PipelineIntegrationTest, BasicPlayback) {
299 ASSERT_TRUE(Start(GetTestDataURL("bear-320x240.webm"), PIPELINE_OK)); 121 ASSERT_TRUE(Start(GetTestDataURL("bear-320x240.webm"), PIPELINE_OK));
300 122
301 Play(); 123 Play();
302 124
303 ASSERT_TRUE(WaitUntilOnEnded()); 125 ASSERT_TRUE(WaitUntilOnEnded());
304 } 126 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 179
358 // Verify video decoder & renderer can handle aborted demuxer reads. 180 // Verify video decoder & renderer can handle aborted demuxer reads.
359 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { 181 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
360 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", 32768, 182 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", 32768,
361 base::TimeDelta::FromMilliseconds(200), 183 base::TimeDelta::FromMilliseconds(200),
362 base::TimeDelta::FromMilliseconds(1668), 184 base::TimeDelta::FromMilliseconds(1668),
363 0x1C896, 65536)); 185 0x1C896, 65536));
364 } 186 }
365 187
366 } // namespace media 188 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/filters/pipeline_integration_test_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698