blob: fbee576f957558d53b3140c612af3b0cf95d278a [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
Donald E Curtisa8736442015-08-05 15:48:13 -070011#include "webrtc/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
Henrik Kjellander15583c12016-02-10 10:53:12 +010017#include "webrtc/api/test/fakeconstraints.h"
nissec80e7412017-01-11 05:56:46 -080018#include "webrtc/base/checks.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000019#include "webrtc/base/common.h"
20#include "webrtc/base/json.h"
21#include "webrtc/base/logging.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/examples/peerconnection/client/defaults.h"
solenberg8ad582d2016-03-16 09:34:56 -070023#include "webrtc/media/engine/webrtcvideocapturerfactory.h"
24#include "webrtc/modules/video_capture/video_capture_factory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000025
26// Names used for a IceCandidate JSON object.
27const char kCandidateSdpMidName[] = "sdpMid";
28const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
29const char kCandidateSdpName[] = "candidate";
30
31// Names used for a SessionDescription JSON object.
32const char kSessionDescriptionTypeName[] = "type";
33const char kSessionDescriptionSdpName[] = "sdp";
34
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +000035#define DTLS_ON true
36#define DTLS_OFF false
37
henrike@webrtc.org28e20752013-07-10 00:45:36 +000038class DummySetSessionDescriptionObserver
39 : public webrtc::SetSessionDescriptionObserver {
40 public:
41 static DummySetSessionDescriptionObserver* Create() {
42 return
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000043 new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044 }
45 virtual void OnSuccess() {
46 LOG(INFO) << __FUNCTION__;
47 }
48 virtual void OnFailure(const std::string& error) {
49 LOG(INFO) << __FUNCTION__ << " " << error;
50 }
51
52 protected:
53 DummySetSessionDescriptionObserver() {}
54 ~DummySetSessionDescriptionObserver() {}
55};
56
57Conductor::Conductor(PeerConnectionClient* client, MainWindow* main_wnd)
58 : peer_id_(-1),
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +000059 loopback_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060 client_(client),
61 main_wnd_(main_wnd) {
62 client_->RegisterObserver(this);
63 main_wnd->RegisterObserver(this);
64}
65
66Conductor::~Conductor() {
67 ASSERT(peer_connection_.get() == NULL);
68}
69
70bool Conductor::connection_active() const {
71 return peer_connection_.get() != NULL;
72}
73
74void Conductor::Close() {
75 client_->SignOut();
76 DeletePeerConnection();
77}
78
79bool Conductor::InitializePeerConnection() {
80 ASSERT(peer_connection_factory_.get() == NULL);
81 ASSERT(peer_connection_.get() == NULL);
82
83 peer_connection_factory_ = webrtc::CreatePeerConnectionFactory();
84
85 if (!peer_connection_factory_.get()) {
86 main_wnd_->MessageBox("Error",
87 "Failed to initialize PeerConnectionFactory", true);
88 DeletePeerConnection();
89 return false;
90 }
91
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +000092 if (!CreatePeerConnection(DTLS_ON)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093 main_wnd_->MessageBox("Error",
94 "CreatePeerConnection failed", true);
95 DeletePeerConnection();
96 }
97 AddStreams();
98 return peer_connection_.get() != NULL;
99}
100
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000101bool Conductor::ReinitializePeerConnectionForLoopback() {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000102 loopback_ = true;
103 rtc::scoped_refptr<webrtc::StreamCollectionInterface> streams(
104 peer_connection_->local_streams());
105 peer_connection_ = NULL;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000106 if (CreatePeerConnection(DTLS_OFF)) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000107 for (size_t i = 0; i < streams->count(); ++i)
108 peer_connection_->AddStream(streams->at(i));
109 peer_connection_->CreateOffer(this, NULL);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000110 }
111 return peer_connection_.get() != NULL;
112}
113
114bool Conductor::CreatePeerConnection(bool dtls) {
115 ASSERT(peer_connection_factory_.get() != NULL);
116 ASSERT(peer_connection_.get() == NULL);
117
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800118 webrtc::PeerConnectionInterface::RTCConfiguration config;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000119 webrtc::PeerConnectionInterface::IceServer server;
120 server.uri = GetPeerConnectionString();
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800121 config.servers.push_back(server);
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000122
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000123 webrtc::FakeConstraints constraints;
124 if (dtls) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000125 constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
126 "true");
jbauch70625e52015-12-09 14:18:14 -0800127 } else {
braveyao@webrtc.org9bfa5f02015-03-11 03:20:59 +0000128 constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
129 "false");
130 }
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000131
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800132 peer_connection_ = peer_connection_factory_->CreatePeerConnection(
hbosd7973cc2016-05-27 06:08:53 -0700133 config, &constraints, NULL, NULL, this);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000134 return peer_connection_.get() != NULL;
135}
136
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137void Conductor::DeletePeerConnection() {
138 peer_connection_ = NULL;
139 active_streams_.clear();
140 main_wnd_->StopLocalRenderer();
141 main_wnd_->StopRemoteRenderer();
142 peer_connection_factory_ = NULL;
143 peer_id_ = -1;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000144 loopback_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145}
146
147void Conductor::EnsureStreamingUI() {
148 ASSERT(peer_connection_.get() != NULL);
149 if (main_wnd_->IsWindow()) {
150 if (main_wnd_->current_ui() != MainWindow::STREAMING)
151 main_wnd_->SwitchToStreamingUI();
152 }
153}
154
155//
156// PeerConnectionObserver implementation.
157//
158
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159// Called when a remote stream is added
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700160void Conductor::OnAddStream(
161 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000162 LOG(INFO) << __FUNCTION__ << " " << stream->label();
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700163 main_wnd_->QueueUIThreadCallback(NEW_STREAM_ADDED, stream.release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164}
165
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700166void Conductor::OnRemoveStream(
167 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168 LOG(INFO) << __FUNCTION__ << " " << stream->label();
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700169 main_wnd_->QueueUIThreadCallback(STREAM_REMOVED, stream.release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170}
171
172void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
173 LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000174 // For loopback test. To save some connecting delay.
175 if (loopback_) {
176 if (!peer_connection_->AddIceCandidate(candidate)) {
177 LOG(WARNING) << "Failed to apply the received candidate";
178 }
179 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000180 }
181
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182 Json::StyledWriter writer;
183 Json::Value jmessage;
184
185 jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
186 jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
187 std::string sdp;
188 if (!candidate->ToString(&sdp)) {
189 LOG(LS_ERROR) << "Failed to serialize candidate";
190 return;
191 }
192 jmessage[kCandidateSdpName] = sdp;
193 SendMessage(writer.write(jmessage));
194}
195
196//
197// PeerConnectionClientObserver implementation.
198//
199
200void Conductor::OnSignedIn() {
201 LOG(INFO) << __FUNCTION__;
202 main_wnd_->SwitchToPeerList(client_->peers());
203}
204
205void Conductor::OnDisconnected() {
206 LOG(INFO) << __FUNCTION__;
207
208 DeletePeerConnection();
209
210 if (main_wnd_->IsWindow())
211 main_wnd_->SwitchToConnectUI();
212}
213
214void Conductor::OnPeerConnected(int id, const std::string& name) {
215 LOG(INFO) << __FUNCTION__;
216 // Refresh the list if we're showing it.
217 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
218 main_wnd_->SwitchToPeerList(client_->peers());
219}
220
221void Conductor::OnPeerDisconnected(int id) {
222 LOG(INFO) << __FUNCTION__;
223 if (id == peer_id_) {
224 LOG(INFO) << "Our peer disconnected";
225 main_wnd_->QueueUIThreadCallback(PEER_CONNECTION_CLOSED, NULL);
226 } else {
227 // Refresh the list if we're showing it.
228 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
229 main_wnd_->SwitchToPeerList(client_->peers());
230 }
231}
232
233void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
234 ASSERT(peer_id_ == peer_id || peer_id_ == -1);
235 ASSERT(!message.empty());
236
237 if (!peer_connection_.get()) {
238 ASSERT(peer_id_ == -1);
239 peer_id_ = peer_id;
240
241 if (!InitializePeerConnection()) {
242 LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
243 client_->SignOut();
244 return;
245 }
246 } else if (peer_id != peer_id_) {
247 ASSERT(peer_id_ != -1);
248 LOG(WARNING) << "Received a message from unknown peer while already in a "
249 "conversation with a different peer.";
250 return;
251 }
252
253 Json::Reader reader;
254 Json::Value jmessage;
255 if (!reader.parse(message, jmessage)) {
256 LOG(WARNING) << "Received unknown message. " << message;
257 return;
258 }
259 std::string type;
260 std::string json_object;
261
Thiago Farinacb76b892015-04-02 09:59:15 +0000262 rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000263 if (!type.empty()) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000264 if (type == "offer-loopback") {
265 // This is a loopback call.
266 // Recreate the peerconnection with DTLS disabled.
267 if (!ReinitializePeerConnectionForLoopback()) {
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000268 LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
269 DeletePeerConnection();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000270 client_->SignOut();
271 }
272 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000273 }
274
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000276 if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
277 &sdp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000278 LOG(WARNING) << "Can't parse received session description message.";
279 return;
280 }
jbauchfabe2c92015-07-16 13:43:14 -0700281 webrtc::SdpParseError error;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000282 webrtc::SessionDescriptionInterface* session_description(
jbauchfabe2c92015-07-16 13:43:14 -0700283 webrtc::CreateSessionDescription(type, sdp, &error));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 if (!session_description) {
jbauchfabe2c92015-07-16 13:43:14 -0700285 LOG(WARNING) << "Can't parse received session description message. "
286 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287 return;
288 }
289 LOG(INFO) << " Received session description :" << message;
290 peer_connection_->SetRemoteDescription(
291 DummySetSessionDescriptionObserver::Create(), session_description);
292 if (session_description->type() ==
293 webrtc::SessionDescriptionInterface::kOffer) {
294 peer_connection_->CreateAnswer(this, NULL);
295 }
296 return;
297 } else {
298 std::string sdp_mid;
299 int sdp_mlineindex = 0;
300 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000301 if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
302 &sdp_mid) ||
303 !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
304 &sdp_mlineindex) ||
305 !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 LOG(WARNING) << "Can't parse received message.";
307 return;
308 }
jbauchfabe2c92015-07-16 13:43:14 -0700309 webrtc::SdpParseError error;
kwibergbfefb032016-05-01 14:53:46 -0700310 std::unique_ptr<webrtc::IceCandidateInterface> candidate(
jbauchfabe2c92015-07-16 13:43:14 -0700311 webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312 if (!candidate.get()) {
jbauchfabe2c92015-07-16 13:43:14 -0700313 LOG(WARNING) << "Can't parse received candidate message. "
314 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000315 return;
316 }
317 if (!peer_connection_->AddIceCandidate(candidate.get())) {
318 LOG(WARNING) << "Failed to apply the received candidate";
319 return;
320 }
321 LOG(INFO) << " Received candidate :" << message;
322 return;
323 }
324}
325
326void Conductor::OnMessageSent(int err) {
327 // Process the next pending message if any.
328 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, NULL);
329}
330
331void Conductor::OnServerConnectionFailure() {
332 main_wnd_->MessageBox("Error", ("Failed to connect to " + server_).c_str(),
333 true);
334}
335
336//
337// MainWndCallback implementation.
338//
339
340void Conductor::StartLogin(const std::string& server, int port) {
341 if (client_->is_connected())
342 return;
343 server_ = server;
344 client_->Connect(server, port, GetPeerName());
345}
346
347void Conductor::DisconnectFromServer() {
348 if (client_->is_connected())
349 client_->SignOut();
350}
351
352void Conductor::ConnectToPeer(int peer_id) {
353 ASSERT(peer_id_ == -1);
354 ASSERT(peer_id != -1);
355
356 if (peer_connection_.get()) {
357 main_wnd_->MessageBox("Error",
358 "We only support connecting to one peer at a time", true);
359 return;
360 }
361
362 if (InitializePeerConnection()) {
363 peer_id_ = peer_id;
364 peer_connection_->CreateOffer(this, NULL);
365 } else {
366 main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true);
367 }
368}
369
370cricket::VideoCapturer* Conductor::OpenVideoCaptureDevice() {
solenberg8ad582d2016-03-16 09:34:56 -0700371 std::vector<std::string> device_names;
372 {
373 std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
nisseb29b9c82016-12-12 00:22:56 -0800374 webrtc::VideoCaptureFactory::CreateDeviceInfo());
solenberg8ad582d2016-03-16 09:34:56 -0700375 if (!info) {
376 return nullptr;
377 }
378 int num_devices = info->NumberOfDevices();
379 for (int i = 0; i < num_devices; ++i) {
380 const uint32_t kSize = 256;
381 char name[kSize] = {0};
382 char id[kSize] = {0};
383 if (info->GetDeviceName(i, name, kSize, id, kSize) != -1) {
384 device_names.push_back(name);
385 }
386 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 }
solenberg8ad582d2016-03-16 09:34:56 -0700388
389 cricket::WebRtcVideoDeviceCapturerFactory factory;
390 cricket::VideoCapturer* capturer = nullptr;
391 for (const auto& name : device_names) {
392 capturer = factory.Create(cricket::Device(name, 0));
393 if (capturer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394 break;
solenberg8ad582d2016-03-16 09:34:56 -0700395 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000396 }
397 return capturer;
398}
399
400void Conductor::AddStreams() {
401 if (active_streams_.find(kStreamLabel) != active_streams_.end())
402 return; // Already added.
403
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000404 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000405 peer_connection_factory_->CreateAudioTrack(
406 kAudioLabel, peer_connection_factory_->CreateAudioSource(NULL)));
407
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000408 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409 peer_connection_factory_->CreateVideoTrack(
410 kVideoLabel,
411 peer_connection_factory_->CreateVideoSource(OpenVideoCaptureDevice(),
412 NULL)));
413 main_wnd_->StartLocalRenderer(video_track);
414
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000415 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416 peer_connection_factory_->CreateLocalMediaStream(kStreamLabel);
417
418 stream->AddTrack(audio_track);
419 stream->AddTrack(video_track);
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000420 if (!peer_connection_->AddStream(stream)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 LOG(LS_ERROR) << "Adding stream to PeerConnection failed";
422 }
423 typedef std::pair<std::string,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000424 rtc::scoped_refptr<webrtc::MediaStreamInterface> >
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 MediaStreamPair;
426 active_streams_.insert(MediaStreamPair(stream->label(), stream));
427 main_wnd_->SwitchToStreamingUI();
428}
429
430void Conductor::DisconnectFromCurrentPeer() {
431 LOG(INFO) << __FUNCTION__;
432 if (peer_connection_.get()) {
433 client_->SendHangUp(peer_id_);
434 DeletePeerConnection();
435 }
436
437 if (main_wnd_->IsWindow())
438 main_wnd_->SwitchToPeerList(client_->peers());
439}
440
441void Conductor::UIThreadCallback(int msg_id, void* data) {
442 switch (msg_id) {
443 case PEER_CONNECTION_CLOSED:
444 LOG(INFO) << "PEER_CONNECTION_CLOSED";
445 DeletePeerConnection();
446
447 ASSERT(active_streams_.empty());
448
449 if (main_wnd_->IsWindow()) {
450 if (client_->is_connected()) {
451 main_wnd_->SwitchToPeerList(client_->peers());
452 } else {
453 main_wnd_->SwitchToConnectUI();
454 }
455 } else {
456 DisconnectFromServer();
457 }
458 break;
459
460 case SEND_MESSAGE_TO_PEER: {
461 LOG(INFO) << "SEND_MESSAGE_TO_PEER";
462 std::string* msg = reinterpret_cast<std::string*>(data);
463 if (msg) {
464 // For convenience, we always run the message through the queue.
465 // This way we can be sure that messages are sent to the server
466 // in the same order they were signaled without much hassle.
467 pending_messages_.push_back(msg);
468 }
469
470 if (!pending_messages_.empty() && !client_->IsSendingMessage()) {
471 msg = pending_messages_.front();
472 pending_messages_.pop_front();
473
474 if (!client_->SendToPeer(peer_id_, *msg) && peer_id_ != -1) {
475 LOG(LS_ERROR) << "SendToPeer failed";
476 DisconnectFromServer();
477 }
478 delete msg;
479 }
480
481 if (!peer_connection_.get())
482 peer_id_ = -1;
483
484 break;
485 }
486
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 case NEW_STREAM_ADDED: {
488 webrtc::MediaStreamInterface* stream =
489 reinterpret_cast<webrtc::MediaStreamInterface*>(
490 data);
491 webrtc::VideoTrackVector tracks = stream->GetVideoTracks();
492 // Only render the first track.
493 if (!tracks.empty()) {
494 webrtc::VideoTrackInterface* track = tracks[0];
495 main_wnd_->StartRemoteRenderer(track);
496 }
497 stream->Release();
498 break;
499 }
500
501 case STREAM_REMOVED: {
502 // Remote peer stopped sending a stream.
503 webrtc::MediaStreamInterface* stream =
504 reinterpret_cast<webrtc::MediaStreamInterface*>(
505 data);
506 stream->Release();
507 break;
508 }
509
510 default:
nissec80e7412017-01-11 05:56:46 -0800511 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 break;
513 }
514}
515
516void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000517 peer_connection_->SetLocalDescription(
518 DummySetSessionDescriptionObserver::Create(), desc);
519
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000520 std::string sdp;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000521 desc->ToString(&sdp);
522
523 // For loopback test. To save some connecting delay.
524 if (loopback_) {
525 // Replace message type from "offer" to "answer"
526 webrtc::SessionDescriptionInterface* session_description(
jbauchfabe2c92015-07-16 13:43:14 -0700527 webrtc::CreateSessionDescription("answer", sdp, nullptr));
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000528 peer_connection_->SetRemoteDescription(
529 DummySetSessionDescriptionObserver::Create(), session_description);
530 return;
531 }
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000532
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 Json::StyledWriter writer;
534 Json::Value jmessage;
535 jmessage[kSessionDescriptionTypeName] = desc->type();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 jmessage[kSessionDescriptionSdpName] = sdp;
537 SendMessage(writer.write(jmessage));
538}
539
540void Conductor::OnFailure(const std::string& error) {
541 LOG(LERROR) << error;
542}
543
544void Conductor::SendMessage(const std::string& json_object) {
545 std::string* msg = new std::string(json_object);
546 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
547}