blob: 0b0a810ed49b1f4077da36452d22615f6000b3f3 [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"
23#include "media/engine/webrtc_video_decoder_factory.h"
24#include "media/engine/webrtc_video_encoder_factory.h"
Qiang Chen43fb9122017-12-20 10:47:36 -080025#include "modules/audio_device/include/audio_device.h"
26#include "modules/audio_processing/include/audio_processing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/video_capture/video_capture_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "pc/video_track_source.h"
Niels Möller0a595352019-01-02 15:12:38 +010029#include "test/vcm_capturer.h"
gyzhouad7cad82017-05-11 16:10:03 -070030
qiangchen42f96d52017-08-08 17:08:03 -070031#if defined(WEBRTC_ANDROID)
Steve Anton10542f22019-01-11 09:11:00 -080032#include "examples/unityplugin/class_reference_holder.h"
George Zhou2770c3d2018-03-07 09:58:54 -080033#include "modules/utility/include/helpers_android.h"
Steve Anton10542f22019-01-11 09:11:00 -080034#include "sdk/android/src/jni/android_video_track_source.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020035#include "sdk/android/src/jni/jni_helpers.h"
qiangchen42f96d52017-08-08 17:08:03 -070036#endif
37
Seth Hampson513449e2018-03-06 09:35:56 -080038// Names used for media stream ids.
gyzhouad7cad82017-05-11 16:10:03 -070039const char kAudioLabel[] = "audio_label";
40const char kVideoLabel[] = "video_label";
Seth Hampson513449e2018-03-06 09:35:56 -080041const char kStreamId[] = "stream_id";
gyzhouad7cad82017-05-11 16:10:03 -070042
43namespace {
44static int g_peer_count = 0;
45static std::unique_ptr<rtc::Thread> g_worker_thread;
46static std::unique_ptr<rtc::Thread> g_signaling_thread;
47static rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
48 g_peer_connection_factory;
qiangchen42f96d52017-08-08 17:08:03 -070049#if defined(WEBRTC_ANDROID)
50// Android case: the video track does not own the capturer, and it
51// relies on the app to dispose the capturer when the peerconnection
52// shuts down.
53static jobject g_camera = nullptr;
Niels Möller0a595352019-01-02 15:12:38 +010054#else
55class CapturerTrackSource : public webrtc::VideoTrackSource {
56 public:
57 static rtc::scoped_refptr<CapturerTrackSource> Create() {
58 const size_t kWidth = 640;
59 const size_t kHeight = 480;
60 const size_t kFps = 30;
61 const size_t kDeviceIndex = 0;
62 std::unique_ptr<webrtc::test::VcmCapturer> capturer = absl::WrapUnique(
63 webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, kDeviceIndex));
64 if (!capturer) {
65 return nullptr;
66 }
67 return new rtc::RefCountedObject<CapturerTrackSource>(std::move(capturer));
68 }
69
70 protected:
71 explicit CapturerTrackSource(
72 std::unique_ptr<webrtc::test::VcmCapturer> capturer)
73 : VideoTrackSource(/*remote=*/false), capturer_(std::move(capturer)) {}
74
75 private:
76 rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override {
77 return capturer_.get();
78 }
79 std::unique_ptr<webrtc::test::VcmCapturer> capturer_;
80};
81
qiangchen42f96d52017-08-08 17:08:03 -070082#endif
gyzhouad7cad82017-05-11 16:10:03 -070083
84std::string GetEnvVarOrDefault(const char* env_var_name,
85 const char* default_value) {
86 std::string value;
87 const char* env_var = getenv(env_var_name);
88 if (env_var)
89 value = env_var;
90
91 if (value.empty())
92 value = default_value;
93
94 return value;
95}
96
97std::string GetPeerConnectionString() {
98 return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302");
99}
100
101class DummySetSessionDescriptionObserver
102 : public webrtc::SetSessionDescriptionObserver {
103 public:
104 static DummySetSessionDescriptionObserver* Create() {
105 return new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
106 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100107 virtual void OnSuccess() { RTC_LOG(INFO) << __FUNCTION__; }
Harald Alvestrand73771a82018-05-24 10:53:49 +0200108 virtual void OnFailure(webrtc::RTCError error) {
109 RTC_LOG(INFO) << __FUNCTION__ << " " << ToString(error.type()) << ": "
110 << error.message();
gyzhouad7cad82017-05-11 16:10:03 -0700111 }
112
113 protected:
114 DummySetSessionDescriptionObserver() {}
115 ~DummySetSessionDescriptionObserver() {}
116};
117
118} // namespace
119
gyzhoub38f3862017-07-25 16:04:31 -0700120bool SimplePeerConnection::InitializePeerConnection(const char** turn_urls,
121 const int no_of_urls,
122 const char* username,
123 const char* credential,
124 bool is_receiver) {
gyzhouad7cad82017-05-11 16:10:03 -0700125 RTC_DCHECK(peer_connection_.get() == nullptr);
126
127 if (g_peer_connection_factory == nullptr) {
128 g_worker_thread.reset(new rtc::Thread());
129 g_worker_thread->Start();
130 g_signaling_thread.reset(new rtc::Thread());
131 g_signaling_thread->Start();
132
133 g_peer_connection_factory = webrtc::CreatePeerConnectionFactory(
134 g_worker_thread.get(), g_worker_thread.get(), g_signaling_thread.get(),
Qiang Chen51e20462017-12-05 11:11:21 -0800135 nullptr, webrtc::CreateBuiltinAudioEncoderFactory(),
Qiang Chen43fb9122017-12-20 10:47:36 -0800136 webrtc::CreateBuiltinAudioDecoderFactory(),
137 std::unique_ptr<webrtc::VideoEncoderFactory>(
Anders Carlssondd8c1652018-01-30 10:32:13 +0100138 new webrtc::MultiplexEncoderFactory(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200139 absl::make_unique<webrtc::InternalEncoderFactory>())),
Qiang Chen43fb9122017-12-20 10:47:36 -0800140 std::unique_ptr<webrtc::VideoDecoderFactory>(
Anders Carlssondd8c1652018-01-30 10:32:13 +0100141 new webrtc::MultiplexDecoderFactory(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200142 absl::make_unique<webrtc::InternalDecoderFactory>())),
Qiang Chen43fb9122017-12-20 10:47:36 -0800143 nullptr, nullptr);
gyzhouad7cad82017-05-11 16:10:03 -0700144 }
145 if (!g_peer_connection_factory.get()) {
146 DeletePeerConnection();
147 return false;
148 }
149
150 g_peer_count++;
Qiang Chen51e20462017-12-05 11:11:21 -0800151 if (!CreatePeerConnection(turn_urls, no_of_urls, username, credential)) {
gyzhouad7cad82017-05-11 16:10:03 -0700152 DeletePeerConnection();
153 return false;
154 }
Qiang Chen51e20462017-12-05 11:11:21 -0800155
156 mandatory_receive_ = is_receiver;
gyzhouad7cad82017-05-11 16:10:03 -0700157 return peer_connection_.get() != nullptr;
158}
159
gyzhoub38f3862017-07-25 16:04:31 -0700160bool SimplePeerConnection::CreatePeerConnection(const char** turn_urls,
161 const int no_of_urls,
162 const char* username,
Qiang Chen51e20462017-12-05 11:11:21 -0800163 const char* credential) {
gyzhouad7cad82017-05-11 16:10:03 -0700164 RTC_DCHECK(g_peer_connection_factory.get() != nullptr);
165 RTC_DCHECK(peer_connection_.get() == nullptr);
166
gyzhoub38f3862017-07-25 16:04:31 -0700167 local_video_observer_.reset(new VideoObserver());
168 remote_video_observer_.reset(new VideoObserver());
169
170 // Add the turn server.
171 if (turn_urls != nullptr) {
172 if (no_of_urls > 0) {
173 webrtc::PeerConnectionInterface::IceServer turn_server;
174 for (int i = 0; i < no_of_urls; i++) {
175 std::string url(turn_urls[i]);
176 if (url.length() > 0)
177 turn_server.urls.push_back(turn_urls[i]);
178 }
179
180 std::string user_name(username);
181 if (user_name.length() > 0)
182 turn_server.username = username;
183
184 std::string password(credential);
185 if (password.length() > 0)
186 turn_server.password = credential;
187
188 config_.servers.push_back(turn_server);
189 }
190 }
191
192 // Add the stun server.
193 webrtc::PeerConnectionInterface::IceServer stun_server;
194 stun_server.uri = GetPeerConnectionString();
195 config_.servers.push_back(stun_server);
Niels Möllerf06f9232018-08-07 12:32:18 +0200196 config_.enable_rtp_data_channel = true;
197 config_.enable_dtls_srtp = false;
gyzhouad7cad82017-05-11 16:10:03 -0700198
gyzhouad7cad82017-05-11 16:10:03 -0700199 peer_connection_ = g_peer_connection_factory->CreatePeerConnection(
Niels Möllerf06f9232018-08-07 12:32:18 +0200200 config_, nullptr, nullptr, this);
gyzhouad7cad82017-05-11 16:10:03 -0700201
202 return peer_connection_.get() != nullptr;
203}
204
205void SimplePeerConnection::DeletePeerConnection() {
206 g_peer_count--;
207
qiangchen42f96d52017-08-08 17:08:03 -0700208#if defined(WEBRTC_ANDROID)
209 if (g_camera) {
magjeda3d4f682017-08-28 16:24:06 -0700210 JNIEnv* env = webrtc::jni::GetEnv();
qiangchen42f96d52017-08-08 17:08:03 -0700211 jclass pc_factory_class =
212 unity_plugin::FindClass(env, "org/webrtc/UnityUtility");
George Zhou2770c3d2018-03-07 09:58:54 -0800213 jmethodID stop_camera_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700214 env, pc_factory_class, "StopCamera", "(Lorg/webrtc/VideoCapturer;)V");
215
216 env->CallStaticVoidMethod(pc_factory_class, stop_camera_method, g_camera);
217 CHECK_EXCEPTION(env);
218
219 g_camera = nullptr;
220 }
221#endif
222
gyzhouad7cad82017-05-11 16:10:03 -0700223 CloseDataChannel();
224 peer_connection_ = nullptr;
225 active_streams_.clear();
226
227 if (g_peer_count == 0) {
228 g_peer_connection_factory = nullptr;
229 g_signaling_thread.reset();
230 g_worker_thread.reset();
231 }
232}
233
234bool SimplePeerConnection::CreateOffer() {
235 if (!peer_connection_.get())
236 return false;
237
Niels Möllerf06f9232018-08-07 12:32:18 +0200238 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
Qiang Chen51e20462017-12-05 11:11:21 -0800239 if (mandatory_receive_) {
Niels Möllerf06f9232018-08-07 12:32:18 +0200240 options.offer_to_receive_audio = true;
241 options.offer_to_receive_video = true;
Qiang Chen51e20462017-12-05 11:11:21 -0800242 }
Niels Möllerf06f9232018-08-07 12:32:18 +0200243 peer_connection_->CreateOffer(this, options);
gyzhouad7cad82017-05-11 16:10:03 -0700244 return true;
245}
246
247bool SimplePeerConnection::CreateAnswer() {
248 if (!peer_connection_.get())
249 return false;
250
Niels Möllerf06f9232018-08-07 12:32:18 +0200251 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
Qiang Chen51e20462017-12-05 11:11:21 -0800252 if (mandatory_receive_) {
Niels Möllerf06f9232018-08-07 12:32:18 +0200253 options.offer_to_receive_audio = true;
254 options.offer_to_receive_video = true;
Qiang Chen51e20462017-12-05 11:11:21 -0800255 }
Niels Möllerf06f9232018-08-07 12:32:18 +0200256 peer_connection_->CreateAnswer(this, options);
gyzhouad7cad82017-05-11 16:10:03 -0700257 return true;
258}
259
260void SimplePeerConnection::OnSuccess(
261 webrtc::SessionDescriptionInterface* desc) {
262 peer_connection_->SetLocalDescription(
263 DummySetSessionDescriptionObserver::Create(), desc);
264
265 std::string sdp;
266 desc->ToString(&sdp);
267
gyzhouad7cad82017-05-11 16:10:03 -0700268 if (OnLocalSdpReady)
gyzhoub38f3862017-07-25 16:04:31 -0700269 OnLocalSdpReady(desc->type().c_str(), sdp.c_str());
gyzhouad7cad82017-05-11 16:10:03 -0700270}
271
Harald Alvestrand73771a82018-05-24 10:53:49 +0200272void SimplePeerConnection::OnFailure(webrtc::RTCError error) {
273 RTC_LOG(LERROR) << ToString(error.type()) << ": " << error.message();
gyzhouad7cad82017-05-11 16:10:03 -0700274
Harald Alvestrand73771a82018-05-24 10:53:49 +0200275 // TODO(hta): include error.type in the message
gyzhouad7cad82017-05-11 16:10:03 -0700276 if (OnFailureMessage)
Harald Alvestrand73771a82018-05-24 10:53:49 +0200277 OnFailureMessage(error.message());
gyzhouad7cad82017-05-11 16:10:03 -0700278}
279
280void SimplePeerConnection::OnIceCandidate(
281 const webrtc::IceCandidateInterface* candidate) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100282 RTC_LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
gyzhouad7cad82017-05-11 16:10:03 -0700283
gyzhouad7cad82017-05-11 16:10:03 -0700284 std::string sdp;
285 if (!candidate->ToString(&sdp)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100286 RTC_LOG(LS_ERROR) << "Failed to serialize candidate";
gyzhouad7cad82017-05-11 16:10:03 -0700287 return;
288 }
gyzhouad7cad82017-05-11 16:10:03 -0700289
290 if (OnIceCandiateReady)
gyzhoub38f3862017-07-25 16:04:31 -0700291 OnIceCandiateReady(sdp.c_str(), candidate->sdp_mline_index(),
292 candidate->sdp_mid().c_str());
gyzhouad7cad82017-05-11 16:10:03 -0700293}
294
gyzhoub38f3862017-07-25 16:04:31 -0700295void SimplePeerConnection::RegisterOnLocalI420FrameReady(
296 I420FRAMEREADY_CALLBACK callback) {
297 if (local_video_observer_)
298 local_video_observer_->SetVideoCallback(callback);
299}
300
301void SimplePeerConnection::RegisterOnRemoteI420FrameReady(
302 I420FRAMEREADY_CALLBACK callback) {
303 if (remote_video_observer_)
304 remote_video_observer_->SetVideoCallback(callback);
gyzhouad7cad82017-05-11 16:10:03 -0700305}
306
307void SimplePeerConnection::RegisterOnLocalDataChannelReady(
308 LOCALDATACHANNELREADY_CALLBACK callback) {
309 OnLocalDataChannelReady = callback;
310}
311
312void SimplePeerConnection::RegisterOnDataFromDataChannelReady(
313 DATAFROMEDATECHANNELREADY_CALLBACK callback) {
314 OnDataFromDataChannelReady = callback;
315}
316
317void SimplePeerConnection::RegisterOnFailure(FAILURE_CALLBACK callback) {
318 OnFailureMessage = callback;
319}
320
321void SimplePeerConnection::RegisterOnAudioBusReady(
322 AUDIOBUSREADY_CALLBACK callback) {
323 OnAudioReady = callback;
324}
325
326void SimplePeerConnection::RegisterOnLocalSdpReadytoSend(
327 LOCALSDPREADYTOSEND_CALLBACK callback) {
328 OnLocalSdpReady = callback;
329}
330
331void SimplePeerConnection::RegisterOnIceCandiateReadytoSend(
332 ICECANDIDATEREADYTOSEND_CALLBACK callback) {
333 OnIceCandiateReady = callback;
334}
335
gyzhoub38f3862017-07-25 16:04:31 -0700336bool SimplePeerConnection::SetRemoteDescription(const char* type,
337 const char* sdp) {
gyzhouad7cad82017-05-11 16:10:03 -0700338 if (!peer_connection_)
339 return false;
340
gyzhoub38f3862017-07-25 16:04:31 -0700341 std::string remote_desc(sdp);
342 std::string sdp_type(type);
gyzhouad7cad82017-05-11 16:10:03 -0700343 webrtc::SdpParseError error;
344 webrtc::SessionDescriptionInterface* session_description(
gyzhoub38f3862017-07-25 16:04:31 -0700345 webrtc::CreateSessionDescription(sdp_type, remote_desc, &error));
gyzhouad7cad82017-05-11 16:10:03 -0700346 if (!session_description) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100347 RTC_LOG(WARNING) << "Can't parse received session description message. "
348 << "SdpParseError was: " << error.description;
gyzhouad7cad82017-05-11 16:10:03 -0700349 return false;
350 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100351 RTC_LOG(INFO) << " Received session description :" << remote_desc;
gyzhouad7cad82017-05-11 16:10:03 -0700352 peer_connection_->SetRemoteDescription(
353 DummySetSessionDescriptionObserver::Create(), session_description);
354
355 return true;
356}
357
gyzhoub38f3862017-07-25 16:04:31 -0700358bool SimplePeerConnection::AddIceCandidate(const char* candidate,
359 const int sdp_mlineindex,
360 const char* sdp_mid) {
gyzhouad7cad82017-05-11 16:10:03 -0700361 if (!peer_connection_)
362 return false;
363
gyzhouad7cad82017-05-11 16:10:03 -0700364 webrtc::SdpParseError error;
gyzhoub38f3862017-07-25 16:04:31 -0700365 std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate(
366 webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, candidate, &error));
367 if (!ice_candidate.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100368 RTC_LOG(WARNING) << "Can't parse received candidate message. "
369 << "SdpParseError was: " << error.description;
gyzhouad7cad82017-05-11 16:10:03 -0700370 return false;
371 }
gyzhoub38f3862017-07-25 16:04:31 -0700372 if (!peer_connection_->AddIceCandidate(ice_candidate.get())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100373 RTC_LOG(WARNING) << "Failed to apply the received candidate";
gyzhouad7cad82017-05-11 16:10:03 -0700374 return false;
375 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100376 RTC_LOG(INFO) << " Received candidate :" << candidate;
gyzhouad7cad82017-05-11 16:10:03 -0700377 return true;
378}
379
380void SimplePeerConnection::SetAudioControl(bool is_mute, bool is_record) {
381 is_mute_audio_ = is_mute;
382 is_record_audio_ = is_record;
383
384 SetAudioControl();
385}
386
387void SimplePeerConnection::SetAudioControl() {
388 if (!remote_stream_)
389 return;
390 webrtc::AudioTrackVector tracks = remote_stream_->GetAudioTracks();
391 if (tracks.empty())
392 return;
393
394 webrtc::AudioTrackInterface* audio_track = tracks[0];
395 std::string id = audio_track->id();
396 if (is_record_audio_)
397 audio_track->AddSink(this);
398 else
399 audio_track->RemoveSink(this);
400
401 for (auto& track : tracks) {
402 if (is_mute_audio_)
403 track->set_enabled(false);
404 else
405 track->set_enabled(true);
406 }
407}
408
409void SimplePeerConnection::OnAddStream(
410 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
Seth Hampson13b8bad2018-03-13 16:05:28 -0700411 RTC_LOG(INFO) << __FUNCTION__ << " " << stream->id();
gyzhouad7cad82017-05-11 16:10:03 -0700412 remote_stream_ = stream;
gyzhoub38f3862017-07-25 16:04:31 -0700413 if (remote_video_observer_ && !remote_stream_->GetVideoTracks().empty()) {
414 remote_stream_->GetVideoTracks()[0]->AddOrUpdateSink(
415 remote_video_observer_.get(), rtc::VideoSinkWants());
416 }
gyzhouad7cad82017-05-11 16:10:03 -0700417 SetAudioControl();
418}
419
gyzhouad7cad82017-05-11 16:10:03 -0700420void SimplePeerConnection::AddStreams(bool audio_only) {
Seth Hampson513449e2018-03-06 09:35:56 -0800421 if (active_streams_.find(kStreamId) != active_streams_.end())
gyzhouad7cad82017-05-11 16:10:03 -0700422 return; // Already added.
423
424 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
Seth Hampson513449e2018-03-06 09:35:56 -0800425 g_peer_connection_factory->CreateLocalMediaStream(kStreamId);
gyzhouad7cad82017-05-11 16:10:03 -0700426
427 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
428 g_peer_connection_factory->CreateAudioTrack(
Niels Möller2d02e082018-05-21 11:23:35 +0200429 kAudioLabel, g_peer_connection_factory->CreateAudioSource(
430 cricket::AudioOptions())));
gyzhouad7cad82017-05-11 16:10:03 -0700431 std::string id = audio_track->id();
432 stream->AddTrack(audio_track);
433
434 if (!audio_only) {
qiangchen42f96d52017-08-08 17:08:03 -0700435#if defined(WEBRTC_ANDROID)
magjeda3d4f682017-08-28 16:24:06 -0700436 JNIEnv* env = webrtc::jni::GetEnv();
qiangchen42f96d52017-08-08 17:08:03 -0700437 jclass pc_factory_class =
438 unity_plugin::FindClass(env, "org/webrtc/UnityUtility");
George Zhou2770c3d2018-03-07 09:58:54 -0800439 jmethodID load_texture_helper_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700440 env, pc_factory_class, "LoadSurfaceTextureHelper",
441 "()Lorg/webrtc/SurfaceTextureHelper;");
442 jobject texture_helper = env->CallStaticObjectMethod(
443 pc_factory_class, load_texture_helper_method);
444 CHECK_EXCEPTION(env);
445 RTC_DCHECK(texture_helper != nullptr)
446 << "Cannot get the Surface Texture Helper.";
447
Qiang Chen51e20462017-12-05 11:11:21 -0800448 rtc::scoped_refptr<webrtc::jni::AndroidVideoTrackSource> source(
449 new rtc::RefCountedObject<webrtc::jni::AndroidVideoTrackSource>(
Magnus Jedvert95140712018-11-15 12:07:32 +0100450 g_signaling_thread.get(), env, /* is_screencast= */ false,
451 /* align_timestamps= */ true));
qiangchen42f96d52017-08-08 17:08:03 -0700452 rtc::scoped_refptr<webrtc::VideoTrackSourceProxy> proxy_source =
453 webrtc::VideoTrackSourceProxy::Create(g_signaling_thread.get(),
454 g_worker_thread.get(), source);
455
456 // link with VideoCapturer (Camera);
George Zhou2770c3d2018-03-07 09:58:54 -0800457 jmethodID link_camera_method = webrtc::GetStaticMethodID(
qiangchen42f96d52017-08-08 17:08:03 -0700458 env, pc_factory_class, "LinkCamera",
459 "(JLorg/webrtc/SurfaceTextureHelper;)Lorg/webrtc/VideoCapturer;");
460 jobject camera_tmp =
461 env->CallStaticObjectMethod(pc_factory_class, link_camera_method,
462 (jlong)proxy_source.get(), texture_helper);
463 CHECK_EXCEPTION(env);
464 g_camera = (jobject)env->NewGlobalRef(camera_tmp);
465
466 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
467 g_peer_connection_factory->CreateVideoTrack(kVideoLabel,
468 proxy_source.release()));
469 stream->AddTrack(video_track);
470#else
Niels Möller0a595352019-01-02 15:12:38 +0100471 rtc::scoped_refptr<CapturerTrackSource> video_device =
472 CapturerTrackSource::Create();
473 if (video_device) {
gyzhouad7cad82017-05-11 16:10:03 -0700474 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
Niels Möller0a595352019-01-02 15:12:38 +0100475 g_peer_connection_factory->CreateVideoTrack(kVideoLabel,
476 video_device));
gyzhouad7cad82017-05-11 16:10:03 -0700477
478 stream->AddTrack(video_track);
qiangchen42f96d52017-08-08 17:08:03 -0700479 }
480#endif
481 if (local_video_observer_ && !stream->GetVideoTracks().empty()) {
482 stream->GetVideoTracks()[0]->AddOrUpdateSink(local_video_observer_.get(),
483 rtc::VideoSinkWants());
gyzhouad7cad82017-05-11 16:10:03 -0700484 }
485 }
486
487 if (!peer_connection_->AddStream(stream)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100488 RTC_LOG(LS_ERROR) << "Adding stream to PeerConnection failed";
gyzhouad7cad82017-05-11 16:10:03 -0700489 }
490
491 typedef std::pair<std::string,
492 rtc::scoped_refptr<webrtc::MediaStreamInterface>>
493 MediaStreamPair;
Seth Hampson13b8bad2018-03-13 16:05:28 -0700494 active_streams_.insert(MediaStreamPair(stream->id(), stream));
gyzhouad7cad82017-05-11 16:10:03 -0700495}
496
497bool SimplePeerConnection::CreateDataChannel() {
498 struct webrtc::DataChannelInit init;
499 init.ordered = true;
500 init.reliable = true;
501 data_channel_ = peer_connection_->CreateDataChannel("Hello", &init);
502 if (data_channel_.get()) {
503 data_channel_->RegisterObserver(this);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100504 RTC_LOG(LS_INFO) << "Succeeds to create data channel";
gyzhouad7cad82017-05-11 16:10:03 -0700505 return true;
506 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100507 RTC_LOG(LS_INFO) << "Fails to create data channel";
gyzhouad7cad82017-05-11 16:10:03 -0700508 return false;
509 }
510}
511
512void SimplePeerConnection::CloseDataChannel() {
513 if (data_channel_.get()) {
514 data_channel_->UnregisterObserver();
515 data_channel_->Close();
516 }
517 data_channel_ = nullptr;
518}
519
520bool SimplePeerConnection::SendDataViaDataChannel(const std::string& data) {
521 if (!data_channel_.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100522 RTC_LOG(LS_INFO) << "Data channel is not established";
gyzhouad7cad82017-05-11 16:10:03 -0700523 return false;
524 }
525 webrtc::DataBuffer buffer(data);
526 data_channel_->Send(buffer);
527 return true;
528}
529
530// Peerconnection observer
531void SimplePeerConnection::OnDataChannel(
532 rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
533 channel->RegisterObserver(this);
534}
535
536void SimplePeerConnection::OnStateChange() {
537 if (data_channel_) {
538 webrtc::DataChannelInterface::DataState state = data_channel_->state();
539 if (state == webrtc::DataChannelInterface::kOpen) {
540 if (OnLocalDataChannelReady)
541 OnLocalDataChannelReady();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100542 RTC_LOG(LS_INFO) << "Data channel is open";
gyzhouad7cad82017-05-11 16:10:03 -0700543 }
544 }
545}
546
547// A data buffer was successfully received.
548void SimplePeerConnection::OnMessage(const webrtc::DataBuffer& buffer) {
549 size_t size = buffer.data.size();
550 char* msg = new char[size + 1];
551 memcpy(msg, buffer.data.data(), size);
552 msg[size] = 0;
553 if (OnDataFromDataChannelReady)
554 OnDataFromDataChannelReady(msg);
555 delete[] msg;
556}
557
558// AudioTrackSinkInterface implementation.
559void SimplePeerConnection::OnData(const void* audio_data,
560 int bits_per_sample,
561 int sample_rate,
562 size_t number_of_channels,
563 size_t number_of_frames) {
564 if (OnAudioReady)
565 OnAudioReady(audio_data, bits_per_sample, sample_rate,
566 static_cast<int>(number_of_channels),
567 static_cast<int>(number_of_frames));
568}
569
570std::vector<uint32_t> SimplePeerConnection::GetRemoteAudioTrackSsrcs() {
571 std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers =
572 peer_connection_->GetReceivers();
573
574 std::vector<uint32_t> ssrcs;
575 for (const auto& receiver : receivers) {
576 if (receiver->media_type() != cricket::MEDIA_TYPE_AUDIO)
577 continue;
578
579 std::vector<webrtc::RtpEncodingParameters> params =
580 receiver->GetParameters().encodings;
581
582 for (const auto& param : params) {
583 uint32_t ssrc = param.ssrc.value_or(0);
584 if (ssrc > 0)
585 ssrcs.push_back(ssrc);
586 }
587 }
588
589 return ssrcs;
590}