| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 #include "content/public/renderer/media_stream_renderer_factory.h" |
| 5 #include "content/renderer/media/webmediaplayer_ms.h" |
| 6 #include "content/renderer/media/webmediaplayer_ms_compositor.h" |
| 7 #include "content/renderer/render_frame_impl.h" |
| 8 #include "media/base/test_helpers.h" |
| 9 #include "media/base/video_frame.h" |
| 10 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" |
| 11 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" |
| 12 |
| 13 namespace content { |
| 14 |
| 15 enum class FrameType { |
| 16 NORMAL_FRAME = 0, |
| 17 BROKEN_FRAME = -1, |
| 18 TEST_BRAKE = -2, // Signal to pause message loop. |
| 19 MIN_TYPE = TEST_BRAKE |
| 20 }; |
| 21 |
| 22 using TestFrame = std::pair<FrameType, scoped_refptr<media::VideoFrame>>; |
| 23 |
| 24 class ReusableMessageLoopEvent { |
| 25 public: |
| 26 ReusableMessageLoopEvent() : event_(new media::WaitableMessageLoopEvent()) {} |
| 27 |
| 28 base::Closure GetClosure() const { return event_->GetClosure(); } |
| 29 |
| 30 media::PipelineStatusCB GetPipelineStatusCB() const { |
| 31 return event_->GetPipelineStatusCB(); |
| 32 } |
| 33 |
| 34 void RunAndWait() { |
| 35 event_->RunAndWait(); |
| 36 event_.reset(new media::WaitableMessageLoopEvent()); |
| 37 } |
| 38 |
| 39 void RunAndWaitForStatus(media::PipelineStatus expected) { |
| 40 event_->RunAndWaitForStatus(expected); |
| 41 event_.reset(new media::WaitableMessageLoopEvent()); |
| 42 } |
| 43 |
| 44 private: |
| 45 scoped_ptr<media::WaitableMessageLoopEvent> event_; |
| 46 }; |
| 47 |
| 48 // The class is used mainly to inject VideoFrames into WebMediaPlayerMS. |
| 49 class MockVideoFrameProvider : public VideoFrameProvider { |
| 50 public: |
| 51 MockVideoFrameProvider( |
| 52 const scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 53 ReusableMessageLoopEvent* message_loop_controller, |
| 54 const base::Closure& error_cb, |
| 55 const VideoFrameProvider::RepaintCB& repaint_cb) |
| 56 : started_(false), |
| 57 task_runner_(task_runner), |
| 58 message_loop_controller_(message_loop_controller), |
| 59 error_cb_(error_cb), |
| 60 repaint_cb_(repaint_cb), |
| 61 delay_till_next_generated_frame_( |
| 62 base::TimeDelta::FromSecondsD(1.0 / 30.0)) {} |
| 63 |
| 64 // Implementation of VideoFrameProvider |
| 65 void Start() override; |
| 66 void Stop() override; |
| 67 void Play() override; |
| 68 void Pause() override; |
| 69 |
| 70 // Methods for test use |
| 71 void QueueFrames(const std::vector<int>& timestamps_or_frame_type); |
| 72 bool Started() { return started_; } |
| 73 bool Paused() { return paused_; } |
| 74 |
| 75 private: |
| 76 ~MockVideoFrameProvider() override {} |
| 77 |
| 78 // Main function that pushes a frame into WebMediaPlayerMS |
| 79 void InjectFrame(); |
| 80 |
| 81 // Methods for test use |
| 82 void AddFrame(FrameType category, |
| 83 const scoped_refptr<media::VideoFrame>& frame); |
| 84 |
| 85 bool started_; |
| 86 bool paused_; |
| 87 |
| 88 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 89 ReusableMessageLoopEvent* const message_loop_controller_; |
| 90 const base::Closure error_cb_; |
| 91 const VideoFrameProvider::RepaintCB repaint_cb_; |
| 92 |
| 93 std::deque<TestFrame> frames_; |
| 94 base::TimeDelta delay_till_next_generated_frame_; |
| 95 }; |
| 96 |
| 97 void MockVideoFrameProvider::Start() { |
| 98 started_ = true; |
| 99 paused_ = false; |
| 100 task_runner_->PostTask( |
| 101 FROM_HERE, |
| 102 base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this))); |
| 103 } |
| 104 |
| 105 void MockVideoFrameProvider::Stop() { |
| 106 started_ = false; |
| 107 frames_.clear(); |
| 108 } |
| 109 |
| 110 void MockVideoFrameProvider::Play() { |
| 111 CHECK(started_); |
| 112 paused_ = false; |
| 113 } |
| 114 |
| 115 void MockVideoFrameProvider::Pause() { |
| 116 CHECK(started_); |
| 117 paused_ = true; |
| 118 } |
| 119 |
| 120 void MockVideoFrameProvider::AddFrame( |
| 121 FrameType category, |
| 122 const scoped_refptr<media::VideoFrame>& frame) { |
| 123 frames_.push_back(std::make_pair(category, frame)); |
| 124 } |
| 125 |
| 126 void MockVideoFrameProvider::QueueFrames( |
| 127 const std::vector<int>& timestamp_or_frame_type) { |
| 128 for (const int token : timestamp_or_frame_type) { |
| 129 if (token < static_cast<int>(FrameType::MIN_TYPE)) { |
| 130 CHECK(false) << "Unrecognized frame type: " << token; |
| 131 return; |
| 132 } |
| 133 |
| 134 if (token < 0) { |
| 135 AddFrame(static_cast<FrameType>(token), nullptr); |
| 136 continue; |
| 137 } |
| 138 |
| 139 if (token >= 0) { |
| 140 gfx::Size natural_size = media::TestVideoConfig::NormalCodedSize(); |
| 141 auto frame = media::VideoFrame::CreateFrame( |
| 142 media::PIXEL_FORMAT_YV12, natural_size, gfx::Rect(natural_size), |
| 143 natural_size, base::TimeDelta::FromMilliseconds(token)); |
| 144 |
| 145 frame->metadata()->SetTimeTicks( |
| 146 media::VideoFrameMetadata::Key::REFERENCE_TIME, |
| 147 base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(token)); |
| 148 |
| 149 AddFrame(FrameType::NORMAL_FRAME, frame); |
| 150 continue; |
| 151 } |
| 152 } |
| 153 } |
| 154 |
| 155 void MockVideoFrameProvider::InjectFrame() { |
| 156 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 157 if (!started_) |
| 158 return; |
| 159 |
| 160 if (frames_.empty()) { |
| 161 message_loop_controller_->GetClosure().Run(); |
| 162 return; |
| 163 } |
| 164 |
| 165 auto frame = frames_.front(); |
| 166 frames_.pop_front(); |
| 167 |
| 168 if (frame.first == FrameType::BROKEN_FRAME) { |
| 169 error_cb_.Run(); |
| 170 return; |
| 171 } |
| 172 |
| 173 // For pause case, the provider will still let the stream continue, but |
| 174 // not send the frames to the player. As is the same case in reality. |
| 175 if (frame.first == FrameType::NORMAL_FRAME) { |
| 176 if (!paused_) |
| 177 repaint_cb_.Run(frame.second); |
| 178 |
| 179 for (size_t i = 0; i < frames_.size(); ++i) { |
| 180 if (frames_[i].first == FrameType::NORMAL_FRAME) { |
| 181 delay_till_next_generated_frame_ = |
| 182 (frames_[i].second->timestamp() - frame.second->timestamp()) / |
| 183 (i + 1); |
| 184 break; |
| 185 } |
| 186 } |
| 187 } |
| 188 |
| 189 task_runner_->PostDelayedTask( |
| 190 FROM_HERE, |
| 191 base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this)), |
| 192 delay_till_next_generated_frame_); |
| 193 |
| 194 // This will pause the |message_loop_|, and the purpose is to allow the main |
| 195 // test function to do some operations (e.g. call pause(), switch to |
| 196 // background rendering, etc) on WebMediaPlayerMS before resuming |
| 197 // |message_loop_|. |
| 198 if (frame.first == FrameType::TEST_BRAKE) |
| 199 message_loop_controller_->GetClosure().Run(); |
| 200 } |
| 201 |
| 202 // The class is used to generate a MockVideoProvider in |
| 203 // WebMediaPlayerMS::load(). |
| 204 class MockRenderFactory : public MediaStreamRendererFactory { |
| 205 public: |
| 206 MockRenderFactory( |
| 207 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 208 ReusableMessageLoopEvent* message_loop_controller) |
| 209 : task_runner_(task_runner), |
| 210 message_loop_controller_(message_loop_controller) {} |
| 211 |
| 212 scoped_refptr<VideoFrameProvider> GetVideoFrameProvider( |
| 213 const GURL& url, |
| 214 const base::Closure& error_cb, |
| 215 const VideoFrameProvider::RepaintCB& repaint_cb, |
| 216 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 217 const scoped_refptr<base::TaskRunner>& worker_task_runner, |
| 218 media::GpuVideoAcceleratorFactories* gpu_factories) override; |
| 219 |
| 220 MockVideoFrameProvider* provider() { |
| 221 return static_cast<MockVideoFrameProvider*>(provider_.get()); |
| 222 } |
| 223 |
| 224 scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer( |
| 225 const GURL& url, |
| 226 int render_frame_id, |
| 227 const std::string& device_id, |
| 228 const url::Origin& security_origin) override { |
| 229 return nullptr; |
| 230 } |
| 231 |
| 232 private: |
| 233 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 234 scoped_refptr<VideoFrameProvider> provider_; |
| 235 ReusableMessageLoopEvent* const message_loop_controller_; |
| 236 }; |
| 237 |
| 238 scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider( |
| 239 const GURL& url, |
| 240 const base::Closure& error_cb, |
| 241 const VideoFrameProvider::RepaintCB& repaint_cb, |
| 242 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 243 const scoped_refptr<base::TaskRunner>& worker_task_runner, |
| 244 media::GpuVideoAcceleratorFactories* gpu_factories) { |
| 245 provider_ = new MockVideoFrameProvider(task_runner_, message_loop_controller_, |
| 246 error_cb, repaint_cb); |
| 247 |
| 248 return provider_; |
| 249 } |
| 250 |
| 251 // This is the main class coordinating the tests. |
| 252 // Basic workflow: |
| 253 // 1. WebMediaPlayerMS::Load will generate and start |
| 254 // content::VideoFrameProvider. |
| 255 // 2. content::VideoFrameProvider will start pushing frames into |
| 256 // WebMediaPlayerMS repeatedly. |
| 257 // 3. On WebMediaPlayerMS receiving the first frame, a WebLayer will be created. |
| 258 // 4. The WebLayer will call |
| 259 // WebMediaPlayerMSCompositor::SetVideoFrameProviderClient, which in turn |
| 260 // will trigger cc::VideoFrameProviderClient::StartRendering. |
| 261 // 5. Then cc::VideoFrameProviderClient will start calling |
| 262 // WebMediaPlayerMSCompositor::UpdateCurrentFrame, GetCurrentFrame for |
| 263 // rendering repeatedly. |
| 264 // 6. When WebMediaPlayerMS::pause gets called, it should trigger |
| 265 // content::VideoFrameProvider::Pause, and then the provider will stop |
| 266 // pushing frames into WebMediaPlayerMS, but instead digesting them; |
| 267 // simultanously, it should call cc::VideoFrameProviderClient::StopRendering, |
| 268 // so cc::VideoFrameProviderClient will stop asking frames from |
| 269 // WebMediaPlayerMSCompositor. |
| 270 // 7. When WebMediaPlayerMS::play gets called, evething paused in step 6 should |
| 271 // be resumed. |
| 272 class WebMediaPlayerMSTest : public testing::Test, |
| 273 public blink::WebMediaPlayerClient, |
| 274 public cc::VideoFrameProvider::Client { |
| 275 public: |
| 276 WebMediaPlayerMSTest() |
| 277 : render_factory_(new MockRenderFactory(message_loop_.task_runner(), |
| 278 &message_loop_controller_)), |
| 279 player_(nullptr, |
| 280 this, |
| 281 base::WeakPtr<media::WebMediaPlayerDelegate>(), |
| 282 new media::MediaLog(), |
| 283 scoped_ptr<MediaStreamRendererFactory>(render_factory_), |
| 284 message_loop_.task_runner(), |
| 285 message_loop_.task_runner(), |
| 286 message_loop_.task_runner(), |
| 287 nullptr, |
| 288 blink::WebString(), |
| 289 blink::WebSecurityOrigin()), |
| 290 rendering_(false) {} |
| 291 ~WebMediaPlayerMSTest() override {} |
| 292 |
| 293 MockVideoFrameProvider* LoadAndGetFrameProvider(bool algorithm_enabled); |
| 294 |
| 295 // Implementation of WebMediaPlayerClient |
| 296 void networkStateChanged() override; |
| 297 void readyStateChanged() override; |
| 298 void timeChanged() override {} |
| 299 void repaint() override {} |
| 300 void durationChanged() override {} |
| 301 void sizeChanged() override {} |
| 302 void playbackStateChanged() override {} |
| 303 void setWebLayer(blink::WebLayer* layer) override; |
| 304 blink::WebMediaPlayer::TrackId addAudioTrack(const blink::WebString& id, |
| 305 AudioTrackKind, |
| 306 const blink::WebString& label, |
| 307 const blink::WebString& language, |
| 308 bool enabled) override { |
| 309 return 0; |
| 310 } |
| 311 void removeAudioTrack(blink::WebMediaPlayer::TrackId) override {} |
| 312 blink::WebMediaPlayer::TrackId addVideoTrack(const blink::WebString& id, |
| 313 VideoTrackKind, |
| 314 const blink::WebString& label, |
| 315 const blink::WebString& language, |
| 316 bool selected) override { |
| 317 return 0; |
| 318 } |
| 319 void removeVideoTrack(blink::WebMediaPlayer::TrackId) override {} |
| 320 void addTextTrack(blink::WebInbandTextTrack*) override {} |
| 321 void removeTextTrack(blink::WebInbandTextTrack*) override {} |
| 322 void mediaSourceOpened(blink::WebMediaSource*) override {} |
| 323 void requestSeek(double) override {} |
| 324 void remoteRouteAvailabilityChanged(bool) override {} |
| 325 void connectedToRemoteDevice() override {} |
| 326 void disconnectedFromRemoteDevice() override {} |
| 327 |
| 328 // Implementation of cc::VideoFrameProvider::Client |
| 329 void StopUsingProvider() override; |
| 330 void StartRendering() override; |
| 331 void StopRendering() override; |
| 332 void DidReceiveFrame() override {} |
| 333 void DidUpdateMatrix(const float* matrix) override {} |
| 334 |
| 335 // For test use |
| 336 void SetBackgroundRendering(bool background_rendering) { |
| 337 background_rendering_ = background_rendering; |
| 338 } |
| 339 |
| 340 protected: |
| 341 MOCK_METHOD0(DoStartRendering, void()); |
| 342 MOCK_METHOD0(DoStopRendering, void()); |
| 343 |
| 344 MOCK_METHOD1(DoSetWebLayer, void(bool)); |
| 345 MOCK_METHOD1(DoNetworkStateChanged, |
| 346 void(blink::WebMediaPlayer::NetworkState)); |
| 347 MOCK_METHOD1(DoReadyStateChanged, void(blink::WebMediaPlayer::ReadyState)); |
| 348 |
| 349 base::MessageLoop message_loop_; |
| 350 MockRenderFactory* render_factory_; |
| 351 WebMediaPlayerMS player_; |
| 352 WebMediaPlayerMSCompositor* compositor_; |
| 353 ReusableMessageLoopEvent message_loop_controller_; |
| 354 |
| 355 private: |
| 356 // Main function trying to ask WebMediaPlayerMS to submit a frame for |
| 357 // rendering. |
| 358 void RenderFrame(); |
| 359 |
| 360 bool rendering_; |
| 361 bool background_rendering_; |
| 362 }; |
| 363 |
| 364 MockVideoFrameProvider* WebMediaPlayerMSTest::LoadAndGetFrameProvider( |
| 365 bool algorithm_enabled) { |
| 366 EXPECT_FALSE(!!render_factory_->provider()) << "There should not be a " |
| 367 "FrameProvider yet."; |
| 368 |
| 369 EXPECT_CALL( |
| 370 *this, DoNetworkStateChanged(blink::WebMediaPlayer::NetworkStateLoading)); |
| 371 EXPECT_CALL( |
| 372 *this, DoReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveNothing)); |
| 373 player_.load(blink::WebMediaPlayer::LoadTypeURL, blink::WebURL(), |
| 374 blink::WebMediaPlayer::CORSModeUnspecified); |
| 375 compositor_ = player_.compositor_.get(); |
| 376 EXPECT_TRUE(!!compositor_); |
| 377 compositor_->SetAlgorithmEnabledForTesting(algorithm_enabled); |
| 378 |
| 379 MockVideoFrameProvider* const provider = render_factory_->provider(); |
| 380 EXPECT_TRUE(!!provider); |
| 381 EXPECT_TRUE(provider->Started()); |
| 382 |
| 383 testing::Mock::VerifyAndClearExpectations(this); |
| 384 return provider; |
| 385 } |
| 386 |
| 387 void WebMediaPlayerMSTest::networkStateChanged() { |
| 388 blink::WebMediaPlayer::NetworkState state = player_.networkState(); |
| 389 DoNetworkStateChanged(state); |
| 390 if (state == blink::WebMediaPlayer::NetworkState::NetworkStateFormatError || |
| 391 state == blink::WebMediaPlayer::NetworkState::NetworkStateDecodeError || |
| 392 state == blink::WebMediaPlayer::NetworkState::NetworkStateNetworkError) { |
| 393 message_loop_controller_.GetPipelineStatusCB().Run( |
| 394 media::PipelineStatus::PIPELINE_ERROR_NETWORK); |
| 395 } |
| 396 } |
| 397 |
| 398 void WebMediaPlayerMSTest::readyStateChanged() { |
| 399 blink::WebMediaPlayer::ReadyState state = player_.readyState(); |
| 400 DoReadyStateChanged(state); |
| 401 if (state == blink::WebMediaPlayer::ReadyState::ReadyStateHaveEnoughData) |
| 402 player_.play(); |
| 403 } |
| 404 |
| 405 void WebMediaPlayerMSTest::setWebLayer(blink::WebLayer* layer) { |
| 406 if (layer) |
| 407 compositor_->SetVideoFrameProviderClient(this); |
| 408 DoSetWebLayer(!!layer); |
| 409 } |
| 410 |
| 411 void WebMediaPlayerMSTest::StopUsingProvider() { |
| 412 if (rendering_) |
| 413 StopRendering(); |
| 414 } |
| 415 |
| 416 void WebMediaPlayerMSTest::StartRendering() { |
| 417 if (!rendering_) { |
| 418 rendering_ = true; |
| 419 message_loop_.PostTask( |
| 420 FROM_HERE, |
| 421 base::Bind(&WebMediaPlayerMSTest::RenderFrame, base::Unretained(this))); |
| 422 } |
| 423 DoStartRendering(); |
| 424 } |
| 425 |
| 426 void WebMediaPlayerMSTest::StopRendering() { |
| 427 rendering_ = false; |
| 428 DoStopRendering(); |
| 429 } |
| 430 |
| 431 void WebMediaPlayerMSTest::RenderFrame() { |
| 432 if (!rendering_ || !compositor_) |
| 433 return; |
| 434 |
| 435 base::TimeTicks now = base::TimeTicks::Now(); |
| 436 base::TimeTicks deadline_min = |
| 437 now + base::TimeDelta::FromSecondsD(1.0 / 60.0); |
| 438 base::TimeTicks deadline_max = |
| 439 deadline_min + base::TimeDelta::FromSecondsD(1.0 / 60.0); |
| 440 |
| 441 // Background rendering is different from stop rendering. The rendering loop |
| 442 // is still running but we do not ask frames from |compositor_|. And |
| 443 // background rendering is not initiated from |compositor_|. |
| 444 if (!background_rendering_) { |
| 445 compositor_->UpdateCurrentFrame(deadline_min, deadline_max); |
| 446 auto frame = compositor_->GetCurrentFrame(); |
| 447 compositor_->PutCurrentFrame(); |
| 448 } |
| 449 message_loop_.PostDelayedTask( |
| 450 FROM_HERE, |
| 451 base::Bind(&WebMediaPlayerMSTest::RenderFrame, base::Unretained(this)), |
| 452 base::TimeDelta::FromSecondsD(1.0 / 60.0)); |
| 453 } |
| 454 |
| 455 TEST_F(WebMediaPlayerMSTest, Playing_Normal) { |
| 456 // This test sends a bunch of normal frames with increasing timestamps |
| 457 // and verifies that they are produced by WebMediaPlayerMS in appropriate |
| 458 // order. |
| 459 |
| 460 MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true); |
| 461 |
| 462 int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300, |
| 463 333, 366, 400, 433, 466, 500, 533, 566, 600}; |
| 464 std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int)); |
| 465 provider->QueueFrames(timestamps); |
| 466 |
| 467 EXPECT_CALL(*this, DoSetWebLayer(true)); |
| 468 EXPECT_CALL(*this, DoStartRendering()); |
| 469 EXPECT_CALL(*this, DoReadyStateChanged( |
| 470 blink::WebMediaPlayer::ReadyStateHaveMetadata)); |
| 471 EXPECT_CALL(*this, DoReadyStateChanged( |
| 472 blink::WebMediaPlayer::ReadyStateHaveEnoughData)); |
| 473 message_loop_controller_.RunAndWaitForStatus( |
| 474 media::PipelineStatus::PIPELINE_OK); |
| 475 testing::Mock::VerifyAndClearExpectations(this); |
| 476 |
| 477 EXPECT_CALL(*this, DoSetWebLayer(false)); |
| 478 EXPECT_CALL(*this, DoStopRendering()); |
| 479 } |
| 480 |
| 481 TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) { |
| 482 // This tests sends a broken frame to WebMediaPlayerMS, and verifies |
| 483 // OnSourceError function works as expected. |
| 484 |
| 485 MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false); |
| 486 |
| 487 const int kBrokenFrame = static_cast<int>(FrameType::BROKEN_FRAME); |
| 488 int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300, |
| 489 333, 366, 400, 433, 466, 500, 533, 566, 600, kBrokenFrame}; |
| 490 std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int)); |
| 491 provider->QueueFrames(timestamps); |
| 492 |
| 493 EXPECT_CALL(*this, DoSetWebLayer(true)); |
| 494 EXPECT_CALL(*this, DoStartRendering()); |
| 495 EXPECT_CALL(*this, DoReadyStateChanged( |
| 496 blink::WebMediaPlayer::ReadyStateHaveMetadata)); |
| 497 EXPECT_CALL(*this, DoReadyStateChanged( |
| 498 blink::WebMediaPlayer::ReadyStateHaveEnoughData)); |
| 499 EXPECT_CALL(*this, DoNetworkStateChanged( |
| 500 blink::WebMediaPlayer::NetworkStateFormatError)); |
| 501 message_loop_controller_.RunAndWaitForStatus( |
| 502 media::PipelineStatus::PIPELINE_ERROR_NETWORK); |
| 503 testing::Mock::VerifyAndClearExpectations(this); |
| 504 |
| 505 EXPECT_CALL(*this, DoSetWebLayer(false)); |
| 506 EXPECT_CALL(*this, DoStopRendering()); |
| 507 } |
| 508 |
| 509 TEST_F(WebMediaPlayerMSTest, PlayThenPause) { |
| 510 // In the middle of this test, WebMediaPlayerMS::pause will be called, and we |
| 511 // are going to verify that during the pause stage, a frame gets freezed, and |
| 512 // cc::VideoFrameProviderClient should also be paused. |
| 513 MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false); |
| 514 |
| 515 const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE); |
| 516 int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166, 200, 233, 266, |
| 517 300, 333, 366, 400, 433, 466, 500, 533, 566, 600}; |
| 518 std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int)); |
| 519 provider->QueueFrames(timestamps); |
| 520 |
| 521 EXPECT_CALL(*this, DoSetWebLayer(true)); |
| 522 EXPECT_CALL(*this, DoStartRendering()); |
| 523 EXPECT_CALL(*this, DoReadyStateChanged( |
| 524 blink::WebMediaPlayer::ReadyStateHaveMetadata)); |
| 525 EXPECT_CALL(*this, DoReadyStateChanged( |
| 526 blink::WebMediaPlayer::ReadyStateHaveEnoughData)); |
| 527 message_loop_controller_.RunAndWaitForStatus( |
| 528 media::PipelineStatus::PIPELINE_OK); |
| 529 testing::Mock::VerifyAndClearExpectations(this); |
| 530 |
| 531 // Here we call pause, and expect a freezing frame. |
| 532 EXPECT_CALL(*this, DoStopRendering()); |
| 533 player_.pause(); |
| 534 auto prev_frame = compositor_->GetCurrentFrame(); |
| 535 message_loop_controller_.RunAndWaitForStatus( |
| 536 media::PipelineStatus::PIPELINE_OK); |
| 537 auto after_frame = compositor_->GetCurrentFrame(); |
| 538 EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp()); |
| 539 testing::Mock::VerifyAndClearExpectations(this); |
| 540 |
| 541 EXPECT_CALL(*this, DoSetWebLayer(false)); |
| 542 } |
| 543 |
| 544 TEST_F(WebMediaPlayerMSTest, PlayThenPauseThenPlay) { |
| 545 // Similary to PlayAndPause test above, this one focuses on testing that |
| 546 // WebMediaPlayerMS can be resumed after a period of paused status. |
| 547 MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false); |
| 548 |
| 549 const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE); |
| 550 int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166, |
| 551 200, 233, 266, 300, 333, 366, 400, |
| 552 433, kTestBrake, 466, 500, 533, 566, 600}; |
| 553 std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int)); |
| 554 provider->QueueFrames(timestamps); |
| 555 |
| 556 EXPECT_CALL(*this, DoSetWebLayer(true)); |
| 557 EXPECT_CALL(*this, DoStartRendering()); |
| 558 EXPECT_CALL(*this, DoReadyStateChanged( |
| 559 blink::WebMediaPlayer::ReadyStateHaveMetadata)); |
| 560 EXPECT_CALL(*this, DoReadyStateChanged( |
| 561 blink::WebMediaPlayer::ReadyStateHaveEnoughData)); |
| 562 message_loop_controller_.RunAndWaitForStatus( |
| 563 media::PipelineStatus::PIPELINE_OK); |
| 564 testing::Mock::VerifyAndClearExpectations(this); |
| 565 |
| 566 // Here we call pause, and expect a freezing frame. |
| 567 EXPECT_CALL(*this, DoStopRendering()); |
| 568 player_.pause(); |
| 569 auto prev_frame = compositor_->GetCurrentFrame(); |
| 570 message_loop_controller_.RunAndWaitForStatus( |
| 571 media::PipelineStatus::PIPELINE_OK); |
| 572 auto after_frame = compositor_->GetCurrentFrame(); |
| 573 EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp()); |
| 574 testing::Mock::VerifyAndClearExpectations(this); |
| 575 |
| 576 // We resume the player, and expect rendering can continue. |
| 577 EXPECT_CALL(*this, DoStartRendering()); |
| 578 player_.play(); |
| 579 prev_frame = compositor_->GetCurrentFrame(); |
| 580 message_loop_controller_.RunAndWaitForStatus( |
| 581 media::PipelineStatus::PIPELINE_OK); |
| 582 after_frame = compositor_->GetCurrentFrame(); |
| 583 EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp()); |
| 584 testing::Mock::VerifyAndClearExpectations(this); |
| 585 |
| 586 EXPECT_CALL(*this, DoSetWebLayer(false)); |
| 587 EXPECT_CALL(*this, DoStopRendering()); |
| 588 } |
| 589 |
| 590 TEST_F(WebMediaPlayerMSTest, BackgroudRendering) { |
| 591 // During this test, we will switch to background rendering mode, in which |
| 592 // WebMediaPlayerMS::pause does not get called, but |
| 593 // cc::VideoFrameProviderClient simply stops asking frames from |
| 594 // WebMediaPlayerMS without an explicit notification. We should expect that |
| 595 // WebMediaPlayerMS can digest old frames, rather than piling frames up and |
| 596 // explode. |
| 597 MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true); |
| 598 |
| 599 const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE); |
| 600 int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166, |
| 601 200, 233, 266, 300, 333, 366, 400, |
| 602 433, kTestBrake, 466, 500, 533, 566, 600}; |
| 603 std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int)); |
| 604 provider->QueueFrames(timestamps); |
| 605 |
| 606 EXPECT_CALL(*this, DoSetWebLayer(true)); |
| 607 EXPECT_CALL(*this, DoStartRendering()); |
| 608 EXPECT_CALL(*this, DoReadyStateChanged( |
| 609 blink::WebMediaPlayer::ReadyStateHaveMetadata)); |
| 610 EXPECT_CALL(*this, DoReadyStateChanged( |
| 611 blink::WebMediaPlayer::ReadyStateHaveEnoughData)); |
| 612 |
| 613 message_loop_controller_.RunAndWaitForStatus( |
| 614 media::PipelineStatus::PIPELINE_OK); |
| 615 testing::Mock::VerifyAndClearExpectations(this); |
| 616 |
| 617 // Switch to background rendering, expect rendering to continue. |
| 618 SetBackgroundRendering(true); |
| 619 auto prev_frame = compositor_->GetCurrentFrame(); |
| 620 message_loop_controller_.RunAndWaitForStatus( |
| 621 media::PipelineStatus::PIPELINE_OK); |
| 622 auto after_frame = compositor_->GetCurrentFrame(); |
| 623 EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp()); |
| 624 |
| 625 // Switch to foreground rendering. |
| 626 SetBackgroundRendering(false); |
| 627 prev_frame = compositor_->GetCurrentFrame(); |
| 628 message_loop_controller_.RunAndWaitForStatus( |
| 629 media::PipelineStatus::PIPELINE_OK); |
| 630 after_frame = compositor_->GetCurrentFrame(); |
| 631 EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp()); |
| 632 testing::Mock::VerifyAndClearExpectations(this); |
| 633 |
| 634 EXPECT_CALL(*this, DoSetWebLayer(false)); |
| 635 EXPECT_CALL(*this, DoStopRendering()); |
| 636 } |
| 637 |
| 638 } // namespace content |
| OLD | NEW |