session_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/mirroring/service/session.h"
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/json/json_reader.h"
  12. #include "base/run_loop.h"
  13. #include "base/test/task_environment.h"
  14. #include "base/time/time.h"
  15. #include "base/values.h"
  16. #include "components/mirroring/service/fake_network_service.h"
  17. #include "components/mirroring/service/fake_video_capture_host.h"
  18. #include "components/mirroring/service/mirror_settings.h"
  19. #include "components/mirroring/service/receiver_response.h"
  20. #include "components/mirroring/service/value_util.h"
  21. #include "media/cast/test/utility/default_config.h"
  22. #include "media/cast/test/utility/net_utility.h"
  23. #include "mojo/public/cpp/bindings/pending_receiver.h"
  24. #include "mojo/public/cpp/bindings/pending_remote.h"
  25. #include "mojo/public/cpp/bindings/receiver.h"
  26. #include "mojo/public/cpp/bindings/remote.h"
  27. #include "net/base/ip_address.h"
  28. #include "services/viz/public/cpp/gpu/gpu.h"
  29. #include "testing/gmock/include/gmock/gmock.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. #include "third_party/openscreen/src/cast/streaming/ssrc.h"
  32. using media::cast::FrameSenderConfig;
  33. using media::cast::Packet;
  34. using media::mojom::RemotingSinkMetadata;
  35. using media::mojom::RemotingSinkMetadataPtr;
  36. using media::mojom::RemotingStartFailReason;
  37. using media::mojom::RemotingStopReason;
  38. using mirroring::mojom::SessionError;
  39. using mirroring::mojom::SessionType;
  40. using ::testing::_;
  41. using ::testing::AtLeast;
  42. using ::testing::InvokeWithoutArgs;
  43. using ::testing::Mock;
  44. using ::testing::NiceMock;
  45. namespace mirroring {
  46. namespace {
  47. constexpr int kDefaultPlayoutDelay = 400; // ms
  48. const openscreen::cast::Answer kAnswerWithConstraints{
  49. 1234,
  50. // Send indexes and SSRCs are set later.
  51. {},
  52. {},
  53. openscreen::cast::Constraints{
  54. openscreen::cast::AudioConstraints{44100, 2, 32000, 960000,
  55. std::chrono::milliseconds(4000)},
  56. openscreen::cast::VideoConstraints{
  57. 40000.0, openscreen::cast::Dimensions{320, 480, {30, 1}},
  58. openscreen::cast::Dimensions{1920, 1080, {60, 1}}, 300000,
  59. 144000000, std::chrono::milliseconds(4000)}},
  60. openscreen::cast::DisplayDescription{
  61. openscreen::cast::Dimensions{1280, 720, {60, 1}},
  62. openscreen::cast::AspectRatio{16, 9},
  63. openscreen::cast::AspectRatioConstraint::kFixed,
  64. },
  65. };
  66. class MockRemotingSource : public media::mojom::RemotingSource {
  67. public:
  68. MockRemotingSource() {}
  69. ~MockRemotingSource() override {}
  70. void Bind(mojo::PendingReceiver<media::mojom::RemotingSource> receiver) {
  71. receiver_.Bind(std::move(receiver));
  72. }
  73. MOCK_METHOD0(OnSinkGone, void());
  74. MOCK_METHOD0(OnStarted, void());
  75. MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason));
  76. MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&));
  77. MOCK_METHOD1(OnStopped, void(RemotingStopReason));
  78. MOCK_METHOD1(OnSinkAvailable, void(const RemotingSinkMetadata&));
  79. void OnSinkAvailable(RemotingSinkMetadataPtr metadata) override {
  80. OnSinkAvailable(*metadata);
  81. }
  82. private:
  83. mojo::Receiver<media::mojom::RemotingSource> receiver_{this};
  84. };
  85. } // namespace
  86. class SessionTest : public mojom::ResourceProvider,
  87. public mojom::SessionObserver,
  88. public mojom::CastMessageChannel,
  89. public ::testing::Test {
  90. public:
  91. SessionTest() = default;
  92. SessionTest(const SessionTest&) = delete;
  93. SessionTest& operator=(const SessionTest&) = delete;
  94. ~SessionTest() override { task_environment_.RunUntilIdle(); }
  95. protected:
  96. // mojom::SessionObserver implemenation.
  97. MOCK_METHOD1(OnError, void(SessionError));
  98. MOCK_METHOD0(DidStart, void());
  99. MOCK_METHOD0(DidStop, void());
  100. MOCK_METHOD1(LogInfoMessage, void(const std::string&));
  101. MOCK_METHOD1(LogErrorMessage, void(const std::string&));
  102. MOCK_METHOD0(OnGetVideoCaptureHost, void());
  103. MOCK_METHOD0(OnGetNetworkContext, void());
  104. MOCK_METHOD0(OnCreateAudioStream, void());
  105. MOCK_METHOD0(OnConnectToRemotingSource, void());
  106. // Called when sends an outbound message.
  107. MOCK_METHOD1(OnOutboundMessage, void(const std::string& message_type));
  108. MOCK_METHOD0(OnInitDone, void());
  109. // mojom::CastMessageHandler implementation. For outbound messages.
  110. void Send(mojom::CastMessagePtr message) override {
  111. EXPECT_TRUE(message->message_namespace == mojom::kWebRtcNamespace ||
  112. message->message_namespace == mojom::kRemotingNamespace);
  113. absl::optional<base::Value> value =
  114. base::JSONReader::Read(message->json_format_data);
  115. ASSERT_TRUE(value);
  116. std::string message_type;
  117. EXPECT_TRUE(GetString(*value, "type", &message_type));
  118. if (message_type == "OFFER") {
  119. EXPECT_TRUE(GetInt(*value, "seqNum", &offer_sequence_number_));
  120. base::Value::Dict* offer = value->GetDict().FindDict("offer");
  121. ASSERT_TRUE(offer);
  122. base::Value* raw_streams = offer->Find("supportedStreams");
  123. if (raw_streams) {
  124. for (auto& value : raw_streams->GetList()) {
  125. EXPECT_EQ(*value.GetDict().FindInt("targetDelay"),
  126. target_playout_delay_ms_);
  127. }
  128. }
  129. } else if (message_type == "GET_CAPABILITIES") {
  130. EXPECT_TRUE(GetInt(*value, "seqNum", &capability_sequence_number_));
  131. }
  132. OnOutboundMessage(message_type);
  133. }
  134. // mojom::ResourceProvider implemenation.
  135. void BindGpu(mojo::PendingReceiver<viz::mojom::Gpu> receiver) override {}
  136. void GetVideoCaptureHost(
  137. mojo::PendingReceiver<media::mojom::VideoCaptureHost> receiver) override {
  138. video_host_ =
  139. std::make_unique<NiceMock<FakeVideoCaptureHost>>(std::move(receiver));
  140. OnGetVideoCaptureHost();
  141. }
  142. void GetNetworkContext(
  143. mojo::PendingReceiver<network::mojom::NetworkContext> receiver) override {
  144. network_context_ =
  145. std::make_unique<NiceMock<MockNetworkContext>>(std::move(receiver));
  146. OnGetNetworkContext();
  147. }
  148. void CreateAudioStream(
  149. mojo::PendingRemote<mojom::AudioStreamCreatorClient> client,
  150. const media::AudioParameters& params,
  151. uint32_t total_segments) override {
  152. OnCreateAudioStream();
  153. }
  154. void ConnectToRemotingSource(
  155. mojo::PendingRemote<media::mojom::Remoter> remoter,
  156. mojo::PendingReceiver<media::mojom::RemotingSource> receiver) override {
  157. remoter_.Bind(std::move(remoter));
  158. remoting_source_.Bind(std::move(receiver));
  159. OnConnectToRemotingSource();
  160. }
  161. void SendAnswer() {
  162. ASSERT_TRUE(session_);
  163. std::vector<FrameSenderConfig> audio_configs;
  164. std::vector<FrameSenderConfig> video_configs;
  165. if (session_type_ != SessionType::VIDEO_ONLY) {
  166. if (cast_mode_ == "remoting") {
  167. audio_configs.emplace_back(MirrorSettings::GetDefaultAudioConfig(
  168. media::cast::RtpPayloadType::REMOTE_AUDIO,
  169. media::cast::Codec::CODEC_AUDIO_REMOTE));
  170. } else {
  171. EXPECT_EQ("mirroring", cast_mode_);
  172. audio_configs.emplace_back(MirrorSettings::GetDefaultAudioConfig(
  173. media::cast::RtpPayloadType::AUDIO_OPUS,
  174. media::cast::Codec::CODEC_AUDIO_OPUS));
  175. }
  176. }
  177. if (session_type_ != SessionType::AUDIO_ONLY) {
  178. if (cast_mode_ == "remoting") {
  179. video_configs.emplace_back(MirrorSettings::GetDefaultVideoConfig(
  180. media::cast::RtpPayloadType::REMOTE_VIDEO,
  181. media::cast::Codec::CODEC_VIDEO_REMOTE));
  182. } else {
  183. EXPECT_EQ("mirroring", cast_mode_);
  184. video_configs.emplace_back(MirrorSettings::GetDefaultVideoConfig(
  185. media::cast::RtpPayloadType::VIDEO_VP8,
  186. media::cast::Codec::CODEC_VIDEO_VP8));
  187. }
  188. }
  189. std::unique_ptr<openscreen::cast::Answer> answer;
  190. if (answer_) {
  191. answer.swap(answer_);
  192. } else {
  193. answer = std::make_unique<openscreen::cast::Answer>();
  194. }
  195. answer->udp_port = receiver_endpoint_.port();
  196. const int number_of_configs = audio_configs.size() + video_configs.size();
  197. for (int i = 0; i < number_of_configs; ++i) {
  198. answer->send_indexes.push_back(i);
  199. answer->ssrcs.push_back(31 + i); // Arbitrary receiver SSRCs.
  200. }
  201. auto response = ReceiverResponse::CreateAnswerResponseForTesting(
  202. offer_sequence_number_, std::move(answer));
  203. session_->OnAnswer(audio_configs, video_configs, response);
  204. task_environment_.RunUntilIdle();
  205. }
  206. Session::AsyncInitializeDoneCB MakeInitDoneCB() {
  207. return base::BindOnce(&SessionTest::OnInitDone, base::Unretained(this));
  208. }
  209. // Create a mirroring session. Expect to send OFFER message.
  210. void CreateSession(SessionType session_type) {
  211. session_type_ = session_type;
  212. mojom::SessionParametersPtr session_params =
  213. mojom::SessionParameters::New();
  214. session_params->receiver_address = receiver_endpoint_.address();
  215. session_params->type = session_type_;
  216. session_params->receiver_model_name = "Chromecast";
  217. if (target_playout_delay_ms_ != kDefaultPlayoutDelay) {
  218. session_params->target_playout_delay =
  219. base::Milliseconds(target_playout_delay_ms_);
  220. }
  221. cast_mode_ = "mirroring";
  222. mojo::PendingRemote<mojom::ResourceProvider> resource_provider_remote;
  223. mojo::PendingRemote<mojom::SessionObserver> session_observer_remote;
  224. mojo::PendingRemote<mojom::CastMessageChannel> outbound_channel_remote;
  225. resource_provider_receiver_.Bind(
  226. resource_provider_remote.InitWithNewPipeAndPassReceiver());
  227. session_observer_receiver_.Bind(
  228. session_observer_remote.InitWithNewPipeAndPassReceiver());
  229. outbound_channel_receiver_.Bind(
  230. outbound_channel_remote.InitWithNewPipeAndPassReceiver());
  231. // Expect to send OFFER message when session is created.
  232. EXPECT_CALL(*this, OnGetNetworkContext()).Times(1);
  233. EXPECT_CALL(*this, OnError(_)).Times(0);
  234. EXPECT_CALL(*this, OnOutboundMessage("OFFER")).Times(1);
  235. EXPECT_CALL(*this, OnInitDone()).Times(1);
  236. session_ = std::make_unique<Session>(
  237. std::move(session_params), gfx::Size(1920, 1080),
  238. std::move(session_observer_remote), std::move(resource_provider_remote),
  239. std::move(outbound_channel_remote),
  240. inbound_channel_.BindNewPipeAndPassReceiver(), nullptr);
  241. session_->AsyncInitialize(MakeInitDoneCB());
  242. task_environment_.RunUntilIdle();
  243. Mock::VerifyAndClear(this);
  244. }
  245. // Starts the mirroring session.
  246. void StartSession() {
  247. ASSERT_EQ(cast_mode_, "mirroring");
  248. // Except mirroing session starts after receiving ANSWER message.
  249. const int num_to_get_video_host =
  250. session_type_ == SessionType::AUDIO_ONLY ? 0 : 1;
  251. const int num_to_create_audio_stream =
  252. session_type_ == SessionType::VIDEO_ONLY ? 0 : 1;
  253. EXPECT_CALL(*this, OnGetVideoCaptureHost()).Times(num_to_get_video_host);
  254. EXPECT_CALL(*this, OnCreateAudioStream()).Times(num_to_create_audio_stream);
  255. EXPECT_CALL(*this, OnError(_)).Times(0);
  256. EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
  257. EXPECT_CALL(*this, DidStart()).Times(1);
  258. SendAnswer();
  259. task_environment_.RunUntilIdle();
  260. Mock::VerifyAndClear(this);
  261. }
  262. void StopSession() {
  263. if (video_host_)
  264. EXPECT_CALL(*video_host_, OnStopped()).Times(1);
  265. EXPECT_CALL(*this, DidStop()).Times(1);
  266. session_.reset();
  267. task_environment_.RunUntilIdle();
  268. Mock::VerifyAndClear(this);
  269. }
  270. void CaptureOneVideoFrame() {
  271. ASSERT_EQ(cast_mode_, "mirroring");
  272. ASSERT_TRUE(video_host_);
  273. // Expect to send out some UDP packets.
  274. EXPECT_CALL(*network_context_->udp_socket(), OnSend()).Times(AtLeast(1));
  275. EXPECT_CALL(*video_host_, ReleaseBuffer(_, _, _)).Times(1);
  276. // Send one video frame to the consumer.
  277. video_host_->SendOneFrame(gfx::Size(64, 32), base::TimeTicks::Now());
  278. task_environment_.RunUntilIdle();
  279. Mock::VerifyAndClear(network_context_.get());
  280. Mock::VerifyAndClear(video_host_.get());
  281. }
  282. void SignalAnswerTimeout() {
  283. if (cast_mode_ == "mirroring") {
  284. EXPECT_CALL(*this, DidStop()).Times(1);
  285. EXPECT_CALL(*this, OnError(SessionError::ANSWER_TIME_OUT)).Times(1);
  286. } else {
  287. EXPECT_CALL(*this, DidStop()).Times(0);
  288. EXPECT_CALL(*this, OnError(SessionError::ANSWER_TIME_OUT)).Times(0);
  289. // Expect to send OFFER message to fallback on mirroring.
  290. EXPECT_CALL(*this, OnOutboundMessage("OFFER")).Times(1);
  291. // The start of remoting is expected to fail.
  292. EXPECT_CALL(remoting_source_,
  293. OnStartFailed(RemotingStartFailReason::INVALID_ANSWER_MESSAGE))
  294. .Times(1);
  295. EXPECT_CALL(remoting_source_, OnSinkGone()).Times(AtLeast(1));
  296. }
  297. session_->OnAnswer(std::vector<FrameSenderConfig>(),
  298. std::vector<FrameSenderConfig>(), ReceiverResponse());
  299. task_environment_.RunUntilIdle();
  300. cast_mode_ = "mirroring";
  301. Mock::VerifyAndClear(this);
  302. Mock::VerifyAndClear(&remoting_source_);
  303. }
  304. void SendRemotingCapabilities() {
  305. EXPECT_CALL(*this, OnConnectToRemotingSource()).Times(1);
  306. EXPECT_CALL(remoting_source_, OnSinkAvailable(_)).Times(1);
  307. auto capabilities = std::make_unique<ReceiverCapability>();
  308. capabilities->remoting = 2;
  309. capabilities->media_caps =
  310. std::vector<std::string>({"video", "audio", "vp8", "opus"});
  311. auto response = ReceiverResponse::CreateCapabilitiesResponseForTesting(
  312. capability_sequence_number_, std::move(capabilities));
  313. session_->OnCapabilitiesResponse(response);
  314. task_environment_.RunUntilIdle();
  315. Mock::VerifyAndClear(this);
  316. Mock::VerifyAndClear(&remoting_source_);
  317. }
  318. void StartRemoting() {
  319. base::RunLoop run_loop;
  320. ASSERT_TRUE(remoter_.is_bound());
  321. // GET_CAPABILITIES is only sent once at the start of mirroring.
  322. EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(0);
  323. EXPECT_CALL(*this, OnOutboundMessage("OFFER"))
  324. .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
  325. remoter_->Start();
  326. run_loop.Run();
  327. task_environment_.RunUntilIdle();
  328. cast_mode_ = "remoting";
  329. Mock::VerifyAndClear(this);
  330. }
  331. void RemotingStarted() {
  332. ASSERT_EQ(cast_mode_, "remoting");
  333. EXPECT_CALL(remoting_source_, OnStarted()).Times(1);
  334. SendAnswer();
  335. task_environment_.RunUntilIdle();
  336. Mock::VerifyAndClear(this);
  337. Mock::VerifyAndClear(&remoting_source_);
  338. }
  339. void StopRemoting() {
  340. ASSERT_EQ(cast_mode_, "remoting");
  341. const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
  342. // Expect to send OFFER message to fallback on mirroring.
  343. EXPECT_CALL(*this, OnOutboundMessage("OFFER")).Times(1);
  344. EXPECT_CALL(remoting_source_, OnStopped(reason)).Times(1);
  345. remoter_->Stop(reason);
  346. task_environment_.RunUntilIdle();
  347. cast_mode_ = "mirroring";
  348. Mock::VerifyAndClear(this);
  349. Mock::VerifyAndClear(&remoting_source_);
  350. }
  351. void SetTargetPlayoutDelay(int target_playout_delay_ms) {
  352. target_playout_delay_ms_ = target_playout_delay_ms;
  353. }
  354. void SetAnswer(std::unique_ptr<openscreen::cast::Answer> answer) {
  355. answer_ = std::move(answer);
  356. }
  357. private:
  358. base::test::TaskEnvironment task_environment_;
  359. const net::IPEndPoint receiver_endpoint_ =
  360. media::cast::test::GetFreeLocalPort();
  361. mojo::Receiver<mojom::ResourceProvider> resource_provider_receiver_{this};
  362. mojo::Receiver<mojom::SessionObserver> session_observer_receiver_{this};
  363. mojo::Receiver<mojom::CastMessageChannel> outbound_channel_receiver_{this};
  364. mojo::Remote<mojom::CastMessageChannel> inbound_channel_;
  365. SessionType session_type_ = SessionType::AUDIO_AND_VIDEO;
  366. mojo::Remote<media::mojom::Remoter> remoter_;
  367. NiceMock<MockRemotingSource> remoting_source_;
  368. std::string cast_mode_;
  369. int32_t offer_sequence_number_ = -1;
  370. int32_t capability_sequence_number_ = -1;
  371. int32_t target_playout_delay_ms_ = kDefaultPlayoutDelay;
  372. std::unique_ptr<Session> session_;
  373. std::unique_ptr<FakeVideoCaptureHost> video_host_;
  374. std::unique_ptr<MockNetworkContext> network_context_;
  375. std::unique_ptr<openscreen::cast::Answer> answer_;
  376. };
  377. TEST_F(SessionTest, AudioOnlyMirroring) {
  378. CreateSession(SessionType::AUDIO_ONLY);
  379. StartSession();
  380. StopSession();
  381. }
  382. TEST_F(SessionTest, VideoOnlyMirroring) {
  383. SetTargetPlayoutDelay(1000);
  384. CreateSession(SessionType::VIDEO_ONLY);
  385. StartSession();
  386. CaptureOneVideoFrame();
  387. StopSession();
  388. }
  389. TEST_F(SessionTest, AudioAndVideoMirroring) {
  390. SetTargetPlayoutDelay(150);
  391. CreateSession(SessionType::AUDIO_AND_VIDEO);
  392. StartSession();
  393. StopSession();
  394. }
  395. TEST_F(SessionTest, AnswerWithConstraints) {
  396. SetAnswer(std::make_unique<openscreen::cast::Answer>(kAnswerWithConstraints));
  397. CreateSession(SessionType::AUDIO_AND_VIDEO);
  398. StartSession();
  399. StopSession();
  400. }
  401. TEST_F(SessionTest, AnswerTimeout) {
  402. CreateSession(SessionType::AUDIO_AND_VIDEO);
  403. SignalAnswerTimeout();
  404. }
  405. TEST_F(SessionTest, SwitchToAndFromRemoting) {
  406. CreateSession(SessionType::AUDIO_AND_VIDEO);
  407. StartSession();
  408. SendRemotingCapabilities();
  409. StartRemoting();
  410. RemotingStarted();
  411. StopRemoting();
  412. StopSession();
  413. }
  414. TEST_F(SessionTest, StopSessionWhileRemoting) {
  415. CreateSession(SessionType::AUDIO_AND_VIDEO);
  416. StartSession();
  417. SendRemotingCapabilities();
  418. StartRemoting();
  419. RemotingStarted();
  420. StopSession();
  421. }
  422. TEST_F(SessionTest, StartRemotingFailed) {
  423. CreateSession(SessionType::AUDIO_AND_VIDEO);
  424. StartSession();
  425. SendRemotingCapabilities();
  426. StartRemoting();
  427. SignalAnswerTimeout();
  428. // Resume mirroring.
  429. SendAnswer();
  430. CaptureOneVideoFrame();
  431. StopSession();
  432. }
  433. } // namespace mirroring