blob: dc5b8fbdea831ce2404c934275f7ad785a43f2cb [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 Zhang4985fe22017-10-12 20:54:22100 double Duration() const override { return duration_in_sec_; }
101
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42102 size_t VideoDecodedByteCount() const override { return decoded_bytes_; }
103
104 size_t AudioDecodedByteCount() const override { return 0; }
105
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30106 unsigned DecodedFrameCount() const override { return decoded_frames_; }
107
Anton Vayvod09fa66e2017-07-20 23:02:12108 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
109
miu9f7788e2017-01-25 00:46:09110 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
111
Xiangjun Zhangc92ec9b2017-07-25 21:56:42112 void InitializeControllerAndBecomeDominant(
Xiangjun Zhang6dc11102017-07-24 23:49:11113 const scoped_refptr<SharedSession> shared_session,
114 const PipelineMetadata& pipeline_metadata,
115 const mojom::RemotingSinkMetadata& sink_metadata) {
116 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangba8724f482017-08-03 06:43:25117 EXPECT_TRUE(sink_name_.empty());
Xiangjun Zhang6dc11102017-07-24 23:49:11118 controller_ = base::MakeUnique<RendererController>(shared_session);
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42119 clock_ = new base::SimpleTestTickClock();
120 controller_->clock_.reset(clock_);
121 clock_->Advance(base::TimeDelta::FromSeconds(1));
Xiangjun Zhang6dc11102017-07-24 23:49:11122 controller_->SetClient(this);
123 RunUntilIdle();
124 EXPECT_FALSE(is_rendering_remotely_);
125 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
126 EXPECT_FALSE(disable_pipeline_suspend_);
127 shared_session->OnSinkAvailable(sink_metadata.Clone());
128 RunUntilIdle();
129 EXPECT_FALSE(is_rendering_remotely_);
130 EXPECT_FALSE(disable_pipeline_suspend_);
131 controller_->OnRemotePlaybackDisabled(false);
132 RunUntilIdle();
133 EXPECT_FALSE(is_rendering_remotely_);
134 EXPECT_FALSE(disable_pipeline_suspend_);
135 controller_->OnMetadataChanged(pipeline_metadata);
136 RunUntilIdle();
137 EXPECT_FALSE(is_rendering_remotely_);
138 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42139 controller_->OnBecameDominantVisibleContent(true);
Xiangjun Zhang6dc11102017-07-24 23:49:11140 RunUntilIdle();
141 EXPECT_FALSE(is_rendering_remotely_);
142 EXPECT_FALSE(disable_pipeline_suspend_);
143 controller_->OnPlaying();
144 RunUntilIdle();
145 }
146
Xiangjun Zhangba8724f482017-08-03 06:43:25147 bool IsInDelayedStart() const {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42148 return controller_->delayed_start_stability_timer_.IsRunning();
149 }
150
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30151 void DelayedStartEnds(bool too_high_bitrate, double frame_rate = 30) {
Xiangjun Zhangc92ec9b2017-07-25 21:56:42152 EXPECT_TRUE(IsInDelayedStart());
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42153 if (too_high_bitrate) {
154 decoded_bytes_ =
155 kHighSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
156 } else {
157 decoded_bytes_ =
158 kNormalSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
159 }
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30160 decoded_frames_ = frame_rate * kDelayedStartDuration.InSeconds();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42161 clock_->Advance(kDelayedStartDuration);
162 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42163 const base::Closure callback =
164 controller_->delayed_start_stability_timer_.user_task();
165 callback.Run();
166 controller_->delayed_start_stability_timer_.Stop();
167 }
168
Xiangjun Zhangba8724f482017-08-03 06:43:25169 void ExpectInDelayedStart() const {
170 EXPECT_FALSE(is_rendering_remotely_);
171 EXPECT_FALSE(disable_pipeline_suspend_);
172 EXPECT_TRUE(sink_name_.empty());
173 EXPECT_TRUE(IsInDelayedStart());
174 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
175 }
176
177 void ExpectInRemoting() const {
178 EXPECT_TRUE(is_rendering_remotely_);
179 EXPECT_TRUE(disable_pipeline_suspend_);
180 EXPECT_EQ(kDefaultReceiver, sink_name_);
181 EXPECT_FALSE(IsInDelayedStart());
182 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
183 }
184
185 void ExpectInLocalRendering() const {
186 EXPECT_FALSE(is_rendering_remotely_);
187 EXPECT_FALSE(disable_pipeline_suspend_);
188 EXPECT_TRUE(sink_name_.empty());
189 EXPECT_FALSE(IsInDelayedStart());
190 }
191
miu9f7788e2017-01-25 00:46:09192 base::MessageLoop message_loop_;
193
194 protected:
miu9f7788e2017-01-25 00:46:09195 bool is_rendering_remotely_ = false;
196 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:35197 bool activate_viewport_intersection_monitoring_ = false;
198 bool disable_pipeline_suspend_ = false;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42199 size_t decoded_bytes_ = 0;
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30200 unsigned decoded_frames_ = 0;
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42201 base::SimpleTestTickClock* clock_; // Own by |controller_|;
Xiangjun Zhangba8724f482017-08-03 06:43:25202 std::string sink_name_;
203 std::unique_ptr<RendererController> controller_;
Xiangjun Zhang4985fe22017-10-12 20:54:22204 double duration_in_sec_ = 120; // 2m duration.
miu9f7788e2017-01-25 00:46:09205
206 private:
207 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
208};
209
Xiangjun Zhangc92ec9b2017-07-25 21:56:42210TEST_F(RendererControllerTest, ToggleRendererOnDominantChange) {
miu9f7788e2017-01-25 00:46:09211 const scoped_refptr<SharedSession> shared_session =
212 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42213 InitializeControllerAndBecomeDominant(shared_session,
214 DefaultMetadata(VideoCodec::kCodecVP8),
215 GetDefaultSinkMetadata(true));
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42216 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42217 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25218 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09219
220 // Leaving fullscreen should shut down remoting.
Xiangjun Zhangc92ec9b2017-07-25 21:56:42221 controller_->OnBecameDominantVisibleContent(false);
miu9f7788e2017-01-25 00:46:09222 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25223 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09224}
225
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42226TEST_F(RendererControllerTest, StartFailedWithTooHighBitrate) {
227 const scoped_refptr<SharedSession> shared_session =
228 FakeRemoterFactory::CreateSharedSession(false);
229 InitializeControllerAndBecomeDominant(shared_session,
230 DefaultMetadata(VideoCodec::kCodecVP8),
231 GetDefaultSinkMetadata(true));
232 EXPECT_FALSE(is_rendering_remotely_);
233 EXPECT_TRUE(IsInDelayedStart());
234 DelayedStartEnds(true);
235 RunUntilIdle();
236 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
237 EXPECT_FALSE(is_rendering_remotely_);
238 EXPECT_FALSE(disable_pipeline_suspend_);
239}
240
miu9f7788e2017-01-25 00:46:09241TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
miu9f7788e2017-01-25 00:46:09242 const scoped_refptr<SharedSession> shared_session =
243 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42244 InitializeControllerAndBecomeDominant(shared_session,
245 DefaultMetadata(VideoCodec::kCodecVP8),
246 GetDefaultSinkMetadata(false));
miu9f7788e2017-01-25 00:46:09247 // An available sink that does not support remote rendering should not cause
248 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25249 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09250 shared_session->OnSinkGone(); // Bye-bye useless sink!
251 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25252 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09253 // A sink that *does* support remote rendering *does* cause the controller to
254 // toggle remote rendering on.
Xiangjun Zhang6dc11102017-07-24 23:49:11255 shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09256 RunUntilIdle();
xjz4e5d4bf32017-02-15 21:26:35257 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42258 EXPECT_FALSE(is_rendering_remotely_);
259 controller_->OnBecameDominantVisibleContent(true);
260 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25261 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42262 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42263 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25264 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09265}
266
267TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
268 EXPECT_FALSE(is_rendering_remotely_);
269 const scoped_refptr<SharedSession> shared_session =
270 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42271 InitializeControllerAndBecomeDominant(shared_session,
272 DefaultMetadata(VideoCodec::kCodecVP8),
273 GetDefaultSinkMetadata(true));
Xiangjun Zhangba8724f482017-08-03 06:43:25274 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42275 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42276 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25277 ExpectInRemoting(); // All requirements now satisfied.
miu9f7788e2017-01-25 00:46:09278
279 // If the page disables remote playback (e.g., by setting the
280 // disableRemotePlayback attribute), this should shut down remoting.
281 controller_->OnRemotePlaybackDisabled(true);
282 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25283 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09284}
285
Xiangjun Zhang4985fe22017-10-12 20:54:22286TEST_F(RendererControllerTest, NotStartForShortContent) {
287 const scoped_refptr<SharedSession> shared_session =
288 FakeRemoterFactory::CreateSharedSession(false);
289 duration_in_sec_ = 30;
290 InitializeControllerAndBecomeDominant(shared_session,
291 DefaultMetadata(VideoCodec::kCodecVP8),
292 GetDefaultSinkMetadata(true));
293 ExpectInLocalRendering();
294}
295
Anton Vayvod9ef77302017-08-08 20:54:02296#if !defined(OS_ANDROID)
297
Xiangjun Zhang6dc11102017-07-24 23:49:11298TEST_F(RendererControllerTest, WithVP9VideoCodec) {
miu9f7788e2017-01-25 00:46:09299 const scoped_refptr<SharedSession> shared_session =
Xiangjun Zhang6dc11102017-07-24 23:49:11300 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42301 InitializeControllerAndBecomeDominant(shared_session,
302 DefaultMetadata(VideoCodec::kCodecVP9),
303 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11304 // An available sink that does not support VP9 video codec should not cause
305 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25306 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11307
308 shared_session->OnSinkGone(); // Bye-bye useless sink!
Xiangjun Zhang6dc11102017-07-24 23:49:11309 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
310 sink_metadata.video_capabilities.push_back(
311 mojom::RemotingSinkVideoCapability::CODEC_VP9);
312 // A sink that *does* support VP9 video codec *does* cause the controller to
313 // toggle remote rendering on.
314 shared_session->OnSinkAvailable(sink_metadata.Clone());
315 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25316 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42317 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42318 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25319 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11320}
321
322TEST_F(RendererControllerTest, WithHEVCVideoCodec) {
323 const scoped_refptr<SharedSession> shared_session =
324 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42325 InitializeControllerAndBecomeDominant(shared_session,
326 DefaultMetadata(VideoCodec::kCodecHEVC),
327 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11328 // An available sink that does not support HEVC video codec should not cause
329 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25330 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11331
332 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09333 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25334 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11335 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
336 sink_metadata.video_capabilities.push_back(
337 mojom::RemotingSinkVideoCapability::CODEC_HEVC);
338 // A sink that *does* support HEVC video codec *does* cause the controller to
339 // toggle remote rendering on.
340 shared_session->OnSinkAvailable(sink_metadata.Clone());
341 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25342 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42343 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42344 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25345 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11346}
347
348TEST_F(RendererControllerTest, WithAACAudioCodec) {
349 const scoped_refptr<SharedSession> shared_session =
350 FakeRemoterFactory::CreateSharedSession(false);
351 const AudioDecoderConfig audio_config = AudioDecoderConfig(
352 AudioCodec::kCodecAAC, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
353 44100, EmptyExtraData(), Unencrypted());
354 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
355 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42356 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
357 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11358 // An available sink that does not support AAC audio codec should not cause
359 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25360 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11361
362 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09363 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25364 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11365 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
366 sink_metadata.audio_capabilities.push_back(
367 mojom::RemotingSinkAudioCapability::CODEC_AAC);
368 // A sink that *does* support AAC audio codec *does* cause the controller to
369 // toggle remote rendering on.
370 shared_session->OnSinkAvailable(sink_metadata.Clone());
miu9f7788e2017-01-25 00:46:09371 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25372 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42373 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42374 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25375 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11376}
377
378TEST_F(RendererControllerTest, WithOpusAudioCodec) {
379 const scoped_refptr<SharedSession> shared_session =
380 FakeRemoterFactory::CreateSharedSession(false);
381 const AudioDecoderConfig audio_config = AudioDecoderConfig(
382 AudioCodec::kCodecOpus, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
383 44100, EmptyExtraData(), Unencrypted());
384 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
385 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42386 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
387 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11388 // An available sink that does not support Opus audio codec should not cause
389 // the controller to toggle remote rendering on.
Xiangjun Zhangba8724f482017-08-03 06:43:25390 ExpectInLocalRendering();
Xiangjun Zhang6dc11102017-07-24 23:49:11391
392 shared_session->OnSinkGone(); // Bye-bye useless sink!
393 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11394 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
395 sink_metadata.audio_capabilities.push_back(
396 mojom::RemotingSinkAudioCapability::CODEC_OPUS);
397 // A sink that *does* support Opus audio codec *does* cause the controller to
398 // toggle remote rendering on.
399 shared_session->OnSinkAvailable(sink_metadata.Clone());
400 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25401 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42402 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42403 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25404 ExpectInRemoting(); // All requirements now satisfied.
Xiangjun Zhang6dc11102017-07-24 23:49:11405}
406
Xiangjun Zhang7fd5be0c2017-10-12 01:20:30407TEST_F(RendererControllerTest, StartFailedWithHighFrameRate) {
408 const scoped_refptr<SharedSession> shared_session =
409 FakeRemoterFactory::CreateSharedSession(false);
410 InitializeControllerAndBecomeDominant(shared_session,
411 DefaultMetadata(VideoCodec::kCodecVP8),
412 GetDefaultSinkMetadata(true));
413 RunUntilIdle();
414 ExpectInDelayedStart();
415 DelayedStartEnds(false, 60);
416 RunUntilIdle();
417 ExpectInLocalRendering();
418}
419
420TEST_F(RendererControllerTest, StartSuccessWithHighFrameRate) {
421 const scoped_refptr<SharedSession> shared_session =
422 FakeRemoterFactory::CreateSharedSession(false);
423 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
424 sink_metadata.video_capabilities.push_back(
425 mojom::RemotingSinkVideoCapability::SUPPORT_4K);
426 InitializeControllerAndBecomeDominant(
427 shared_session, DefaultMetadata(VideoCodec::kCodecVP8), sink_metadata);
428 RunUntilIdle();
429 ExpectInDelayedStart();
430 DelayedStartEnds(false, 60);
431 RunUntilIdle();
432 ExpectInRemoting();
433}
434
Anton Vayvod9ef77302017-08-08 20:54:02435#endif // OS_ANDROID
436
Xiangjun Zhang6dc11102017-07-24 23:49:11437TEST_F(RendererControllerTest, StartFailed) {
438 const scoped_refptr<SharedSession> shared_session =
439 FakeRemoterFactory::CreateSharedSession(true);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42440 InitializeControllerAndBecomeDominant(shared_session,
441 DefaultMetadata(VideoCodec::kCodecVP8),
442 GetDefaultSinkMetadata(true));
443 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25444 ExpectInDelayedStart();
Xiangjun Zhang8f6cf3b2017-08-02 07:12:42445 DelayedStartEnds(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42446 RunUntilIdle();
Xiangjun Zhangba8724f482017-08-03 06:43:25447 ExpectInLocalRendering();
miu9f7788e2017-01-25 00:46:09448}
449
450TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11451 const scoped_refptr<SharedSession> shared_session =
452 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42453 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
454 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09455 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11456
miu9f7788e2017-01-25 00:46:09457 const scoped_refptr<SharedSession> cdm_shared_session =
458 FakeRemoterFactory::CreateSharedSession(false);
459 std::unique_ptr<RemotingCdmController> cdm_controller =
460 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11461 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09462 cdm_controller->ShouldCreateRemotingCdm(
463 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
464 RunUntilIdle();
465 EXPECT_FALSE(is_rendering_remotely_);
466 EXPECT_TRUE(is_remoting_cdm_);
467
468 // Create a RemotingCdm with |cdm_controller|.
469 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
470 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
471 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
472 std::move(cdm_controller));
473 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
474 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
475 controller_->OnSetCdm(remoting_cdm_context.get());
476 RunUntilIdle();
477 EXPECT_TRUE(is_rendering_remotely_);
478
Xiangjun Zhangc92ec9b2017-07-25 21:56:42479 // For encrypted contents, becoming/exiting dominant has no effect.
480 controller_->OnBecameDominantVisibleContent(true);
miu9f7788e2017-01-25 00:46:09481 RunUntilIdle();
482 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42483 EXPECT_FALSE(IsInDelayedStart());
484 controller_->OnBecameDominantVisibleContent(false);
485 RunUntilIdle();
486 EXPECT_TRUE(is_rendering_remotely_);
487 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09488
489 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
490 controller_->session()->state());
491 cdm_shared_session->OnSinkGone();
492 RunUntilIdle();
493 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
494 controller_->session()->state());
495 // Don't switch renderer in this case. Still using the remoting renderer to
496 // show the failure interstitial.
497 EXPECT_TRUE(is_rendering_remotely_);
498}
499
500TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11501 const scoped_refptr<SharedSession> shared_session =
miu9f7788e2017-01-25 00:46:09502 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42503 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
504 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09505 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42506 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09507
508 const scoped_refptr<SharedSession> cdm_shared_session =
509 FakeRemoterFactory::CreateSharedSession(true);
510 std::unique_ptr<RemotingCdmController> cdm_controller =
511 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11512 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09513 cdm_controller->ShouldCreateRemotingCdm(
514 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
515 RunUntilIdle();
516 EXPECT_FALSE(is_rendering_remotely_);
517 EXPECT_FALSE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42518 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09519}
520
521TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11522 const scoped_refptr<SharedSession> shared_session =
523 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42524 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
525 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09526 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42527 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09528
529 const scoped_refptr<SharedSession> cdm_shared_session =
530 FakeRemoterFactory::CreateSharedSession(false);
531 std::unique_ptr<RemotingCdmController> cdm_controller =
532 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11533 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09534 cdm_controller->ShouldCreateRemotingCdm(
535 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
536 RunUntilIdle();
537 EXPECT_FALSE(is_rendering_remotely_);
538 EXPECT_TRUE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42539 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09540
541 cdm_shared_session->OnSinkGone();
542 RunUntilIdle();
543 EXPECT_FALSE(is_rendering_remotely_);
544 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
545 controller_->session()->state());
546
547 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
548 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
549 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
550 std::move(cdm_controller));
551 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
552 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
553 controller_->OnSetCdm(remoting_cdm_context.get());
554 RunUntilIdle();
555 // Switch to using the remoting renderer, even when the remoting CDM session
556 // was already terminated, to show the failure interstitial.
557 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42558 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09559 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
560 controller_->session()->state());
561}
562
563} // namespace remoting
564} // namespace media