• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2019 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 #include "test/peer_scenario/peer_scenario_client.h"
11 
12 #include <limits>
13 #include <memory>
14 #include <utility>
15 
16 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
17 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
18 #include "api/rtc_event_log/rtc_event_log_factory.h"
19 #include "api/task_queue/default_task_queue_factory.h"
20 #include "api/test/create_time_controller.h"
21 #include "api/video_codecs/builtin_video_decoder_factory.h"
22 #include "api/video_codecs/builtin_video_encoder_factory.h"
23 #include "media/engine/webrtc_media_engine.h"
24 #include "modules/audio_device/include/test_audio_device.h"
25 #include "p2p/client/basic_port_allocator.h"
26 #include "test/fake_decoder.h"
27 #include "test/fake_vp8_encoder.h"
28 #include "test/frame_generator_capturer.h"
29 #include "test/peer_scenario/sdp_callbacks.h"
30 
31 namespace webrtc {
32 namespace test {
33 
34 namespace {
35 
36 constexpr char kCommonStreamId[] = "stream_id";
37 
CreateEndpoints(NetworkEmulationManager * net,std::map<int,EmulatedEndpointConfig> endpoint_configs)38 std::map<int, EmulatedEndpoint*> CreateEndpoints(
39     NetworkEmulationManager* net,
40     std::map<int, EmulatedEndpointConfig> endpoint_configs) {
41   std::map<int, EmulatedEndpoint*> endpoints;
42   for (const auto& kv : endpoint_configs)
43     endpoints[kv.first] = net->CreateEndpoint(kv.second);
44   return endpoints;
45 }
46 
47 class LambdaPeerConnectionObserver final : public PeerConnectionObserver {
48  public:
LambdaPeerConnectionObserver(PeerScenarioClient::CallbackHandlers * handlers)49   explicit LambdaPeerConnectionObserver(
50       PeerScenarioClient::CallbackHandlers* handlers)
51       : handlers_(handlers) {}
OnSignalingChange(PeerConnectionInterface::SignalingState new_state)52   void OnSignalingChange(
53       PeerConnectionInterface::SignalingState new_state) override {
54     for (const auto& handler : handlers_->on_signaling_change)
55       handler(new_state);
56   }
OnDataChannel(rtc::scoped_refptr<DataChannelInterface> data_channel)57   void OnDataChannel(
58       rtc::scoped_refptr<DataChannelInterface> data_channel) override {
59     for (const auto& handler : handlers_->on_data_channel)
60       handler(data_channel);
61   }
OnRenegotiationNeeded()62   void OnRenegotiationNeeded() override {
63     for (const auto& handler : handlers_->on_renegotiation_needed)
64       handler();
65   }
OnStandardizedIceConnectionChange(PeerConnectionInterface::IceConnectionState new_state)66   void OnStandardizedIceConnectionChange(
67       PeerConnectionInterface::IceConnectionState new_state) override {
68     for (const auto& handler : handlers_->on_standardized_ice_connection_change)
69       handler(new_state);
70   }
OnConnectionChange(PeerConnectionInterface::PeerConnectionState new_state)71   void OnConnectionChange(
72       PeerConnectionInterface::PeerConnectionState new_state) override {
73     for (const auto& handler : handlers_->on_connection_change)
74       handler(new_state);
75   }
OnIceGatheringChange(PeerConnectionInterface::IceGatheringState new_state)76   void OnIceGatheringChange(
77       PeerConnectionInterface::IceGatheringState new_state) override {
78     for (const auto& handler : handlers_->on_ice_gathering_change)
79       handler(new_state);
80   }
OnIceCandidate(const IceCandidateInterface * candidate)81   void OnIceCandidate(const IceCandidateInterface* candidate) override {
82     for (const auto& handler : handlers_->on_ice_candidate)
83       handler(candidate);
84   }
OnIceCandidateError(const std::string & address,int port,const std::string & url,int error_code,const std::string & error_text)85   void OnIceCandidateError(const std::string& address,
86                            int port,
87                            const std::string& url,
88                            int error_code,
89                            const std::string& error_text) override {
90     for (const auto& handler : handlers_->on_ice_candidate_error)
91       handler(address, port, url, error_code, error_text);
92   }
OnIceCandidatesRemoved(const std::vector<cricket::Candidate> & candidates)93   void OnIceCandidatesRemoved(
94       const std::vector<cricket::Candidate>& candidates) override {
95     for (const auto& handler : handlers_->on_ice_candidates_removed)
96       handler(candidates);
97   }
OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,const std::vector<rtc::scoped_refptr<MediaStreamInterface>> & streams)98   void OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,
99                   const std::vector<rtc::scoped_refptr<MediaStreamInterface> >&
100                       streams) override {
101     for (const auto& handler : handlers_->on_add_track)
102       handler(receiver, streams);
103   }
OnTrack(rtc::scoped_refptr<RtpTransceiverInterface> transceiver)104   void OnTrack(
105       rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override {
106     for (const auto& handler : handlers_->on_track)
107       handler(transceiver);
108   }
OnRemoveTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver)109   void OnRemoveTrack(
110       rtc::scoped_refptr<RtpReceiverInterface> receiver) override {
111     for (const auto& handler : handlers_->on_remove_track)
112       handler(receiver);
113   }
114 
115  private:
116   PeerScenarioClient::CallbackHandlers* handlers_;
117 };
118 
119 class FakeVideoEncoderFactory : public VideoEncoderFactory {
120  public:
FakeVideoEncoderFactory(Clock * clock)121   FakeVideoEncoderFactory(Clock* clock) : clock_(clock) {}
GetSupportedFormats() const122   std::vector<SdpVideoFormat> GetSupportedFormats() const override {
123     return {SdpVideoFormat("VP8")};
124   }
QueryVideoEncoder(const SdpVideoFormat & format) const125   CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override {
126     RTC_CHECK_EQ(format.name, "VP8");
127     CodecInfo info;
128     info.has_internal_source = false;
129     info.is_hardware_accelerated = false;
130     return info;
131   }
CreateVideoEncoder(const SdpVideoFormat & format)132   std::unique_ptr<VideoEncoder> CreateVideoEncoder(
133       const SdpVideoFormat& format) override {
134     return std::make_unique<FakeVp8Encoder>(clock_);
135   }
136 
137  private:
138   Clock* const clock_;
139 };
140 class FakeVideoDecoderFactory : public VideoDecoderFactory {
141  public:
GetSupportedFormats() const142   std::vector<SdpVideoFormat> GetSupportedFormats() const override {
143     return {SdpVideoFormat("VP8")};
144   }
CreateVideoDecoder(const SdpVideoFormat & format)145   std::unique_ptr<VideoDecoder> CreateVideoDecoder(
146       const SdpVideoFormat& format) override {
147     return std::make_unique<FakeDecoder>();
148   }
149 };
150 }  // namespace
151 
PeerScenarioClient(NetworkEmulationManager * net,rtc::Thread * signaling_thread,std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,PeerScenarioClient::Config config)152 PeerScenarioClient::PeerScenarioClient(
153     NetworkEmulationManager* net,
154     rtc::Thread* signaling_thread,
155     std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
156     PeerScenarioClient::Config config)
157     : endpoints_(CreateEndpoints(net, config.endpoints)),
158       task_queue_factory_(net->time_controller()->GetTaskQueueFactory()),
159       signaling_thread_(signaling_thread),
160       log_writer_factory_(std::move(log_writer_factory)),
161       worker_thread_(net->time_controller()->CreateThread("worker")),
162       handlers_(config.handlers),
163       observer_(new LambdaPeerConnectionObserver(&handlers_)) {
164   handlers_.on_track.push_back(
165       [this](rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
166         auto track = transceiver->receiver()->track().get();
167         if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
168           auto* video = static_cast<VideoTrackInterface*>(track);
169           RTC_DCHECK_RUN_ON(signaling_thread_);
170           for (auto* sink : track_id_to_video_sinks_[track->id()]) {
171             video->AddOrUpdateSink(sink, rtc::VideoSinkWants());
172           }
173         }
174       });
175   handlers_.on_signaling_change.push_back(
176       [this](PeerConnectionInterface::SignalingState state) {
177         RTC_DCHECK_RUN_ON(signaling_thread_);
178         if (state == PeerConnectionInterface::SignalingState::kStable &&
179             peer_connection_->current_remote_description()) {
180           for (const auto& candidate : pending_ice_candidates_) {
181             RTC_CHECK(peer_connection_->AddIceCandidate(candidate.get()));
182           }
183           pending_ice_candidates_.clear();
184         }
185       });
186 
187   std::vector<EmulatedEndpoint*> endpoints_vector;
188   for (const auto& kv : endpoints_)
189     endpoints_vector.push_back(kv.second);
190   auto* manager = net->CreateEmulatedNetworkManagerInterface(endpoints_vector);
191 
192   PeerConnectionFactoryDependencies pcf_deps;
193   pcf_deps.network_thread = manager->network_thread();
194   pcf_deps.signaling_thread = signaling_thread_;
195   pcf_deps.worker_thread = worker_thread_.get();
196   pcf_deps.call_factory =
197       CreateTimeControllerBasedCallFactory(net->time_controller());
198   pcf_deps.task_queue_factory =
199       net->time_controller()->CreateTaskQueueFactory();
200   pcf_deps.event_log_factory =
201       std::make_unique<RtcEventLogFactory>(task_queue_factory_);
202 
203   cricket::MediaEngineDependencies media_deps;
204   media_deps.task_queue_factory = task_queue_factory_;
205   media_deps.adm = TestAudioDeviceModule::Create(
206       task_queue_factory_,
207       TestAudioDeviceModule::CreatePulsedNoiseCapturer(
208           config.audio.pulsed_noise->amplitude *
209               std::numeric_limits<int16_t>::max(),
210           config.audio.sample_rate, config.audio.channels),
211       TestAudioDeviceModule::CreateDiscardRenderer(config.audio.sample_rate));
212 
213   media_deps.audio_processing = AudioProcessingBuilder().Create();
214   if (config.video.use_fake_codecs) {
215     media_deps.video_encoder_factory =
216         std::make_unique<FakeVideoEncoderFactory>(
217             net->time_controller()->GetClock());
218     media_deps.video_decoder_factory =
219         std::make_unique<FakeVideoDecoderFactory>();
220   } else {
221     media_deps.video_encoder_factory = CreateBuiltinVideoEncoderFactory();
222     media_deps.video_decoder_factory = CreateBuiltinVideoDecoderFactory();
223   }
224   media_deps.audio_encoder_factory = CreateBuiltinAudioEncoderFactory();
225   media_deps.audio_decoder_factory = CreateBuiltinAudioDecoderFactory();
226 
227   pcf_deps.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
228   pcf_deps.fec_controller_factory = nullptr;
229   pcf_deps.network_controller_factory = nullptr;
230   pcf_deps.network_state_predictor_factory = nullptr;
231 
232   pc_factory_ = CreateModularPeerConnectionFactory(std::move(pcf_deps));
233 
234   PeerConnectionDependencies pc_deps(observer_.get());
235   pc_deps.allocator =
236       std::make_unique<cricket::BasicPortAllocator>(manager->network_manager());
237   pc_deps.allocator->set_flags(pc_deps.allocator->flags() |
238                                cricket::PORTALLOCATOR_DISABLE_TCP);
239   peer_connection_ =
240       pc_factory_->CreatePeerConnection(config.rtc_config, std::move(pc_deps));
241   if (log_writer_factory_) {
242     peer_connection_->StartRtcEventLog(log_writer_factory_->Create(".rtc.dat"),
243                                        /*output_period_ms=*/1000);
244   }
245 }
246 
endpoint(int index)247 EmulatedEndpoint* PeerScenarioClient::endpoint(int index) {
248   RTC_CHECK_GT(endpoints_.size(), index);
249   return endpoints_.at(index);
250 }
251 
CreateAudio(std::string track_id,cricket::AudioOptions options)252 PeerScenarioClient::AudioSendTrack PeerScenarioClient::CreateAudio(
253     std::string track_id,
254     cricket::AudioOptions options) {
255   RTC_DCHECK_RUN_ON(signaling_thread_);
256   AudioSendTrack res;
257   auto source = pc_factory_->CreateAudioSource(options);
258   auto track = pc_factory_->CreateAudioTrack(track_id, source);
259   res.track = track;
260   res.sender = peer_connection_->AddTrack(track, {kCommonStreamId}).value();
261   return res;
262 }
263 
CreateVideo(std::string track_id,VideoSendTrackConfig config)264 PeerScenarioClient::VideoSendTrack PeerScenarioClient::CreateVideo(
265     std::string track_id,
266     VideoSendTrackConfig config) {
267   RTC_DCHECK_RUN_ON(signaling_thread_);
268   VideoSendTrack res;
269   auto capturer = FrameGeneratorCapturer::Create(clock(), *task_queue_factory_,
270                                                  config.generator);
271   res.capturer = capturer.get();
272   capturer->Init();
273   res.source =
274       new rtc::RefCountedObject<FrameGeneratorCapturerVideoTrackSource>(
275           std::move(capturer), config.screencast);
276   auto track = pc_factory_->CreateVideoTrack(track_id, res.source);
277   res.track = track;
278   res.sender = peer_connection_->AddTrack(track, {kCommonStreamId}).MoveValue();
279   return res;
280 }
281 
AddVideoReceiveSink(std::string track_id,rtc::VideoSinkInterface<VideoFrame> * video_sink)282 void PeerScenarioClient::AddVideoReceiveSink(
283     std::string track_id,
284     rtc::VideoSinkInterface<VideoFrame>* video_sink) {
285   RTC_DCHECK_RUN_ON(signaling_thread_);
286   track_id_to_video_sinks_[track_id].push_back(video_sink);
287 }
288 
CreateAndSetSdp(std::function<void (std::string)> offer_handler)289 void PeerScenarioClient::CreateAndSetSdp(
290     std::function<void(std::string)> offer_handler) {
291   RTC_DCHECK_RUN_ON(signaling_thread_);
292   peer_connection_->CreateOffer(
293       SdpCreateObserver([=](SessionDescriptionInterface* offer) {
294         RTC_DCHECK_RUN_ON(signaling_thread_);
295         std::string sdp_offer;
296         offer->ToString(&sdp_offer);
297         RTC_LOG(LS_INFO) << sdp_offer;
298         peer_connection_->SetLocalDescription(
299             SdpSetObserver(
300                 [sdp_offer, offer_handler]() { offer_handler(sdp_offer); }),
301             offer);
302       }),
303       PeerConnectionInterface::RTCOfferAnswerOptions());
304 }
305 
SetSdpOfferAndGetAnswer(std::string remote_offer,std::function<void (std::string)> answer_handler)306 void PeerScenarioClient::SetSdpOfferAndGetAnswer(
307     std::string remote_offer,
308     std::function<void(std::string)> answer_handler) {
309   if (!signaling_thread_->IsCurrent()) {
310     signaling_thread_->PostTask(RTC_FROM_HERE, [=] {
311       SetSdpOfferAndGetAnswer(remote_offer, answer_handler);
312     });
313     return;
314   }
315   RTC_DCHECK_RUN_ON(signaling_thread_);
316   peer_connection_->SetRemoteDescription(
317       CreateSessionDescription(SdpType::kOffer, remote_offer),
318       SdpSetObserver([=]() {
319         RTC_DCHECK_RUN_ON(signaling_thread_);
320         peer_connection_->CreateAnswer(
321             SdpCreateObserver([=](SessionDescriptionInterface* answer) {
322               RTC_DCHECK_RUN_ON(signaling_thread_);
323               std::string sdp_answer;
324               answer->ToString(&sdp_answer);
325               RTC_LOG(LS_INFO) << sdp_answer;
326               peer_connection_->SetLocalDescription(
327                   SdpSetObserver([answer_handler, sdp_answer]() {
328                     answer_handler(sdp_answer);
329                   }),
330                   answer);
331             }),
332             PeerConnectionInterface::RTCOfferAnswerOptions());
333       }));
334 }
335 
SetSdpAnswer(std::string remote_answer,std::function<void (const SessionDescriptionInterface &)> done_handler)336 void PeerScenarioClient::SetSdpAnswer(
337     std::string remote_answer,
338     std::function<void(const SessionDescriptionInterface&)> done_handler) {
339   if (!signaling_thread_->IsCurrent()) {
340     signaling_thread_->PostTask(
341         RTC_FROM_HERE, [=] { SetSdpAnswer(remote_answer, done_handler); });
342     return;
343   }
344   RTC_DCHECK_RUN_ON(signaling_thread_);
345   peer_connection_->SetRemoteDescription(
346       CreateSessionDescription(SdpType::kAnswer, remote_answer),
347       SdpSetObserver([remote_answer, done_handler] {
348         auto answer = CreateSessionDescription(SdpType::kAnswer, remote_answer);
349         done_handler(*answer);
350       }));
351 }
352 
AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate)353 void PeerScenarioClient::AddIceCandidate(
354     std::unique_ptr<IceCandidateInterface> candidate) {
355   RTC_DCHECK_RUN_ON(signaling_thread_);
356   if (peer_connection_->signaling_state() ==
357           PeerConnectionInterface::SignalingState::kStable &&
358       peer_connection_->current_remote_description()) {
359     RTC_CHECK(peer_connection_->AddIceCandidate(candidate.get()));
360   } else {
361     pending_ice_candidates_.push_back(std::move(candidate));
362   }
363 }
364 
365 }  // namespace test
366 }  // namespace webrtc
367