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

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: rebase over split out CLs 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
« no previous file with comments | « media/filters/video_renderer_impl.cc ('k') | media/tools/player_x11/player_x11.cc » ('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 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 void DisplayFramesUpTo(int ms) {
259 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 218 scheduler_->DisplayFramesUpTo(
260 base::AutoLock l(lock_); 219 base::TimeTicks::FromInternalValue(ms * 1000));
261 time_ += base::TimeDelta::FromMilliseconds(time_ms); 220 }
262 DCHECK_LE(time_.InMicroseconds(), GetDuration().InMicroseconds()); 221
222 void DropFramesUpTo(int ms) {
223 scheduler_->DropFramesUpTo(
224 base::TimeTicks::FromInternalValue(ms * 1000));
225 }
226
227 // Returns a string representation of all scheduled frames' timestamps.
228 // Timestamps are in milliseconds.
229 //
230 // Example: "0 10 20"
231 std::string ScheduledFrameTimestamps() {
232 std::string str;
233 for (size_t i = 0; i < scheduler_->scheduled_frames().size(); ++i) {
234 base::TimeDelta timestamp =
235 scheduler_->scheduled_frames()[i].frame->timestamp();
236
237 if (i > 0)
238 str += " ";
239 str += base::Int64ToString(timestamp.InMilliseconds());
240 }
241 return str;
242 }
243
244 // Returns a string representation of all scheduled frames' wall ticks. Ticks
245 // are represented using their internal value.
246 //
247 // Example: "0 10000 20000"
248 std::string ScheduledFrameWallTicks() {
249 std::string str;
250 for (size_t i = 0; i < scheduler_->scheduled_frames().size(); ++i) {
251 base::TimeTicks wall_ticks = scheduler_->scheduled_frames()[i].wall_ticks;
252
253 if (i > 0)
254 str += " ";
255 str += base::Int64ToString(wall_ticks.ToInternalValue());
256 }
257 return str;
258 }
259
260 bool pending_read() const { return !read_cb_.is_null(); }
261 base::TimeDelta time() const { return time_; }
262 void set_time(base::TimeDelta time) { time_ = time; }
263 base::TimeDelta max_time() const { return max_time_; }
264 int decoded_frames() const { return decoded_frames_; }
265 int dropped_frames() const { return dropped_frames_; }
266 bool ended_cb_run() const { return ended_cb_run_; }
267
268 base::TimeDelta duration() const {
269 // Arbitrary value. Has to be large to cover any timestamp used in tests.
270 return base::TimeDelta::FromMilliseconds(1000);
263 } 271 }
264 272
265 protected: 273 protected:
266 // Fixture members. 274 base::MessageLoop message_loop_;
267 scoped_ptr<VideoRendererImpl> renderer_; 275 scoped_ptr<VideoRendererImpl> renderer_;
268 MockVideoDecoder* decoder_; // Owned by |renderer_|. 276 MockVideoDecoder* decoder_; // Owned by |renderer_|.
269 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 277
279 private: 278 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, 279 void FrameRequested(const scoped_refptr<DecoderBuffer>& buffer,
290 const VideoDecoder::DecodeCB& read_cb) { 280 const VideoDecoder::DecodeCB& read_cb) {
291 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 281 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
292 CHECK(read_cb_.is_null()); 282 CHECK(read_cb_.is_null());
293 read_cb_ = read_cb; 283 read_cb_ = read_cb;
294 284
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()) 285 if (decode_results_.empty())
300 return; 286 return;
301 287
302 SatisfyPendingRead(); 288 SatisfyPendingRead();
303 } 289 }
304 290
305 void FlushRequested(const base::Closure& callback) { 291 void FlushRequested(const base::Closure& callback) {
306 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 292 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
307 decode_results_.clear(); 293 decode_results_.clear();
308 if (!read_cb_.is_null()) { 294 if (!read_cb_.is_null()) {
309 QueueFrames("abort"); 295 QueueFrames("abort");
310 SatisfyPendingRead(); 296 SatisfyPendingRead();
311 } 297 }
312 298
313 message_loop_.PostTask(FROM_HERE, callback); 299 message_loop_.PostTask(FROM_HERE, callback);
314 } 300 }
315 301
316 void StopRequested() { 302 void StopRequested() {
317 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 303 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
318 decode_results_.clear(); 304 decode_results_.clear();
319 if (!read_cb_.is_null()) { 305 if (!read_cb_.is_null()) {
320 QueueFrames("abort"); 306 QueueFrames("abort");
321 SatisfyPendingRead(); 307 SatisfyPendingRead();
322 } 308 }
323 } 309 }
324 310
325 base::MessageLoop message_loop_; 311 void OnMaxTimeUpdate(base::TimeDelta max_time) { max_time_ = max_time; }
326 312
327 // Used to protect |time_|. 313 void OnStatisticsUpdate(const PipelineStatistics& stats) {
328 base::Lock lock_; 314 decoded_frames_ = stats.video_frames_decoded;
329 base::TimeDelta time_; 315 dropped_frames_ = stats.video_frames_dropped;
316 }
317
318 TestVideoFrameScheduler* scheduler_; // Owned by |renderer_|.
319 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
320 NiceMock<MockDemuxerStream> demuxer_stream_;
330 321
331 // Used for satisfying reads. 322 // Used for satisfying reads.
332 VideoDecoder::DecodeCB read_cb_; 323 VideoDecoder::DecodeCB read_cb_;
333 base::TimeDelta next_frame_timestamp_; 324 base::TimeDelta next_frame_timestamp_;
334 325
335 WaitableMessageLoopEvent error_event_; 326 WaitableMessageLoopEvent error_event_;
336 WaitableMessageLoopEvent ended_event_;
337
338 // Run during FrameRequested() to unblock WaitForPendingRead().
339 base::Closure wait_for_pending_read_cb_;
340 327
341 std::deque<std::pair< 328 std::deque<std::pair<
342 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; 329 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
343 330
331 base::TimeDelta time_;
332 base::TimeDelta max_time_;
333 int decoded_frames_;
334 int dropped_frames_;
335 bool ended_cb_run_;
336
344 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); 337 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
345 }; 338 };
346 339
347 TEST_F(VideoRendererImplTest, DoNothing) { 340 TEST_F(VideoRendererImplTest, DoNothing) {
348 // Test that creation and deletion doesn't depend on calls to Initialize() 341 // Test that creation and deletion doesn't depend on calls to Initialize()
349 // and/or Stop(). 342 // and/or Stop().
350 } 343 }
351 344
352 TEST_F(VideoRendererImplTest, StopWithoutInitialize) { 345 TEST_F(VideoRendererImplTest, StopWithoutInitialize) {
353 Stop(); 346 Stop();
354 } 347 }
355 348
356 TEST_F(VideoRendererImplTest, Initialize) { 349 TEST_F(VideoRendererImplTest, Initialize) {
357 Initialize(); 350 Initialize();
358 Shutdown(); 351 Shutdown();
359 } 352 }
360 353
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) { 354 static void ExpectNotCalled(PipelineStatus) {
370 base::debug::StackTrace stack; 355 base::debug::StackTrace stack;
371 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString(); 356 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString();
372 } 357 }
373 358
374 TEST_F(VideoRendererImplTest, StopWhileInitializing) { 359 TEST_F(VideoRendererImplTest, StopWhileInitializing) {
375 EXPECT_CALL(*decoder_, Initialize(_, _)) 360 EXPECT_CALL(*decoder_, Initialize(_, _))
376 .WillOnce(RunCallback<1>(PIPELINE_OK)); 361 .WillOnce(RunCallback<1>(PIPELINE_OK));
377 CallInitialize(base::Bind(&ExpectNotCalled)); 362 CallInitialize(base::Bind(&ExpectNotCalled));
378 Stop(); 363 Stop();
379 364
380 // ~VideoRendererImpl() will CHECK() if we left anything initialized. 365 // ~VideoRendererImpl() will CHECK() if we left anything initialized.
381 } 366 }
382 367
383 TEST_F(VideoRendererImplTest, StopWhileFlushing) { 368 TEST_F(VideoRendererImplTest, StopWhileFlushing) {
384 Initialize(); 369 Initialize();
385 Pause(); 370 Pause();
386 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK)); 371 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK));
387 Stop(); 372 Stop();
388 373
389 // ~VideoRendererImpl() will CHECK() if we left anything initialized. 374 // ~VideoRendererImpl() will CHECK() if we left anything initialized.
390 } 375 }
391 376
392 TEST_F(VideoRendererImplTest, Play) { 377 TEST_F(VideoRendererImplTest, PrerollSchedulesFirstFrame) {
393 Initialize(); 378 Initialize();
394 QueueFrames("0 10 20 30"); 379 QueueFrames("0 10 20 30");
395 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
396 Preroll(0, PIPELINE_OK); 380 Preroll(0, PIPELINE_OK);
397 Play(); 381
382 EXPECT_EQ("0", ScheduledFrameTimestamps());
383 EXPECT_EQ("0", ScheduledFrameWallTicks());
384
398 Shutdown(); 385 Shutdown();
399 } 386 }
400 387
401 TEST_F(VideoRendererImplTest, EndOfStream_ClipDuration) { 388 TEST_F(VideoRendererImplTest, PlaySchedulesAllFrames) {
402 Initialize(); 389 Initialize();
403 QueueFrames("0 10 20 30"); 390 QueueFrames("0 10 20 30");
404 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
405 Preroll(0, PIPELINE_OK); 391 Preroll(0, PIPELINE_OK);
406 Play(); 392 Play();
407 393
408 // Next frame has timestamp way past duration. Its timestamp will be adjusted 394 EXPECT_EQ("0 10 20 30", ScheduledFrameTimestamps());
409 // to match the duration of the video. 395 EXPECT_EQ("0 10000 20000 30000", ScheduledFrameWallTicks());
410 QueueFrames(base::IntToString(kVideoDurationInMs + 1000));
411
412 // Queue the end of stream frame and wait for the last frame to be rendered.
413 QueueFrames("eos");
414 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(kVideoDurationInMs)));
415 AdvanceTimeInMs(kVideoDurationInMs);
416 WaitForEnded();
417 396
418 Shutdown(); 397 Shutdown();
419 } 398 }
399
400 TEST_F(VideoRendererImplTest, PauseResetsScheduledFrames) {
401 Initialize();
402 QueueFrames("0 10 20 30");
403 Preroll(0, PIPELINE_OK);
404 Play();
405 Pause();
406
407 EXPECT_EQ("", ScheduledFrameTimestamps());
408
409 Shutdown();
410 }
411
412 TEST_F(VideoRendererImplTest, SetPlaybackRateReschedulesFrames) {
413 Initialize();
414 QueueFrames("0 10 20 30");
415 Preroll(0, PIPELINE_OK);
416 Play();
417
418 renderer_->SetPlaybackRate(2.0);
419
420 // Wall times should be cut in half.
421 EXPECT_EQ("0 10 20 30", ScheduledFrameTimestamps());
422 EXPECT_EQ("0 5000 10000 15000", ScheduledFrameWallTicks());
423
424 renderer_->SetPlaybackRate(0.5);
425
426 // Wall times should be doubled.
427 EXPECT_EQ("0 10 20 30", ScheduledFrameTimestamps());
428 EXPECT_EQ("0 20000 40000 60000", ScheduledFrameWallTicks());
429
430 Shutdown();
431 }
432
433 TEST_F(VideoRendererImplTest, MediaTimeUsedToScheduleFrames) {
434 Initialize();
435 QueueFrames("0 10 20 30");
436 Preroll(0, PIPELINE_OK);
437
438 // Introduce an offset in the media time before playing.
439 set_time(base::TimeDelta::FromMilliseconds(20));
440
441 Play();
442
443 // All newly scheduled frames should respect the media time.
444 // The first frame is present due to prerolling.
445 EXPECT_EQ("0 10 20 30", ScheduledFrameTimestamps());
446 EXPECT_EQ("0 -10000 0 10000", ScheduledFrameWallTicks());
447
448 Shutdown();
449 }
450
451 TEST_F(VideoRendererImplTest, EndedWaitsForLastFrame) {
452 Initialize();
453 QueueFrames("0 10 20 30 eos");
454 Preroll(0, PIPELINE_OK);
455 Play();
456
457 // Display up to last frame.
458 DisplayFramesUpTo(20);
459 message_loop_.RunUntilIdle();
460 EXPECT_FALSE(ended_cb_run());
461
462 // Display last frame.
463 DisplayFramesUpTo(30);
464 message_loop_.RunUntilIdle();
465 EXPECT_TRUE(ended_cb_run());
466
467 Shutdown();
468 }
469
470 TEST_F(VideoRendererImplTest, EndedWaitsForEndOfStream) {
471 Initialize();
472 QueueFrames("0 10 20 30");
473 Preroll(0, PIPELINE_OK);
474 Play();
475
476 // Display last frame.
477 DisplayFramesUpTo(30);
478 message_loop_.RunUntilIdle();
479 EXPECT_FALSE(ended_cb_run());
480
481 // Deliver end of stream.
482 QueueFrames("eos");
483 SatisfyPendingRead();
484 message_loop_.RunUntilIdle();
485 EXPECT_TRUE(ended_cb_run());
486
487 Shutdown();
488 }
489
490 TEST_F(VideoRendererImplTest, AdjustTimestampsPastDuration) {
491 Initialize();
492 QueueFrames("0 10 20 30");
493 Preroll(0, PIPELINE_OK);
494 Play();
495
496 // Last frame has timestamp way past duration. Its timestamp will be adjusted
497 // to match the duration of the video.
498 QueueFrames(base::IntToString((duration() * 10).InMilliseconds()));
499 QueueFrames("eos");
500
501 DisplayFramesUpTo(30);
502 message_loop_.RunUntilIdle();
503
504 EXPECT_EQ("1000", ScheduledFrameTimestamps());
505
506 Shutdown();
507 }
508
509 TEST_F(VideoRendererImplTest, IncomingFramesUpdateMaxTime) {
510 EXPECT_EQ(kNoTimestamp(), max_time());
511
512 Initialize();
513 QueueFrames("0 10 20 30");
514 Preroll(0, PIPELINE_OK);
515
516 EXPECT_EQ(base::TimeDelta::FromMilliseconds(30), max_time());
517
518 Shutdown();
519 }
520
521 TEST_F(VideoRendererImplTest, EndOfStreamSetsMaxTimeToDuration) {
522 EXPECT_EQ(kNoTimestamp(), max_time());
523
524 Initialize();
525 QueueFrames("0 10 20 eos");
526 Preroll(0, PIPELINE_OK);
527
528 EXPECT_EQ(duration(), max_time());
529
530 Shutdown();
531 }
532
533 TEST_F(VideoRendererImplTest, DisplayedFramesIncrementStatistics) {
534 Initialize();
535 QueueFrames("0 10 20 30");
536 Preroll(0, PIPELINE_OK);
537 Play();
538
539 EXPECT_EQ(0, decoded_frames());
540 EXPECT_EQ(0, dropped_frames());
541
542 DisplayFramesUpTo(0);
543
544 EXPECT_EQ(1, decoded_frames());
545 EXPECT_EQ(0, dropped_frames());
546
547 Shutdown();
548 }
549
550 TEST_F(VideoRendererImplTest, DroppedFramesIncrementStatistics) {
551 Initialize();
552 QueueFrames("0 10 20 30");
553 Preroll(0, PIPELINE_OK);
554 Play();
555
556 EXPECT_EQ(0, decoded_frames());
557 EXPECT_EQ(0, dropped_frames());
558
559 DropFramesUpTo(0);
560
561 EXPECT_EQ(1, decoded_frames());
562 EXPECT_EQ(1, dropped_frames());
563
564 Shutdown();
565 }
420 566
421 TEST_F(VideoRendererImplTest, DecodeError_Playing) { 567 TEST_F(VideoRendererImplTest, DecodeError_Playing) {
422 Initialize(); 568 Initialize();
423 QueueFrames("0 10 20 30"); 569 QueueFrames("0 10 20 30");
424 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
425 Preroll(0, PIPELINE_OK); 570 Preroll(0, PIPELINE_OK);
426 Play(); 571 Play();
427 572
573 DisplayFramesUpTo(3);
574 EXPECT_TRUE(pending_read());
575
428 QueueFrames("error"); 576 QueueFrames("error");
429 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 577 SatisfyPendingRead();
430 AdvanceTimeInMs(10);
431 WaitForError(PIPELINE_ERROR_DECODE); 578 WaitForError(PIPELINE_ERROR_DECODE);
432 Shutdown(); 579 Shutdown();
433 } 580 }
434 581
435 TEST_F(VideoRendererImplTest, DecodeError_DuringPreroll) { 582 TEST_F(VideoRendererImplTest, DecodeError_DuringPreroll) {
436 Initialize(); 583 Initialize();
437 QueueFrames("error"); 584 QueueFrames("error");
438 Preroll(0, PIPELINE_ERROR_DECODE); 585 Preroll(0, PIPELINE_ERROR_DECODE);
439 Shutdown(); 586 Shutdown();
440 } 587 }
441 588
442 TEST_F(VideoRendererImplTest, Preroll_Exact) { 589 TEST_F(VideoRendererImplTest, Preroll_Exact) {
443 Initialize(); 590 Initialize();
444 QueueFrames("50 60 70 80 90"); 591 QueueFrames("50 60 70 80 90");
445
446 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
447 Preroll(60, PIPELINE_OK); 592 Preroll(60, PIPELINE_OK);
593 EXPECT_EQ("60", ScheduledFrameTimestamps());
448 Shutdown(); 594 Shutdown();
449 } 595 }
450 596
451 TEST_F(VideoRendererImplTest, Preroll_RightBefore) { 597 TEST_F(VideoRendererImplTest, Preroll_RightBefore) {
452 Initialize(); 598 Initialize();
453 QueueFrames("50 60 70 80 90"); 599 QueueFrames("50 60 70 80 90");
454
455 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(50)));
456 Preroll(59, PIPELINE_OK); 600 Preroll(59, PIPELINE_OK);
601 EXPECT_EQ("50", ScheduledFrameTimestamps());
457 Shutdown(); 602 Shutdown();
458 } 603 }
459 604
460 TEST_F(VideoRendererImplTest, Preroll_RightAfter) { 605 TEST_F(VideoRendererImplTest, Preroll_RightAfter) {
461 Initialize(); 606 Initialize();
462 QueueFrames("50 60 70 80 90"); 607 QueueFrames("50 60 70 80 90");
463
464 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
465 Preroll(61, PIPELINE_OK); 608 Preroll(61, PIPELINE_OK);
609 EXPECT_EQ("60", ScheduledFrameTimestamps());
466 Shutdown(); 610 Shutdown();
467 } 611 }
468 612
469 TEST_F(VideoRendererImplTest, PlayAfterPreroll) { 613 TEST_F(VideoRendererImplTest, PlayAfterPreroll) {
470 Initialize(); 614 Initialize();
471 QueueFrames("0 10 20 30"); 615 QueueFrames("0 10 20 30");
472 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
473 Preroll(0, PIPELINE_OK); 616 Preroll(0, PIPELINE_OK);
474 Play(); 617 Play();
475 618
476 // Advance time past prerolled time to trigger a Read(). 619 DisplayFramesUpTo(0);
477 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 620 EXPECT_TRUE(pending_read());
478 AdvanceTimeInMs(10); 621
479 WaitForPendingRead();
480 Shutdown(); 622 Shutdown();
481 } 623 }
482 624
483 TEST_F(VideoRendererImplTest, Rebuffer) { 625 TEST_F(VideoRendererImplTest, Rebuffer) {
484 Initialize(); 626 Initialize();
485 QueueFrames("0 10 20 30"); 627 QueueFrames("0 10 20 30");
486 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
487 Preroll(0, PIPELINE_OK); 628 Preroll(0, PIPELINE_OK);
488 Play(); 629 Play();
489 630
490 // Advance time past prerolled time drain the ready frame queue. 631 // Display all frames to empty frame buffer.
491 AdvanceTimeInMs(50); 632 DisplayFramesUpTo(30);
492 WaitForPendingRead(); 633 EXPECT_TRUE(pending_read());
493 634
494 // Simulate a Pause/Preroll/Play rebuffer sequence. 635 // Simulate a Pause/Preroll/Play rebuffer sequence.
495 Pause(); 636 Pause();
496 637
497 WaitableMessageLoopEvent event; 638 WaitableMessageLoopEvent event;
498 renderer_->Preroll(kNoTimestamp(), 639 renderer_->Preroll(kNoTimestamp(),
499 event.GetPipelineStatusCB()); 640 event.GetPipelineStatusCB());
500 641
501 // Queue enough frames to satisfy preroll. 642 // Queue enough frames to satisfy preroll.
502 QueueFrames("40 50 60 70"); 643 QueueFrames("40 50 60 70");
503 SatisfyPendingRead(); 644 SatisfyPendingRead();
645 event.RunAndWaitForStatus(PIPELINE_OK);
504 646
505 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer 647 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer
506 // situation, see http://crbug.com/365516 648 // situation, see http://crbug.com/365516
507 EXPECT_CALL(mock_display_cb_, Display(_)); 649 EXPECT_EQ("40", ScheduledFrameTimestamps());
508
509 event.RunAndWaitForStatus(PIPELINE_OK);
510 650
511 Play(); 651 Play();
512 652
513 Shutdown(); 653 Shutdown();
514 } 654 }
515 655
516 TEST_F(VideoRendererImplTest, Rebuffer_AlreadyHaveEnoughFrames) { 656 TEST_F(VideoRendererImplTest, Rebuffer_AlreadyHaveEnoughFrames) {
517 Initialize(); 657 Initialize();
518 QueueFrames("0 10 20 30"); 658 QueueFrames("0 10 20 30");
519 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
520 Preroll(0, PIPELINE_OK); 659 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(); 660 Play();
526 661
527 // Simulate a Pause/Preroll/Play rebuffer sequence. 662 // Simulate a Pause/Preroll/Play rebuffer sequence.
528 Pause(); 663 Pause();
529 664
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; 665 WaitableMessageLoopEvent event;
535 renderer_->Preroll(kNoTimestamp(), 666 renderer_->Preroll(kNoTimestamp(),
536 event.GetPipelineStatusCB()); 667 event.GetPipelineStatusCB());
668 event.RunAndWaitForStatus(PIPELINE_OK);
537 669
538 event.RunAndWaitForStatus(PIPELINE_OK); 670 // TODO(scherkus): We shouldn't display the next ready frame in a rebuffer
671 // situation, see http://crbug.com/365516
672 EXPECT_EQ("0", ScheduledFrameTimestamps());
539 673
540 Play(); 674 Play();
541 675
542 Shutdown(); 676 Shutdown();
543 } 677 }
544 678
545 // Verify that a late decoder response doesn't break invariants in the renderer. 679 // Verify that a late decoder response doesn't break invariants in the renderer.
546 TEST_F(VideoRendererImplTest, StopDuringOutstandingRead) { 680 TEST_F(VideoRendererImplTest, StopDuringOutstandingRead) {
547 Initialize(); 681 Initialize();
548 QueueFrames("0 10 20 30"); 682 QueueFrames("0 10 20 30");
549 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
550 Preroll(0, PIPELINE_OK); 683 Preroll(0, PIPELINE_OK);
551 Play(); 684 Play();
552 685
553 // Advance time a bit to trigger a Read(). 686 DisplayFramesUpTo(0);
554 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 687 EXPECT_TRUE(pending_read());
555 AdvanceTimeInMs(10);
556 WaitForPendingRead();
557 688
558 WaitableMessageLoopEvent event; 689 WaitableMessageLoopEvent event;
559 renderer_->Stop(event.GetClosure()); 690 renderer_->Stop(event.GetClosure());
560 event.RunAndWait(); 691 event.RunAndWait();
561 } 692 }
562 693
563 TEST_F(VideoRendererImplTest, AbortPendingRead_Playing) { 694 TEST_F(VideoRendererImplTest, AbortPendingRead_Playing) {
564 Initialize(); 695 Initialize();
565 QueueFrames("0 10 20 30"); 696 QueueFrames("0 10 20 30");
566 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
567 Preroll(0, PIPELINE_OK); 697 Preroll(0, PIPELINE_OK);
568 Play(); 698 Play();
569 699
570 // Advance time a bit to trigger a Read(). 700 DisplayFramesUpTo(0);
571 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 701 EXPECT_TRUE(pending_read());
572 AdvanceTimeInMs(10);
573 WaitForPendingRead();
574 QueueFrames("abort"); 702 QueueFrames("abort");
575 SatisfyPendingRead(); 703 SatisfyPendingRead();
576 704
577 Pause(); 705 Pause();
578 Flush(); 706 Flush();
579 QueueFrames("60 70 80 90"); 707 QueueFrames("60 70 80 90");
580 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(60)));
581 Preroll(60, PIPELINE_OK); 708 Preroll(60, PIPELINE_OK);
582 Shutdown(); 709 Shutdown();
583 } 710 }
584 711
585 TEST_F(VideoRendererImplTest, AbortPendingRead_Flush) { 712 TEST_F(VideoRendererImplTest, AbortPendingRead_Flush) {
586 Initialize(); 713 Initialize();
587 QueueFrames("0 10 20 30"); 714 QueueFrames("0 10 20 30");
588 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
589 Preroll(0, PIPELINE_OK); 715 Preroll(0, PIPELINE_OK);
590 Play(); 716 Play();
591 717
592 // Advance time a bit to trigger a Read(). 718 DisplayFramesUpTo(0);
593 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(10))); 719 EXPECT_TRUE(pending_read());
594 AdvanceTimeInMs(10);
595 WaitForPendingRead();
596 720
597 Pause(); 721 Pause();
598 Flush(); 722 Flush();
599 Shutdown(); 723 Shutdown();
600 } 724 }
601 725
602 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) { 726 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) {
603 Initialize(); 727 Initialize();
604 QueueFrames("0 10 abort"); 728 QueueFrames("0 10 abort");
605 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
606 Preroll(0, PIPELINE_OK); 729 Preroll(0, PIPELINE_OK);
607 Shutdown(); 730 Shutdown();
608 } 731 }
609 732
610 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { 733 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
611 InSequence s;
612
613 EXPECT_CALL(*decoder_, Initialize(_, _)) 734 EXPECT_CALL(*decoder_, Initialize(_, _))
614 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); 735 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED));
615 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED); 736 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED);
616 737
617 Stop(); 738 Stop();
618 } 739 }
619 740
620 } // namespace media 741 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_impl.cc ('k') | media/tools/player_x11/player_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698