xref: /aosp_15_r20/external/webrtc/pc/test/peer_connection_test_wrapper.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/test/peer_connection_test_wrapper.h"
12 
13 #include <stddef.h>
14 
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 #include "absl/types/optional.h"
21 #include "api/audio/audio_mixer.h"
22 #include "api/create_peerconnection_factory.h"
23 #include "api/sequence_checker.h"
24 #include "api/video_codecs/builtin_video_decoder_factory.h"
25 #include "api/video_codecs/builtin_video_encoder_factory.h"
26 #include "api/video_codecs/video_decoder_factory.h"
27 #include "api/video_codecs/video_encoder_factory.h"
28 #include "modules/audio_device/include/audio_device.h"
29 #include "modules/audio_processing/include/audio_processing.h"
30 #include "p2p/base/fake_port_allocator.h"
31 #include "p2p/base/port_allocator.h"
32 #include "pc/test/fake_periodic_video_source.h"
33 #include "pc/test/fake_periodic_video_track_source.h"
34 #include "pc/test/fake_rtc_certificate_generator.h"
35 #include "pc/test/mock_peer_connection_observers.h"
36 #include "rtc_base/gunit.h"
37 #include "rtc_base/logging.h"
38 #include "rtc_base/rtc_certificate_generator.h"
39 #include "rtc_base/string_encode.h"
40 #include "rtc_base/time_utils.h"
41 #include "test/gtest.h"
42 
43 using webrtc::FakeVideoTrackRenderer;
44 using webrtc::IceCandidateInterface;
45 using webrtc::MediaStreamInterface;
46 using webrtc::MediaStreamTrackInterface;
47 using webrtc::MockSetSessionDescriptionObserver;
48 using webrtc::PeerConnectionInterface;
49 using webrtc::RtpReceiverInterface;
50 using webrtc::SdpType;
51 using webrtc::SessionDescriptionInterface;
52 using webrtc::VideoTrackInterface;
53 
54 namespace {
55 const char kStreamIdBase[] = "stream_id";
56 const char kVideoTrackLabelBase[] = "video_track";
57 const char kAudioTrackLabelBase[] = "audio_track";
58 constexpr int kMaxWait = 10000;
59 constexpr int kTestAudioFrameCount = 3;
60 constexpr int kTestVideoFrameCount = 3;
61 }  // namespace
62 
Connect(PeerConnectionTestWrapper * caller,PeerConnectionTestWrapper * callee)63 void PeerConnectionTestWrapper::Connect(PeerConnectionTestWrapper* caller,
64                                         PeerConnectionTestWrapper* callee) {
65   caller->SignalOnIceCandidateReady.connect(
66       callee, &PeerConnectionTestWrapper::AddIceCandidate);
67   callee->SignalOnIceCandidateReady.connect(
68       caller, &PeerConnectionTestWrapper::AddIceCandidate);
69 
70   caller->SignalOnSdpReady.connect(callee,
71                                    &PeerConnectionTestWrapper::ReceiveOfferSdp);
72   callee->SignalOnSdpReady.connect(
73       caller, &PeerConnectionTestWrapper::ReceiveAnswerSdp);
74 }
75 
PeerConnectionTestWrapper(const std::string & name,rtc::SocketServer * socket_server,rtc::Thread * network_thread,rtc::Thread * worker_thread)76 PeerConnectionTestWrapper::PeerConnectionTestWrapper(
77     const std::string& name,
78     rtc::SocketServer* socket_server,
79     rtc::Thread* network_thread,
80     rtc::Thread* worker_thread)
81     : name_(name),
82       socket_server_(socket_server),
83       network_thread_(network_thread),
84       worker_thread_(worker_thread),
85       pending_negotiation_(false) {
86   pc_thread_checker_.Detach();
87 }
88 
~PeerConnectionTestWrapper()89 PeerConnectionTestWrapper::~PeerConnectionTestWrapper() {
90   RTC_DCHECK_RUN_ON(&pc_thread_checker_);
91   // Either network_thread or worker_thread might be active at this point.
92   // Relying on ~PeerConnection to properly wait for them doesn't work,
93   // as a vptr race might occur (before we enter the destruction body).
94   // See: bugs.webrtc.org/9847
95   if (pc()) {
96     pc()->Close();
97   }
98 }
99 
CreatePc(const webrtc::PeerConnectionInterface::RTCConfiguration & config,rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory,rtc::scoped_refptr<webrtc::AudioDecoderFactory> audio_decoder_factory)100 bool PeerConnectionTestWrapper::CreatePc(
101     const webrtc::PeerConnectionInterface::RTCConfiguration& config,
102     rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory,
103     rtc::scoped_refptr<webrtc::AudioDecoderFactory> audio_decoder_factory) {
104   std::unique_ptr<cricket::PortAllocator> port_allocator(
105       new cricket::FakePortAllocator(
106           network_thread_,
107           std::make_unique<rtc::BasicPacketSocketFactory>(socket_server_)));
108 
109   RTC_DCHECK_RUN_ON(&pc_thread_checker_);
110 
111   fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
112   if (fake_audio_capture_module_ == nullptr) {
113     return false;
114   }
115 
116   peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
117       network_thread_, worker_thread_, rtc::Thread::Current(),
118       rtc::scoped_refptr<webrtc::AudioDeviceModule>(fake_audio_capture_module_),
119       audio_encoder_factory, audio_decoder_factory,
120       webrtc::CreateBuiltinVideoEncoderFactory(),
121       webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
122       nullptr /* audio_processing */);
123   if (!peer_connection_factory_) {
124     return false;
125   }
126 
127   std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator(
128       new FakeRTCCertificateGenerator());
129   webrtc::PeerConnectionDependencies deps(this);
130   deps.allocator = std::move(port_allocator);
131   deps.cert_generator = std::move(cert_generator);
132   auto result = peer_connection_factory_->CreatePeerConnectionOrError(
133       config, std::move(deps));
134   if (result.ok()) {
135     peer_connection_ = result.MoveValue();
136     return true;
137   } else {
138     return false;
139   }
140 }
141 
142 rtc::scoped_refptr<webrtc::DataChannelInterface>
CreateDataChannel(const std::string & label,const webrtc::DataChannelInit & init)143 PeerConnectionTestWrapper::CreateDataChannel(
144     const std::string& label,
145     const webrtc::DataChannelInit& init) {
146   auto result = peer_connection_->CreateDataChannelOrError(label, &init);
147   if (!result.ok()) {
148     RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
149                       << ToString(result.error().type()) << " "
150                       << result.error().message();
151     return nullptr;
152   }
153   return result.MoveValue();
154 }
155 
WaitForNegotiation()156 void PeerConnectionTestWrapper::WaitForNegotiation() {
157   EXPECT_TRUE_WAIT(!pending_negotiation_, kMaxWait);
158 }
159 
OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state)160 void PeerConnectionTestWrapper::OnSignalingChange(
161     webrtc::PeerConnectionInterface::SignalingState new_state) {
162   if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) {
163     pending_negotiation_ = false;
164   }
165 }
166 
OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,const std::vector<rtc::scoped_refptr<MediaStreamInterface>> & streams)167 void PeerConnectionTestWrapper::OnAddTrack(
168     rtc::scoped_refptr<RtpReceiverInterface> receiver,
169     const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
170   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": OnAddTrack";
171   if (receiver->track()->kind() == MediaStreamTrackInterface::kVideoKind) {
172     auto* video_track =
173         static_cast<VideoTrackInterface*>(receiver->track().get());
174     renderer_ = std::make_unique<FakeVideoTrackRenderer>(video_track);
175   }
176 }
177 
OnIceCandidate(const IceCandidateInterface * candidate)178 void PeerConnectionTestWrapper::OnIceCandidate(
179     const IceCandidateInterface* candidate) {
180   std::string sdp;
181   EXPECT_TRUE(candidate->ToString(&sdp));
182   SignalOnIceCandidateReady(candidate->sdp_mid(), candidate->sdp_mline_index(),
183                             sdp);
184 }
185 
OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel)186 void PeerConnectionTestWrapper::OnDataChannel(
187     rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
188   SignalOnDataChannel(data_channel.get());
189 }
190 
OnSuccess(SessionDescriptionInterface * desc)191 void PeerConnectionTestWrapper::OnSuccess(SessionDescriptionInterface* desc) {
192   // This callback should take the ownership of `desc`.
193   std::unique_ptr<SessionDescriptionInterface> owned_desc(desc);
194   std::string sdp;
195   EXPECT_TRUE(desc->ToString(&sdp));
196 
197   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": "
198                    << webrtc::SdpTypeToString(desc->GetType())
199                    << " sdp created: " << sdp;
200 
201   SetLocalDescription(desc->GetType(), sdp);
202 
203   SignalOnSdpReady(sdp);
204 }
205 
CreateOffer(const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions & options)206 void PeerConnectionTestWrapper::CreateOffer(
207     const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) {
208   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": CreateOffer.";
209   pending_negotiation_ = true;
210   peer_connection_->CreateOffer(this, options);
211 }
212 
CreateAnswer(const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions & options)213 void PeerConnectionTestWrapper::CreateAnswer(
214     const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) {
215   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
216                    << ": CreateAnswer.";
217   pending_negotiation_ = true;
218   peer_connection_->CreateAnswer(this, options);
219 }
220 
ReceiveOfferSdp(const std::string & sdp)221 void PeerConnectionTestWrapper::ReceiveOfferSdp(const std::string& sdp) {
222   SetRemoteDescription(SdpType::kOffer, sdp);
223   CreateAnswer(webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
224 }
225 
ReceiveAnswerSdp(const std::string & sdp)226 void PeerConnectionTestWrapper::ReceiveAnswerSdp(const std::string& sdp) {
227   SetRemoteDescription(SdpType::kAnswer, sdp);
228 }
229 
SetLocalDescription(SdpType type,const std::string & sdp)230 void PeerConnectionTestWrapper::SetLocalDescription(SdpType type,
231                                                     const std::string& sdp) {
232   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
233                    << ": SetLocalDescription " << webrtc::SdpTypeToString(type)
234                    << " " << sdp;
235 
236   auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
237   peer_connection_->SetLocalDescription(
238       observer.get(), webrtc::CreateSessionDescription(type, sdp).release());
239 }
240 
SetRemoteDescription(SdpType type,const std::string & sdp)241 void PeerConnectionTestWrapper::SetRemoteDescription(SdpType type,
242                                                      const std::string& sdp) {
243   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
244                    << ": SetRemoteDescription " << webrtc::SdpTypeToString(type)
245                    << " " << sdp;
246 
247   auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
248   peer_connection_->SetRemoteDescription(
249       observer.get(), webrtc::CreateSessionDescription(type, sdp).release());
250 }
251 
AddIceCandidate(const std::string & sdp_mid,int sdp_mline_index,const std::string & candidate)252 void PeerConnectionTestWrapper::AddIceCandidate(const std::string& sdp_mid,
253                                                 int sdp_mline_index,
254                                                 const std::string& candidate) {
255   std::unique_ptr<webrtc::IceCandidateInterface> owned_candidate(
256       webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, candidate, NULL));
257   EXPECT_TRUE(peer_connection_->AddIceCandidate(owned_candidate.get()));
258 }
259 
WaitForCallEstablished()260 void PeerConnectionTestWrapper::WaitForCallEstablished() {
261   WaitForConnection();
262   WaitForAudio();
263   WaitForVideo();
264 }
265 
WaitForConnection()266 void PeerConnectionTestWrapper::WaitForConnection() {
267   EXPECT_TRUE_WAIT(CheckForConnection(), kMaxWait);
268   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": Connected.";
269 }
270 
CheckForConnection()271 bool PeerConnectionTestWrapper::CheckForConnection() {
272   return (peer_connection_->ice_connection_state() ==
273           PeerConnectionInterface::kIceConnectionConnected) ||
274          (peer_connection_->ice_connection_state() ==
275           PeerConnectionInterface::kIceConnectionCompleted);
276 }
277 
WaitForAudio()278 void PeerConnectionTestWrapper::WaitForAudio() {
279   EXPECT_TRUE_WAIT(CheckForAudio(), kMaxWait);
280   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
281                    << ": Got enough audio frames.";
282 }
283 
CheckForAudio()284 bool PeerConnectionTestWrapper::CheckForAudio() {
285   return (fake_audio_capture_module_->frames_received() >=
286           kTestAudioFrameCount);
287 }
288 
WaitForVideo()289 void PeerConnectionTestWrapper::WaitForVideo() {
290   EXPECT_TRUE_WAIT(CheckForVideo(), kMaxWait);
291   RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
292                    << ": Got enough video frames.";
293 }
294 
CheckForVideo()295 bool PeerConnectionTestWrapper::CheckForVideo() {
296   if (!renderer_) {
297     return false;
298   }
299   return (renderer_->num_rendered_frames() >= kTestVideoFrameCount);
300 }
301 
GetAndAddUserMedia(bool audio,const cricket::AudioOptions & audio_options,bool video)302 void PeerConnectionTestWrapper::GetAndAddUserMedia(
303     bool audio,
304     const cricket::AudioOptions& audio_options,
305     bool video) {
306   rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
307       GetUserMedia(audio, audio_options, video);
308   for (const auto& audio_track : stream->GetAudioTracks()) {
309     EXPECT_TRUE(peer_connection_->AddTrack(audio_track, {stream->id()}).ok());
310   }
311   for (const auto& video_track : stream->GetVideoTracks()) {
312     EXPECT_TRUE(peer_connection_->AddTrack(video_track, {stream->id()}).ok());
313   }
314 }
315 
316 rtc::scoped_refptr<webrtc::MediaStreamInterface>
GetUserMedia(bool audio,const cricket::AudioOptions & audio_options,bool video)317 PeerConnectionTestWrapper::GetUserMedia(
318     bool audio,
319     const cricket::AudioOptions& audio_options,
320     bool video) {
321   std::string stream_id =
322       kStreamIdBase + rtc::ToString(num_get_user_media_calls_++);
323   rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
324       peer_connection_factory_->CreateLocalMediaStream(stream_id);
325 
326   if (audio) {
327     cricket::AudioOptions options = audio_options;
328     // Disable highpass filter so that we can get all the test audio frames.
329     options.highpass_filter = false;
330     rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
331         peer_connection_factory_->CreateAudioSource(options);
332     rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
333         peer_connection_factory_->CreateAudioTrack(kAudioTrackLabelBase,
334                                                    source.get()));
335     stream->AddTrack(audio_track);
336   }
337 
338   if (video) {
339     // Set max frame rate to 10fps to reduce the risk of the tests to be flaky.
340     webrtc::FakePeriodicVideoSource::Config config;
341     config.frame_interval_ms = 100;
342     config.timestamp_offset_ms = rtc::TimeMillis();
343 
344     auto source = rtc::make_ref_counted<webrtc::FakePeriodicVideoTrackSource>(
345         config, /* remote */ false);
346 
347     std::string videotrack_label = stream_id + kVideoTrackLabelBase;
348     rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
349         peer_connection_factory_->CreateVideoTrack(videotrack_label,
350                                                    source.get()));
351 
352     stream->AddTrack(video_track);
353   }
354   return stream;
355 }
356