blob: 4a8621ce9ace17dfdd9b942d6f2ed61ec5b6eb78 [file] [log] [blame]
miu9f7788e2017-01-25 00:46:091// Copyright 2016 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
5#include "media/remoting/renderer_controller.h"
6
Gyuyoung Kim62a5de42018-01-10 09:48:427#include <memory>
8
miu9f7788e2017-01-25 00:46:099#include "base/callback.h"
miu9f7788e2017-01-25 00:46:0910#include "base/message_loop/message_loop.h"
11#include "base/run_loop.h"
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4212#include "base/test/simple_test_tick_clock.h"
Anton Vayvod9ef77302017-08-08 20:54:0213#include "build/build_config.h"
miu9f7788e2017-01-25 00:46:0914#include "media/base/audio_decoder_config.h"
15#include "media/base/cdm_config.h"
16#include "media/base/limits.h"
17#include "media/base/media_util.h"
18#include "media/base/test_helpers.h"
19#include "media/base/video_decoder_config.h"
20#include "media/remoting/fake_remoter.h"
21#include "media/remoting/remoting_cdm.h"
22#include "mojo/public/cpp/bindings/strong_binding.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25namespace media {
26namespace remoting {
27
28namespace {
29
Xiangjun Zhang6dc11102017-07-24 23:49:1130PipelineMetadata DefaultMetadata(VideoCodec codec) {
miu9f7788e2017-01-25 00:46:0931 PipelineMetadata data;
32 data.has_audio = true;
33 data.has_video = true;
Xiangjun Zhang6dc11102017-07-24 23:49:1134 data.video_decoder_config = TestVideoConfig::Normal(codec);
35 data.audio_decoder_config = TestAudioConfig::Normal();
Xiangjun Zhang7fd5be0c2017-10-12 01:20:3036 data.natural_size = gfx::Size(1920, 1080);
miu9f7788e2017-01-25 00:46:0937 return data;
38}
39
40PipelineMetadata EncryptedMetadata() {
41 PipelineMetadata data;
42 data.has_audio = true;
43 data.has_video = true;
44 data.video_decoder_config = TestVideoConfig::NormalEncrypted();
45 return data;
46}
47
Xiangjun Zhangba8724f482017-08-03 06:43:2548const std::string kDefaultReceiver = "TestingChromeCast";
49
Xiangjun Zhang6dc11102017-07-24 23:49:1150mojom::RemotingSinkMetadata GetDefaultSinkMetadata(bool enable) {
51 mojom::RemotingSinkMetadata metadata;
52 if (enable) {
53 metadata.features.push_back(mojom::RemotingSinkFeature::RENDERING);
54 metadata.features.push_back(mojom::RemotingSinkFeature::CONTENT_DECRYPTION);
55 } else {
56 metadata.features.clear();
57 }
58 metadata.video_capabilities.push_back(
59 mojom::RemotingSinkVideoCapability::CODEC_VP8);
60 metadata.audio_capabilities.push_back(
61 mojom::RemotingSinkAudioCapability::CODEC_BASELINE_SET);
Xiangjun Zhangba8724f482017-08-03 06:43:2562 metadata.friendly_name = kDefaultReceiver;
Xiangjun Zhang6dc11102017-07-24 23:49:1163 return metadata;
64}
65
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4266constexpr base::TimeDelta kDelayedStartDuration =
67 base::TimeDelta::FromSeconds(5);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4268
miu9f7788e2017-01-25 00:46:0969} // namespace
70
xjz4e5d4bf32017-02-15 21:26:3571class RendererControllerTest : public ::testing::Test,
72 public MediaObserverClient {
miu9f7788e2017-01-25 00:46:0973 public:
Chris Watkins2de69292017-12-01 03:08:0174 RendererControllerTest() = default;
75 ~RendererControllerTest() override = default;
miu9f7788e2017-01-25 00:46:0976
77 void TearDown() final { RunUntilIdle(); }
78
79 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
80
xjz4e5d4bf32017-02-15 21:26:3581 // MediaObserverClient implementation.
Xiangjun Zhangba8724f482017-08-03 06:43:2582 void SwitchToRemoteRenderer(
83 const std::string& remote_device_friendly_name) override {
84 is_rendering_remotely_ = true;
85 disable_pipeline_suspend_ = true;
86 sink_name_ = remote_device_friendly_name;
87 }
88
89 void SwitchToLocalRenderer() override {
90 is_rendering_remotely_ = false;
91 disable_pipeline_suspend_ = false;
92 sink_name_.clear();
xjz4e5d4bf32017-02-15 21:26:3593 }
94
95 void ActivateViewportIntersectionMonitoring(bool activate) override {
96 activate_viewport_intersection_monitoring_ = activate;
miu9f7788e2017-01-25 00:46:0997 }
98
Xiangjun Zhang4985fe22017-10-12 20:54:2299 double Duration() const override { return duration_in_sec_; }
100
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30101 unsigned DecodedFrameCount() const override { return decoded_frames_; }
102
Anton Vayvod09fa66e2017-07-20 23:02:12103 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
104
miu9f7788e2017-01-25 00:46:09105 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
106
Xiangjun Zhangc92ec9b2017-07-25 21:56:42107 void InitializeControllerAndBecomeDominant(
Xiangjun Zhang6dc11102017-07-24 23:49:11108 const scoped_refptr<SharedSession> shared_session,
109 const PipelineMetadata& pipeline_metadata,
110 const mojom::RemotingSinkMetadata& sink_metadata) {
111 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangba8724f482017-08-03 06:43:25112 EXPECT_TRUE(sink_name_.empty());
Gyuyoung Kim62a5de42018-01-10 09:48:42113 controller_ = std::make_unique<RendererController>(shared_session);
tzik2c963b872017-12-07 06:57:24114 controller_->clock_ = &clock_;
115 clock_.Advance(base::TimeDelta::FromSeconds(1));
Xiangjun Zhang6dc11102017-07-24 23:49:11116 controller_->SetClient(this);
117 RunUntilIdle();
118 EXPECT_FALSE(is_rendering_remotely_);
119 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
120 EXPECT_FALSE(disable_pipeline_suspend_);
121 shared_session->OnSinkAvailable(sink_metadata.Clone());
122 RunUntilIdle();
123 EXPECT_FALSE(is_rendering_remotely_);
124 EXPECT_FALSE(disable_pipeline_suspend_);
125 controller_->OnRemotePlaybackDisabled(false);
126 RunUntilIdle();
127 EXPECT_FALSE(is_rendering_remotely_);
128 EXPECT_FALSE(disable_pipeline_suspend_);
129 controller_->OnMetadataChanged(pipeline_metadata);
130 RunUntilIdle();
131 EXPECT_FALSE(is_rendering_remotely_);
132 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42133 controller_->OnBecameDominantVisibleContent(true);
Xiangjun Zhang6dc11102017-07-24 23:49:11134 RunUntilIdle();
135 EXPECT_FALSE(is_rendering_remotely_);
136 EXPECT_FALSE(disable_pipeline_suspend_);
137 controller_->OnPlaying();
138 RunUntilIdle();
139 }
140
Xiangjun Zhangba8724f482017-08-03 06:43:25141 bool IsInDelayedStart() const {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42142 return controller_->delayed_start_stability_timer_.IsRunning();
143 }
144
Xiangjun Zhang2cacf422017-11-29 02:22:50145 void DelayedStartEnds(double frame_rate = 30) {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42146 EXPECT_TRUE(IsInDelayedStart());
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30147 decoded_frames_ = frame_rate * kDelayedStartDuration.InSeconds();
tzik2c963b872017-12-07 06:57:24148 clock_.Advance(kDelayedStartDuration);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42149 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42150 const base::Closure callback =
151 controller_->delayed_start_stability_timer_.user_task();
152 callback.Run();
153 controller_->delayed_start_stability_timer_.Stop();
154 }
155
Xiangjun Zhangba8724f482017-08-03 06:43:25156 void ExpectInDelayedStart() const {
157 EXPECT_FALSE(is_rendering_remotely_);
158 EXPECT_FALSE(disable_pipeline_suspend_);
159 EXPECT_TRUE(sink_name_.empty());
160 EXPECT_TRUE(IsInDelayedStart());
161 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
162 }
163
164 void ExpectInRemoting() const {
165 EXPECT_TRUE(is_rendering_remotely_);
166 EXPECT_TRUE(disable_pipeline_suspend_);
167 EXPECT_EQ(kDefaultReceiver, sink_name_);
168 EXPECT_FALSE(IsInDelayedStart());
169 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
170 }
171
172 void ExpectInLocalRendering() const {
173 EXPECT_FALSE(is_rendering_remotely_);
174 EXPECT_FALSE(disable_pipeline_suspend_);
175 EXPECT_TRUE(sink_name_.empty());
176 EXPECT_FALSE(IsInDelayedStart());
177 }
178
miu9f7788e2017-01-25 00:46:09179 base::MessageLoop message_loop_;
180
181 protected:
miu9f7788e2017-01-25 00:46:09182 bool is_rendering_remotely_ = false;
183 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:35184 bool activate_viewport_intersection_monitoring_ = false;
185 bool disable_pipeline_suspend_ = false;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42186 size_t decoded_bytes_ = 0;
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30187 unsigned decoded_frames_ = 0;
tzik2c963b872017-12-07 06:57:24188 base::SimpleTestTickClock clock_;
Xiangjun Zhangba8724f482017-08-03 06:43:25189 std::string sink_name_;
190 std::unique_ptr<RendererController> controller_;
Xiangjun Zhang4985fe22017-10-12 20:54:22191 double duration_in_sec_ = 120; // 2m duration.
miu9f7788e2017-01-25 00:46:09192
193 private:
194 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
195};
196
Xiangjun Zhangc92ec9b2017-07-25 21:56:42197TEST_F(RendererControllerTest, ToggleRendererOnDominantChange) {
miu9f7788e2017-01-25 00:46:09198 const scoped_refptr<SharedSession> shared_session =
199 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42200 InitializeControllerAndBecomeDominant(shared_session,
201 DefaultMetadata(VideoCodec::kCodecVP8),
202 GetDefaultSinkMetadata(true));
Xiangjun Zhang2cacf422017-11-29 02:22:50203 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42204 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25205 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09206
207 // Leaving fullscreen should shut down remoting.
Xiangjun Zhangc92ec9b2017-07-25 21:56:42208 controller_->OnBecameDominantVisibleContent(false);
miu9f7788e2017-01-25 00:46:09209 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25210 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09211}
212
miu9f7788e2017-01-25 00:46:09213TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
miu9f7788e2017-01-25 00:46:09214 const scoped_refptr<SharedSession> shared_session =
215 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42216 InitializeControllerAndBecomeDominant(shared_session,
217 DefaultMetadata(VideoCodec::kCodecVP8),
218 GetDefaultSinkMetadata(false));
miu9f7788e2017-01-25 00:46:09219 // An available sink that does not support remote rendering should not cause
220 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25221 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09222 shared_session->OnSinkGone(); // Bye-bye useless sink!
223 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25224 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09225 // A sink that *does* support remote rendering *does* cause the controller to
226 // toggle remote rendering on.
Xiangjun Zhang6dc11102017-07-24 23:49:11227 shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09228 RunUntilIdle();
xjz4e5d4bf32017-02-15 21:26:35229 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42230 EXPECT_FALSE(is_rendering_remotely_);
231 controller_->OnBecameDominantVisibleContent(true);
232 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25233 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50234 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42235 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25236 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09237}
238
239TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
240 EXPECT_FALSE(is_rendering_remotely_);
241 const scoped_refptr<SharedSession> shared_session =
242 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42243 InitializeControllerAndBecomeDominant(shared_session,
244 DefaultMetadata(VideoCodec::kCodecVP8),
245 GetDefaultSinkMetadata(true));
Xiangjun Zhangba8724f482017-08-03 06:43:25246 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50247 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42248 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25249 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09250
251 // If the page disables remote playback (e.g., by setting the
252 // disableRemotePlayback attribute), this should shut down remoting.
253 controller_->OnRemotePlaybackDisabled(true);
254 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25255 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09256}
257
Xiangjun Zhang4985fe22017-10-12 20:54:22258TEST_F(RendererControllerTest, NotStartForShortContent) {
259 const scoped_refptr<SharedSession> shared_session =
260 FakeRemoterFactory::CreateSharedSession(false);
261 duration_in_sec_ = 30;
262 InitializeControllerAndBecomeDominant(shared_session,
263 DefaultMetadata(VideoCodec::kCodecVP8),
264 GetDefaultSinkMetadata(true));
265 ExpectInLocalRendering();
266}
267
Anton Vayvod9ef77302017-08-08 20:54:02268#if !defined(OS_ANDROID)
269
Xiangjun Zhang6dc11102017-07-24 23:49:11270TEST_F(RendererControllerTest, WithVP9VideoCodec) {
miu9f7788e2017-01-25 00:46:09271 const scoped_refptr<SharedSession> shared_session =
Xiangjun Zhang6dc11102017-07-24 23:49:11272 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42273 InitializeControllerAndBecomeDominant(shared_session,
274 DefaultMetadata(VideoCodec::kCodecVP9),
275 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11276 // An available sink that does not support VP9 video codec should not cause
277 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25278 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11279
280 shared_session->OnSinkGone(); // Bye-bye useless sink!
Xiangjun Zhang6dc11102017-07-24 23:49:11281 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
282 sink_metadata.video_capabilities.push_back(
283 mojom::RemotingSinkVideoCapability::CODEC_VP9);
284 // A sink that *does* support VP9 video codec *does* cause the controller to
285 // toggle remote rendering on.
286 shared_session->OnSinkAvailable(sink_metadata.Clone());
287 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25288 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50289 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42290 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25291 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11292}
293
294TEST_F(RendererControllerTest, WithHEVCVideoCodec) {
295 const scoped_refptr<SharedSession> shared_session =
296 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42297 InitializeControllerAndBecomeDominant(shared_session,
298 DefaultMetadata(VideoCodec::kCodecHEVC),
299 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11300 // An available sink that does not support HEVC video codec should not cause
301 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25302 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11303
304 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09305 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25306 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11307 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
308 sink_metadata.video_capabilities.push_back(
309 mojom::RemotingSinkVideoCapability::CODEC_HEVC);
310 // A sink that *does* support HEVC video codec *does* cause the controller to
311 // toggle remote rendering on.
312 shared_session->OnSinkAvailable(sink_metadata.Clone());
313 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25314 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50315 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42316 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25317 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11318}
319
320TEST_F(RendererControllerTest, WithAACAudioCodec) {
321 const scoped_refptr<SharedSession> shared_session =
322 FakeRemoterFactory::CreateSharedSession(false);
323 const AudioDecoderConfig audio_config = AudioDecoderConfig(
324 AudioCodec::kCodecAAC, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
325 44100, EmptyExtraData(), Unencrypted());
326 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
327 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42328 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
329 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11330 // An available sink that does not support AAC audio codec should not cause
331 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25332 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11333
334 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09335 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25336 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11337 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
338 sink_metadata.audio_capabilities.push_back(
339 mojom::RemotingSinkAudioCapability::CODEC_AAC);
340 // A sink that *does* support AAC audio codec *does* cause the controller to
341 // toggle remote rendering on.
342 shared_session->OnSinkAvailable(sink_metadata.Clone());
miu9f7788e2017-01-25 00:46:09343 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25344 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50345 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42346 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25347 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11348}
349
350TEST_F(RendererControllerTest, WithOpusAudioCodec) {
351 const scoped_refptr<SharedSession> shared_session =
352 FakeRemoterFactory::CreateSharedSession(false);
353 const AudioDecoderConfig audio_config = AudioDecoderConfig(
354 AudioCodec::kCodecOpus, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
355 44100, EmptyExtraData(), Unencrypted());
356 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
357 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42358 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
359 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11360 // An available sink that does not support Opus audio codec should not cause
361 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25362 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11363
364 shared_session->OnSinkGone(); // Bye-bye useless sink!
365 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11366 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
367 sink_metadata.audio_capabilities.push_back(
368 mojom::RemotingSinkAudioCapability::CODEC_OPUS);
369 // A sink that *does* support Opus audio codec *does* cause the controller to
370 // toggle remote rendering on.
371 shared_session->OnSinkAvailable(sink_metadata.Clone());
372 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25373 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50374 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42375 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25376 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11377}
378
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30379TEST_F(RendererControllerTest, StartFailedWithHighFrameRate) {
380 const scoped_refptr<SharedSession> shared_session =
381 FakeRemoterFactory::CreateSharedSession(false);
382 InitializeControllerAndBecomeDominant(shared_session,
383 DefaultMetadata(VideoCodec::kCodecVP8),
384 GetDefaultSinkMetadata(true));
385 RunUntilIdle();
386 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50387 DelayedStartEnds(60);
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30388 RunUntilIdle();
389 ExpectInLocalRendering();
390}
391
392TEST_F(RendererControllerTest, StartSuccessWithHighFrameRate) {
393 const scoped_refptr<SharedSession> shared_session =
394 FakeRemoterFactory::CreateSharedSession(false);
395 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
396 sink_metadata.video_capabilities.push_back(
397 mojom::RemotingSinkVideoCapability::SUPPORT_4K);
398 InitializeControllerAndBecomeDominant(
399 shared_session, DefaultMetadata(VideoCodec::kCodecVP8), sink_metadata);
400 RunUntilIdle();
401 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50402 DelayedStartEnds(60);
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30403 RunUntilIdle();
404 ExpectInRemoting();
405}
406
Xiangjun Zhang4e722f42017-11-29 20:39:03407TEST_F(RendererControllerTest, PacingTooSlowly) {
408 const scoped_refptr<SharedSession> shared_session =
409 FakeRemoterFactory::CreateSharedSession(false);
410 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
411 InitializeControllerAndBecomeDominant(
412 shared_session, DefaultMetadata(VideoCodec::kCodecVP8), sink_metadata);
413 RunUntilIdle();
414 ExpectInDelayedStart();
415 DelayedStartEnds(false);
416 RunUntilIdle();
417 ExpectInRemoting(); // All requirements now satisfied.
418 controller_->OnRendererFatalError(StopTrigger::PACING_TOO_SLOWLY);
419 RunUntilIdle();
420 ExpectInLocalRendering();
421 shared_session->OnSinkAvailable(sink_metadata.Clone());
422 RunUntilIdle();
423 controller_->OnBecameDominantVisibleContent(false);
424 RunUntilIdle();
425 ExpectInLocalRendering();
426 controller_->OnBecameDominantVisibleContent(true);
427 RunUntilIdle();
428 ExpectInDelayedStart(); // Try start remoting again.
429}
430
Anton Vayvod9ef77302017-08-08 20:54:02431#endif // OS_ANDROID
432
Xiangjun Zhang6dc11102017-07-24 23:49:11433TEST_F(RendererControllerTest, StartFailed) {
434 const scoped_refptr<SharedSession> shared_session =
435 FakeRemoterFactory::CreateSharedSession(true);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42436 InitializeControllerAndBecomeDominant(shared_session,
437 DefaultMetadata(VideoCodec::kCodecVP8),
438 GetDefaultSinkMetadata(true));
439 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25440 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50441 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42442 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25443 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09444}
445
446TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11447 const scoped_refptr<SharedSession> shared_session =
448 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42449 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
450 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09451 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11452
miu9f7788e2017-01-25 00:46:09453 const scoped_refptr<SharedSession> cdm_shared_session =
454 FakeRemoterFactory::CreateSharedSession(false);
455 std::unique_ptr<RemotingCdmController> cdm_controller =
Gyuyoung Kim62a5de42018-01-10 09:48:42456 std::make_unique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11457 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09458 cdm_controller->ShouldCreateRemotingCdm(
459 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
460 RunUntilIdle();
461 EXPECT_FALSE(is_rendering_remotely_);
462 EXPECT_TRUE(is_remoting_cdm_);
463
464 // Create a RemotingCdm with |cdm_controller|.
465 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
466 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
467 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
468 std::move(cdm_controller));
469 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
Gyuyoung Kim62a5de42018-01-10 09:48:42470 std::make_unique<RemotingCdmContext>(remoting_cdm.get());
miu9f7788e2017-01-25 00:46:09471 controller_->OnSetCdm(remoting_cdm_context.get());
472 RunUntilIdle();
473 EXPECT_TRUE(is_rendering_remotely_);
474
Xiangjun Zhangc92ec9b2017-07-25 21:56:42475 // For encrypted contents, becoming/exiting dominant has no effect.
476 controller_->OnBecameDominantVisibleContent(true);
miu9f7788e2017-01-25 00:46:09477 RunUntilIdle();
478 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42479 EXPECT_FALSE(IsInDelayedStart());
480 controller_->OnBecameDominantVisibleContent(false);
481 RunUntilIdle();
482 EXPECT_TRUE(is_rendering_remotely_);
483 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09484
485 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
486 controller_->session()->state());
487 cdm_shared_session->OnSinkGone();
Xiangjun Zhang96242132017-12-22 23:47:46488 cdm_shared_session->OnStopped(mojom::RemotingStopReason::ROUTE_TERMINATED);
miu9f7788e2017-01-25 00:46:09489 RunUntilIdle();
490 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
491 controller_->session()->state());
492 // Don't switch renderer in this case. Still using the remoting renderer to
493 // show the failure interstitial.
494 EXPECT_TRUE(is_rendering_remotely_);
495}
496
497TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11498 const scoped_refptr<SharedSession> shared_session =
miu9f7788e2017-01-25 00:46:09499 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42500 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
501 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09502 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42503 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09504
505 const scoped_refptr<SharedSession> cdm_shared_session =
506 FakeRemoterFactory::CreateSharedSession(true);
507 std::unique_ptr<RemotingCdmController> cdm_controller =
Gyuyoung Kim62a5de42018-01-10 09:48:42508 std::make_unique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11509 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09510 cdm_controller->ShouldCreateRemotingCdm(
511 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
512 RunUntilIdle();
513 EXPECT_FALSE(is_rendering_remotely_);
514 EXPECT_FALSE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42515 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09516}
517
518TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11519 const scoped_refptr<SharedSession> shared_session =
520 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42521 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
522 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09523 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42524 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09525
526 const scoped_refptr<SharedSession> cdm_shared_session =
527 FakeRemoterFactory::CreateSharedSession(false);
528 std::unique_ptr<RemotingCdmController> cdm_controller =
Gyuyoung Kim62a5de42018-01-10 09:48:42529 std::make_unique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11530 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09531 cdm_controller->ShouldCreateRemotingCdm(
532 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
533 RunUntilIdle();
534 EXPECT_FALSE(is_rendering_remotely_);
535 EXPECT_TRUE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42536 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09537
538 cdm_shared_session->OnSinkGone();
Xiangjun Zhang96242132017-12-22 23:47:46539 cdm_shared_session->OnStopped(mojom::RemotingStopReason::ROUTE_TERMINATED);
miu9f7788e2017-01-25 00:46:09540 RunUntilIdle();
541 EXPECT_FALSE(is_rendering_remotely_);
542 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
543 controller_->session()->state());
544
545 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
546 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
547 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
548 std::move(cdm_controller));
549 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
Gyuyoung Kim62a5de42018-01-10 09:48:42550 std::make_unique<RemotingCdmContext>(remoting_cdm.get());
miu9f7788e2017-01-25 00:46:09551 controller_->OnSetCdm(remoting_cdm_context.get());
552 RunUntilIdle();
553 // Switch to using the remoting renderer, even when the remoting CDM session
554 // was already terminated, to show the failure interstitial.
555 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42556 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09557 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
558 controller_->session()->state());
559}
560
561} // namespace remoting
562} // namespace media