1 // Copyright (c) 2017 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 "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/check.h"
11 #include "base/memory/scoped_refptr.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
17 #include "third_party/blink/public/platform/web_string.h"
18 #include "third_party/blink/public/web/web_heap.h"
19 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
20 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h"
21 #include "third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h"
22 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
23 #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
24 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
25 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
26 #include "third_party/webrtc/api/stats/rtc_stats_report.h"
27 #include "third_party/webrtc/api/stats/rtcstats_objects.h"
28 #include "third_party/webrtc/api/test/mock_rtpreceiver.h"
29 
30 namespace blink {
31 
32 class RTCRtpReceiverImplTest : public ::testing::Test {
33  public:
SetUp()34   void SetUp() override {
35     dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
36     main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
37     track_map_ = base::MakeRefCounted<blink::WebRtcMediaStreamTrackAdapterMap>(
38         dependency_factory_.get(), main_thread_);
39     peer_connection_ = new rtc::RefCountedObject<blink::MockPeerConnectionImpl>(
40         dependency_factory_.get(), nullptr);
41   }
42 
TearDown()43   void TearDown() override {
44     receiver_.reset();
45     // Syncing up with the signaling thread ensures any pending operations on
46     // that thread are executed. If they post back to the main thread, such as
47     // the sender's destructor traits, this is allowed to execute before the
48     // test shuts down the threads.
49     SyncWithSignalingThread();
50     blink::WebHeap::CollectAllGarbageForTesting();
51   }
52 
53   // Wait for the signaling thread to perform any queued tasks, executing tasks
54   // posted to the current thread in the meantime while waiting.
SyncWithSignalingThread() const55   void SyncWithSignalingThread() const {
56     base::RunLoop run_loop;
57     dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
58         FROM_HERE, run_loop.QuitClosure());
59     run_loop.Run();
60   }
61 
CreateReceiver(scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,bool force_encoded_audio_insertable_streams=false,bool force_encoded_video_insertable_streams=false)62   std::unique_ptr<RTCRtpReceiverImpl> CreateReceiver(
63       scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,
64       bool force_encoded_audio_insertable_streams = false,
65       bool force_encoded_video_insertable_streams = false) {
66     std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
67         track_ref;
68     base::RunLoop run_loop;
69     dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
70         FROM_HERE,
71         base::BindOnce(&RTCRtpReceiverImplTest::CreateReceiverOnSignalingThread,
72                        base::Unretained(this), std::move(webrtc_track),
73                        base::Unretained(&track_ref),
74                        base::Unretained(&run_loop)));
75     run_loop.Run();
76     DCHECK(mock_webrtc_receiver_);
77     DCHECK(track_ref);
78     blink::RtpReceiverState state(
79         main_thread_, dependency_factory_->GetWebRtcSignalingTaskRunner(),
80         mock_webrtc_receiver_.get(), std::move(track_ref), {});
81     state.Initialize();
82     return std::make_unique<RTCRtpReceiverImpl>(
83         peer_connection_.get(), std::move(state),
84         force_encoded_audio_insertable_streams,
85         force_encoded_video_insertable_streams);
86   }
87 
GetStats()88   scoped_refptr<blink::TestWebRTCStatsReportObtainer> GetStats() {
89     scoped_refptr<blink::TestWebRTCStatsReportObtainer> obtainer =
90         base::MakeRefCounted<TestWebRTCStatsReportObtainer>();
91     receiver_->GetStats(obtainer->GetStatsCallbackWrapper(), {});
92     return obtainer;
93   }
94 
95  protected:
CreateReceiverOnSignalingThread(scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef> * track_ref,base::RunLoop * run_loop)96   void CreateReceiverOnSignalingThread(
97       scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,
98       std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>*
99           track_ref,
100       base::RunLoop* run_loop) {
101     mock_webrtc_receiver_ =
102         new rtc::RefCountedObject<webrtc::MockRtpReceiver>();
103     *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track);
104     run_loop->Quit();
105   }
106 
107   ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
108 
109   std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
110       dependency_factory_;
111   scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
112   scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map_;
113   rtc::scoped_refptr<blink::MockPeerConnectionImpl> peer_connection_;
114   rtc::scoped_refptr<webrtc::MockRtpReceiver> mock_webrtc_receiver_;
115   std::unique_ptr<RTCRtpReceiverImpl> receiver_;
116 };
117 
TEST_F(RTCRtpReceiverImplTest,CreateReceiver)118 TEST_F(RTCRtpReceiverImplTest, CreateReceiver) {
119   scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
120       blink::MockWebRtcAudioTrack::Create("webrtc_track");
121   receiver_ = CreateReceiver(webrtc_track);
122   EXPECT_FALSE(!receiver_->Track());
123   EXPECT_EQ(receiver_->Track()->Id().Utf8(), webrtc_track->id());
124   EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track);
125   EXPECT_FALSE(receiver_->GetEncodedAudioStreamTransformer());
126   EXPECT_FALSE(receiver_->GetEncodedVideoStreamTransformer());
127 }
128 
TEST_F(RTCRtpReceiverImplTest,ShallowCopy)129 TEST_F(RTCRtpReceiverImplTest, ShallowCopy) {
130   scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
131       blink::MockWebRtcAudioTrack::Create("webrtc_track");
132   receiver_ = CreateReceiver(webrtc_track);
133   auto copy = std::make_unique<RTCRtpReceiverImpl>(*receiver_);
134   EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track);
135   const auto& webrtc_receiver = receiver_->state().webrtc_receiver();
136   auto web_track_unique_id = receiver_->Track()->UniqueId();
137   // Copy is identical to original.
138   EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver);
139   EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track);
140   EXPECT_EQ(copy->Track()->UniqueId(), web_track_unique_id);
141   // Copy keeps the internal state alive.
142   receiver_.reset();
143   EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver);
144   EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track);
145   EXPECT_EQ(copy->Track()->UniqueId(), web_track_unique_id);
146 }
147 
TEST_F(RTCRtpReceiverImplTest,GetStats)148 TEST_F(RTCRtpReceiverImplTest, GetStats) {
149   scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
150       blink::MockWebRtcAudioTrack::Create("webrtc_track");
151   receiver_ = CreateReceiver(webrtc_track);
152 
153   // Make the mock return a blink version of the |webtc_report|. The mock does
154   // not perform any stats filtering, we just set it to a dummy value.
155   rtc::scoped_refptr<webrtc::RTCStatsReport> webrtc_report =
156       webrtc::RTCStatsReport::Create(0u);
157   webrtc_report->AddStats(
158       std::make_unique<webrtc::RTCInboundRTPStreamStats>("stats-id", 1234u));
159   peer_connection_->SetGetStatsReport(webrtc_report);
160 
161   auto obtainer = GetStats();
162   // Make sure the operation is async.
163   EXPECT_FALSE(obtainer->report());
164   // Wait for the report, this performs the necessary run-loop.
165   auto* report = obtainer->WaitForReport();
166   EXPECT_TRUE(report);
167 
168   // Verify dummy value.
169   EXPECT_EQ(report->Size(), 1u);
170   auto stats = report->GetStats(blink::WebString::FromUTF8("stats-id"));
171   EXPECT_TRUE(stats);
172   EXPECT_EQ(stats->Timestamp(), 1.234);
173 }
174 
TEST_F(RTCRtpReceiverImplTest,CreateReceiverWithInsertableStreams)175 TEST_F(RTCRtpReceiverImplTest, CreateReceiverWithInsertableStreams) {
176   scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
177       blink::MockWebRtcAudioTrack::Create("webrtc_track");
178   receiver_ = CreateReceiver(webrtc_track,
179                              /*force_encoded_audio_insertable_streams=*/true,
180                              /*force_encoded_video_insertable_streams=*/true);
181   EXPECT_TRUE(receiver_->GetEncodedAudioStreamTransformer());
182   // There should be no video transformer in audio receivers.
183   EXPECT_FALSE(receiver_->GetEncodedVideoStreamTransformer());
184 }
185 
186 }  // namespace blink
187