| 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 | 
|---|