d052b8f991842777a3fcc03c43a1ed5be480a58e
[WebKit-https.git] / Source / WebCore / Modules / mediastream / libwebrtc / LibWebRTCMediaEndpoint.cpp
1 /*
2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26 #include "LibWebRTCMediaEndpoint.h"
27
28 #if USE(LIBWEBRTC)
29
30 #include "EventNames.h"
31 #include "JSDOMPromiseDeferred.h"
32 #include "JSRTCStatsReport.h"
33 #include "LibWebRTCDataChannelHandler.h"
34 #include "LibWebRTCPeerConnectionBackend.h"
35 #include "LibWebRTCProvider.h"
36 #include "LibWebRTCRtpReceiverBackend.h"
37 #include "LibWebRTCRtpSenderBackend.h"
38 #include "LibWebRTCRtpTransceiverBackend.h"
39 #include "LibWebRTCStatsCollector.h"
40 #include "LibWebRTCUtils.h"
41 #include "Logging.h"
42 #include "NotImplemented.h"
43 #include "Performance.h"
44 #include "PlatformStrategies.h"
45 #include "RTCDataChannel.h"
46 #include "RTCDataChannelEvent.h"
47 #include "RTCOfferOptions.h"
48 #include "RTCPeerConnection.h"
49 #include "RTCSessionDescription.h"
50 #include "RTCStatsReport.h"
51 #include "RealtimeIncomingAudioSource.h"
52 #include "RealtimeIncomingVideoSource.h"
53 #include "RealtimeOutgoingAudioSource.h"
54 #include "RealtimeOutgoingVideoSource.h"
55 #include "RuntimeEnabledFeatures.h"
56 #include <webrtc/rtc_base/physicalsocketserver.h>
57 #include <webrtc/p2p/base/basicpacketsocketfactory.h>
58 #include <webrtc/p2p/client/basicportallocator.h>
59 #include <webrtc/pc/peerconnectionfactory.h>
60 #include <webrtc/system_wrappers/include/field_trial.h>
61 #include <wtf/MainThread.h>
62
63 namespace WebCore {
64
65 LibWebRTCMediaEndpoint::LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend& peerConnection, LibWebRTCProvider& client)
66     : m_peerConnectionBackend(peerConnection)
67     , m_peerConnectionFactory(*client.factory())
68     , m_createSessionDescriptionObserver(*this)
69     , m_setLocalSessionDescriptionObserver(*this)
70     , m_setRemoteSessionDescriptionObserver(*this)
71     , m_statsLogTimer(*this, &LibWebRTCMediaEndpoint::gatherStatsForLogging)
72 #if !RELEASE_LOG_DISABLED
73     , m_logger(peerConnection.logger())
74     , m_logIdentifier(peerConnection.logIdentifier())
75 #endif
76 {
77     ASSERT(isMainThread());
78     ASSERT(client.factory());
79
80     if (RuntimeEnabledFeatures::sharedFeatures().webRTCH264SimulcastEnabled())
81         webrtc::field_trial::InitFieldTrialsFromString("WebRTC-H264Simulcast/Enabled/");
82 }
83
84 bool LibWebRTCMediaEndpoint::setConfiguration(LibWebRTCProvider& client, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
85 {
86     if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
87         configuration.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
88
89     if (!m_backend) {
90         if (!m_rtcSocketFactory) {
91             auto& document = downcast<Document>(*m_peerConnectionBackend.connection().scriptExecutionContext());
92             m_rtcSocketFactory = client.createSocketFactory(document.userAgent(document.url()));
93         }
94         m_backend = client.createPeerConnection(*this, m_rtcSocketFactory.get(), WTFMove(configuration));
95         return !!m_backend;
96     }
97     auto oldConfiguration = m_backend->GetConfiguration();
98     configuration.certificates = oldConfiguration.certificates;
99     return m_backend->SetConfiguration(WTFMove(configuration));
100 }
101
102 void LibWebRTCMediaEndpoint::suspend()
103 {
104     if (m_rtcSocketFactory)
105         m_rtcSocketFactory->suspend();
106 }
107
108 void LibWebRTCMediaEndpoint::resume()
109 {
110     if (m_rtcSocketFactory)
111         m_rtcSocketFactory->resume();
112 }
113
114 static inline const char* sessionDescriptionType(RTCSdpType sdpType)
115 {
116     switch (sdpType) {
117     case RTCSdpType::Offer:
118         return "offer";
119     case RTCSdpType::Pranswer:
120         return "pranswer";
121     case RTCSdpType::Answer:
122         return "answer";
123     case RTCSdpType::Rollback:
124         return "rollback";
125     }
126
127     ASSERT_NOT_REACHED();
128     return "";
129 }
130
131 static inline RTCSdpType fromSessionDescriptionType(const webrtc::SessionDescriptionInterface& description)
132 {
133     auto type = description.type();
134     if (type == webrtc::SessionDescriptionInterface::kOffer)
135         return RTCSdpType::Offer;
136     if (type == webrtc::SessionDescriptionInterface::kAnswer)
137         return RTCSdpType::Answer;
138     ASSERT(type == webrtc::SessionDescriptionInterface::kPrAnswer);
139     return RTCSdpType::Pranswer;
140 }
141
142 static inline RefPtr<RTCSessionDescription> fromSessionDescription(const webrtc::SessionDescriptionInterface* description)
143 {
144     if (!description)
145         return nullptr;
146
147     std::string sdp;
148     description->ToString(&sdp);
149
150     return RTCSessionDescription::create(fromSessionDescriptionType(*description), fromStdString(sdp));
151 }
152
153 // FIXME: We might want to create a new object only if the session actually changed for all description getters.
154 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentLocalDescription() const
155 {
156     return m_backend ? fromSessionDescription(m_backend->current_local_description()) : nullptr;
157 }
158
159 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentRemoteDescription() const
160 {
161     return m_backend ? fromSessionDescription(m_backend->current_remote_description()) : nullptr;
162 }
163
164 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingLocalDescription() const
165 {
166     return m_backend ? fromSessionDescription(m_backend->pending_local_description()) : nullptr;
167 }
168
169 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingRemoteDescription() const
170 {
171     return m_backend ? fromSessionDescription(m_backend->pending_remote_description()) : nullptr;
172 }
173
174 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::localDescription() const
175 {
176     return m_backend ? fromSessionDescription(m_backend->local_description()) : nullptr;
177 }
178
179 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::remoteDescription() const
180 {
181     return m_backend ? fromSessionDescription(m_backend->remote_description()) : nullptr;
182 }
183
184 void LibWebRTCMediaEndpoint::doSetLocalDescription(RTCSessionDescription& description)
185 {
186     ASSERT(m_backend);
187
188     webrtc::SdpParseError error;
189     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
190
191     if (!sessionDescription) {
192         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, fromStdString(error.description) });
193         return;
194     }
195
196     // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=173783. Remove this test once fixed at LibWebRTC level.
197     if (description.type() == RTCSdpType::Answer && !m_backend->pending_remote_description()) {
198         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { InvalidStateError, "Failed to set local answer sdp: no pending remote description."_s });
199         return;
200     }
201
202     m_backend->SetLocalDescription(&m_setLocalSessionDescriptionObserver, sessionDescription.release());
203 }
204
205 void LibWebRTCMediaEndpoint::doSetRemoteDescription(RTCSessionDescription& description)
206 {
207     ASSERT(m_backend);
208
209     webrtc::SdpParseError error;
210     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
211     if (!sessionDescription) {
212         m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { SyntaxError, fromStdString(error.description) });
213         return;
214     }
215     m_backend->SetRemoteDescription(&m_setRemoteSessionDescriptionObserver, sessionDescription.release());
216
217     startLoggingStats();
218 }
219
220 bool LibWebRTCMediaEndpoint::addTrack(LibWebRTCRtpSenderBackend& sender, MediaStreamTrack& track, const Vector<String>& mediaStreamIds)
221 {
222     ASSERT(m_backend);
223
224     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled()) {
225         String mediaStreamId = mediaStreamIds.isEmpty() ? createCanonicalUUIDString() : mediaStreamIds[0];
226         m_localStreams.ensure(mediaStreamId, [&] {
227             auto mediaStream = m_peerConnectionFactory.CreateLocalMediaStream(mediaStreamId.utf8().data());
228             m_backend->AddStream(mediaStream);
229             return mediaStream;
230         });
231     }
232
233     LibWebRTCRtpSenderBackend::Source source;
234     rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> rtcTrack;
235     switch (track.privateTrack().type()) {
236     case RealtimeMediaSource::Type::Audio: {
237         auto audioSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
238         rtcTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
239         source = WTFMove(audioSource);
240         break;
241     }
242     case RealtimeMediaSource::Type::Video: {
243         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
244         rtcTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
245         source = WTFMove(videoSource);
246         break;
247     }
248     case RealtimeMediaSource::Type::None:
249         ASSERT_NOT_REACHED();
250         return false;
251     }
252
253     sender.setSource(WTFMove(source));
254     if (auto rtpSender = sender.rtcSender()) {
255         rtpSender->SetTrack(rtcTrack.get());
256         return true;
257     }
258
259     std::vector<std::string> ids;
260     for (auto& id : mediaStreamIds)
261         ids.push_back(id.utf8().data());
262
263     auto newRTPSender = m_backend->AddTrack(rtcTrack.get(), WTFMove(ids));
264     if (!newRTPSender.ok())
265         return false;
266     sender.setRTCSender(newRTPSender.MoveValue());
267     return true;
268 }
269
270 void LibWebRTCMediaEndpoint::removeTrack(LibWebRTCRtpSenderBackend& sender)
271 {
272     ASSERT(m_backend);
273     m_backend->RemoveTrack(sender.rtcSender());
274     sender.clearSource();
275 }
276
277 void LibWebRTCMediaEndpoint::doCreateOffer(const RTCOfferOptions& options)
278 {
279     ASSERT(m_backend);
280
281     m_isInitiator = true;
282     webrtc::PeerConnectionInterface::RTCOfferAnswerOptions rtcOptions;
283     rtcOptions.ice_restart = options.iceRestart;
284     rtcOptions.voice_activity_detection = options.voiceActivityDetection;
285
286     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled()) {
287         if (m_peerConnectionBackend.shouldOfferAllowToReceive("audio"_s))
288             rtcOptions.offer_to_receive_audio = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
289         if (m_peerConnectionBackend.shouldOfferAllowToReceive("video"_s))
290             rtcOptions.offer_to_receive_video = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
291     }
292     m_backend->CreateOffer(&m_createSessionDescriptionObserver, rtcOptions);
293 }
294
295 void LibWebRTCMediaEndpoint::doCreateAnswer()
296 {
297     ASSERT(m_backend);
298
299     m_isInitiator = false;
300     m_backend->CreateAnswer(&m_createSessionDescriptionObserver, { });
301 }
302
303 rtc::scoped_refptr<LibWebRTCStatsCollector> LibWebRTCMediaEndpoint::createStatsCollector(Ref<DeferredPromise>&& promise)
304 {
305     return LibWebRTCStatsCollector::create([promise = WTFMove(promise), protectedThis = makeRef(*this)]() mutable -> RefPtr<RTCStatsReport> {
306         ASSERT(isMainThread());
307         if (protectedThis->isStopped())
308             return nullptr;
309
310         auto report = RTCStatsReport::create();
311
312         promise->resolve<IDLInterface<RTCStatsReport>>(report.copyRef());
313
314         // The promise resolution might fail in which case no backing map will be created.
315         if (!report->backingMap())
316             return nullptr;
317         return report;
318     });
319 }
320
321 void LibWebRTCMediaEndpoint::getStats(Ref<DeferredPromise>&& promise)
322 {
323     if (m_backend)
324         m_backend->GetStats(createStatsCollector(WTFMove(promise)));
325 }
326
327 void LibWebRTCMediaEndpoint::getStats(webrtc::RtpReceiverInterface& receiver, Ref<DeferredPromise>&& promise)
328 {
329     if (m_backend)
330         m_backend->GetStats(rtc::scoped_refptr<webrtc::RtpReceiverInterface>(&receiver), createStatsCollector(WTFMove(promise)));
331 }
332
333 void LibWebRTCMediaEndpoint::getStats(webrtc::RtpSenderInterface& sender, Ref<DeferredPromise>&& promise)
334 {
335     if (m_backend)
336         m_backend->GetStats(rtc::scoped_refptr<webrtc::RtpSenderInterface>(&sender), createStatsCollector(WTFMove(promise)));
337 }
338
339 static RTCSignalingState signalingState(webrtc::PeerConnectionInterface::SignalingState state)
340 {
341     switch (state) {
342     case webrtc::PeerConnectionInterface::kStable:
343         return RTCSignalingState::Stable;
344     case webrtc::PeerConnectionInterface::kHaveLocalOffer:
345         return RTCSignalingState::HaveLocalOffer;
346     case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
347         return RTCSignalingState::HaveLocalPranswer;
348     case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
349         return RTCSignalingState::HaveRemoteOffer;
350     case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
351         return RTCSignalingState::HaveRemotePranswer;
352     case webrtc::PeerConnectionInterface::kClosed:
353         return RTCSignalingState::Stable;
354     }
355
356     ASSERT_NOT_REACHED();
357     return RTCSignalingState::Stable;
358 }
359
360 void LibWebRTCMediaEndpoint::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState rtcState)
361 {
362     auto state = signalingState(rtcState);
363     callOnMainThread([protectedThis = makeRef(*this), state] {
364         if (protectedThis->isStopped())
365             return;
366         protectedThis->m_peerConnectionBackend.updateSignalingState(state);
367     });
368 }
369
370 MediaStream& LibWebRTCMediaEndpoint::mediaStreamFromRTCStream(webrtc::MediaStreamInterface& rtcStream)
371 {
372     auto label = fromStdString(rtcStream.id());
373     auto mediaStream = m_remoteStreamsById.ensure(label, [label, this]() mutable {
374         auto& document = downcast<Document>(*m_peerConnectionBackend.connection().scriptExecutionContext());
375         return MediaStream::create(document, MediaStreamPrivate::create(document.logger(), { }, WTFMove(label)));
376     });
377     return *mediaStream.iterator->value;
378 }
379
380 void LibWebRTCMediaEndpoint::addRemoteStream(webrtc::MediaStreamInterface&)
381 {
382 }
383
384 void LibWebRTCMediaEndpoint::addRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& rtcReceiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& rtcStreams)
385 {
386     ASSERT(rtcReceiver);
387     RefPtr<RTCRtpReceiver> receiver;
388     RefPtr<RealtimeMediaSource> remoteSource;
389
390     auto* rtcTrack = rtcReceiver->track().get();
391
392     switch (rtcReceiver->media_type()) {
393     case cricket::MEDIA_TYPE_DATA:
394         return;
395     case cricket::MEDIA_TYPE_AUDIO: {
396         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack);
397         auto audioReceiver = m_peerConnectionBackend.audioReceiver(fromStdString(rtcTrack->id()));
398
399         receiver = WTFMove(audioReceiver.receiver);
400         audioReceiver.source->setSourceTrack(WTFMove(audioTrack));
401         break;
402     }
403     case cricket::MEDIA_TYPE_VIDEO: {
404         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack);
405         auto videoReceiver = m_peerConnectionBackend.videoReceiver(fromStdString(rtcTrack->id()));
406
407         receiver = WTFMove(videoReceiver.receiver);
408         videoReceiver.source->setSourceTrack(WTFMove(videoTrack));
409         break;
410     }
411     }
412
413     receiver->setBackend(makeUnique<LibWebRTCRtpReceiverBackend>(WTFMove(rtcReceiver)));
414     auto& track = receiver->track();
415     addPendingTrackEvent(receiver.releaseNonNull(), track, rtcStreams, nullptr);
416 }
417
418 void LibWebRTCMediaEndpoint::addPendingTrackEvent(Ref<RTCRtpReceiver>&& receiver, MediaStreamTrack& track, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& rtcStreams, RefPtr<RTCRtpTransceiver>&& transceiver)
419 {
420     Vector<RefPtr<MediaStream>> streams;
421     for (auto& rtcStream : rtcStreams) {
422         auto& mediaStream = mediaStreamFromRTCStream(*rtcStream.get());
423         streams.append(&mediaStream);
424         mediaStream.addTrackFromPlatform(track);
425     }
426     auto streamIds = WTF::map(streams, [](auto& stream) -> String {
427         return stream->id();
428     });
429     m_remoteStreamsFromRemoteTrack.add(&track, WTFMove(streamIds));
430
431     m_peerConnectionBackend.addPendingTrackEvent({ WTFMove(receiver), makeRef(track), WTFMove(streams), WTFMove(transceiver) });
432 }
433
434 static inline void setExistingReceiverSourceTrack(RealtimeMediaSource& existingSource, webrtc::RtpReceiverInterface& rtcReceiver)
435 {
436     switch (rtcReceiver.media_type()) {
437     case cricket::MEDIA_TYPE_AUDIO: {
438         ASSERT(existingSource.type() == RealtimeMediaSource::Type::Audio);
439         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcReceiver.track().get());
440         downcast<RealtimeIncomingAudioSource>(existingSource).setSourceTrack(WTFMove(audioTrack));
441         return;
442     }
443     case cricket::MEDIA_TYPE_VIDEO: {
444         ASSERT(existingSource.type() == RealtimeMediaSource::Type::Video);
445         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcReceiver.track().get());
446         downcast<RealtimeIncomingVideoSource>(existingSource).setSourceTrack(WTFMove(videoTrack));
447         return;
448     }
449     case cricket::MEDIA_TYPE_DATA:
450         ASSERT_NOT_REACHED();
451         return;
452     }
453 }
454
455 RefPtr<RealtimeMediaSource> LibWebRTCMediaEndpoint::sourceFromNewReceiver(webrtc::RtpReceiverInterface& rtcReceiver)
456 {
457     auto rtcTrack = rtcReceiver.track();
458     switch (rtcReceiver.media_type()) {
459     case cricket::MEDIA_TYPE_DATA:
460         return nullptr;
461     case cricket::MEDIA_TYPE_AUDIO: {
462         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack.get());
463         return RealtimeIncomingAudioSource::create(WTFMove(audioTrack), fromStdString(rtcTrack->id()));
464     }
465     case cricket::MEDIA_TYPE_VIDEO: {
466         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack.get());
467         return RealtimeIncomingVideoSource::create(WTFMove(videoTrack), fromStdString(rtcTrack->id()));
468     }
469     }
470
471     RELEASE_ASSERT_NOT_REACHED();
472 }
473
474 void LibWebRTCMediaEndpoint::collectTransceivers()
475 {
476     if (!m_backend)
477         return;
478
479     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
480         return;
481
482     for (auto& rtcTransceiver : m_backend->GetTransceivers()) {
483         auto* existingTransceiver = m_peerConnectionBackend.existingTransceiver([&](auto& transceiverBackend) {
484             return rtcTransceiver.get() == transceiverBackend.rtcTransceiver();
485         });
486         if (existingTransceiver)
487             continue;
488
489         auto rtcReceiver = rtcTransceiver->receiver();
490         auto source = sourceFromNewReceiver(*rtcReceiver);
491         if (!source)
492             return;
493
494         m_peerConnectionBackend.newRemoteTransceiver(makeUnique<LibWebRTCRtpTransceiverBackend>(WTFMove(rtcTransceiver)), source.releaseNonNull());
495     }
496 }
497
498 void LibWebRTCMediaEndpoint::newTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>&& rtcTransceiver)
499 {
500     auto* transceiver = m_peerConnectionBackend.existingTransceiver([&](auto& transceiverBackend) {
501         return rtcTransceiver.get() == transceiverBackend.rtcTransceiver();
502     });
503     if (transceiver) {
504         auto rtcReceiver = rtcTransceiver->receiver();
505         setExistingReceiverSourceTrack(transceiver->receiver().track().source(), *rtcReceiver);
506         addPendingTrackEvent(makeRef(transceiver->receiver()), transceiver->receiver().track(), rtcReceiver->streams(), makeRef(*transceiver));
507         return;
508     }
509
510     auto rtcReceiver = rtcTransceiver->receiver();
511     auto source = sourceFromNewReceiver(*rtcReceiver);
512     if (!source)
513         return;
514
515     auto& newTransceiver = m_peerConnectionBackend.newRemoteTransceiver(makeUnique<LibWebRTCRtpTransceiverBackend>(WTFMove(rtcTransceiver)), source.releaseNonNull());
516
517     addPendingTrackEvent(makeRef(newTransceiver.receiver()), newTransceiver.receiver().track(), rtcReceiver->streams(), makeRef(newTransceiver));
518 }
519
520 void LibWebRTCMediaEndpoint::removeRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& receiver)
521 {
522     // FIXME: Support plan B code path.
523     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
524         return;
525
526     auto* transceiver = m_peerConnectionBackend.existingTransceiver([&receiver](auto& transceiverBackend) {
527         auto* rtcTransceiver = transceiverBackend.rtcTransceiver();
528         return rtcTransceiver && receiver.get() == rtcTransceiver->receiver().get();
529     });
530     if (!transceiver)
531         return;
532
533     auto& track = transceiver->receiver().track();
534
535     for (auto& id : m_remoteStreamsFromRemoteTrack.get(&track)) {
536         if (auto stream = m_remoteStreamsById.get(id))
537             stream->privateStream().removeTrack(track.privateTrack(), MediaStreamPrivate::NotifyClientOption::Notify);
538     }
539
540     track.source().setMuted(true);
541 }
542
543 template<typename T>
544 Optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::createTransceiverBackends(T&& trackOrKind, const RTCRtpTransceiverInit& init, LibWebRTCRtpSenderBackend::Source&& source)
545 {
546     auto result = m_backend->AddTransceiver(WTFMove(trackOrKind), fromRtpTransceiverInit(init));
547     if (!result.ok())
548         return WTF::nullopt;
549
550     auto transceiver = makeUnique<LibWebRTCRtpTransceiverBackend>(result.MoveValue());
551     return LibWebRTCMediaEndpoint::Backends { transceiver->createSenderBackend(m_peerConnectionBackend, WTFMove(source)), transceiver->createReceiverBackend(), WTFMove(transceiver) };
552 }
553
554 Optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::addTransceiver(const String& trackKind, const RTCRtpTransceiverInit& init)
555 {
556     auto type = trackKind == "audio" ? cricket::MediaType::MEDIA_TYPE_AUDIO : cricket::MediaType::MEDIA_TYPE_VIDEO;
557     return createTransceiverBackends(type, init, nullptr);
558 }
559
560 std::pair<LibWebRTCRtpSenderBackend::Source, rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>> LibWebRTCMediaEndpoint::createSourceAndRTCTrack(MediaStreamTrack& track)
561 {
562     LibWebRTCRtpSenderBackend::Source source;
563     rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> rtcTrack;
564     switch (track.privateTrack().type()) {
565     case RealtimeMediaSource::Type::None:
566         ASSERT_NOT_REACHED();
567         break;
568     case RealtimeMediaSource::Type::Audio: {
569         auto audioSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
570         rtcTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
571         source = WTFMove(audioSource);
572         break;
573     }
574     case RealtimeMediaSource::Type::Video: {
575         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
576         rtcTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
577         source = WTFMove(videoSource);
578         break;
579     }
580     }
581     return std::make_pair(WTFMove(source), WTFMove(rtcTrack));
582 }
583
584 Optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::addTransceiver(MediaStreamTrack& track, const RTCRtpTransceiverInit& init)
585 {
586     auto sourceAndTrack = createSourceAndRTCTrack(track);
587     return createTransceiverBackends(WTFMove(sourceAndTrack.second), init, WTFMove(sourceAndTrack.first));
588 }
589
590 void LibWebRTCMediaEndpoint::setSenderSourceFromTrack(LibWebRTCRtpSenderBackend& sender, MediaStreamTrack& track)
591 {
592     auto sourceAndTrack = createSourceAndRTCTrack(track);
593     sender.setSource(WTFMove(sourceAndTrack.first));
594     sender.rtcSender()->SetTrack(WTFMove(sourceAndTrack.second));
595 }
596
597 std::unique_ptr<LibWebRTCRtpTransceiverBackend> LibWebRTCMediaEndpoint::transceiverBackendFromSender(LibWebRTCRtpSenderBackend& backend)
598 {
599     for (auto& transceiver : m_backend->GetTransceivers()) {
600         if (transceiver->sender().get() == backend.rtcSender())
601             return makeUnique<LibWebRTCRtpTransceiverBackend>(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>(transceiver));
602     }
603     return nullptr;
604 }
605
606
607 void LibWebRTCMediaEndpoint::removeRemoteStream(webrtc::MediaStreamInterface& rtcStream)
608 {
609     bool removed = m_remoteStreamsById.remove(fromStdString(rtcStream.id()));
610     ASSERT_UNUSED(removed, removed);
611 }
612
613 void LibWebRTCMediaEndpoint::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
614 {
615     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
616         if (protectedThis->isStopped())
617             return;
618         ASSERT(stream);
619         protectedThis->addRemoteStream(*stream.get());
620     });
621 }
622
623 void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
624 {
625     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
626         if (protectedThis->isStopped())
627             return;
628         ASSERT(stream);
629         protectedThis->removeRemoteStream(*stream.get());
630     });
631 }
632
633 void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams)
634 {
635     if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
636         return;
637
638     callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver), streams]() mutable {
639         if (protectedThis->isStopped())
640             return;
641         protectedThis->addRemoteTrack(WTFMove(receiver), streams);
642     });
643 }
644
645 void LibWebRTCMediaEndpoint::OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver)
646 {
647     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
648         return;
649
650     callOnMainThread([protectedThis = makeRef(*this), transceiver = WTFMove(transceiver)]() mutable {
651         if (protectedThis->isStopped())
652             return;
653         protectedThis->newTransceiver(WTFMove(transceiver));
654     });
655 }
656
657 void LibWebRTCMediaEndpoint::OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver)
658 {
659     callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver)]() mutable {
660         if (protectedThis->isStopped())
661             return;
662         protectedThis->removeRemoteTrack(WTFMove(receiver));
663     });
664 }
665
666 std::unique_ptr<RTCDataChannelHandler> LibWebRTCMediaEndpoint::createDataChannel(const String& label, const RTCDataChannelInit& options)
667 {
668     auto init = LibWebRTCDataChannelHandler::fromRTCDataChannelInit(options);
669     auto channel = m_backend->CreateDataChannel(label.utf8().data(), &init);
670     return channel ? makeUnique<LibWebRTCDataChannelHandler>(WTFMove(channel)) : nullptr;
671 }
672
673 void LibWebRTCMediaEndpoint::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel)
674 {
675     callOnMainThread([protectedThis = makeRef(*this), dataChannel = WTFMove(dataChannel)]() mutable {
676         if (protectedThis->isStopped())
677             return;
678         auto& connection = protectedThis->m_peerConnectionBackend.connection();
679         connection.dispatchEventWhenFeasible(LibWebRTCDataChannelHandler::channelEvent(*connection.document(), WTFMove(dataChannel)));
680     });
681 }
682
683 void LibWebRTCMediaEndpoint::stop()
684 {
685     if (!m_backend)
686         return;
687
688     stopLoggingStats();
689
690     m_backend->Close();
691     m_backend = nullptr;
692     m_remoteStreamsById.clear();
693     m_remoteStreamsFromRemoteTrack.clear();
694 }
695
696 void LibWebRTCMediaEndpoint::OnRenegotiationNeeded()
697 {
698     callOnMainThread([protectedThis = makeRef(*this)] {
699         if (protectedThis->isStopped())
700             return;
701         protectedThis->m_peerConnectionBackend.markAsNeedingNegotiation();
702     });
703 }
704
705 static inline RTCIceConnectionState toRTCIceConnectionState(webrtc::PeerConnectionInterface::IceConnectionState state)
706 {
707     switch (state) {
708     case webrtc::PeerConnectionInterface::kIceConnectionNew:
709         return RTCIceConnectionState::New;
710     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
711         return RTCIceConnectionState::Checking;
712     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
713         return RTCIceConnectionState::Connected;
714     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
715         return RTCIceConnectionState::Completed;
716     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
717         return RTCIceConnectionState::Failed;
718     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
719         return RTCIceConnectionState::Disconnected;
720     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
721         return RTCIceConnectionState::Closed;
722     case webrtc::PeerConnectionInterface::kIceConnectionMax:
723         break;
724     }
725
726     ASSERT_NOT_REACHED();
727     return RTCIceConnectionState::New;
728 }
729
730 void LibWebRTCMediaEndpoint::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state)
731 {
732     auto connectionState = toRTCIceConnectionState(state);
733     callOnMainThread([protectedThis = makeRef(*this), connectionState] {
734         if (protectedThis->isStopped())
735             return;
736         if (protectedThis->m_peerConnectionBackend.connection().iceConnectionState() != connectionState)
737             protectedThis->m_peerConnectionBackend.connection().updateIceConnectionState(connectionState);
738     });
739 }
740
741 void LibWebRTCMediaEndpoint::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState state)
742 {
743     callOnMainThread([protectedThis = makeRef(*this), state] {
744         if (protectedThis->isStopped())
745             return;
746         if (state == webrtc::PeerConnectionInterface::kIceGatheringComplete)
747             protectedThis->m_peerConnectionBackend.doneGatheringCandidates();
748         else if (state == webrtc::PeerConnectionInterface::kIceGatheringGathering)
749             protectedThis->m_peerConnectionBackend.connection().updateIceGatheringState(RTCIceGatheringState::Gathering);
750     });
751 }
752
753 void LibWebRTCMediaEndpoint::OnIceCandidate(const webrtc::IceCandidateInterface *rtcCandidate)
754 {
755     ASSERT(rtcCandidate);
756
757     std::string sdp;
758     rtcCandidate->ToString(&sdp);
759
760     auto sdpMLineIndex = safeCast<unsigned short>(rtcCandidate->sdp_mline_index());
761
762     callOnMainThread([protectedThis = makeRef(*this), mid = fromStdString(rtcCandidate->sdp_mid()), sdp = fromStdString(sdp), sdpMLineIndex, url = fromStdString(rtcCandidate->server_url())]() mutable {
763         if (protectedThis->isStopped())
764             return;
765         protectedThis->m_peerConnectionBackend.newICECandidate(WTFMove(sdp), WTFMove(mid), sdpMLineIndex, WTFMove(url));
766     });
767 }
768
769 void LibWebRTCMediaEndpoint::OnIceCandidatesRemoved(const std::vector<cricket::Candidate>&)
770 {
771     ASSERT_NOT_REACHED();
772 }
773
774 void LibWebRTCMediaEndpoint::createSessionDescriptionSucceeded(std::unique_ptr<webrtc::SessionDescriptionInterface>&& description)
775 {
776     std::string sdp;
777     description->ToString(&sdp);
778
779     callOnMainThread([protectedThis = makeRef(*this), sdp = fromStdString(sdp)]() mutable {
780         if (protectedThis->isStopped())
781             return;
782         if (protectedThis->m_isInitiator)
783             protectedThis->m_peerConnectionBackend.createOfferSucceeded(WTFMove(sdp));
784         else
785             protectedThis->m_peerConnectionBackend.createAnswerSucceeded(WTFMove(sdp));
786     });
787 }
788
789 void LibWebRTCMediaEndpoint::createSessionDescriptionFailed(ExceptionCode errorCode, const char* errorMessage)
790 {
791     callOnMainThread([protectedThis = makeRef(*this), errorCode, errorMessage = String(errorMessage)] () mutable {
792         if (protectedThis->isStopped())
793             return;
794         if (protectedThis->m_isInitiator)
795             protectedThis->m_peerConnectionBackend.createOfferFailed(Exception { errorCode, WTFMove(errorMessage) });
796         else
797             protectedThis->m_peerConnectionBackend.createAnswerFailed(Exception { errorCode, WTFMove(errorMessage) });
798     });
799 }
800
801 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionSucceeded()
802 {
803     callOnMainThread([protectedThis = makeRef(*this)] {
804         if (protectedThis->isStopped())
805             return;
806         protectedThis->m_peerConnectionBackend.setLocalDescriptionSucceeded();
807     });
808 }
809
810 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionFailed(ExceptionCode errorCode, const char* errorMessage)
811 {
812     callOnMainThread([protectedThis = makeRef(*this), errorCode, errorMessage = String(errorMessage)] () mutable {
813         if (protectedThis->isStopped())
814             return;
815         protectedThis->m_peerConnectionBackend.setLocalDescriptionFailed(Exception { errorCode, WTFMove(errorMessage) });
816     });
817 }
818
819 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionSucceeded()
820 {
821     callOnMainThread([protectedThis = makeRef(*this)] {
822         if (protectedThis->isStopped())
823             return;
824         protectedThis->m_peerConnectionBackend.setRemoteDescriptionSucceeded();
825     });
826 }
827
828 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionFailed(ExceptionCode errorCode, const char* errorMessage)
829 {
830     callOnMainThread([protectedThis = makeRef(*this), errorCode, errorMessage = String(errorMessage)] () mutable {
831         if (protectedThis->isStopped())
832             return;
833         protectedThis->m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { errorCode, WTFMove(errorMessage) });
834     });
835 }
836
837 void LibWebRTCMediaEndpoint::gatherStatsForLogging()
838 {
839     m_backend->GetStats(this);
840 }
841
842 class RTCStatsLogger {
843 public:
844     explicit RTCStatsLogger(const webrtc::RTCStats& stats)
845         : m_stats(stats)
846     {
847     }
848
849     String toJSONString() const { return String(m_stats.ToJson().c_str()); }
850
851 private:
852     const webrtc::RTCStats& m_stats;
853 };
854
855 void LibWebRTCMediaEndpoint::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report)
856 {
857 #if !RELEASE_LOG_DISABLED
858     int64_t timestamp = report->timestamp_us();
859     if (!m_statsFirstDeliveredTimestamp)
860         m_statsFirstDeliveredTimestamp = timestamp;
861
862     callOnMainThread([protectedThis = makeRef(*this), this, timestamp, report] {
863         if (m_backend && m_statsLogTimer.repeatInterval() != statsLogInterval(timestamp)) {
864             m_statsLogTimer.stop();
865             m_statsLogTimer.startRepeating(statsLogInterval(timestamp));
866         }
867
868         for (auto iterator = report->begin(); iterator != report->end(); ++iterator) {
869             if (logger().willLog(logChannel(), WTFLogLevel::Debug)) {
870                 // Stats are very verbose, let's only display them in inspector console in verbose mode.
871                 logger().debug(LogWebRTC,
872                     Logger::LogSiteIdentifier("LibWebRTCMediaEndpoint", "OnStatsDelivered", logIdentifier()),
873                     RTCStatsLogger { *iterator });
874             } else {
875                 logger().logAlways(LogWebRTCStats,
876                     Logger::LogSiteIdentifier("LibWebRTCMediaEndpoint", "OnStatsDelivered", logIdentifier()),
877                     RTCStatsLogger { *iterator });
878             }
879         }
880     });
881 #else
882     UNUSED_PARAM(report);
883 #endif
884 }
885
886 void LibWebRTCMediaEndpoint::startLoggingStats()
887 {
888 #if !RELEASE_LOG_DISABLED
889     if (m_statsLogTimer.isActive())
890         m_statsLogTimer.stop();
891     m_statsLogTimer.startRepeating(statsLogInterval(0));
892 #endif
893 }
894
895 void LibWebRTCMediaEndpoint::stopLoggingStats()
896 {
897     m_statsLogTimer.stop();
898 }
899
900 #if !RELEASE_LOG_DISABLED
901 WTFLogChannel& LibWebRTCMediaEndpoint::logChannel() const
902 {
903     return LogWebRTC;
904 }
905
906 Seconds LibWebRTCMediaEndpoint::statsLogInterval(int64_t reportTimestamp) const
907 {
908     if (logger().willLog(logChannel(), WTFLogLevel::Info))
909         return 2_s;
910
911     if (reportTimestamp - m_statsFirstDeliveredTimestamp > 15000000)
912         return 10_s;
913
914     return 4_s;
915 }
916 #endif
917
918 } // namespace WebCore
919
920 namespace WTF {
921
922 template<typename Type>
923 struct LogArgument;
924
925 template <>
926 struct LogArgument<WebCore::RTCStatsLogger> {
927     static String toString(const WebCore::RTCStatsLogger& logger)
928     {
929         return String(logger.toJSONString());
930     }
931 };
932
933 }; // namespace WTF
934
935
936 #endif // USE(LIBWEBRTC)