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