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::SetLocalDescriptionObserverInterface { 54 public: 55 void OnSetLocalDescriptionComplete(webrtc::RTCError error) override; 56}; 57 58} // namespace 59 60ObjCCallClient::ObjCCallClient() 61 : call_started_(false), pc_observer_(std::make_unique<PCObserver>(this)) { 62 thread_checker_.Detach(); 63 CreatePeerConnectionFactory(); 64} 65 66void ObjCCallClient::Call(RTC_OBJC_TYPE(RTCVideoCapturer) * capturer, 67 id<RTC_OBJC_TYPE(RTCVideoRenderer)> remote_renderer) { 68 RTC_DCHECK_RUN_ON(&thread_checker_); 69 70 webrtc::MutexLock lock(&pc_mutex_); 71 if (call_started_) { 72 RTC_LOG(LS_WARNING) << "Call already started."; 73 return; 74 } 75 call_started_ = true; 76 77 remote_sink_ = webrtc::ObjCToNativeVideoRenderer(remote_renderer); 78 79 video_source_ = 80 webrtc::ObjCToNativeVideoCapturer(capturer, signaling_thread_.get(), worker_thread_.get()); 81 82 CreatePeerConnection(); 83 Connect(); 84} 85 86void ObjCCallClient::Hangup() { 87 RTC_DCHECK_RUN_ON(&thread_checker_); 88 89 call_started_ = false; 90 91 { 92 webrtc::MutexLock lock(&pc_mutex_); 93 if (pc_ != nullptr) { 94 pc_->Close(); 95 pc_ = nullptr; 96 } 97 } 98 99 remote_sink_ = nullptr; 100 video_source_ = nullptr; 101} 102 103void ObjCCallClient::CreatePeerConnectionFactory() { 104 network_thread_ = rtc::Thread::CreateWithSocketServer(); 105 network_thread_->SetName("network_thread", nullptr); 106 RTC_CHECK(network_thread_->Start()) << "Failed to start thread"; 107 108 worker_thread_ = rtc::Thread::Create(); 109 worker_thread_->SetName("worker_thread", nullptr); 110 RTC_CHECK(worker_thread_->Start()) << "Failed to start thread"; 111 112 signaling_thread_ = rtc::Thread::Create(); 113 signaling_thread_->SetName("signaling_thread", nullptr); 114 RTC_CHECK(signaling_thread_->Start()) << "Failed to start thread"; 115 116 webrtc::PeerConnectionFactoryDependencies dependencies; 117 dependencies.network_thread = network_thread_.get(); 118 dependencies.worker_thread = worker_thread_.get(); 119 dependencies.signaling_thread = signaling_thread_.get(); 120 dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); 121 cricket::MediaEngineDependencies media_deps; 122 media_deps.task_queue_factory = dependencies.task_queue_factory.get(); 123 media_deps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory(); 124 media_deps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory(); 125 media_deps.video_encoder_factory = webrtc::ObjCToNativeVideoEncoderFactory( 126 [[RTC_OBJC_TYPE(RTCDefaultVideoEncoderFactory) alloc] init]); 127 media_deps.video_decoder_factory = webrtc::ObjCToNativeVideoDecoderFactory( 128 [[RTC_OBJC_TYPE(RTCDefaultVideoDecoderFactory) alloc] init]); 129 media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create(); 130 dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps)); 131 RTC_LOG(LS_INFO) << "Media engine created: " << dependencies.media_engine.get(); 132 dependencies.call_factory = webrtc::CreateCallFactory(); 133 dependencies.event_log_factory = 134 std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get()); 135 pcf_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies)); 136 RTC_LOG(LS_INFO) << "PeerConnectionFactory created: " << pcf_.get(); 137} 138 139void ObjCCallClient::CreatePeerConnection() { 140 webrtc::MutexLock lock(&pc_mutex_); 141 webrtc::PeerConnectionInterface::RTCConfiguration config; 142 config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; 143 // Encryption has to be disabled for loopback to work. 144 webrtc::PeerConnectionFactoryInterface::Options options; 145 options.disable_encryption = true; 146 pcf_->SetOptions(options); 147 webrtc::PeerConnectionDependencies pc_dependencies(pc_observer_.get()); 148 pc_ = pcf_->CreatePeerConnectionOrError(config, std::move(pc_dependencies)).MoveValue(); 149 RTC_LOG(LS_INFO) << "PeerConnection created: " << pc_.get(); 150 151 rtc::scoped_refptr<webrtc::VideoTrackInterface> local_video_track = 152 pcf_->CreateVideoTrack("video", video_source_.get()); 153 pc_->AddTransceiver(local_video_track); 154 RTC_LOG(LS_INFO) << "Local video sink set up: " << local_video_track.get(); 155 156 for (const rtc::scoped_refptr<webrtc::RtpTransceiverInterface>& tranceiver : 157 pc_->GetTransceivers()) { 158 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track = tranceiver->receiver()->track(); 159 if (track && track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) { 160 static_cast<webrtc::VideoTrackInterface*>(track.get()) 161 ->AddOrUpdateSink(remote_sink_.get(), rtc::VideoSinkWants()); 162 RTC_LOG(LS_INFO) << "Remote video sink set up: " << track.get(); 163 break; 164 } 165 } 166} 167 168void ObjCCallClient::Connect() { 169 webrtc::MutexLock lock(&pc_mutex_); 170 pc_->CreateOffer(rtc::make_ref_counted<CreateOfferObserver>(pc_).get(), 171 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions()); 172} 173 174ObjCCallClient::PCObserver::PCObserver(ObjCCallClient* client) : client_(client) {} 175 176void ObjCCallClient::PCObserver::OnSignalingChange( 177 webrtc::PeerConnectionInterface::SignalingState new_state) { 178 RTC_LOG(LS_INFO) << "OnSignalingChange: " << new_state; 179} 180 181void ObjCCallClient::PCObserver::OnDataChannel( 182 rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { 183 RTC_LOG(LS_INFO) << "OnDataChannel"; 184} 185 186void ObjCCallClient::PCObserver::OnRenegotiationNeeded() { 187 RTC_LOG(LS_INFO) << "OnRenegotiationNeeded"; 188} 189 190void ObjCCallClient::PCObserver::OnIceConnectionChange( 191 webrtc::PeerConnectionInterface::IceConnectionState new_state) { 192 RTC_LOG(LS_INFO) << "OnIceConnectionChange: " << new_state; 193} 194 195void ObjCCallClient::PCObserver::OnIceGatheringChange( 196 webrtc::PeerConnectionInterface::IceGatheringState new_state) { 197 RTC_LOG(LS_INFO) << "OnIceGatheringChange: " << new_state; 198} 199 200void ObjCCallClient::PCObserver::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { 201 RTC_LOG(LS_INFO) << "OnIceCandidate: " << candidate->server_url(); 202 webrtc::MutexLock lock(&client_->pc_mutex_); 203 RTC_DCHECK(client_->pc_ != nullptr); 204 client_->pc_->AddIceCandidate(candidate); 205} 206 207CreateOfferObserver::CreateOfferObserver(rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc) 208 : pc_(pc) {} 209 210void CreateOfferObserver::OnSuccess(webrtc::SessionDescriptionInterface* desc) { 211 std::string sdp; 212 desc->ToString(&sdp); 213 RTC_LOG(LS_INFO) << "Created offer: " << sdp; 214 215 // Ownership of desc was transferred to us, now we transfer it forward. 216 pc_->SetLocalDescription(absl::WrapUnique(desc), 217 rtc::make_ref_counted<SetLocalSessionDescriptionObserver>()); 218 219 // Generate a fake answer. 220 std::unique_ptr<webrtc::SessionDescriptionInterface> answer( 221 webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp)); 222 pc_->SetRemoteDescription(std::move(answer), 223 rtc::make_ref_counted<SetRemoteSessionDescriptionObserver>()); 224} 225 226void CreateOfferObserver::OnFailure(webrtc::RTCError error) { 227 RTC_LOG(LS_INFO) << "Failed to create offer: " << error.message(); 228} 229 230void SetRemoteSessionDescriptionObserver::OnSetRemoteDescriptionComplete(webrtc::RTCError error) { 231 RTC_LOG(LS_INFO) << "Set remote description: " << error.message(); 232} 233 234void SetLocalSessionDescriptionObserver::OnSetLocalDescriptionComplete(webrtc::RTCError error) { 235 RTC_LOG(LS_INFO) << "Set local description: " << error.message(); 236} 237 238} // namespace webrtc_examples 239