blob: 5bfa9dee5ff3d3736060b5e5421a4bc12e29b19e [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);
67constexpr double kNormalSpeedBitsPerSecond = 5000000;
68constexpr double kHighSpeedBitsPerSecond = 15000000;
69
miu9f7788e2017-01-25 00:46:0970} // namespace
71
xjz4e5d4bf32017-02-15 21:26:3572class RendererControllerTest : public ::testing::Test,
73 public MediaObserverClient {
miu9f7788e2017-01-25 00:46:0974 public:
75 RendererControllerTest() {}
76 ~RendererControllerTest() override {}
77
78 void TearDown() final { RunUntilIdle(); }
79
80 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
81
xjz4e5d4bf32017-02-15 21:26:3582 // MediaObserverClient implementation.
Xiangjun Zhangba8724f482017-08-03 06:43:2583 void SwitchToRemoteRenderer(
84 const std::string& remote_device_friendly_name) override {
85 is_rendering_remotely_ = true;
86 disable_pipeline_suspend_ = true;
87 sink_name_ = remote_device_friendly_name;
88 }
89
90 void SwitchToLocalRenderer() override {
91 is_rendering_remotely_ = false;
92 disable_pipeline_suspend_ = false;
93 sink_name_.clear();
xjz4e5d4bf32017-02-15 21:26:3594 }
95
96 void ActivateViewportIntersectionMonitoring(bool activate) override {
97 activate_viewport_intersection_monitoring_ = activate;
miu9f7788e2017-01-25 00:46:0998 }
99
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42100 size_t VideoDecodedByteCount() const override { return decoded_bytes_; }
101
102 size_t AudioDecodedByteCount() const override { return 0; }
103
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30104 unsigned DecodedFrameCount() const override { return decoded_frames_; }
105
Anton Vayvod09fa66e2017-07-20 23:02:12106 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
107
miu9f7788e2017-01-25 00:46:09108 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
109
Xiangjun Zhangc92ec9b2017-07-25 21:56:42110 void InitializeControllerAndBecomeDominant(
Xiangjun Zhang6dc11102017-07-24 23:49:11111 const scoped_refptr<SharedSession> shared_session,
112 const PipelineMetadata& pipeline_metadata,
113 const mojom::RemotingSinkMetadata& sink_metadata) {
114 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangba8724f482017-08-03 06:43:25115 EXPECT_TRUE(sink_name_.empty());
Xiangjun Zhang6dc11102017-07-24 23:49:11116 controller_ = base::MakeUnique<RendererController>(shared_session);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42117 clock_ = new base::SimpleTestTickClock();
118 controller_->clock_.reset(clock_);
119 clock_->Advance(base::TimeDelta::FromSeconds(1));
Xiangjun Zhang6dc11102017-07-24 23:49:11120 controller_->SetClient(this);
121 RunUntilIdle();
122 EXPECT_FALSE(is_rendering_remotely_);
123 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
124 EXPECT_FALSE(disable_pipeline_suspend_);
125 shared_session->OnSinkAvailable(sink_metadata.Clone());
126 RunUntilIdle();
127 EXPECT_FALSE(is_rendering_remotely_);
128 EXPECT_FALSE(disable_pipeline_suspend_);
129 controller_->OnRemotePlaybackDisabled(false);
130 RunUntilIdle();
131 EXPECT_FALSE(is_rendering_remotely_);
132 EXPECT_FALSE(disable_pipeline_suspend_);
133 controller_->OnMetadataChanged(pipeline_metadata);
134 RunUntilIdle();
135 EXPECT_FALSE(is_rendering_remotely_);
136 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42137 controller_->OnBecameDominantVisibleContent(true);
Xiangjun Zhang6dc11102017-07-24 23:49:11138 RunUntilIdle();
139 EXPECT_FALSE(is_rendering_remotely_);
140 EXPECT_FALSE(disable_pipeline_suspend_);
141 controller_->OnPlaying();
142 RunUntilIdle();
143 }
144
Xiangjun Zhangba8724f482017-08-03 06:43:25145 bool IsInDelayedStart() const {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42146 return controller_->delayed_start_stability_timer_.IsRunning();
147 }
148
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30149 void DelayedStartEnds(bool too_high_bitrate, double frame_rate = 30) {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42150 EXPECT_TRUE(IsInDelayedStart());
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42151 if (too_high_bitrate) {
152 decoded_bytes_ =
153 kHighSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
154 } else {
155 decoded_bytes_ =
156 kNormalSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
157 }
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30158 decoded_frames_ = frame_rate * kDelayedStartDuration.InSeconds();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42159 clock_->Advance(kDelayedStartDuration);
160 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42161 const base::Closure callback =
162 controller_->delayed_start_stability_timer_.user_task();
163 callback.Run();
164 controller_->delayed_start_stability_timer_.Stop();
165 }
166
Xiangjun Zhangba8724f482017-08-03 06:43:25167 void ExpectInDelayedStart() const {
168 EXPECT_FALSE(is_rendering_remotely_);
169 EXPECT_FALSE(disable_pipeline_suspend_);
170 EXPECT_TRUE(sink_name_.empty());
171 EXPECT_TRUE(IsInDelayedStart());
172 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
173 }
174
175 void ExpectInRemoting() const {
176 EXPECT_TRUE(is_rendering_remotely_);
177 EXPECT_TRUE(disable_pipeline_suspend_);
178 EXPECT_EQ(kDefaultReceiver, sink_name_);
179 EXPECT_FALSE(IsInDelayedStart());
180 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
181 }
182
183 void ExpectInLocalRendering() const {
184 EXPECT_FALSE(is_rendering_remotely_);
185 EXPECT_FALSE(disable_pipeline_suspend_);
186 EXPECT_TRUE(sink_name_.empty());
187 EXPECT_FALSE(IsInDelayedStart());
188 }
189
miu9f7788e2017-01-25 00:46:09190 base::MessageLoop message_loop_;
191
192 protected:
miu9f7788e2017-01-25 00:46:09193 bool is_rendering_remotely_ = false;
194 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:35195 bool activate_viewport_intersection_monitoring_ = false;
196 bool disable_pipeline_suspend_ = false;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42197 size_t decoded_bytes_ = 0;
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30198 unsigned decoded_frames_ = 0;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42199 base::SimpleTestTickClock* clock_; // Own by |controller_|;
Xiangjun Zhangba8724f482017-08-03 06:43:25200 std::string sink_name_;
201 std::unique_ptr<RendererController> controller_;
miu9f7788e2017-01-25 00:46:09202
203 private:
204 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
205};
206
Xiangjun Zhangc92ec9b2017-07-25 21:56:42207TEST_F(RendererControllerTest, ToggleRendererOnDominantChange) {
miu9f7788e2017-01-25 00:46:09208 const scoped_refptr<SharedSession> shared_session =
209 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42210 InitializeControllerAndBecomeDominant(shared_session,
211 DefaultMetadata(VideoCodec::kCodecVP8),
212 GetDefaultSinkMetadata(true));
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42213 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42214 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25215 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09216
217 // Leaving fullscreen should shut down remoting.
Xiangjun Zhangc92ec9b2017-07-25 21:56:42218 controller_->OnBecameDominantVisibleContent(false);
miu9f7788e2017-01-25 00:46:09219 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25220 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09221}
222
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42223TEST_F(RendererControllerTest, StartFailedWithTooHighBitrate) {
224 const scoped_refptr<SharedSession> shared_session =
225 FakeRemoterFactory::CreateSharedSession(false);
226 InitializeControllerAndBecomeDominant(shared_session,
227 DefaultMetadata(VideoCodec::kCodecVP8),
228 GetDefaultSinkMetadata(true));
229 EXPECT_FALSE(is_rendering_remotely_);
230 EXPECT_TRUE(IsInDelayedStart());
231 DelayedStartEnds(true);
232 RunUntilIdle();
233 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
234 EXPECT_FALSE(is_rendering_remotely_);
235 EXPECT_FALSE(disable_pipeline_suspend_);
236}
237
miu9f7788e2017-01-25 00:46:09238TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
miu9f7788e2017-01-25 00:46:09239 const scoped_refptr<SharedSession> shared_session =
240 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42241 InitializeControllerAndBecomeDominant(shared_session,
242 DefaultMetadata(VideoCodec::kCodecVP8),
243 GetDefaultSinkMetadata(false));
miu9f7788e2017-01-25 00:46:09244 // An available sink that does not support remote rendering should not cause
245 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25246 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09247 shared_session->OnSinkGone(); // Bye-bye useless sink!
248 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25249 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09250 // A sink that *does* support remote rendering *does* cause the controller to
251 // toggle remote rendering on.
Xiangjun Zhang6dc11102017-07-24 23:49:11252 shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09253 RunUntilIdle();
xjz4e5d4bf32017-02-15 21:26:35254 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42255 EXPECT_FALSE(is_rendering_remotely_);
256 controller_->OnBecameDominantVisibleContent(true);
257 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25258 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42259 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42260 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25261 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09262}
263
264TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
265 EXPECT_FALSE(is_rendering_remotely_);
266 const scoped_refptr<SharedSession> shared_session =
267 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42268 InitializeControllerAndBecomeDominant(shared_session,
269 DefaultMetadata(VideoCodec::kCodecVP8),
270 GetDefaultSinkMetadata(true));
Xiangjun Zhangba8724f482017-08-03 06:43:25271 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42272 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42273 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25274 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09275
276 // If the page disables remote playback (e.g., by setting the
277 // disableRemotePlayback attribute), this should shut down remoting.
278 controller_->OnRemotePlaybackDisabled(true);
279 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25280 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09281}
282
Anton Vayvod9ef77302017-08-08 20:54:02283#if !defined(OS_ANDROID)
284
Xiangjun Zhang6dc11102017-07-24 23:49:11285TEST_F(RendererControllerTest, WithVP9VideoCodec) {
miu9f7788e2017-01-25 00:46:09286 const scoped_refptr<SharedSession> shared_session =
Xiangjun Zhang6dc11102017-07-24 23:49:11287 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42288 InitializeControllerAndBecomeDominant(shared_session,
289 DefaultMetadata(VideoCodec::kCodecVP9),
290 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11291 // An available sink that does not support VP9 video codec should not cause
292 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25293 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11294
295 shared_session->OnSinkGone(); // Bye-bye useless sink!
Xiangjun Zhang6dc11102017-07-24 23:49:11296 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
297 sink_metadata.video_capabilities.push_back(
298 mojom::RemotingSinkVideoCapability::CODEC_VP9);
299 // A sink that *does* support VP9 video codec *does* cause the controller to
300 // toggle remote rendering on.
301 shared_session->OnSinkAvailable(sink_metadata.Clone());
302 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25303 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42304 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42305 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25306 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11307}
308
309TEST_F(RendererControllerTest, WithHEVCVideoCodec) {
310 const scoped_refptr<SharedSession> shared_session =
311 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42312 InitializeControllerAndBecomeDominant(shared_session,
313 DefaultMetadata(VideoCodec::kCodecHEVC),
314 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11315 // An available sink that does not support HEVC video codec should not cause
316 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25317 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11318
319 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09320 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25321 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11322 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
323 sink_metadata.video_capabilities.push_back(
324 mojom::RemotingSinkVideoCapability::CODEC_HEVC);
325 // A sink that *does* support HEVC video codec *does* cause the controller to
326 // toggle remote rendering on.
327 shared_session->OnSinkAvailable(sink_metadata.Clone());
328 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25329 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42330 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42331 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25332 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11333}
334
335TEST_F(RendererControllerTest, WithAACAudioCodec) {
336 const scoped_refptr<SharedSession> shared_session =
337 FakeRemoterFactory::CreateSharedSession(false);
338 const AudioDecoderConfig audio_config = AudioDecoderConfig(
339 AudioCodec::kCodecAAC, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
340 44100, EmptyExtraData(), Unencrypted());
341 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
342 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42343 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
344 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11345 // An available sink that does not support AAC audio codec should not cause
346 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25347 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11348
349 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09350 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25351 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11352 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
353 sink_metadata.audio_capabilities.push_back(
354 mojom::RemotingSinkAudioCapability::CODEC_AAC);
355 // A sink that *does* support AAC audio codec *does* cause the controller to
356 // toggle remote rendering on.
357 shared_session->OnSinkAvailable(sink_metadata.Clone());
miu9f7788e2017-01-25 00:46:09358 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25359 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42360 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42361 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25362 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11363}
364
365TEST_F(RendererControllerTest, WithOpusAudioCodec) {
366 const scoped_refptr<SharedSession> shared_session =
367 FakeRemoterFactory::CreateSharedSession(false);
368 const AudioDecoderConfig audio_config = AudioDecoderConfig(
369 AudioCodec::kCodecOpus, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
370 44100, EmptyExtraData(), Unencrypted());
371 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
372 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42373 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
374 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11375 // An available sink that does not support Opus audio codec should not cause
376 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25377 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11378
379 shared_session->OnSinkGone(); // Bye-bye useless sink!
380 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11381 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
382 sink_metadata.audio_capabilities.push_back(
383 mojom::RemotingSinkAudioCapability::CODEC_OPUS);
384 // A sink that *does* support Opus audio codec *does* cause the controller to
385 // toggle remote rendering on.
386 shared_session->OnSinkAvailable(sink_metadata.Clone());
387 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25388 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42389 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42390 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25391 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11392}
393
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30394TEST_F(RendererControllerTest, StartFailedWithHighFrameRate) {
395 const scoped_refptr<SharedSession> shared_session =
396 FakeRemoterFactory::CreateSharedSession(false);
397 InitializeControllerAndBecomeDominant(shared_session,
398 DefaultMetadata(VideoCodec::kCodecVP8),
399 GetDefaultSinkMetadata(true));
400 RunUntilIdle();
401 ExpectInDelayedStart();
402 DelayedStartEnds(false, 60);
403 RunUntilIdle();
404 ExpectInLocalRendering();
405}
406
407TEST_F(RendererControllerTest, StartSuccessWithHighFrameRate) {
408 const scoped_refptr<SharedSession> shared_session =
409 FakeRemoterFactory::CreateSharedSession(false);
410 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
411 sink_metadata.video_capabilities.push_back(
412 mojom::RemotingSinkVideoCapability::SUPPORT_4K);
413 InitializeControllerAndBecomeDominant(
414 shared_session, DefaultMetadata(VideoCodec::kCodecVP8), sink_metadata);
415 RunUntilIdle();
416 ExpectInDelayedStart();
417 DelayedStartEnds(false, 60);
418 RunUntilIdle();
419 ExpectInRemoting();
420}
421
Anton Vayvod9ef77302017-08-08 20:54:02422#endif // OS_ANDROID
423
Xiangjun Zhang6dc11102017-07-24 23:49:11424TEST_F(RendererControllerTest, StartFailed) {
425 const scoped_refptr<SharedSession> shared_session =
426 FakeRemoterFactory::CreateSharedSession(true);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42427 InitializeControllerAndBecomeDominant(shared_session,
428 DefaultMetadata(VideoCodec::kCodecVP8),
429 GetDefaultSinkMetadata(true));
430 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25431 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42432 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42433 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25434 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09435}
436
437TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11438 const scoped_refptr<SharedSession> shared_session =
439 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42440 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
441 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09442 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11443
miu9f7788e2017-01-25 00:46:09444 const scoped_refptr<SharedSession> cdm_shared_session =
445 FakeRemoterFactory::CreateSharedSession(false);
446 std::unique_ptr<RemotingCdmController> cdm_controller =
447 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11448 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09449 cdm_controller->ShouldCreateRemotingCdm(
450 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
451 RunUntilIdle();
452 EXPECT_FALSE(is_rendering_remotely_);
453 EXPECT_TRUE(is_remoting_cdm_);
454
455 // Create a RemotingCdm with |cdm_controller|.
456 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
457 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
458 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
459 std::move(cdm_controller));
460 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
461 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
462 controller_->OnSetCdm(remoting_cdm_context.get());
463 RunUntilIdle();
464 EXPECT_TRUE(is_rendering_remotely_);
465
Xiangjun Zhangc92ec9b2017-07-25 21:56:42466 // For encrypted contents, becoming/exiting dominant has no effect.
467 controller_->OnBecameDominantVisibleContent(true);
miu9f7788e2017-01-25 00:46:09468 RunUntilIdle();
469 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42470 EXPECT_FALSE(IsInDelayedStart());
471 controller_->OnBecameDominantVisibleContent(false);
472 RunUntilIdle();
473 EXPECT_TRUE(is_rendering_remotely_);
474 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09475
476 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
477 controller_->session()->state());
478 cdm_shared_session->OnSinkGone();
479 RunUntilIdle();
480 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
481 controller_->session()->state());
482 // Don't switch renderer in this case. Still using the remoting renderer to
483 // show the failure interstitial.
484 EXPECT_TRUE(is_rendering_remotely_);
485}
486
487TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11488 const scoped_refptr<SharedSession> shared_session =
miu9f7788e2017-01-25 00:46:09489 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42490 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
491 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09492 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42493 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09494
495 const scoped_refptr<SharedSession> cdm_shared_session =
496 FakeRemoterFactory::CreateSharedSession(true);
497 std::unique_ptr<RemotingCdmController> cdm_controller =
498 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11499 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09500 cdm_controller->ShouldCreateRemotingCdm(
501 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
502 RunUntilIdle();
503 EXPECT_FALSE(is_rendering_remotely_);
504 EXPECT_FALSE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42505 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09506}
507
508TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11509 const scoped_refptr<SharedSession> shared_session =
510 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42511 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
512 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09513 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42514 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09515
516 const scoped_refptr<SharedSession> cdm_shared_session =
517 FakeRemoterFactory::CreateSharedSession(false);
518 std::unique_ptr<RemotingCdmController> cdm_controller =
519 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11520 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09521 cdm_controller->ShouldCreateRemotingCdm(
522 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
523 RunUntilIdle();
524 EXPECT_FALSE(is_rendering_remotely_);
525 EXPECT_TRUE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42526 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09527
528 cdm_shared_session->OnSinkGone();
529 RunUntilIdle();
530 EXPECT_FALSE(is_rendering_remotely_);
531 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
532 controller_->session()->state());
533
534 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
535 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
536 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
537 std::move(cdm_controller));
538 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
539 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
540 controller_->OnSetCdm(remoting_cdm_context.get());
541 RunUntilIdle();
542 // Switch to using the remoting renderer, even when the remoting CDM session
543 // was already terminated, to show the failure interstitial.
544 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42545 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09546 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
547 controller_->session()->state());
548}
549
550} // namespace remoting
551} // namespace media