• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 *  Copyright 2018 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
11#include "examples/objcnativeapi/objc/objc_call_client.h"
12
13#include <memory>
14#include <utility>
15
16#import "sdk/objc/base/RTCVideoRenderer.h"
17#import "sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.h"
18#import "sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.h"
19#import "sdk/objc/helpers/RTCCameraPreviewView.h"
20
21#include "api/audio_codecs/builtin_audio_decoder_factory.h"
22#include "api/audio_codecs/builtin_audio_encoder_factory.h"
23#include "api/peer_connection_interface.h"
24#include "api/rtc_event_log/rtc_event_log_factory.h"
25#include "api/task_queue/default_task_queue_factory.h"
26#include "media/engine/webrtc_media_engine.h"
27#include "modules/audio_processing/include/audio_processing.h"
28#include "sdk/objc/native/api/video_capturer.h"
29#include "sdk/objc/native/api/video_decoder_factory.h"
30#include "sdk/objc/native/api/video_encoder_factory.h"
31#include "sdk/objc/native/api/video_renderer.h"
32
33namespace webrtc_examples {
34
35namespace {
36
37class CreateOfferObserver : public webrtc::CreateSessionDescriptionObserver {
38 public:
39  explicit CreateOfferObserver(rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc);
40
41  void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
42  void OnFailure(webrtc::RTCError error) override;
43
44 private:
45  const rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc_;
46};
47
48class SetRemoteSessionDescriptionObserver : public webrtc::SetRemoteDescriptionObserverInterface {
49 public:
50  void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override;
51};
52
53class SetLocalSessionDescriptionObserver : public webrtc::SetSessionDescriptionObserver {
54 public:
55  void OnSuccess() override;
56  void OnFailure(webrtc::RTCError error) override;
57};
58
59}  // namespace
60
61ObjCCallClient::ObjCCallClient()
62    : call_started_(false), pc_observer_(std::make_unique<PCObserver>(this)) {
63  thread_checker_.Detach();
64  CreatePeerConnectionFactory();
65}
66
67void ObjCCallClient::Call(RTC_OBJC_TYPE(RTCVideoCapturer) * capturer,
68                          id<RTC_OBJC_TYPE(RTCVideoRenderer)> remote_renderer) {
69  RTC_DCHECK_RUN_ON(&thread_checker_);
70
71  webrtc::MutexLock lock(&pc_mutex_);
72  if (call_started_) {
73    RTC_LOG(LS_WARNING) << "Call already started.";
74    return;
75  }
76  call_started_ = true;
77
78  remote_sink_ = webrtc::ObjCToNativeVideoRenderer(remote_renderer);
79
80  video_source_ =
81      webrtc::ObjCToNativeVideoCapturer(capturer, signaling_thread_.get(), worker_thread_.get());
82
83  CreatePeerConnection();
84  Connect();
85}
86
87void ObjCCallClient::Hangup() {
88  RTC_DCHECK_RUN_ON(&thread_checker_);
89
90  call_started_ = false;
91
92  {
93    webrtc::MutexLock lock(&pc_mutex_);
94    if (pc_ != nullptr) {
95      pc_->Close();
96      pc_ = nullptr;
97    }
98  }
99
100  remote_sink_ = nullptr;
101  video_source_ = nullptr;
102}
103
104void ObjCCallClient::CreatePeerConnectionFactory() {
105  network_thread_ = rtc::Thread::CreateWithSocketServer();
106  network_thread_->SetName("network_thread", nullptr);
107  RTC_CHECK(network_thread_->Start()) << "Failed to start thread";
108
109  worker_thread_ = rtc::Thread::Create();
110  worker_thread_->SetName("worker_thread", nullptr);
111  RTC_CHECK(worker_thread_->Start()) << "Failed to start thread";
112
113  signaling_thread_ = rtc::Thread::Create();
114  signaling_thread_->SetName("signaling_thread", nullptr);
115  RTC_CHECK(signaling_thread_->Start()) << "Failed to start thread";
116
117  webrtc::PeerConnectionFactoryDependencies dependencies;
118  dependencies.network_thread = network_thread_.get();
119  dependencies.worker_thread = worker_thread_.get();
120  dependencies.signaling_thread = signaling_thread_.get();
121  dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
122  cricket::MediaEngineDependencies media_deps;
123  media_deps.task_queue_factory = dependencies.task_queue_factory.get();
124  media_deps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
125  media_deps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
126  media_deps.video_encoder_factory = webrtc::ObjCToNativeVideoEncoderFactory(
127      [[RTC_OBJC_TYPE(RTCDefaultVideoEncoderFactory) alloc] init]);
128  media_deps.video_decoder_factory = webrtc::ObjCToNativeVideoDecoderFactory(
129      [[RTC_OBJC_TYPE(RTCDefaultVideoDecoderFactory) alloc] init]);
130  media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create();
131  dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
132  RTC_LOG(LS_INFO) << "Media engine created: " << dependencies.media_engine.get();
133  dependencies.call_factory = webrtc::CreateCallFactory();
134  dependencies.event_log_factory =
135      std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get());
136  pcf_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
137  RTC_LOG(LS_INFO) << "PeerConnectionFactory created: " << pcf_;
138}
139
140void ObjCCallClient::CreatePeerConnection() {
141  webrtc::MutexLock lock(&pc_mutex_);
142  webrtc::PeerConnectionInterface::RTCConfiguration config;
143  config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
144  // DTLS SRTP has to be disabled for loopback to work.
145  config.enable_dtls_srtp = false;
146  webrtc::PeerConnectionDependencies pc_dependencies(pc_observer_.get());
147  pc_ = pcf_->CreatePeerConnection(config, std::move(pc_dependencies));
148  RTC_LOG(LS_INFO) << "PeerConnection created: " << pc_;
149
150  rtc::scoped_refptr<webrtc::VideoTrackInterface> local_video_track =
151      pcf_->CreateVideoTrack("video", video_source_);
152  pc_->AddTransceiver(local_video_track);
153  RTC_LOG(LS_INFO) << "Local video sink set up: " << local_video_track;
154
155  for (const rtc::scoped_refptr<webrtc::RtpTransceiverInterface>& tranceiver :
156       pc_->GetTransceivers()) {
157    rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track = tranceiver->receiver()->track();
158    if (track && track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
159      static_cast<webrtc::VideoTrackInterface*>(track.get())
160          ->AddOrUpdateSink(remote_sink_.get(), rtc::VideoSinkWants());
161      RTC_LOG(LS_INFO) << "Remote video sink set up: " << track;
162      break;
163    }
164  }
165}
166
167void ObjCCallClient::Connect() {
168  webrtc::MutexLock lock(&pc_mutex_);
169  pc_->CreateOffer(new rtc::RefCountedObject<CreateOfferObserver>(pc_),
170                   webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
171}
172
173ObjCCallClient::PCObserver::PCObserver(ObjCCallClient* client) : client_(client) {}
174
175void ObjCCallClient::PCObserver::OnSignalingChange(
176    webrtc::PeerConnectionInterface::SignalingState new_state) {
177  RTC_LOG(LS_INFO) << "OnSignalingChange: " << new_state;
178}
179
180void ObjCCallClient::PCObserver::OnDataChannel(
181    rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
182  RTC_LOG(LS_INFO) << "OnDataChannel";
183}
184
185void ObjCCallClient::PCObserver::OnRenegotiationNeeded() {
186  RTC_LOG(LS_INFO) << "OnRenegotiationNeeded";
187}
188
189void ObjCCallClient::PCObserver::OnIceConnectionChange(
190    webrtc::PeerConnectionInterface::IceConnectionState new_state) {
191  RTC_LOG(LS_INFO) << "OnIceConnectionChange: " << new_state;
192}
193
194void ObjCCallClient::PCObserver::OnIceGatheringChange(
195    webrtc::PeerConnectionInterface::IceGatheringState new_state) {
196  RTC_LOG(LS_INFO) << "OnIceGatheringChange: " << new_state;
197}
198
199void ObjCCallClient::PCObserver::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
200  RTC_LOG(LS_INFO) << "OnIceCandidate: " << candidate->server_url();
201  webrtc::MutexLock lock(&client_->pc_mutex_);
202  RTC_DCHECK(client_->pc_ != nullptr);
203  client_->pc_->AddIceCandidate(candidate);
204}
205
206CreateOfferObserver::CreateOfferObserver(rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc)
207    : pc_(pc) {}
208
209void CreateOfferObserver::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
210  std::string sdp;
211  desc->ToString(&sdp);
212  RTC_LOG(LS_INFO) << "Created offer: " << sdp;
213
214  // Ownership of desc was transferred to us, now we transfer it forward.
215  pc_->SetLocalDescription(new rtc::RefCountedObject<SetLocalSessionDescriptionObserver>(), desc);
216
217  // Generate a fake answer.
218  std::unique_ptr<webrtc::SessionDescriptionInterface> answer(
219      webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp));
220  pc_->SetRemoteDescription(std::move(answer),
221                            new rtc::RefCountedObject<SetRemoteSessionDescriptionObserver>());
222}
223
224void CreateOfferObserver::OnFailure(webrtc::RTCError error) {
225  RTC_LOG(LS_INFO) << "Failed to create offer: " << error.message();
226}
227
228void SetRemoteSessionDescriptionObserver::OnSetRemoteDescriptionComplete(webrtc::RTCError error) {
229  RTC_LOG(LS_INFO) << "Set remote description: " << error.message();
230}
231
232void SetLocalSessionDescriptionObserver::OnSuccess() {
233  RTC_LOG(LS_INFO) << "Set local description success!";
234}
235
236void SetLocalSessionDescriptionObserver::OnFailure(webrtc::RTCError error) {
237  RTC_LOG(LS_INFO) << "Set local description failure: " << error.message();
238}
239
240}  // namespace webrtc_examples
241