blob: 89c898469281f24a2ef9df0760406da47027c863 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "examples/peerconnection/client/conductor.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
kwibergbfefb032016-05-01 14:53:46 -070013#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014#include <utility>
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +000015#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
Karl Wiberg1b0eae32017-10-17 14:48:54 +020017#include "api/audio_codecs/builtin_audio_decoder_factory.h"
18#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "api/test/fakeconstraints.h"
Anders Carlsson67537952018-05-03 11:28:29 +020020#include "api/video_codecs/builtin_video_decoder_factory.h"
21#include "api/video_codecs/builtin_video_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "examples/peerconnection/client/defaults.h"
23#include "media/engine/webrtcvideocapturerfactory.h"
Anders Carlsson67537952018-05-03 11:28:29 +020024#include "modules/audio_device/include/audio_device.h"
25#include "modules/audio_processing/include/audio_processing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/video_capture/video_capture_factory.h"
27#include "rtc_base/checks.h"
28#include "rtc_base/json.h"
29#include "rtc_base/logging.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
31// Names used for a IceCandidate JSON object.
32const char kCandidateSdpMidName[] = "sdpMid";
33const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
34const char kCandidateSdpName[] = "candidate";
35
36// Names used for a SessionDescription JSON object.
37const char kSessionDescriptionTypeName[] = "type";
38const char kSessionDescriptionSdpName[] = "sdp";
39
40class DummySetSessionDescriptionObserver
41 : public webrtc::SetSessionDescriptionObserver {
42 public:
43 static DummySetSessionDescriptionObserver* Create() {
Yves Gerey665174f2018-06-19 15:03:05 +020044 return new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045 }
Mirko Bonadei675513b2017-11-09 11:09:25 +010046 virtual void OnSuccess() { RTC_LOG(INFO) << __FUNCTION__; }
Harald Alvestrand73771a82018-05-24 10:53:49 +020047 virtual void OnFailure(webrtc::RTCError error) {
48 RTC_LOG(INFO) << __FUNCTION__ << " " << ToString(error.type()) << ": "
49 << error.message();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051};
52
53Conductor::Conductor(PeerConnectionClient* client, MainWindow* main_wnd)
Yves Gerey665174f2018-06-19 15:03:05 +020054 : peer_id_(-1), loopback_(false), client_(client), main_wnd_(main_wnd) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055 client_->RegisterObserver(this);
56 main_wnd->RegisterObserver(this);
57}
58
59Conductor::~Conductor() {
Steve Antonc06ed702018-04-17 12:53:02 -070060 RTC_DCHECK(!peer_connection_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061}
62
63bool Conductor::connection_active() const {
Steve Antonc06ed702018-04-17 12:53:02 -070064 return peer_connection_ != nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065}
66
67void Conductor::Close() {
68 client_->SignOut();
69 DeletePeerConnection();
70}
71
72bool Conductor::InitializePeerConnection() {
Steve Antonc06ed702018-04-17 12:53:02 -070073 RTC_DCHECK(!peer_connection_factory_);
74 RTC_DCHECK(!peer_connection_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075
Karl Wiberg1b0eae32017-10-17 14:48:54 +020076 peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
Anders Carlsson67537952018-05-03 11:28:29 +020077 nullptr /* network_thread */, nullptr /* worker_thread */,
78 nullptr /* signaling_thread */, nullptr /* default_adm */,
Karl Wiberg1b0eae32017-10-17 14:48:54 +020079 webrtc::CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +020080 webrtc::CreateBuiltinAudioDecoderFactory(),
81 webrtc::CreateBuiltinVideoEncoderFactory(),
82 webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
83 nullptr /* audio_processing */);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
Steve Antonc06ed702018-04-17 12:53:02 -070085 if (!peer_connection_factory_) {
Yves Gerey665174f2018-06-19 15:03:05 +020086 main_wnd_->MessageBox("Error", "Failed to initialize PeerConnectionFactory",
87 true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 DeletePeerConnection();
89 return false;
90 }
91
Steve Antonc06ed702018-04-17 12:53:02 -070092 if (!CreatePeerConnection(/*dtls=*/true)) {
Yves Gerey665174f2018-06-19 15:03:05 +020093 main_wnd_->MessageBox("Error", "CreatePeerConnection failed", true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 DeletePeerConnection();
95 }
Steve Antonc06ed702018-04-17 12:53:02 -070096
97 AddTracks();
98
99 return peer_connection_ != nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100}
101
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000102bool Conductor::ReinitializePeerConnectionForLoopback() {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000103 loopback_ = true;
Steve Antonc06ed702018-04-17 12:53:02 -0700104 std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> senders =
105 peer_connection_->GetSenders();
106 peer_connection_ = nullptr;
107 if (CreatePeerConnection(/*dtls=*/false)) {
108 for (const auto& sender : senders) {
109 peer_connection_->AddTrack(sender->track(), sender->stream_ids());
110 }
111 peer_connection_->CreateOffer(
112 this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000113 }
Steve Antonc06ed702018-04-17 12:53:02 -0700114 return peer_connection_ != nullptr;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000115}
116
117bool Conductor::CreatePeerConnection(bool dtls) {
Steve Antonc06ed702018-04-17 12:53:02 -0700118 RTC_DCHECK(peer_connection_factory_);
119 RTC_DCHECK(!peer_connection_);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000120
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800121 webrtc::PeerConnectionInterface::RTCConfiguration config;
Steve Antonc06ed702018-04-17 12:53:02 -0700122 config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
123 config.enable_dtls_srtp = dtls;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000124 webrtc::PeerConnectionInterface::IceServer server;
125 server.uri = GetPeerConnectionString();
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800126 config.servers.push_back(server);
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000127
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800128 peer_connection_ = peer_connection_factory_->CreatePeerConnection(
Steve Antonc06ed702018-04-17 12:53:02 -0700129 config, nullptr, nullptr, this);
130 return peer_connection_ != nullptr;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000131}
132
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133void Conductor::DeletePeerConnection() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134 main_wnd_->StopLocalRenderer();
135 main_wnd_->StopRemoteRenderer();
Steve Antonc06ed702018-04-17 12:53:02 -0700136 peer_connection_ = nullptr;
137 peer_connection_factory_ = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000138 peer_id_ = -1;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000139 loopback_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000140}
141
142void Conductor::EnsureStreamingUI() {
Steve Antonc06ed702018-04-17 12:53:02 -0700143 RTC_DCHECK(peer_connection_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000144 if (main_wnd_->IsWindow()) {
145 if (main_wnd_->current_ui() != MainWindow::STREAMING)
146 main_wnd_->SwitchToStreamingUI();
147 }
148}
149
150//
151// PeerConnectionObserver implementation.
152//
153
Steve Antonc06ed702018-04-17 12:53:02 -0700154void Conductor::OnAddTrack(
155 rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
156 const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&
157 streams) {
158 RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id();
159 main_wnd_->QueueUIThreadCallback(NEW_TRACK_ADDED,
160 receiver->track().release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161}
162
Steve Antonc06ed702018-04-17 12:53:02 -0700163void Conductor::OnRemoveTrack(
164 rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
165 RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id();
166 main_wnd_->QueueUIThreadCallback(TRACK_REMOVED, receiver->track().release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167}
168
169void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100170 RTC_LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000171 // For loopback test. To save some connecting delay.
172 if (loopback_) {
173 if (!peer_connection_->AddIceCandidate(candidate)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100174 RTC_LOG(WARNING) << "Failed to apply the received candidate";
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000175 }
176 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000177 }
178
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179 Json::StyledWriter writer;
180 Json::Value jmessage;
181
182 jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
183 jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
184 std::string sdp;
185 if (!candidate->ToString(&sdp)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100186 RTC_LOG(LS_ERROR) << "Failed to serialize candidate";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000187 return;
188 }
189 jmessage[kCandidateSdpName] = sdp;
190 SendMessage(writer.write(jmessage));
191}
192
193//
194// PeerConnectionClientObserver implementation.
195//
196
197void Conductor::OnSignedIn() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100198 RTC_LOG(INFO) << __FUNCTION__;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 main_wnd_->SwitchToPeerList(client_->peers());
200}
201
202void Conductor::OnDisconnected() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100203 RTC_LOG(INFO) << __FUNCTION__;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000204
205 DeletePeerConnection();
206
207 if (main_wnd_->IsWindow())
208 main_wnd_->SwitchToConnectUI();
209}
210
211void Conductor::OnPeerConnected(int id, const std::string& name) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100212 RTC_LOG(INFO) << __FUNCTION__;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000213 // Refresh the list if we're showing it.
214 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
215 main_wnd_->SwitchToPeerList(client_->peers());
216}
217
218void Conductor::OnPeerDisconnected(int id) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100219 RTC_LOG(INFO) << __FUNCTION__;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000220 if (id == peer_id_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100221 RTC_LOG(INFO) << "Our peer disconnected";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 main_wnd_->QueueUIThreadCallback(PEER_CONNECTION_CLOSED, NULL);
223 } else {
224 // Refresh the list if we're showing it.
225 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
226 main_wnd_->SwitchToPeerList(client_->peers());
227 }
228}
229
230void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
nisseede5da42017-01-12 05:15:36 -0800231 RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1);
232 RTC_DCHECK(!message.empty());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233
234 if (!peer_connection_.get()) {
nisseede5da42017-01-12 05:15:36 -0800235 RTC_DCHECK(peer_id_ == -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236 peer_id_ = peer_id;
237
238 if (!InitializePeerConnection()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100239 RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240 client_->SignOut();
241 return;
242 }
243 } else if (peer_id != peer_id_) {
nisseede5da42017-01-12 05:15:36 -0800244 RTC_DCHECK(peer_id_ != -1);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100245 RTC_LOG(WARNING)
246 << "Received a message from unknown peer while already in a "
247 "conversation with a different peer.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248 return;
249 }
250
251 Json::Reader reader;
252 Json::Value jmessage;
253 if (!reader.parse(message, jmessage)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100254 RTC_LOG(WARNING) << "Received unknown message. " << message;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000255 return;
256 }
Steve Antona3a92c22017-12-07 10:27:41 -0800257 std::string type_str;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258 std::string json_object;
259
Steve Antona3a92c22017-12-07 10:27:41 -0800260 rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName,
261 &type_str);
262 if (!type_str.empty()) {
263 if (type_str == "offer-loopback") {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000264 // This is a loopback call.
265 // Recreate the peerconnection with DTLS disabled.
266 if (!ReinitializePeerConnectionForLoopback()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100267 RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000268 DeletePeerConnection();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000269 client_->SignOut();
270 }
271 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000272 }
Danil Chapovalov196100e2018-06-21 10:17:24 +0200273 absl::optional<webrtc::SdpType> type_maybe =
Steve Antonc06ed702018-04-17 12:53:02 -0700274 webrtc::SdpTypeFromString(type_str);
Steve Antona3a92c22017-12-07 10:27:41 -0800275 if (!type_maybe) {
276 RTC_LOG(LS_ERROR) << "Unknown SDP type: " << type_str;
277 return;
278 }
Steve Antonc06ed702018-04-17 12:53:02 -0700279 webrtc::SdpType type = *type_maybe;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000281 if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
282 &sdp)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100283 RTC_LOG(WARNING) << "Can't parse received session description message.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 return;
285 }
jbauchfabe2c92015-07-16 13:43:14 -0700286 webrtc::SdpParseError error;
Steve Antona3a92c22017-12-07 10:27:41 -0800287 std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
288 webrtc::CreateSessionDescription(type, sdp, &error);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 if (!session_description) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100290 RTC_LOG(WARNING) << "Can't parse received session description message. "
291 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 return;
293 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100294 RTC_LOG(INFO) << " Received session description :" << message;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295 peer_connection_->SetRemoteDescription(
Steve Antona3a92c22017-12-07 10:27:41 -0800296 DummySetSessionDescriptionObserver::Create(),
297 session_description.release());
Steve Antonc06ed702018-04-17 12:53:02 -0700298 if (type == webrtc::SdpType::kOffer) {
299 peer_connection_->CreateAnswer(
300 this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302 } else {
303 std::string sdp_mid;
304 int sdp_mlineindex = 0;
305 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000306 if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
307 &sdp_mid) ||
308 !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
309 &sdp_mlineindex) ||
310 !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100311 RTC_LOG(WARNING) << "Can't parse received message.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312 return;
313 }
jbauchfabe2c92015-07-16 13:43:14 -0700314 webrtc::SdpParseError error;
kwibergbfefb032016-05-01 14:53:46 -0700315 std::unique_ptr<webrtc::IceCandidateInterface> candidate(
jbauchfabe2c92015-07-16 13:43:14 -0700316 webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317 if (!candidate.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100318 RTC_LOG(WARNING) << "Can't parse received candidate message. "
319 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320 return;
321 }
322 if (!peer_connection_->AddIceCandidate(candidate.get())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100323 RTC_LOG(WARNING) << "Failed to apply the received candidate";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000324 return;
325 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100326 RTC_LOG(INFO) << " Received candidate :" << message;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327 }
328}
329
330void Conductor::OnMessageSent(int err) {
331 // Process the next pending message if any.
332 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, NULL);
333}
334
335void Conductor::OnServerConnectionFailure() {
Steve Antonc06ed702018-04-17 12:53:02 -0700336 main_wnd_->MessageBox("Error", ("Failed to connect to " + server_).c_str(),
337 true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338}
339
340//
341// MainWndCallback implementation.
342//
343
344void Conductor::StartLogin(const std::string& server, int port) {
345 if (client_->is_connected())
346 return;
347 server_ = server;
348 client_->Connect(server, port, GetPeerName());
349}
350
351void Conductor::DisconnectFromServer() {
352 if (client_->is_connected())
353 client_->SignOut();
354}
355
356void Conductor::ConnectToPeer(int peer_id) {
nisseede5da42017-01-12 05:15:36 -0800357 RTC_DCHECK(peer_id_ == -1);
358 RTC_DCHECK(peer_id != -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359
360 if (peer_connection_.get()) {
Yves Gerey665174f2018-06-19 15:03:05 +0200361 main_wnd_->MessageBox(
362 "Error", "We only support connecting to one peer at a time", true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 return;
364 }
365
366 if (InitializePeerConnection()) {
367 peer_id_ = peer_id;
Steve Antonc06ed702018-04-17 12:53:02 -0700368 peer_connection_->CreateOffer(
369 this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370 } else {
371 main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true);
372 }
373}
374
deadbeef112b2e92017-02-10 20:13:37 -0800375std::unique_ptr<cricket::VideoCapturer> Conductor::OpenVideoCaptureDevice() {
solenberg8ad582d2016-03-16 09:34:56 -0700376 std::vector<std::string> device_names;
377 {
378 std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
nisseb29b9c82016-12-12 00:22:56 -0800379 webrtc::VideoCaptureFactory::CreateDeviceInfo());
solenberg8ad582d2016-03-16 09:34:56 -0700380 if (!info) {
381 return nullptr;
382 }
383 int num_devices = info->NumberOfDevices();
384 for (int i = 0; i < num_devices; ++i) {
385 const uint32_t kSize = 256;
386 char name[kSize] = {0};
387 char id[kSize] = {0};
388 if (info->GetDeviceName(i, name, kSize, id, kSize) != -1) {
389 device_names.push_back(name);
390 }
391 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392 }
solenberg8ad582d2016-03-16 09:34:56 -0700393
394 cricket::WebRtcVideoDeviceCapturerFactory factory;
deadbeef112b2e92017-02-10 20:13:37 -0800395 std::unique_ptr<cricket::VideoCapturer> capturer;
solenberg8ad582d2016-03-16 09:34:56 -0700396 for (const auto& name : device_names) {
397 capturer = factory.Create(cricket::Device(name, 0));
398 if (capturer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000399 break;
solenberg8ad582d2016-03-16 09:34:56 -0700400 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000401 }
402 return capturer;
403}
404
Steve Antonc06ed702018-04-17 12:53:02 -0700405void Conductor::AddTracks() {
406 if (!peer_connection_->GetSenders().empty()) {
407 return; // Already added tracks.
408 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000410 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 peer_connection_factory_->CreateAudioTrack(
Niels Möller2d02e082018-05-21 11:23:35 +0200412 kAudioLabel, peer_connection_factory_->CreateAudioSource(
413 cricket::AudioOptions())));
Steve Antonc06ed702018-04-17 12:53:02 -0700414 auto result_or_error = peer_connection_->AddTrack(audio_track, {kStreamId});
415 if (!result_or_error.ok()) {
416 RTC_LOG(LS_ERROR) << "Failed to add audio track to PeerConnection: "
417 << result_or_error.error().message();
418 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000419
Steve Antonc06ed702018-04-17 12:53:02 -0700420 std::unique_ptr<cricket::VideoCapturer> video_device =
421 OpenVideoCaptureDevice();
Tommi2c599d62018-02-15 11:08:36 +0100422 if (video_device) {
Steve Antonc06ed702018-04-17 12:53:02 -0700423 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track_(
Tommi2c599d62018-02-15 11:08:36 +0100424 peer_connection_factory_->CreateVideoTrack(
Steve Antonc06ed702018-04-17 12:53:02 -0700425 kVideoLabel, peer_connection_factory_->CreateVideoSource(
426 std::move(video_device), nullptr)));
427 main_wnd_->StartLocalRenderer(video_track_);
428
429 result_or_error = peer_connection_->AddTrack(video_track_, {kStreamId});
430 if (!result_or_error.ok()) {
431 RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: "
432 << result_or_error.error().message();
433 }
Tommi2c599d62018-02-15 11:08:36 +0100434 } else {
435 RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed";
436 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 main_wnd_->SwitchToStreamingUI();
439}
440
441void Conductor::DisconnectFromCurrentPeer() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100442 RTC_LOG(INFO) << __FUNCTION__;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000443 if (peer_connection_.get()) {
444 client_->SendHangUp(peer_id_);
445 DeletePeerConnection();
446 }
447
448 if (main_wnd_->IsWindow())
449 main_wnd_->SwitchToPeerList(client_->peers());
450}
451
452void Conductor::UIThreadCallback(int msg_id, void* data) {
453 switch (msg_id) {
454 case PEER_CONNECTION_CLOSED:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100455 RTC_LOG(INFO) << "PEER_CONNECTION_CLOSED";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 DeletePeerConnection();
457
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458 if (main_wnd_->IsWindow()) {
459 if (client_->is_connected()) {
460 main_wnd_->SwitchToPeerList(client_->peers());
461 } else {
462 main_wnd_->SwitchToConnectUI();
463 }
464 } else {
465 DisconnectFromServer();
466 }
467 break;
468
469 case SEND_MESSAGE_TO_PEER: {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100470 RTC_LOG(INFO) << "SEND_MESSAGE_TO_PEER";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 std::string* msg = reinterpret_cast<std::string*>(data);
472 if (msg) {
473 // For convenience, we always run the message through the queue.
474 // This way we can be sure that messages are sent to the server
475 // in the same order they were signaled without much hassle.
476 pending_messages_.push_back(msg);
477 }
478
479 if (!pending_messages_.empty() && !client_->IsSendingMessage()) {
480 msg = pending_messages_.front();
481 pending_messages_.pop_front();
482
483 if (!client_->SendToPeer(peer_id_, *msg) && peer_id_ != -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100484 RTC_LOG(LS_ERROR) << "SendToPeer failed";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000485 DisconnectFromServer();
486 }
487 delete msg;
488 }
489
490 if (!peer_connection_.get())
491 peer_id_ = -1;
492
493 break;
494 }
495
Steve Antonc06ed702018-04-17 12:53:02 -0700496 case NEW_TRACK_ADDED: {
497 auto* track = reinterpret_cast<webrtc::MediaStreamTrackInterface*>(data);
498 if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
499 auto* video_track = static_cast<webrtc::VideoTrackInterface*>(track);
500 main_wnd_->StartRemoteRenderer(video_track);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000501 }
Steve Antonc06ed702018-04-17 12:53:02 -0700502 track->Release();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 break;
504 }
505
Steve Antonc06ed702018-04-17 12:53:02 -0700506 case TRACK_REMOVED: {
507 // Remote peer stopped sending a track.
508 auto* track = reinterpret_cast<webrtc::MediaStreamTrackInterface*>(data);
509 track->Release();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000510 break;
511 }
512
513 default:
nissec80e7412017-01-11 05:56:46 -0800514 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515 break;
516 }
517}
518
519void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000520 peer_connection_->SetLocalDescription(
521 DummySetSessionDescriptionObserver::Create(), desc);
522
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000523 std::string sdp;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000524 desc->ToString(&sdp);
525
526 // For loopback test. To save some connecting delay.
527 if (loopback_) {
528 // Replace message type from "offer" to "answer"
Steve Antona3a92c22017-12-07 10:27:41 -0800529 std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
Steve Antonc06ed702018-04-17 12:53:02 -0700530 webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp);
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000531 peer_connection_->SetRemoteDescription(
Steve Antona3a92c22017-12-07 10:27:41 -0800532 DummySetSessionDescriptionObserver::Create(),
533 session_description.release());
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000534 return;
535 }
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000536
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000537 Json::StyledWriter writer;
538 Json::Value jmessage;
Steve Antona3a92c22017-12-07 10:27:41 -0800539 jmessage[kSessionDescriptionTypeName] =
540 webrtc::SdpTypeToString(desc->GetType());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 jmessage[kSessionDescriptionSdpName] = sdp;
542 SendMessage(writer.write(jmessage));
543}
544
Harald Alvestrand73771a82018-05-24 10:53:49 +0200545void Conductor::OnFailure(webrtc::RTCError error) {
546 RTC_LOG(LERROR) << ToString(error.type()) << ": " << error.message();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547}
548
549void Conductor::SendMessage(const std::string& json_object) {
550 std::string* msg = new std::string(json_object);
551 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
552}