blob: 06bfe93919410d9077f6f3a50d683e8440b55d20 [file] [log] [blame]
gyzhouad7cad82017-05-11 16:10:03 -07001/*
2 * Copyright (c) 2017 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "examples/unityplugin/simple_peer_connection.h"
gyzhouad7cad82017-05-11 16:10:03 -070012
13#include <utility>
14
Karl Wiberg918f50c2018-07-05 11:40:33 +020015#include "absl/memory/memory.h"
Qiang Chen51e20462017-12-05 11:11:21 -080016#include "api/audio_codecs/builtin_audio_decoder_factory.h"
17#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010018#include "api/create_peerconnection_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "api/video_track_source_proxy.h"
20#include "media/engine/internal_decoder_factory.h"
21#include "media/engine/internal_encoder_factory.h"
22#include "media/engine/multiplex_codec_factory.h"
Qiang Chen43fb9122017-12-20 10:47:36 -080023#include "modules/audio_device/include/audio_device.h"
24#include "modules/audio_processing/include/audio_processing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/video_capture/video_capture_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "pc/video_track_source.h"
Niels Möller0a595352019-01-02 15:12:38 +010027#include "test/vcm_capturer.h"
gyzhouad7cad82017-05-11 16:10:03 -070028
qiangchen42f96d52017-08-08 17:08:03 -070029#if defined(WEBRTC_ANDROID)
Steve Anton10542f22019-01-11 09:11:00 -080030#include "examples/unityplugin/class_reference_holder.h"
George Zhou2770c3d2018-03-07 09:58:54 -080031#include "modules/utility/include/helpers_android.h"
Steve Anton10542f22019-01-11 09:11:00 -080032#include "sdk/android/src/jni/android_video_track_source.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "sdk/android/src/jni/jni_helpers.h"
qiangchen42f96d52017-08-08 17:08:03 -070034#endif
35
Seth Hampson513449e2018-03-06 09:35:56 -080036// Names used for media stream ids.
gyzhouad7cad82017-05-11 16:10:03 -070037const char kAudioLabel[] = "audio_label";
38const char kVideoLabel[] = "video_label";
Seth Hampson513449e2018-03-06 09:35:56 -080039const char kStreamId[] = "stream_id";
gyzhouad7cad82017-05-11 16:10:03 -070040
41namespace {
42static int g_peer_count = 0;
43static std::unique_ptr<rtc::Thread> g_worker_thread;
44static std::unique_ptr<rtc::Thread> g_signaling_thread;
45static rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
46 g_peer_connection_factory;
qiangchen42f96d52017-08-08 17:08:03 -070047#if defined(WEBRTC_ANDROID)
48// Android case: the video track does not own the capturer, and it
49// relies on the app to dispose the capturer when the peerconnection
50// shuts down.
51static jobject g_camera = nullptr;
Niels Möller0a595352019-01-02 15:12:38 +010052#else
53class CapturerTrackSource : public webrtc::VideoTrackSource {
54 public:
55 static rtc::scoped_refptr<CapturerTrackSource> Create() {
56 const size_t kWidth = 640;
57 const size_t kHeight = 480;
58 const size_t kFps = 30;
59 const size_t kDeviceIndex = 0;
60 std::unique_ptr<webrtc::test::VcmCapturer> capturer = absl::WrapUnique(
61 webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, kDeviceIndex));
62 if (!capturer) {
63 return nullptr;
64 }
65 return new rtc::RefCountedObject<CapturerTrackSource>(std::move(capturer));
66 }
67
68 protected:
69 explicit CapturerTrackSource(
70 std::unique_ptr<webrtc::test::VcmCapturer> capturer)
71 : VideoTrackSource(/*remote=*/false), capturer_(std::move(capturer)) {}
72
73 private:
74 rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override {
75 return capturer_.get();
76 }
77 std::unique_ptr<webrtc::test::VcmCapturer> capturer_;
78};
79
qiangchen42f96d52017-08-08 17:08:03 -070080#endif
gyzhouad7cad82017-05-11 16:10:03 -070081
82std::string GetEnvVarOrDefault(const char* env_var_name,
83 const char* default_value) {
84 std::string value;
85 const char* env_var = getenv(env_var_name);
86 if (env_var)
87 value = env_var;
88
89 if (value.empty())
90 value = default_value;
91
92 return value;
93}
94
95std::string GetPeerConnectionString() {
96 return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302");
97}
98
99class DummySetSessionDescriptionObserver
100 : public webrtc::SetSessionDescriptionObserver {
101 public:
102 static DummySetSessionDescriptionObserver* Create() {
103 return new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
104 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100105 virtual void OnSuccess() { RTC_LOG(INFO) << __FUNCTION__; }
Harald Alvestrand73771a82018-05-24 10:53:49 +0200106 virtual void OnFailure(webrtc::RTCError error) {
107 RTC_LOG(INFO) << __FUNCTION__ << " " << ToString(error.type()) << ": "
108 << error.message();
gyzhouad7cad82017-05-11 16:10:03 -0700109 }
110
111 protected:
112 DummySetSessionDescriptionObserver() {}
113 ~DummySetSessionDescriptionObserver() {}
114};
115
116} // namespace
117
gyzhoub38f3862017-07-25 16:04:31 -0700118bool SimplePeerConnection::InitializePeerConnection(const char** turn_urls,
119 const int no_of_urls,
120 const char* username,
121 const char* credential,
122 bool is_receiver) {
gyzhouad7cad82017-05-11 16:10:03 -0700123 RTC_DCHECK(peer_connection_.get() == nullptr);
124
125 if (g_peer_connection_factory == nullptr) {
126 g_worker_thread.reset(new rtc::Thread());
127 g_worker_thread->Start();
128 g_signaling_thread.reset(new rtc::Thread());
129 g_signaling_thread->Start();
130
131 g_peer_connection_factory = webrtc::CreatePeerConnectionFactory(
132 g_worker_thread.get(), g_worker_thread.get(), g_signaling_thread.get(),
Qiang Chen51e20462017-12-05 11:11:21 -0800133 nullptr, webrtc::CreateBuiltinAudioEncoderFactory(),
Qiang Chen43fb9122017-12-20 10:47:36 -0800134 webrtc::CreateBuiltinAudioDecoderFactory(),
135 std::unique_ptr<webrtc::VideoEncoderFactory>(
Anders Carlssondd8c1652018-01-30 10:32:13 +0100136 new webrtc::MultiplexEncoderFactory(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200137 absl::make_unique<webrtc::InternalEncoderFactory>())),
Qiang Chen43fb9122017-12-20 10:47:36 -0800138 std::unique_ptr<webrtc::VideoDecoderFactory>(
Anders Carlssondd8c1652018-01-30 10:32:13 +0100139 new webrtc::MultiplexDecoderFactory(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200140 absl::make_unique<webrtc::InternalDecoderFactory>())),
Qiang Chen43fb9122017-12-20 10:47:36 -0800141 nullptr, nullptr);
gyzhouad7cad82017-05-11 16:10:03 -0700142 }
143 if (!g_peer_connection_factory.get()) {
144 DeletePeerConnection();
145 return false;
146 }
147
148 g_peer_count++;
Qiang Chen51e20462017-12-05 11:11:21 -0800149 if (!CreatePeerConnection(turn_urls, no_of_urls, username, credential)) {
gyzhouad7cad82017-05-11 16:10:03 -0700150 DeletePeerConnection();
151 return false;
152 }
Qiang Chen51e20462017-12-05 11:11:21 -0800153
154 mandatory_receive_ = is_receiver;
gyzhouad7cad82017-05-11 16:10:03 -0700155 return peer_connection_.get() != nullptr;
156}
157
gyzhoub38f3862017-07-25 16:04:31 -0700158bool SimplePeerConnection::CreatePeerConnection(const char** turn_urls,
159 const int no_of_urls,
160 const char* username,
Qiang Chen51e20462017-12-05 11:11:21 -0800161 const char* credential) {
gyzhouad7cad82017-05-11 16:10:03 -0700162 RTC_DCHECK(g_peer_connection_factory.get() != nullptr);
163 RTC_DCHECK(peer_connection_.get() == nullptr);
164
gyzhoub38f3862017-07-25 16:04:31 -0700165 local_video_observer_.reset(new VideoObserver());
166 remote_video_observer_.reset(new VideoObserver());
167
168 // Add the turn server.
169 if (turn_urls != nullptr) {
170 if (no_of_urls > 0) {
171 webrtc::PeerConnectionInterface::IceServer turn_server;
172 for (int i = 0; i < no_of_urls; i++) {
173 std::string url(turn_urls[i]);
174 if (url.length() > 0)
175 turn_server.urls.push_back(turn_urls[i]);
176 }
177
178 std::string user_name(username);
179 if (user_name.length() > 0)
180 turn_server.username = username;
181
182 std::string password(credential);
183 if (password.length() > 0)
184 turn_server.password = credential;
185
186 config_.servers.push_back(turn_server);
187 }
188 }
189
190 // Add the stun server.
191 webrtc::PeerConnectionInterface::IceServer stun_server;
192 stun_server.uri = GetPeerConnectionString();
193 config_.servers.push_back(stun_server);
Niels Möllerf06f9232018-08-07 12:32:18 +0200194 config_.enable_rtp_data_channel = true;
195 config_.enable_dtls_srtp = false;
gyzhouad7cad82017-05-11 16:10:03 -0700196
gyzhouad7cad82017-05-11 16:10:03 -0700197 peer_connection_ = g_peer_connection_factory->CreatePeerConnection(
Niels Möllerf06f9232018-08-07 12:32:18 +0200198 config_, nullptr, nullptr, this);
gyzhouad7cad82017-05-11 16:10:03 -0700199
200 return peer_connection_.get() != nullptr;
201}
202
203void SimplePeerConnection::DeletePeerConnection() {
204 g_peer_count--;
205
qiangchen42f96d52017-08-08 17:08:03 -0700206#if defined(WEBRTC_ANDROID)
207 if (g_camera) {
magjeda3d4f682017-08-28 16:24:06 -0700208 JNIEnv* env = webrtc::jni::GetEnv();
qiangchen42f96d52017-08-08 17:08:03 -0700209 jclass pc_factory_class =
210 unity_plugin::FindClass(env, "org/webrtc/UnityUtility");
George Zhou2770c3d2018-03-07 09:58:54 -0800211 jmethodID stop_camera_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700212 env, pc_factory_class, "StopCamera", "(Lorg/webrtc/VideoCapturer;)V");
213
214 env->CallStaticVoidMethod(pc_factory_class, stop_camera_method, g_camera);
215 CHECK_EXCEPTION(env);
216
217 g_camera = nullptr;
218 }
219#endif
220
gyzhouad7cad82017-05-11 16:10:03 -0700221 CloseDataChannel();
222 peer_connection_ = nullptr;
223 active_streams_.clear();
224
225 if (g_peer_count == 0) {
226 g_peer_connection_factory = nullptr;
227 g_signaling_thread.reset();
228 g_worker_thread.reset();
229 }
230}
231
232bool SimplePeerConnection::CreateOffer() {
233 if (!peer_connection_.get())
234 return false;
235
Niels Möllerf06f9232018-08-07 12:32:18 +0200236 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
Qiang Chen51e20462017-12-05 11:11:21 -0800237 if (mandatory_receive_) {
Niels Möllerf06f9232018-08-07 12:32:18 +0200238 options.offer_to_receive_audio = true;
239 options.offer_to_receive_video = true;
Qiang Chen51e20462017-12-05 11:11:21 -0800240 }
Niels Möllerf06f9232018-08-07 12:32:18 +0200241 peer_connection_->CreateOffer(this, options);
gyzhouad7cad82017-05-11 16:10:03 -0700242 return true;
243}
244
245bool SimplePeerConnection::CreateAnswer() {
246 if (!peer_connection_.get())
247 return false;
248
Niels Möllerf06f9232018-08-07 12:32:18 +0200249 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
Qiang Chen51e20462017-12-05 11:11:21 -0800250 if (mandatory_receive_) {
Niels Möllerf06f9232018-08-07 12:32:18 +0200251 options.offer_to_receive_audio = true;
252 options.offer_to_receive_video = true;
Qiang Chen51e20462017-12-05 11:11:21 -0800253 }
Niels Möllerf06f9232018-08-07 12:32:18 +0200254 peer_connection_->CreateAnswer(this, options);
gyzhouad7cad82017-05-11 16:10:03 -0700255 return true;
256}
257
258void SimplePeerConnection::OnSuccess(
259 webrtc::SessionDescriptionInterface* desc) {
260 peer_connection_->SetLocalDescription(
261 DummySetSessionDescriptionObserver::Create(), desc);
262
263 std::string sdp;
264 desc->ToString(&sdp);
265
gyzhouad7cad82017-05-11 16:10:03 -0700266 if (OnLocalSdpReady)
gyzhoub38f3862017-07-25 16:04:31 -0700267 OnLocalSdpReady(desc->type().c_str(), sdp.c_str());
gyzhouad7cad82017-05-11 16:10:03 -0700268}
269
Harald Alvestrand73771a82018-05-24 10:53:49 +0200270void SimplePeerConnection::OnFailure(webrtc::RTCError error) {
271 RTC_LOG(LERROR) << ToString(error.type()) << ": " << error.message();
gyzhouad7cad82017-05-11 16:10:03 -0700272
Harald Alvestrand73771a82018-05-24 10:53:49 +0200273 // TODO(hta): include error.type in the message
gyzhouad7cad82017-05-11 16:10:03 -0700274 if (OnFailureMessage)
Harald Alvestrand73771a82018-05-24 10:53:49 +0200275 OnFailureMessage(error.message());
gyzhouad7cad82017-05-11 16:10:03 -0700276}
277
278void SimplePeerConnection::OnIceCandidate(
279 const webrtc::IceCandidateInterface* candidate) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100280 RTC_LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
gyzhouad7cad82017-05-11 16:10:03 -0700281
gyzhouad7cad82017-05-11 16:10:03 -0700282 std::string sdp;
283 if (!candidate->ToString(&sdp)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100284 RTC_LOG(LS_ERROR) << "Failed to serialize candidate";
gyzhouad7cad82017-05-11 16:10:03 -0700285 return;
286 }
gyzhouad7cad82017-05-11 16:10:03 -0700287
288 if (OnIceCandiateReady)
gyzhoub38f3862017-07-25 16:04:31 -0700289 OnIceCandiateReady(sdp.c_str(), candidate->sdp_mline_index(),
290 candidate->sdp_mid().c_str());
gyzhouad7cad82017-05-11 16:10:03 -0700291}
292
gyzhoub38f3862017-07-25 16:04:31 -0700293void SimplePeerConnection::RegisterOnLocalI420FrameReady(
294 I420FRAMEREADY_CALLBACK callback) {
295 if (local_video_observer_)
296 local_video_observer_->SetVideoCallback(callback);
297}
298
299void SimplePeerConnection::RegisterOnRemoteI420FrameReady(
300 I420FRAMEREADY_CALLBACK callback) {
301 if (remote_video_observer_)
302 remote_video_observer_->SetVideoCallback(callback);
gyzhouad7cad82017-05-11 16:10:03 -0700303}
304
305void SimplePeerConnection::RegisterOnLocalDataChannelReady(
306 LOCALDATACHANNELREADY_CALLBACK callback) {
307 OnLocalDataChannelReady = callback;
308}
309
310void SimplePeerConnection::RegisterOnDataFromDataChannelReady(
311 DATAFROMEDATECHANNELREADY_CALLBACK callback) {
312 OnDataFromDataChannelReady = callback;
313}
314
315void SimplePeerConnection::RegisterOnFailure(FAILURE_CALLBACK callback) {
316 OnFailureMessage = callback;
317}
318
319void SimplePeerConnection::RegisterOnAudioBusReady(
320 AUDIOBUSREADY_CALLBACK callback) {
321 OnAudioReady = callback;
322}
323
324void SimplePeerConnection::RegisterOnLocalSdpReadytoSend(
325 LOCALSDPREADYTOSEND_CALLBACK callback) {
326 OnLocalSdpReady = callback;
327}
328
329void SimplePeerConnection::RegisterOnIceCandiateReadytoSend(
330 ICECANDIDATEREADYTOSEND_CALLBACK callback) {
331 OnIceCandiateReady = callback;
332}
333
gyzhoub38f3862017-07-25 16:04:31 -0700334bool SimplePeerConnection::SetRemoteDescription(const char* type,
335 const char* sdp) {
gyzhouad7cad82017-05-11 16:10:03 -0700336 if (!peer_connection_)
337 return false;
338
gyzhoub38f3862017-07-25 16:04:31 -0700339 std::string remote_desc(sdp);
340 std::string sdp_type(type);
gyzhouad7cad82017-05-11 16:10:03 -0700341 webrtc::SdpParseError error;
342 webrtc::SessionDescriptionInterface* session_description(
gyzhoub38f3862017-07-25 16:04:31 -0700343 webrtc::CreateSessionDescription(sdp_type, remote_desc, &error));
gyzhouad7cad82017-05-11 16:10:03 -0700344 if (!session_description) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100345 RTC_LOG(WARNING) << "Can't parse received session description message. "
346 << "SdpParseError was: " << error.description;
gyzhouad7cad82017-05-11 16:10:03 -0700347 return false;
348 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100349 RTC_LOG(INFO) << " Received session description :" << remote_desc;
gyzhouad7cad82017-05-11 16:10:03 -0700350 peer_connection_->SetRemoteDescription(
351 DummySetSessionDescriptionObserver::Create(), session_description);
352
353 return true;
354}
355
gyzhoub38f3862017-07-25 16:04:31 -0700356bool SimplePeerConnection::AddIceCandidate(const char* candidate,
357 const int sdp_mlineindex,
358 const char* sdp_mid) {
gyzhouad7cad82017-05-11 16:10:03 -0700359 if (!peer_connection_)
360 return false;
361
gyzhouad7cad82017-05-11 16:10:03 -0700362 webrtc::SdpParseError error;
gyzhoub38f3862017-07-25 16:04:31 -0700363 std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate(
364 webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, candidate, &error));
365 if (!ice_candidate.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100366 RTC_LOG(WARNING) << "Can't parse received candidate message. "
367 << "SdpParseError was: " << error.description;
gyzhouad7cad82017-05-11 16:10:03 -0700368 return false;
369 }
gyzhoub38f3862017-07-25 16:04:31 -0700370 if (!peer_connection_->AddIceCandidate(ice_candidate.get())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100371 RTC_LOG(WARNING) << "Failed to apply the received candidate";
gyzhouad7cad82017-05-11 16:10:03 -0700372 return false;
373 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100374 RTC_LOG(INFO) << " Received candidate :" << candidate;
gyzhouad7cad82017-05-11 16:10:03 -0700375 return true;
376}
377
378void SimplePeerConnection::SetAudioControl(bool is_mute, bool is_record) {
379 is_mute_audio_ = is_mute;
380 is_record_audio_ = is_record;
381
382 SetAudioControl();
383}
384
385void SimplePeerConnection::SetAudioControl() {
386 if (!remote_stream_)
387 return;
388 webrtc::AudioTrackVector tracks = remote_stream_->GetAudioTracks();
389 if (tracks.empty())
390 return;
391
392 webrtc::AudioTrackInterface* audio_track = tracks[0];
393 std::string id = audio_track->id();
394 if (is_record_audio_)
395 audio_track->AddSink(this);
396 else
397 audio_track->RemoveSink(this);
398
399 for (auto& track : tracks) {
400 if (is_mute_audio_)
401 track->set_enabled(false);
402 else
403 track->set_enabled(true);
404 }
405}
406
407void SimplePeerConnection::OnAddStream(
408 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
Seth Hampson13b8bad2018-03-13 16:05:28 -0700409 RTC_LOG(INFO) << __FUNCTION__ << " " << stream->id();
gyzhouad7cad82017-05-11 16:10:03 -0700410 remote_stream_ = stream;
gyzhoub38f3862017-07-25 16:04:31 -0700411 if (remote_video_observer_ && !remote_stream_->GetVideoTracks().empty()) {
412 remote_stream_->GetVideoTracks()[0]->AddOrUpdateSink(
413 remote_video_observer_.get(), rtc::VideoSinkWants());
414 }
gyzhouad7cad82017-05-11 16:10:03 -0700415 SetAudioControl();
416}
417
gyzhouad7cad82017-05-11 16:10:03 -0700418void SimplePeerConnection::AddStreams(bool audio_only) {
Seth Hampson513449e2018-03-06 09:35:56 -0800419 if (active_streams_.find(kStreamId) != active_streams_.end())
gyzhouad7cad82017-05-11 16:10:03 -0700420 return; // Already added.
421
422 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
Seth Hampson513449e2018-03-06 09:35:56 -0800423 g_peer_connection_factory->CreateLocalMediaStream(kStreamId);
gyzhouad7cad82017-05-11 16:10:03 -0700424
425 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
426 g_peer_connection_factory->CreateAudioTrack(
Niels Möller2d02e082018-05-21 11:23:35 +0200427 kAudioLabel, g_peer_connection_factory->CreateAudioSource(
428 cricket::AudioOptions())));
gyzhouad7cad82017-05-11 16:10:03 -0700429 std::string id = audio_track->id();
430 stream->AddTrack(audio_track);
431
432 if (!audio_only) {
qiangchen42f96d52017-08-08 17:08:03 -0700433#if defined(WEBRTC_ANDROID)
magjeda3d4f682017-08-28 16:24:06 -0700434 JNIEnv* env = webrtc::jni::GetEnv();
qiangchen42f96d52017-08-08 17:08:03 -0700435 jclass pc_factory_class =
436 unity_plugin::FindClass(env, "org/webrtc/UnityUtility");
George Zhou2770c3d2018-03-07 09:58:54 -0800437 jmethodID load_texture_helper_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700438 env, pc_factory_class, "LoadSurfaceTextureHelper",
439 "()Lorg/webrtc/SurfaceTextureHelper;");
440 jobject texture_helper = env->CallStaticObjectMethod(
441 pc_factory_class, load_texture_helper_method);
442 CHECK_EXCEPTION(env);
443 RTC_DCHECK(texture_helper != nullptr)
444 << "Cannot get the Surface Texture Helper.";
445
Qiang Chen51e20462017-12-05 11:11:21 -0800446 rtc::scoped_refptr<webrtc::jni::AndroidVideoTrackSource> source(
447 new rtc::RefCountedObject<webrtc::jni::AndroidVideoTrackSource>(
Magnus Jedvert95140712018-11-15 12:07:32 +0100448 g_signaling_thread.get(), env, /* is_screencast= */ false,
449 /* align_timestamps= */ true));
qiangchen42f96d52017-08-08 17:08:03 -0700450 rtc::scoped_refptr<webrtc::VideoTrackSourceProxy> proxy_source =
451 webrtc::VideoTrackSourceProxy::Create(g_signaling_thread.get(),
452 g_worker_thread.get(), source);
453
454 // link with VideoCapturer (Camera);
George Zhou2770c3d2018-03-07 09:58:54 -0800455 jmethodID link_camera_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700456 env, pc_factory_class, "LinkCamera",
457 "(JLorg/webrtc/SurfaceTextureHelper;)Lorg/webrtc/VideoCapturer;");
458 jobject camera_tmp =
459 env->CallStaticObjectMethod(pc_factory_class, link_camera_method,
460 (jlong)proxy_source.get(), texture_helper);
461 CHECK_EXCEPTION(env);
462 g_camera = (jobject)env->NewGlobalRef(camera_tmp);
463
464 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
465 g_peer_connection_factory->CreateVideoTrack(kVideoLabel,
466 proxy_source.release()));
467 stream->AddTrack(video_track);
468#else
Niels Möller0a595352019-01-02 15:12:38 +0100469 rtc::scoped_refptr<CapturerTrackSource> video_device =
470 CapturerTrackSource::Create();
471 if (video_device) {
gyzhouad7cad82017-05-11 16:10:03 -0700472 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
Niels Möller0a595352019-01-02 15:12:38 +0100473 g_peer_connection_factory->CreateVideoTrack(kVideoLabel,
474 video_device));
gyzhouad7cad82017-05-11 16:10:03 -0700475
476 stream->AddTrack(video_track);
qiangchen42f96d52017-08-08 17:08:03 -0700477 }
478#endif
479 if (local_video_observer_ && !stream->GetVideoTracks().empty()) {
480 stream->GetVideoTracks()[0]->AddOrUpdateSink(local_video_observer_.get(),
481 rtc::VideoSinkWants());
gyzhouad7cad82017-05-11 16:10:03 -0700482 }
483 }
484
485 if (!peer_connection_->AddStream(stream)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100486 RTC_LOG(LS_ERROR) << "Adding stream to PeerConnection failed";
gyzhouad7cad82017-05-11 16:10:03 -0700487 }
488
489 typedef std::pair<std::string,
490 rtc::scoped_refptr<webrtc::MediaStreamInterface>>
491 MediaStreamPair;
Seth Hampson13b8bad2018-03-13 16:05:28 -0700492 active_streams_.insert(MediaStreamPair(stream->id(), stream));
gyzhouad7cad82017-05-11 16:10:03 -0700493}
494
495bool SimplePeerConnection::CreateDataChannel() {
496 struct webrtc::DataChannelInit init;
497 init.ordered = true;
498 init.reliable = true;
499 data_channel_ = peer_connection_->CreateDataChannel("Hello", &init);
500 if (data_channel_.get()) {
501 data_channel_->RegisterObserver(this);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100502 RTC_LOG(LS_INFO) << "Succeeds to create data channel";
gyzhouad7cad82017-05-11 16:10:03 -0700503 return true;
504 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100505 RTC_LOG(LS_INFO) << "Fails to create data channel";
gyzhouad7cad82017-05-11 16:10:03 -0700506 return false;
507 }
508}
509
510void SimplePeerConnection::CloseDataChannel() {
511 if (data_channel_.get()) {
512 data_channel_->UnregisterObserver();
513 data_channel_->Close();
514 }
515 data_channel_ = nullptr;
516}
517
518bool SimplePeerConnection::SendDataViaDataChannel(const std::string& data) {
519 if (!data_channel_.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100520 RTC_LOG(LS_INFO) << "Data channel is not established";
gyzhouad7cad82017-05-11 16:10:03 -0700521 return false;
522 }
523 webrtc::DataBuffer buffer(data);
524 data_channel_->Send(buffer);
525 return true;
526}
527
528// Peerconnection observer
529void SimplePeerConnection::OnDataChannel(
530 rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
531 channel->RegisterObserver(this);
532}
533
534void SimplePeerConnection::OnStateChange() {
535 if (data_channel_) {
536 webrtc::DataChannelInterface::DataState state = data_channel_->state();
537 if (state == webrtc::DataChannelInterface::kOpen) {
538 if (OnLocalDataChannelReady)
539 OnLocalDataChannelReady();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100540 RTC_LOG(LS_INFO) << "Data channel is open";
gyzhouad7cad82017-05-11 16:10:03 -0700541 }
542 }
543}
544
545// A data buffer was successfully received.
546void SimplePeerConnection::OnMessage(const webrtc::DataBuffer& buffer) {
547 size_t size = buffer.data.size();
548 char* msg = new char[size + 1];
549 memcpy(msg, buffer.data.data(), size);
550 msg[size] = 0;
551 if (OnDataFromDataChannelReady)
552 OnDataFromDataChannelReady(msg);
553 delete[] msg;
554}
555
556// AudioTrackSinkInterface implementation.
557void SimplePeerConnection::OnData(const void* audio_data,
558 int bits_per_sample,
559 int sample_rate,
560 size_t number_of_channels,
561 size_t number_of_frames) {
562 if (OnAudioReady)
563 OnAudioReady(audio_data, bits_per_sample, sample_rate,
564 static_cast<int>(number_of_channels),
565 static_cast<int>(number_of_frames));
566}
567
568std::vector<uint32_t> SimplePeerConnection::GetRemoteAudioTrackSsrcs() {
569 std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers =
570 peer_connection_->GetReceivers();
571
572 std::vector<uint32_t> ssrcs;
573 for (const auto& receiver : receivers) {
574 if (receiver->media_type() != cricket::MEDIA_TYPE_AUDIO)
575 continue;
576
577 std::vector<webrtc::RtpEncodingParameters> params =
578 receiver->GetParameters().encodings;
579
580 for (const auto& param : params) {
581 uint32_t ssrc = param.ssrc.value_or(0);
582 if (ssrc > 0)
583 ssrcs.push_back(ssrc);
584 }
585 }
586
587 return ssrcs;
588}