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

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

Issue 237353007: Refactor VideoRendererImpl to use VideoFrameScheduler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: pretty much done Created 6 years, 8 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 <utility>
6
7 #include "base/bind.h" 5 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/callback_helpers.h"
10 #include "base/debug/stack_trace.h" 6 #include "base/debug/stack_trace.h"
11 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
15 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
16 #include "base/synchronization/lock.h" 11 #include "base/test/simple_test_tick_clock.h"
17 #include "base/timer/timer.h"
18 #include "media/base/data_buffer.h"
19 #include "media/base/gmock_callback_support.h" 12 #include "media/base/gmock_callback_support.h"
20 #include "media/base/limits.h"
21 #include "media/base/mock_filters.h" 13 #include "media/base/mock_filters.h"
22 #include "media/base/test_helpers.h" 14 #include "media/base/test_helpers.h"
23 #include "media/base/video_frame.h" 15 #include "media/filters/test_video_frame_scheduler.h"
24 #include "media/filters/video_renderer_impl.h" 16 #include "media/filters/video_renderer_impl.h"
25 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
26 18
27 using ::testing::_; 19 using ::testing::_;
28 using ::testing::AnyNumber; 20 using ::testing::AnyNumber;
29 using ::testing::InSequence;
30 using ::testing::Invoke; 21 using ::testing::Invoke;
31 using ::testing::NiceMock; 22 using ::testing::NiceMock;
32 using ::testing::NotNull;
33 using ::testing::Return;
34 using ::testing::StrictMock;
35 23
36 namespace media { 24 namespace media {
37 25
38 MATCHER_P(HasTimestamp, ms, "") { 26 static void AssignValue(bool* b, bool value) {
39 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); 27 *b = value;
40 return arg->timestamp().InMilliseconds() == ms;
41 } 28 }
42 29
43 // Arbitrary value. Has to be larger to cover any timestamp value used in tests.
44 static const int kVideoDurationInMs = 1000;
45
46 class VideoRendererImplTest : public ::testing::Test { 30 class VideoRendererImplTest : public ::testing::Test {
47 public: 31 public:
48 VideoRendererImplTest() 32 VideoRendererImplTest()
49 : decoder_(new MockVideoDecoder()), 33 : decoder_(new MockVideoDecoder()),
50 demuxer_stream_(DemuxerStream::VIDEO) { 34 scheduler_(new TestVideoFrameScheduler()),
35 tick_clock_(new base::SimpleTestTickClock()),
36 demuxer_stream_(DemuxerStream::VIDEO),
37 max_time_(kNoTimestamp()),
38 decoded_frames_(0),
39 dropped_frames_(0),
40 ended_cb_run_(false) {
51 ScopedVector<VideoDecoder> decoders; 41 ScopedVector<VideoDecoder> decoders;
52 decoders.push_back(decoder_); 42 decoders.push_back(decoder_);
53 43
54 renderer_.reset( 44 renderer_.reset(
55 new VideoRendererImpl(message_loop_.message_loop_proxy(), 45 new VideoRendererImpl(message_loop_.message_loop_proxy(),
46 scoped_ptr<VideoFrameScheduler>(scheduler_),
56 decoders.Pass(), 47 decoders.Pass(),
57 media::SetDecryptorReadyCB(), 48 media::SetDecryptorReadyCB()));
58 base::Bind(&StrictMock<MockDisplayCB>::Display, 49 renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
59 base::Unretained(&mock_display_cb_)),
60 true));
61 50
62 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal()); 51 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
63 52
64 // We expect these to be called but we don't care how/when. 53 // We expect these to be called but we don't care how/when.
65 EXPECT_CALL(demuxer_stream_, Read(_)) 54 EXPECT_CALL(demuxer_stream_, Read(_))
66 .WillRepeatedly(RunCallback<0>(DemuxerStream::kOk, 55 .WillRepeatedly(RunCallback<0>(DemuxerStream::kOk,
67 DecoderBuffer::CreateEOSBuffer())); 56 DecoderBuffer::CreateEOSBuffer()));
68 EXPECT_CALL(*decoder_, Stop()) 57 EXPECT_CALL(*decoder_, Stop())
69 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::StopRequested)); 58 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::StopRequested));
70 EXPECT_CALL(statistics_cb_object_, OnStatistics(_))
71 .Times(AnyNumber());
72 EXPECT_CALL(*this, OnTimeUpdate(_))
73 .Times(AnyNumber());
74 } 59 }
75 60
76 virtual ~VideoRendererImplTest() {} 61 virtual ~VideoRendererImplTest() {}
77 62
78 // Callbacks passed into Initialize().
79 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta));
80
81 void Initialize() { 63 void Initialize() {
82 // Monitor decodes from the decoder. 64 // Monitor decodes from the decoder.
83 EXPECT_CALL(*decoder_, Decode(_, _)) 65 EXPECT_CALL(*decoder_, Decode(_, _))
84 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FrameRequested)); 66 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FrameRequested));
85 67
86 EXPECT_CALL(*decoder_, Reset(_)) 68 EXPECT_CALL(*decoder_, Reset(_))
87 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested)); 69 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested));
88 70
89 InSequence s;
90
91 EXPECT_CALL(*decoder_, Initialize(_, _)) 71 EXPECT_CALL(*decoder_, Initialize(_, _))
92 .WillOnce(RunCallback<1>(PIPELINE_OK)); 72 .WillOnce(RunCallback<1>(PIPELINE_OK));
93 73
94 // Set playback rate before anything else happens. 74 // Set playback rate before anything else happens.
95 renderer_->SetPlaybackRate(1.0f); 75 renderer_->SetPlaybackRate(1.0f);
96 76
97 // Initialize, we shouldn't have any reads. 77 // Initialize, we shouldn't have any reads.
98 InitializeRenderer(PIPELINE_OK); 78 InitializeRenderer(PIPELINE_OK);
99 } 79 }
100 80
101 void InitializeRenderer(PipelineStatus expected) { 81 void InitializeRenderer(PipelineStatus expected) {
102 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected)); 82 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected));
103 WaitableMessageLoopEvent event; 83 WaitableMessageLoopEvent event;
104 CallInitialize(event.GetPipelineStatusCB()); 84 CallInitialize(event.GetPipelineStatusCB());
105 event.RunAndWaitForStatus(expected); 85 event.RunAndWaitForStatus(expected);
106 } 86 }
107 87
108 void CallInitialize(const PipelineStatusCB& status_cb) { 88 void CallInitialize(const PipelineStatusCB& status_cb) {
109 renderer_->Initialize( 89 renderer_->Initialize(
110 &demuxer_stream_, 90 &demuxer_stream_,
111 status_cb, 91 status_cb,
112 base::Bind(&MockStatisticsCB::OnStatistics, 92 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate,
113 base::Unretained(&statistics_cb_object_)),
114 base::Bind(&VideoRendererImplTest::OnTimeUpdate,
115 base::Unretained(this)), 93 base::Unretained(this)),
116 ended_event_.GetClosure(), 94 base::Bind(&VideoRendererImplTest::OnMaxTimeUpdate,
95 base::Unretained(this)),
96 base::Bind(&AssignValue, &ended_cb_run_, true),
117 error_event_.GetPipelineStatusCB(), 97 error_event_.GetPipelineStatusCB(),
118 base::Bind(&VideoRendererImplTest::GetTime, base::Unretained(this)), 98 base::Bind(&VideoRendererImplTest::time, base::Unretained(this)),
119 base::Bind(&VideoRendererImplTest::GetDuration, 99 base::Bind(&VideoRendererImplTest::duration, base::Unretained(this)));
120 base::Unretained(this)));
121 } 100 }
122 101
123 void Play() { 102 void Play() {
124 SCOPED_TRACE("Play()"); 103 SCOPED_TRACE("Play()");
125 WaitableMessageLoopEvent event; 104 WaitableMessageLoopEvent event;
126 renderer_->Play(event.GetClosure()); 105 renderer_->Play(event.GetClosure());
127 event.RunAndWait(); 106 event.RunAndWait();
128 } 107 }
129 108
130 void Preroll(int timestamp_ms, PipelineStatus expected) { 109 void Preroll(int timestamp_ms, PipelineStatus expected) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 193
215 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i]; 194 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i];
216 } 195 }
217 } 196 }
218 197
219 void WaitForError(PipelineStatus expected) { 198 void WaitForError(PipelineStatus expected) {
220 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); 199 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected));
221 error_event_.RunAndWaitForStatus(expected); 200 error_event_.RunAndWaitForStatus(expected);
222 } 201 }
223 202
224 void WaitForEnded() {
225 SCOPED_TRACE("WaitForEnded()");
226 ended_event_.RunAndWait();
227 }
228
229 void WaitForPendingRead() {
230 SCOPED_TRACE("WaitForPendingRead()");
231 if (!read_cb_.is_null())
232 return;
233
234 DCHECK(wait_for_pending_read_cb_.is_null());
235
236 WaitableMessageLoopEvent event;
237 wait_for_pending_read_cb_ = event.GetClosure();
238 event.RunAndWait();
239
240 DCHECK(!read_cb_.is_null());
241 DCHECK(wait_for_pending_read_cb_.is_null());
242 }
243
244 void SatisfyPendingRead() { 203 void SatisfyPendingRead() {
245 CHECK(!read_cb_.is_null()); 204 CHECK(!read_cb_.is_null());
246 CHECK(!decode_results_.empty()); 205 CHECK(!decode_results_.empty());
247 206
248 base::Closure closure = base::Bind( 207 base::Closure closure = base::Bind(
249 read_cb_, decode_results_.front().first, 208 read_cb_, decode_results_.front().first,
250 decode_results_.front().second); 209 decode_results_.front().second);
251 210
252 read_cb_.Reset(); 211 read_cb_.Reset();
253 decode_results_.pop_front(); 212 decode_results_.pop_front();
254 213
255 message_loop_.PostTask(FROM_HERE, closure); 214 message_loop_.PostTask(FROM_HERE, closure);
256 } 215 }
257 216
258 void AdvanceTimeInMs(int time_ms) { 217 bool pending_read() { return !read_cb_.is_null(); }
259 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 218 base::TimeDelta time() { return time_; }
260 base::AutoLock l(lock_); 219 void set_time(base::TimeDelta time) { time_ = time; }
261 time_ += base::TimeDelta::FromMilliseconds(time_ms); 220 base::TimeDelta max_time() { return max_time_; }
262 DCHECK_LE(time_.InMicroseconds(), GetDuration().InMicroseconds()); 221 int decoded_frames() { return decoded_frames_; }
222 int dropped_frames() { return dropped_frames_; }
223 bool ended_cb_run() { return ended_cb_run_; }
xhwang 2014/04/24 18:48:44 nit: make getters const?
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
224
225 base::TimeDelta duration() {
226 // Arbitrary value. Has to be larger to cover any timestamp used in tests.
acolwell GONE FROM CHROMIUM 2014/04/24 16:43:59 nit: s/larger/large/?
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
227 return base::TimeDelta::FromMilliseconds(1000);
263 } 228 }
264 229
265 protected: 230 protected:
266 // Fixture members. 231 base::MessageLoop message_loop_;
232
267 scoped_ptr<VideoRendererImpl> renderer_; 233 scoped_ptr<VideoRendererImpl> renderer_;
268 MockVideoDecoder* decoder_; // Owned by |renderer_|. 234 MockVideoDecoder* decoder_; // Owned by |renderer_|.
235 TestVideoFrameScheduler* scheduler_; // Owned by |renderer_|.
236 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
xhwang 2014/04/24 18:48:44 nit: if you align the comments, why not also align
scherkus (not reviewing) 2014/04/25 02:04:47 Done. (I think clang-format did this)
269 NiceMock<MockDemuxerStream> demuxer_stream_; 237 NiceMock<MockDemuxerStream> demuxer_stream_;
270 MockStatisticsCB statistics_cb_object_;
271
272 // Use StrictMock<T> to catch missing/extra display callbacks.
273 class MockDisplayCB {
274 public:
275 MOCK_METHOD1(Display, void(const scoped_refptr<VideoFrame>&));
276 };
277 StrictMock<MockDisplayCB> mock_display_cb_;
278 238
279 private: 239 private:
280 base::TimeDelta GetTime() {
281 base::AutoLock l(lock_);
282 return time_;
283 }
284
285 base::TimeDelta GetDuration() {
286 return base::TimeDelta::FromMilliseconds(kVideoDurationInMs);
287 }
288
289 void FrameRequested(const scoped_refptr<DecoderBuffer>& buffer, 240 void FrameRequested(const scoped_refptr<DecoderBuffer>& buffer,
290 const VideoDecoder::DecodeCB& read_cb) { 241 const VideoDecoder::DecodeCB& read_cb) {
291 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 242 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
292 CHECK(read_cb_.is_null()); 243 CHECK(read_cb_.is_null());
293 read_cb_ = read_cb; 244 read_cb_ = read_cb;
294 245
295 // Wake up WaitForPendingRead() if needed.
296 if (!wait_for_pending_read_cb_.is_null())
297 base::ResetAndReturn(&wait_for_pending_read_cb_).Run();
298
299 if (decode_results_.empty()) 246 if (decode_results_.empty())
300 return; 247 return;
301 248
302 SatisfyPendingRead(); 249 SatisfyPendingRead();
303 } 250 }
304 251
305 void FlushRequested(const base::Closure& callback) { 252 void FlushRequested(const base::Closure& callback) {
306 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 253 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
307 decode_results_.clear(); 254 decode_results_.clear();
308 if (!read_cb_.is_null()) { 255 if (!read_cb_.is_null()) {
309 QueueFrames("abort"); 256 QueueFrames("abort");
310 SatisfyPendingRead(); 257 SatisfyPendingRead();
311 } 258 }
312 259
313 message_loop_.PostTask(FROM_HERE, callback); 260 message_loop_.PostTask(FROM_HERE, callback);
314 } 261 }
315 262
316 void StopRequested() { 263 void StopRequested() {
317 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 264 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
318 decode_results_.clear(); 265 decode_results_.clear();
319 if (!read_cb_.is_null()) { 266 if (!read_cb_.is_null()) {
320 QueueFrames("abort"); 267 QueueFrames("abort");
321 SatisfyPendingRead(); 268 SatisfyPendingRead();
322 } 269 }
323 } 270 }
324 271
325 base::MessageLoop message_loop_; 272 void OnMaxTimeUpdate(base::TimeDelta max_time) { max_time_ = max_time; }
326 273
327 // Used to protect |time_|. 274 void OnStatisticsUpdate(const PipelineStatistics& stats) {
328 base::Lock lock_; 275 decoded_frames_ = stats.video_frames_decoded;
329 base::TimeDelta time_; 276 dropped_frames_ = stats.video_frames_dropped;
277 }
330 278
331 // Used for satisfying reads. 279 // Used for satisfying reads.
332 VideoDecoder::DecodeCB read_cb_; 280 VideoDecoder::DecodeCB read_cb_;
333 base::TimeDelta next_frame_timestamp_; 281 base::TimeDelta next_frame_timestamp_;
334 282
335 WaitableMessageLoopEvent error_event_; 283 WaitableMessageLoopEvent error_event_;
336 WaitableMessageLoopEvent ended_event_;
337
338 // Run during FrameRequested() to unblock WaitForPendingRead().
339 base::Closure wait_for_pending_read_cb_;
340 284
341 std::deque<std::pair< 285 std::deque<std::pair<
342 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; 286 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
343 287
288 base::TimeDelta time_;
289 base::TimeDelta max_time_;
290 int decoded_frames_;
291 int dropped_frames_;
292 bool ended_cb_run_;
293
344 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); 294 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
345 }; 295 };
346 296
347 TEST_F(VideoRendererImplTest, DoNothing) { 297 TEST_F(VideoRendererImplTest, DoNothing) {
348 // Test that creation and deletion doesn't depend on calls to Initialize() 298 // Test that creation and deletion doesn't depend on calls to Initialize()
349 // and/or Stop(). 299 // and/or Stop().
350 } 300 }
351 301
352 TEST_F(VideoRendererImplTest, StopWithoutInitialize) { 302 TEST_F(VideoRendererImplTest, StopWithoutInitialize) {
353 Stop(); 303 Stop();
354 } 304 }
355 305
356 TEST_F(VideoRendererImplTest, Initialize) { 306 TEST_F(VideoRendererImplTest, Initialize) {
357 Initialize(); 307 Initialize();
358 Shutdown(); 308 Shutdown();
359 } 309 }
360 310
361 TEST_F(VideoRendererImplTest, InitializeAndPreroll) {
362 Initialize();
363 QueueFrames("0 10 20 30");
364 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
365 Preroll(0, PIPELINE_OK);
366 Shutdown();
367 }
368
369 static void ExpectNotCalled(PipelineStatus) { 311 static void ExpectNotCalled(PipelineStatus) {
370 base::debug::StackTrace stack; 312 base::debug::StackTrace stack;
371 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString(); 313 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString();
372 } 314 }
373 315
374 TEST_F(VideoRendererImplTest, StopWhileInitializing) { 316 TEST_F(VideoRendererImplTest, StopWhileInitializing) {
375 EXPECT_CALL(*decoder_, Initialize(_, _)) 317 EXPECT_CALL(*decoder_, Initialize(_, _))
376 .WillOnce(RunCallback<1>(PIPELINE_OK)); 318 .WillOnce(RunCallback<1>(PIPELINE_OK));
377 CallInitialize(base::Bind(&ExpectNotCalled)); 319 CallInitialize(base::Bind(&ExpectNotCalled));
378 Stop(); 320 Stop();
379 321
380 // ~VideoRendererImpl() will CHECK() if we left anything initialized. 322 // ~VideoRendererImpl() will CHECK() if we left anything initialized.
381 } 323 }
382 324
383 TEST_F(VideoRendererImplTest, StopWhileFlushing) { 325 TEST_F(VideoRendererImplTest, StopWhileFlushing) {
384 Initialize(); 326 Initialize();
385 Pause(); 327 Pause();
386 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK)); 328 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK));
387 Stop(); 329 Stop();
388 330
389 // ~VideoRendererImpl() will CHECK() if we left anything initialized. 331 // ~VideoRendererImpl() will CHECK() if we left anything initialized.
390 } 332 }
391 333
392 TEST_F(VideoRendererImplTest, Play) { 334 TEST_F(VideoRendererImplTest, PrerollSchedulesFirstFrame) {
393 Initialize(); 335 Initialize();
394 QueueFrames("0 10 20 30"); 336 QueueFrames("0 10 20 30");
395 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0))); 337 Preroll(0, PIPELINE_OK);
396 Preroll(0, PIPELINE_OK); 338
397 Play(); 339 EXPECT_EQ(1u, scheduler_->scheduled_frames().size());
398 Shutdown(); 340 EXPECT_EQ(base::TimeDelta(),
399 } 341 scheduler_->scheduled_frames().front().frame->timestamp());
400 342 EXPECT_EQ(base::TimeTicks(),
xhwang 2014/04/24 18:48:44 Should base::TimeTicks() be tick_clock_->NowTicks(
scherkus (not reviewing) 2014/04/25 02:04:47 Replaced with string format.
401 TEST_F(VideoRendererImplTest, EndOfStream_ClipDuration) { 343 scheduler_->scheduled_frames().front().wall_ticks);
402 Initialize(); 344
403 QueueFrames("0 10 20 30"); 345 Shutdown();
404 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0))); 346 }
405 Preroll(0, PIPELINE_OK); 347
406 Play(); 348 TEST_F(VideoRendererImplTest, PlaySchedulesAllFrames) {
407 349 Initialize();
408 // Next frame has timestamp way past duration. Its timestamp will be adjusted 350 QueueFrames("0 10 20 30");
351 Preroll(0, PIPELINE_OK);
352 Play();
353
354 EXPECT_EQ(4u, scheduler_->scheduled_frames().size());
355 EXPECT_EQ(base::TimeDelta(),
356 scheduler_->scheduled_frames()[0].frame->timestamp());
357 EXPECT_EQ(base::TimeTicks(), scheduler_->scheduled_frames()[0].wall_ticks);
acolwell GONE FROM CHROMIUM 2014/04/24 16:43:59 String format verification for these too? Either t
xhwang 2014/04/24 18:48:44 ditto about tick_clock_->NowTicks(). Agreed with a
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
358 EXPECT_EQ(base::TimeDelta::FromMilliseconds(10),
359 scheduler_->scheduled_frames()[1].frame->timestamp());
360 EXPECT_EQ(base::TimeTicks::FromInternalValue(10000),
361 scheduler_->scheduled_frames()[1].wall_ticks);
362 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
363 scheduler_->scheduled_frames()[2].frame->timestamp());
364 EXPECT_EQ(base::TimeTicks::FromInternalValue(20000),
365 scheduler_->scheduled_frames()[2].wall_ticks);
366 EXPECT_EQ(base::TimeDelta::FromMilliseconds(30),
367 scheduler_->scheduled_frames()[3].frame->timestamp());
368 EXPECT_EQ(base::TimeTicks::FromInternalValue(30000),
369 scheduler_->scheduled_frames()[3].wall_ticks);
370
371 Shutdown();
372 }
373
374 TEST_F(VideoRendererImplTest, PauseResetsScheduledFrames) {
375 Initialize();
376 QueueFrames("0 10 20 30");
377 Preroll(0, PIPELINE_OK);
378 Play();
379 Pause();
380
381 EXPECT_EQ(0u, scheduler_->scheduled_frames().size());
xhwang 2014/04/24 18:48:44 Also check that "RESET" frames are pushed back to
scherkus (not reviewing) 2014/04/25 02:04:47 Isn't needed due to change in Reset() behaviour
382
383 Shutdown();
384 }
385
386 TEST_F(VideoRendererImplTest, PauseWaitsForResetFrames) {
387 Initialize();
388 QueueFrames("0 10 20 30");
389 Preroll(0, PIPELINE_OK);
390 Play();
391
392 scheduler_->set_should_reset(false);
acolwell GONE FROM CHROMIUM 2014/04/24 16:43:59 This is for simulating the proxy VFS case right? A
scherkus (not reviewing) 2014/04/25 02:04:47 Removed this test case due to change in Reset() be
393
394 bool pause_cb_run = false;
395 renderer_->Pause(base::Bind(&AssignValue, &pause_cb_run, true));
396 EXPECT_FALSE(pause_cb_run);
397
398 scheduler_->set_should_reset(true);
399 scheduler_->Reset();
xhwang 2014/04/24 18:48:44 See comments above about calling scheduler_->Reset
scherkus (not reviewing) 2014/04/25 02:04:47 Ditto
400 EXPECT_TRUE(pause_cb_run);
401
402 Shutdown();
403 }
404
405 TEST_F(VideoRendererImplTest, SetPlaybackRateReschedulesFrames) {
406 Initialize();
407 QueueFrames("0 10 20 30");
408 Preroll(0, PIPELINE_OK);
409 Play();
410
411 renderer_->SetPlaybackRate(2.0);
412
xhwang 2014/04/24 18:48:44 hmm, Reset() and SetPlaybackRate() all finishes sy
scherkus (not reviewing) 2014/04/25 02:04:47 actually this test started failing once I made Res
413 // Wall times should be cut in half.
414 EXPECT_EQ(4u, scheduler_->scheduled_frames().size());
acolwell GONE FROM CHROMIUM 2014/04/24 16:43:59 ditto. more concise expectations would be nice.
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
415 EXPECT_EQ(base::TimeTicks(), scheduler_->scheduled_frames()[0].wall_ticks);
xhwang 2014/04/24 18:48:44 So even the first frame is rescheduled because Res
scherkus (not reviewing) 2014/04/25 02:04:47 had to change this stuff
416 EXPECT_EQ(base::TimeDelta::FromMilliseconds(10),
417 scheduler_->scheduled_frames()[1].frame->timestamp());
418 EXPECT_EQ(base::TimeTicks::FromInternalValue(5000),
419 scheduler_->scheduled_frames()[1].wall_ticks);
420 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
421 scheduler_->scheduled_frames()[2].frame->timestamp());
422 EXPECT_EQ(base::TimeTicks::FromInternalValue(10000),
423 scheduler_->scheduled_frames()[2].wall_ticks);
424 EXPECT_EQ(base::TimeDelta::FromMilliseconds(30),
425 scheduler_->scheduled_frames()[3].frame->timestamp());
426 EXPECT_EQ(base::TimeTicks::FromInternalValue(15000),
427 scheduler_->scheduled_frames()[3].wall_ticks);
428
429 Shutdown();
430 }
431
432 TEST_F(VideoRendererImplTest, MediaTimeUsedToScheduleFrames) {
433 Initialize();
434 QueueFrames("0 10 20 30");
435 Preroll(0, PIPELINE_OK);
436
437 // Introduce an offset in the media time before playing.
438 set_time(base::TimeDelta::FromMilliseconds(20));
439
440 Play();
441
442 // All newly scheduled frames should respect the media time.
443 EXPECT_EQ(4u, scheduler_->scheduled_frames().size());
444 EXPECT_EQ(base::TimeTicks(), scheduler_->scheduled_frames()[0].wall_ticks);
xhwang 2014/04/24 18:48:44 So this is from the ScheduleFirstFrameForImmediate
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
445 EXPECT_EQ(base::TimeDelta::FromMilliseconds(10),
446 scheduler_->scheduled_frames()[1].frame->timestamp());
447 EXPECT_EQ(base::TimeTicks::FromInternalValue(-10000),
448 scheduler_->scheduled_frames()[1].wall_ticks);
449 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
450 scheduler_->scheduled_frames()[2].frame->timestamp());
451 EXPECT_EQ(base::TimeTicks(), scheduler_->scheduled_frames()[2].wall_ticks);
xhwang 2014/04/24 18:48:44 This make it harder to read, I'd rather see base::
scherkus (not reviewing) 2014/04/25 02:04:47 Replaced with string format.
452 EXPECT_EQ(base::TimeDelta::FromMilliseconds(30),
453 scheduler_->scheduled_frames()[3].frame->timestamp());
454 EXPECT_EQ(base::TimeTicks::FromInternalValue(10000),
455 scheduler_->scheduled_frames()[3].wall_ticks);
456
457 Shutdown();
458 }
459
460 TEST_F(VideoRendererImplTest, EndedWaitsForLastFrame) {
461 Initialize();
462 QueueFrames("0 10 20 30 eos");
463 Preroll(0, PIPELINE_OK);
464 Play();
465
466 // Display up to last frame.
467 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(20000));
xhwang 2014/04/24 18:48:44 Write a helper function DisplayFrames(ms) so that
scherkus (not reviewing) 2014/04/25 02:04:47 Done.
468 message_loop_.RunUntilIdle();
469 EXPECT_FALSE(ended_cb_run());
470
471 // Display last frame.
472 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(30000));
473 message_loop_.RunUntilIdle();
474 EXPECT_TRUE(ended_cb_run());
475
476 Shutdown();
477 }
478
479 TEST_F(VideoRendererImplTest, EndedWaitsForEndOfStream) {
480 Initialize();
481 QueueFrames("0 10 20 30");
482 Preroll(0, PIPELINE_OK);
483 Play();
484
485 // Display last frame.
486 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(30000));
487 message_loop_.RunUntilIdle();
488 EXPECT_FALSE(ended_cb_run());
489
490 // Deliver end of stream.
491 QueueFrames("eos");
492 SatisfyPendingRead();
493 message_loop_.RunUntilIdle();
494 EXPECT_TRUE(ended_cb_run());
495
496 Shutdown();
497 }
498
499 TEST_F(VideoRendererImplTest, AdjustTimestampsPastDuration) {
500 Initialize();
501 QueueFrames("0 10 20 30");
502 Preroll(0, PIPELINE_OK);
503 Play();
504
505 // Last frame has timestamp way past duration. Its timestamp will be adjusted
409 // to match the duration of the video. 506 // to match the duration of the video.
410 QueueFrames(base::IntToString(kVideoDurationInMs + 1000)); 507 QueueFrames(base::IntToString((duration() * 10).InMilliseconds()));
411
412 // Queue the end of stream frame and wait for the last frame to be rendered.
413 QueueFrames("eos"); 508 QueueFrames("eos");
414 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(kVideoDurationInMs))); 509
415 AdvanceTimeInMs(kVideoDurationInMs); 510 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(30000));
416 WaitForEnded(); 511 message_loop_.RunUntilIdle();
417 512
418 Shutdown(); 513 EXPECT_EQ(1u, scheduler_->scheduled_frames().size());
419 } 514 EXPECT_EQ(duration(),
515 scheduler_->scheduled_frames().front().frame->timestamp());
516
517 Shutdown();
518 }
519
520 TEST_F(VideoRendererImplTest, IncomingFramesUpdateMaxTime) {
521 EXPECT_EQ(kNoTimestamp(), max_time());
522
523 Initialize();
524 QueueFrames("0 10 20 30");
525 Preroll(0, PIPELINE_OK);
526
527 EXPECT_EQ(base::TimeDelta::FromMilliseconds(30), max_time());
528
529 Shutdown();
530 }
531
532 TEST_F(VideoRendererImplTest, EndOfStreamSetsMaxTimeToDuration) {
533 EXPECT_EQ(kNoTimestamp(), max_time());
534
535 Initialize();
536 QueueFrames("0 10 20 eos");
537 Preroll(0, PIPELINE_OK);
538
539 EXPECT_EQ(duration(), max_time());
540
541 Shutdown();
542 }
543
544 TEST_F(VideoRendererImplTest, DisplayedFramesIncrementStatistics) {
545 Initialize();
546 QueueFrames("0 10 20 30");
547 Preroll(0, PIPELINE_OK);
548 Play();
549
550 EXPECT_EQ(0, decoded_frames());
551 EXPECT_EQ(0, dropped_frames());
552
553 scheduler_->DisplayFrames(base::TimeTicks());
554
555 EXPECT_EQ(1, decoded_frames());
556 EXPECT_EQ(0, dropped_frames());
557
558 Shutdown();
559 }
560
561 TEST_F(VideoRendererImplTest, DroppedFramesIncrementStatistics) {
562 Initialize();
563 QueueFrames("0 10 20 30");
564 Preroll(0, PIPELINE_OK);
565 Play();
566
567 EXPECT_EQ(0, decoded_frames());
568 EXPECT_EQ(0, dropped_frames());
569
570 scheduler_->DropFrames(base::TimeTicks());
571
572 EXPECT_EQ(1, decoded_frames());
573 EXPECT_EQ(1, dropped_frames());
574
575 Shutdown();
576 }
420 577
xhwang 2014/04/24 18:48:44 Also test that reset doesn't affect stats?
scherkus (not reviewing) 2014/04/25 02:04:47 Changed reset so it no longer calls back
421 TEST_F(VideoRendererImplTest, DecodeError_Playing) { 578 TEST_F(VideoRendererImplTest, DecodeError_Playing) {
422 Initialize(); 579 Initialize();
423 QueueFrames("0 10 20 30"); 580 QueueFrames("0 10 20 30");
424 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
425 Preroll(0, PIPELINE_OK); 581 Preroll(0, PIPELINE_OK);
426 Play(); 582 Play();
427 583
584 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(30000));
585 EXPECT_TRUE(pending_read());
586
428 QueueFrames("error"); 587 QueueFrames("error");
429 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 588 SatisfyPendingRead();
430 AdvanceTimeInMs(10);
431 WaitForError(PIPELINE_ERROR_DECODE); 589 WaitForError(PIPELINE_ERROR_DECODE);
432 Shutdown(); 590 Shutdown();
433 } 591 }
434 592
435 TEST_F(VideoRendererImplTest, DecodeError_DuringPreroll) { 593 TEST_F(VideoRendererImplTest, DecodeError_DuringPreroll) {
436 Initialize(); 594 Initialize();
437 QueueFrames("error"); 595 QueueFrames("error");
438 Preroll(0, PIPELINE_ERROR_DECODE); 596 Preroll(0, PIPELINE_ERROR_DECODE);
439 Shutdown(); 597 Shutdown();
440 } 598 }
441 599
442 TEST_F(VideoRendererImplTest, Preroll_Exact) { 600 TEST_F(VideoRendererImplTest, Preroll_Exact) {
443 Initialize(); 601 Initialize();
444 QueueFrames("50 60 70 80 90"); 602 QueueFrames("50 60 70 80 90");
445
446 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
447 Preroll(60, PIPELINE_OK); 603 Preroll(60, PIPELINE_OK);
604 EXPECT_EQ(base::TimeDelta::FromMilliseconds(60),
605 scheduler_->scheduled_frames().front().frame->timestamp());
448 Shutdown(); 606 Shutdown();
449 } 607 }
450 608
451 TEST_F(VideoRendererImplTest, Preroll_RightBefore) { 609 TEST_F(VideoRendererImplTest, Preroll_RightBefore) {
452 Initialize(); 610 Initialize();
453 QueueFrames("50 60 70 80 90"); 611 QueueFrames("50 60 70 80 90");
454
455 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(50)));
456 Preroll(59, PIPELINE_OK); 612 Preroll(59, PIPELINE_OK);
613 EXPECT_EQ(base::TimeDelta::FromMilliseconds(50),
614 scheduler_->scheduled_frames().front().frame->timestamp());
457 Shutdown(); 615 Shutdown();
458 } 616 }
459 617
460 TEST_F(VideoRendererImplTest, Preroll_RightAfter) { 618 TEST_F(VideoRendererImplTest, Preroll_RightAfter) {
461 Initialize(); 619 Initialize();
462 QueueFrames("50 60 70 80 90"); 620 QueueFrames("50 60 70 80 90");
463
464 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
465 Preroll(61, PIPELINE_OK); 621 Preroll(61, PIPELINE_OK);
622 EXPECT_EQ(base::TimeDelta::FromMilliseconds(60),
623 scheduler_->scheduled_frames().front().frame->timestamp());
466 Shutdown(); 624 Shutdown();
467 } 625 }
468 626
469 TEST_F(VideoRendererImplTest, PlayAfterPreroll) { 627 TEST_F(VideoRendererImplTest, PlayAfterPreroll) {
470 Initialize(); 628 Initialize();
471 QueueFrames("0 10 20 30"); 629 QueueFrames("0 10 20 30");
472 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
473 Preroll(0, PIPELINE_OK); 630 Preroll(0, PIPELINE_OK);
474 Play(); 631 Play();
475 632
476 // Advance time past prerolled time to trigger a Read(). 633 scheduler_->DisplayFrames(base::TimeTicks());
477 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 634 EXPECT_TRUE(pending_read());
478 AdvanceTimeInMs(10); 635
479 WaitForPendingRead();
480 Shutdown(); 636 Shutdown();
481 } 637 }
482 638
483 TEST_F(VideoRendererImplTest, Rebuffer) { 639 TEST_F(VideoRendererImplTest, Rebuffer) {
484 Initialize(); 640 Initialize();
485 QueueFrames("0 10 20 30"); 641 QueueFrames("0 10 20 30");
486 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
487 Preroll(0, PIPELINE_OK); 642 Preroll(0, PIPELINE_OK);
488 Play(); 643 Play();
489 644
490 // Advance time past prerolled time drain the ready frame queue. 645 // Display all frames to empty frame buffer.
491 AdvanceTimeInMs(50); 646 scheduler_->DisplayFrames(base::TimeTicks::FromInternalValue(30000));
492 WaitForPendingRead(); 647 EXPECT_TRUE(pending_read());
493 648
494 // Simulate a Pause/Preroll/Play rebuffer sequence. 649 // Simulate a Pause/Preroll/Play rebuffer sequence.
495 Pause(); 650 Pause();
496 651
497 WaitableMessageLoopEvent event; 652 WaitableMessageLoopEvent event;
498 renderer_->Preroll(kNoTimestamp(), 653 renderer_->Preroll(kNoTimestamp(),
499 event.GetPipelineStatusCB()); 654 event.GetPipelineStatusCB());
500 655
501 // Queue enough frames to satisfy preroll. 656 // Queue enough frames to satisfy preroll.
502 QueueFrames("40 50 60 70"); 657 QueueFrames("40 50 60 70");
503 SatisfyPendingRead(); 658 SatisfyPendingRead();
659 event.RunAndWaitForStatus(PIPELINE_OK);
504 660
505 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer 661 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer
506 // situation, see http://crbug.com/365516 662 // situation, see http://crbug.com/365516
507 EXPECT_CALL(mock_display_cb_, Display(_)); 663 EXPECT_EQ(1u, scheduler_->scheduled_frames().size());
508
509 event.RunAndWaitForStatus(PIPELINE_OK);
510 664
511 Play(); 665 Play();
512 666
513 Shutdown(); 667 Shutdown();
514 } 668 }
515 669
516 TEST_F(VideoRendererImplTest, Rebuffer_AlreadyHaveEnoughFrames) { 670 TEST_F(VideoRendererImplTest, Rebuffer_AlreadyHaveEnoughFrames) {
517 Initialize(); 671 Initialize();
518 QueueFrames("0 10 20 30"); 672 QueueFrames("0 10 20 30");
519 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
520 Preroll(0, PIPELINE_OK); 673 Preroll(0, PIPELINE_OK);
521
522 // Queue an extra frame so that we'll have enough frames to satisfy
523 // preroll even after the first frame is painted.
524 QueueFrames("40");
525 Play(); 674 Play();
526 675
527 // Simulate a Pause/Preroll/Play rebuffer sequence. 676 // Simulate a Pause/Preroll/Play rebuffer sequence.
528 Pause(); 677 Pause();
529 678
530 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer
531 // situation, see http://crbug.com/365516
532 EXPECT_CALL(mock_display_cb_, Display(_));
533
534 WaitableMessageLoopEvent event; 679 WaitableMessageLoopEvent event;
535 renderer_->Preroll(kNoTimestamp(), 680 renderer_->Preroll(kNoTimestamp(),
536 event.GetPipelineStatusCB()); 681 event.GetPipelineStatusCB());
682 event.RunAndWaitForStatus(PIPELINE_OK);
537 683
538 event.RunAndWaitForStatus(PIPELINE_OK); 684 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer
685 // situation, see http://crbug.com/365516
686 EXPECT_EQ(1u, scheduler_->scheduled_frames().size());
539 687
540 Play(); 688 Play();
541 689
542 Shutdown(); 690 Shutdown();
543 } 691 }
544 692
545 // Verify that a late decoder response doesn't break invariants in the renderer. 693 // Verify that a late decoder response doesn't break invariants in the renderer.
546 TEST_F(VideoRendererImplTest, StopDuringOutstandingRead) { 694 TEST_F(VideoRendererImplTest, StopDuringOutstandingRead) {
547 Initialize(); 695 Initialize();
548 QueueFrames("0 10 20 30"); 696 QueueFrames("0 10 20 30");
549 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
550 Preroll(0, PIPELINE_OK); 697 Preroll(0, PIPELINE_OK);
551 Play(); 698 Play();
552 699
553 // Advance time a bit to trigger a Read(). 700 scheduler_->DisplayFrames(base::TimeTicks());
554 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 701 EXPECT_TRUE(pending_read());
555 AdvanceTimeInMs(10);
556 WaitForPendingRead();
557 702
558 WaitableMessageLoopEvent event; 703 WaitableMessageLoopEvent event;
559 renderer_->Stop(event.GetClosure()); 704 renderer_->Stop(event.GetClosure());
560 event.RunAndWait(); 705 event.RunAndWait();
561 } 706 }
562 707
563 TEST_F(VideoRendererImplTest, AbortPendingRead_Playing) { 708 TEST_F(VideoRendererImplTest, AbortPendingRead_Playing) {
564 Initialize(); 709 Initialize();
565 QueueFrames("0 10 20 30"); 710 QueueFrames("0 10 20 30");
566 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
567 Preroll(0, PIPELINE_OK); 711 Preroll(0, PIPELINE_OK);
568 Play(); 712 Play();
569 713
570 // Advance time a bit to trigger a Read(). 714 scheduler_->DisplayFrames(base::TimeTicks());
571 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 715 EXPECT_TRUE(pending_read());
572 AdvanceTimeInMs(10);
573 WaitForPendingRead();
574 QueueFrames("abort"); 716 QueueFrames("abort");
575 SatisfyPendingRead(); 717 SatisfyPendingRead();
576 718
577 Pause(); 719 Pause();
578 Flush(); 720 Flush();
579 QueueFrames("60 70 80 90"); 721 QueueFrames("60 70 80 90");
580 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
581 Preroll(60, PIPELINE_OK); 722 Preroll(60, PIPELINE_OK);
582 Shutdown(); 723 Shutdown();
583 } 724 }
584 725
585 TEST_F(VideoRendererImplTest, AbortPendingRead_Flush) { 726 TEST_F(VideoRendererImplTest, AbortPendingRead_Flush) {
586 Initialize(); 727 Initialize();
587 QueueFrames("0 10 20 30"); 728 QueueFrames("0 10 20 30");
588 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
589 Preroll(0, PIPELINE_OK); 729 Preroll(0, PIPELINE_OK);
590 Play(); 730 Play();
591 731
592 // Advance time a bit to trigger a Read(). 732 scheduler_->DisplayFrames(base::TimeTicks());
593 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 733 EXPECT_TRUE(pending_read());
594 AdvanceTimeInMs(10);
595 WaitForPendingRead();
596 734
597 Pause(); 735 Pause();
598 Flush(); 736 Flush();
599 Shutdown(); 737 Shutdown();
600 } 738 }
601 739
602 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) { 740 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) {
603 Initialize(); 741 Initialize();
604 QueueFrames("0 10 abort"); 742 QueueFrames("0 10 abort");
605 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
606 Preroll(0, PIPELINE_OK); 743 Preroll(0, PIPELINE_OK);
607 Shutdown(); 744 Shutdown();
608 } 745 }
609 746
610 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { 747 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
611 InSequence s;
612
613 EXPECT_CALL(*decoder_, Initialize(_, _)) 748 EXPECT_CALL(*decoder_, Initialize(_, _))
614 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); 749 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED));
615 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED); 750 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED);
616 751
617 Stop(); 752 Stop();
618 } 753 }
619 754
620 } // namespace media 755 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698