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