blob: 3d455a7b67fea6577241b8f6aa4dade3fe04ffd8 [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
7#include "base/callback.h"
8#include "base/memory/ptr_util.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4211#include "base/test/simple_test_tick_clock.h"
Anton Vayvod9ef77302017-08-08 20:54:0212#include "build/build_config.h"
miu9f7788e2017-01-25 00:46:0913#include "media/base/audio_decoder_config.h"
14#include "media/base/cdm_config.h"
15#include "media/base/limits.h"
16#include "media/base/media_util.h"
17#include "media/base/test_helpers.h"
18#include "media/base/video_decoder_config.h"
19#include "media/remoting/fake_remoter.h"
20#include "media/remoting/remoting_cdm.h"
21#include "mojo/public/cpp/bindings/strong_binding.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24namespace media {
25namespace remoting {
26
27namespace {
28
Xiangjun Zhang6dc11102017-07-24 23:49:1129PipelineMetadata DefaultMetadata(VideoCodec codec) {
miu9f7788e2017-01-25 00:46:0930 PipelineMetadata data;
31 data.has_audio = true;
32 data.has_video = true;
Xiangjun Zhang6dc11102017-07-24 23:49:1133 data.video_decoder_config = TestVideoConfig::Normal(codec);
34 data.audio_decoder_config = TestAudioConfig::Normal();
Xiangjun Zhang7fd5be0c2017-10-12 01:20:3035 data.natural_size = gfx::Size(1920, 1080);
miu9f7788e2017-01-25 00:46:0936 return data;
37}
38
39PipelineMetadata EncryptedMetadata() {
40 PipelineMetadata data;
41 data.has_audio = true;
42 data.has_video = true;
43 data.video_decoder_config = TestVideoConfig::NormalEncrypted();
44 return data;
45}
46
Xiangjun Zhangba8724f482017-08-03 06:43:2547const std::string kDefaultReceiver = "TestingChromeCast";
48
Xiangjun Zhang6dc11102017-07-24 23:49:1149mojom::RemotingSinkMetadata GetDefaultSinkMetadata(bool enable) {
50 mojom::RemotingSinkMetadata metadata;
51 if (enable) {
52 metadata.features.push_back(mojom::RemotingSinkFeature::RENDERING);
53 metadata.features.push_back(mojom::RemotingSinkFeature::CONTENT_DECRYPTION);
54 } else {
55 metadata.features.clear();
56 }
57 metadata.video_capabilities.push_back(
58 mojom::RemotingSinkVideoCapability::CODEC_VP8);
59 metadata.audio_capabilities.push_back(
60 mojom::RemotingSinkAudioCapability::CODEC_BASELINE_SET);
Xiangjun Zhangba8724f482017-08-03 06:43:2561 metadata.friendly_name = kDefaultReceiver;
Xiangjun Zhang6dc11102017-07-24 23:49:1162 return metadata;
63}
64
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4265constexpr base::TimeDelta kDelayedStartDuration =
66 base::TimeDelta::FromSeconds(5);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:4267
miu9f7788e2017-01-25 00:46:0968} // namespace
69
xjz4e5d4bf32017-02-15 21:26:3570class RendererControllerTest : public ::testing::Test,
71 public MediaObserverClient {
miu9f7788e2017-01-25 00:46:0972 public:
73 RendererControllerTest() {}
74 ~RendererControllerTest() override {}
75
76 void TearDown() final { RunUntilIdle(); }
77
78 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
79
xjz4e5d4bf32017-02-15 21:26:3580 // MediaObserverClient implementation.
Xiangjun Zhangba8724f482017-08-03 06:43:2581 void SwitchToRemoteRenderer(
82 const std::string& remote_device_friendly_name) override {
83 is_rendering_remotely_ = true;
84 disable_pipeline_suspend_ = true;
85 sink_name_ = remote_device_friendly_name;
86 }
87
88 void SwitchToLocalRenderer() override {
89 is_rendering_remotely_ = false;
90 disable_pipeline_suspend_ = false;
91 sink_name_.clear();
xjz4e5d4bf32017-02-15 21:26:3592 }
93
94 void ActivateViewportIntersectionMonitoring(bool activate) override {
95 activate_viewport_intersection_monitoring_ = activate;
miu9f7788e2017-01-25 00:46:0996 }
97
Xiangjun Zhang4985fe22017-10-12 20:54:2298 double Duration() const override { return duration_in_sec_; }
99
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30100 unsigned DecodedFrameCount() const override { return decoded_frames_; }
101
Anton Vayvod09fa66e2017-07-20 23:02:12102 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
103
miu9f7788e2017-01-25 00:46:09104 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
105
Xiangjun Zhangc92ec9b2017-07-25 21:56:42106 void InitializeControllerAndBecomeDominant(
Xiangjun Zhang6dc11102017-07-24 23:49:11107 const scoped_refptr<SharedSession> shared_session,
108 const PipelineMetadata& pipeline_metadata,
109 const mojom::RemotingSinkMetadata& sink_metadata) {
110 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangba8724f482017-08-03 06:43:25111 EXPECT_TRUE(sink_name_.empty());
Xiangjun Zhang6dc11102017-07-24 23:49:11112 controller_ = base::MakeUnique<RendererController>(shared_session);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42113 clock_ = new base::SimpleTestTickClock();
114 controller_->clock_.reset(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();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42148 clock_->Advance(kDelayedStartDuration);
149 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;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42188 base::SimpleTestTickClock* clock_; // Own by |controller_|;
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
Anton Vayvod9ef77302017-08-08 20:54:02407#endif // OS_ANDROID
408
Xiangjun Zhang6dc11102017-07-24 23:49:11409TEST_F(RendererControllerTest, StartFailed) {
410 const scoped_refptr<SharedSession> shared_session =
411 FakeRemoterFactory::CreateSharedSession(true);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42412 InitializeControllerAndBecomeDominant(shared_session,
413 DefaultMetadata(VideoCodec::kCodecVP8),
414 GetDefaultSinkMetadata(true));
415 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25416 ExpectInDelayedStart();
Xiangjun Zhang2cacf422017-11-29 02:22:50417 DelayedStartEnds();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42418 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25419 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09420}
421
422TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11423 const scoped_refptr<SharedSession> shared_session =
424 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42425 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
426 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09427 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11428
miu9f7788e2017-01-25 00:46:09429 const scoped_refptr<SharedSession> cdm_shared_session =
430 FakeRemoterFactory::CreateSharedSession(false);
431 std::unique_ptr<RemotingCdmController> cdm_controller =
432 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11433 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09434 cdm_controller->ShouldCreateRemotingCdm(
435 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
436 RunUntilIdle();
437 EXPECT_FALSE(is_rendering_remotely_);
438 EXPECT_TRUE(is_remoting_cdm_);
439
440 // Create a RemotingCdm with |cdm_controller|.
441 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
442 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
443 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
444 std::move(cdm_controller));
445 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
446 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
447 controller_->OnSetCdm(remoting_cdm_context.get());
448 RunUntilIdle();
449 EXPECT_TRUE(is_rendering_remotely_);
450
Xiangjun Zhangc92ec9b2017-07-25 21:56:42451 // For encrypted contents, becoming/exiting dominant has no effect.
452 controller_->OnBecameDominantVisibleContent(true);
miu9f7788e2017-01-25 00:46:09453 RunUntilIdle();
454 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42455 EXPECT_FALSE(IsInDelayedStart());
456 controller_->OnBecameDominantVisibleContent(false);
457 RunUntilIdle();
458 EXPECT_TRUE(is_rendering_remotely_);
459 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09460
461 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
462 controller_->session()->state());
463 cdm_shared_session->OnSinkGone();
464 RunUntilIdle();
465 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
466 controller_->session()->state());
467 // Don't switch renderer in this case. Still using the remoting renderer to
468 // show the failure interstitial.
469 EXPECT_TRUE(is_rendering_remotely_);
470}
471
472TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11473 const scoped_refptr<SharedSession> shared_session =
miu9f7788e2017-01-25 00:46:09474 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42475 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
476 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09477 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42478 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09479
480 const scoped_refptr<SharedSession> cdm_shared_session =
481 FakeRemoterFactory::CreateSharedSession(true);
482 std::unique_ptr<RemotingCdmController> cdm_controller =
483 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11484 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09485 cdm_controller->ShouldCreateRemotingCdm(
486 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
487 RunUntilIdle();
488 EXPECT_FALSE(is_rendering_remotely_);
489 EXPECT_FALSE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42490 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09491}
492
493TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11494 const scoped_refptr<SharedSession> shared_session =
495 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42496 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
497 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09498 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42499 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09500
501 const scoped_refptr<SharedSession> cdm_shared_session =
502 FakeRemoterFactory::CreateSharedSession(false);
503 std::unique_ptr<RemotingCdmController> cdm_controller =
504 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11505 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09506 cdm_controller->ShouldCreateRemotingCdm(
507 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
508 RunUntilIdle();
509 EXPECT_FALSE(is_rendering_remotely_);
510 EXPECT_TRUE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42511 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09512
513 cdm_shared_session->OnSinkGone();
514 RunUntilIdle();
515 EXPECT_FALSE(is_rendering_remotely_);
516 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
517 controller_->session()->state());
518
519 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
520 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
521 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
522 std::move(cdm_controller));
523 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
524 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
525 controller_->OnSetCdm(remoting_cdm_context.get());
526 RunUntilIdle();
527 // Switch to using the remoting renderer, even when the remoting CDM session
528 // was already terminated, to show the failure interstitial.
529 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42530 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09531 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
532 controller_->session()->state());
533}
534
535} // namespace remoting
536} // namespace media