| OLD | NEW |
| 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 Loading... |
| 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 |
| OLD | NEW |