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