fe70a1345e6a79f0312dea2784d547cbbeebd808
[WebKit-https.git] / Source / WebCore / Modules / mediastream / libwebrtc / LibWebRTCPeerConnectionBackend.cpp
1 /*
2  * Copyright (C) 2017-2018 Apple Inc.
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 "LibWebRTCPeerConnectionBackend.h"
27
28 #if USE(LIBWEBRTC)
29
30 #include "Document.h"
31 #include "IceCandidate.h"
32 #include "LibWebRTCDataChannelHandler.h"
33 #include "LibWebRTCMediaEndpoint.h"
34 #include "LibWebRTCRtpReceiverBackend.h"
35 #include "LibWebRTCRtpSenderBackend.h"
36 #include "LibWebRTCRtpTransceiverBackend.h"
37 #include "MediaEndpointConfiguration.h"
38 #include "Page.h"
39 #include "RTCIceCandidate.h"
40 #include "RTCPeerConnection.h"
41 #include "RTCRtpCapabilities.h"
42 #include "RTCRtpReceiver.h"
43 #include "RTCSessionDescription.h"
44 #include "RealtimeIncomingAudioSource.h"
45 #include "RealtimeIncomingVideoSource.h"
46 #include "RealtimeOutgoingAudioSource.h"
47 #include "RealtimeOutgoingVideoSource.h"
48 #include "RuntimeEnabledFeatures.h"
49 #include "Settings.h"
50
51 namespace WebCore {
52
53 static std::unique_ptr<PeerConnectionBackend> createLibWebRTCPeerConnectionBackend(RTCPeerConnection& peerConnection)
54 {
55     if (!LibWebRTCProvider::webRTCAvailable())
56         return nullptr;
57
58     auto* page = downcast<Document>(*peerConnection.scriptExecutionContext()).page();
59     if (!page)
60         return nullptr;
61
62     page->libWebRTCProvider().setEnableWebRTCEncryption(page->settings().webRTCEncryptionEnabled());
63
64     return makeUnique<LibWebRTCPeerConnectionBackend>(peerConnection, page->libWebRTCProvider());
65 }
66
67 CreatePeerConnectionBackend PeerConnectionBackend::create = createLibWebRTCPeerConnectionBackend;
68
69 Optional<RTCRtpCapabilities> PeerConnectionBackend::receiverCapabilities(ScriptExecutionContext& context, const String& kind)
70 {
71     auto* page = downcast<Document>(context).page();
72     if (!page)
73         return { };
74     return page->libWebRTCProvider().receiverCapabilities(kind);
75 }
76
77 Optional<RTCRtpCapabilities> PeerConnectionBackend::senderCapabilities(ScriptExecutionContext& context, const String& kind)
78 {
79     auto* page = downcast<Document>(context).page();
80     if (!page)
81         return { };
82     return page->libWebRTCProvider().senderCapabilities(kind);
83 }
84
85 LibWebRTCPeerConnectionBackend::LibWebRTCPeerConnectionBackend(RTCPeerConnection& peerConnection, LibWebRTCProvider& provider)
86     : PeerConnectionBackend(peerConnection)
87     , m_endpoint(LibWebRTCMediaEndpoint::create(*this, provider))
88 {
89 }
90
91 LibWebRTCPeerConnectionBackend::~LibWebRTCPeerConnectionBackend() = default;
92
93 void LibWebRTCPeerConnectionBackend::suspend()
94 {
95     m_endpoint->suspend();
96 }
97
98 void LibWebRTCPeerConnectionBackend::resume()
99 {
100     m_endpoint->resume();
101 }
102
103 static inline webrtc::PeerConnectionInterface::BundlePolicy bundlePolicyfromConfiguration(const MediaEndpointConfiguration& configuration)
104 {
105     switch (configuration.bundlePolicy) {
106     case RTCBundlePolicy::MaxCompat:
107         return webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
108     case RTCBundlePolicy::MaxBundle:
109         return webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
110     case RTCBundlePolicy::Balanced:
111         return webrtc::PeerConnectionInterface::kBundlePolicyBalanced;
112     }
113
114     ASSERT_NOT_REACHED();
115     return webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
116 }
117
118 static inline webrtc::PeerConnectionInterface::RtcpMuxPolicy rtcpMuxPolicyfromConfiguration(const MediaEndpointConfiguration& configuration)
119 {
120     switch (configuration.rtcpMuxPolicy) {
121     case RTCPMuxPolicy::Negotiate:
122         return webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
123     case RTCPMuxPolicy::Require:
124         return webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
125     }
126
127     ASSERT_NOT_REACHED();
128     return webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
129 }
130
131 static inline webrtc::PeerConnectionInterface::IceTransportsType iceTransportPolicyfromConfiguration(const MediaEndpointConfiguration& configuration)
132 {
133     switch (configuration.iceTransportPolicy) {
134     case RTCIceTransportPolicy::Relay:
135         return webrtc::PeerConnectionInterface::kRelay;
136     case RTCIceTransportPolicy::All:
137         return webrtc::PeerConnectionInterface::kAll;
138     }
139
140     ASSERT_NOT_REACHED();
141     return webrtc::PeerConnectionInterface::kNone;
142 }
143
144 static webrtc::PeerConnectionInterface::RTCConfiguration configurationFromMediaEndpointConfiguration(MediaEndpointConfiguration&& configuration)
145 {
146     webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration;
147
148     rtcConfiguration.type = iceTransportPolicyfromConfiguration(configuration);
149     rtcConfiguration.bundle_policy = bundlePolicyfromConfiguration(configuration);
150     rtcConfiguration.rtcp_mux_policy = rtcpMuxPolicyfromConfiguration(configuration);
151
152     for (auto& server : configuration.iceServers) {
153         webrtc::PeerConnectionInterface::IceServer iceServer;
154         iceServer.username = server.username.utf8().data();
155         iceServer.password = server.credential.utf8().data();
156         for (auto& url : server.urls)
157             iceServer.urls.push_back({ url.string().utf8().data() });
158         rtcConfiguration.servers.push_back(WTFMove(iceServer));
159     }
160
161     rtcConfiguration.set_cpu_adaptation(false);
162     // FIXME: Activate ice candidate pool size once it no longer bothers test bots.
163     // rtcConfiguration.ice_candidate_pool_size = configuration.iceCandidatePoolSize;
164
165     for (auto& pem : configuration.certificates) {
166         rtcConfiguration.certificates.push_back(rtc::RTCCertificate::FromPEM(rtc::RTCCertificatePEM {
167             pem.privateKey.utf8().data(), pem.certificate.utf8().data()
168         }));
169     }
170
171     return rtcConfiguration;
172 }
173
174 bool LibWebRTCPeerConnectionBackend::setConfiguration(MediaEndpointConfiguration&& configuration)
175 {
176     auto* page = downcast<Document>(*m_peerConnection.scriptExecutionContext()).page();
177     if (!page)
178         return false;
179
180     return m_endpoint->setConfiguration(page->libWebRTCProvider(), configurationFromMediaEndpointConfiguration(WTFMove(configuration)));
181 }
182
183 void LibWebRTCPeerConnectionBackend::getStats(Ref<DeferredPromise>&& promise)
184 {
185     m_endpoint->getStats(WTFMove(promise));
186 }
187
188 static inline LibWebRTCRtpSenderBackend& backendFromRTPSender(RTCRtpSender& sender)
189 {
190     ASSERT(!sender.isStopped());
191     return static_cast<LibWebRTCRtpSenderBackend&>(*sender.backend());
192 }
193
194 void LibWebRTCPeerConnectionBackend::getStats(RTCRtpSender& sender, Ref<DeferredPromise>&& promise)
195 {
196     webrtc::RtpSenderInterface* rtcSender = sender.backend() ? backendFromRTPSender(sender).rtcSender() : nullptr;
197
198     if (!rtcSender) {
199         m_endpoint->getStats(WTFMove(promise));
200         return;
201     }
202     m_endpoint->getStats(*rtcSender, WTFMove(promise));
203 }
204
205 void LibWebRTCPeerConnectionBackend::getStats(RTCRtpReceiver& receiver, Ref<DeferredPromise>&& promise)
206 {
207     webrtc::RtpReceiverInterface* rtcReceiver = receiver.backend() ? static_cast<LibWebRTCRtpReceiverBackend*>(receiver.backend())->rtcReceiver() : nullptr;
208
209     if (!rtcReceiver) {
210         m_endpoint->getStats(WTFMove(promise));
211         return;
212     }
213     m_endpoint->getStats(*rtcReceiver, WTFMove(promise));
214 }
215
216 void LibWebRTCPeerConnectionBackend::doSetLocalDescription(RTCSessionDescription& description)
217 {
218     m_endpoint->doSetLocalDescription(description);
219     if (!m_isLocalDescriptionSet) {
220         if (m_isRemoteDescriptionSet) {
221             for (auto& candidate : m_pendingCandidates)
222                 m_endpoint->addIceCandidate(*candidate);
223             m_pendingCandidates.clear();
224         }
225         m_isLocalDescriptionSet = true;
226     }
227 }
228
229 void LibWebRTCPeerConnectionBackend::doSetRemoteDescription(RTCSessionDescription& description)
230 {
231     m_endpoint->doSetRemoteDescription(description);
232     if (!m_isRemoteDescriptionSet) {
233         if (m_isLocalDescriptionSet) {
234             for (auto& candidate : m_pendingCandidates)
235                 m_endpoint->addIceCandidate(*candidate);
236         }
237         m_isRemoteDescriptionSet = true;
238     }
239 }
240
241 void LibWebRTCPeerConnectionBackend::doCreateOffer(RTCOfferOptions&& options)
242 {
243     m_endpoint->doCreateOffer(options);
244 }
245
246 void LibWebRTCPeerConnectionBackend::doCreateAnswer(RTCAnswerOptions&&)
247 {
248     if (!m_isRemoteDescriptionSet) {
249         createAnswerFailed(Exception { InvalidStateError, "No remote description set" });
250         return;
251     }
252     m_endpoint->doCreateAnswer();
253 }
254
255 void LibWebRTCPeerConnectionBackend::doStop()
256 {
257     m_endpoint->stop();
258     m_pendingReceivers.clear();
259 }
260
261 void LibWebRTCPeerConnectionBackend::doAddIceCandidate(RTCIceCandidate& candidate)
262 {
263     webrtc::SdpParseError error;
264     int sdpMLineIndex = candidate.sdpMLineIndex() ? candidate.sdpMLineIndex().value() : 0;
265     std::unique_ptr<webrtc::IceCandidateInterface> rtcCandidate(webrtc::CreateIceCandidate(candidate.sdpMid().utf8().data(), sdpMLineIndex, candidate.candidate().utf8().data(), &error));
266
267     if (!rtcCandidate) {
268         addIceCandidateFailed(Exception { OperationError, String::fromUTF8(error.description.data(), error.description.length()) });
269         return;
270     }
271
272     // libwebrtc does not like that ice candidates are set before the description.
273     if (!m_isLocalDescriptionSet || !m_isRemoteDescriptionSet)
274         m_pendingCandidates.append(WTFMove(rtcCandidate));
275     else if (!m_endpoint->addIceCandidate(*rtcCandidate.get())) {
276         ASSERT_NOT_REACHED();
277         addIceCandidateFailed(Exception { OperationError, "Failed to apply the received candidate"_s });
278         return;
279     }
280     addIceCandidateSucceeded();
281 }
282
283 Ref<RTCRtpReceiver> LibWebRTCPeerConnectionBackend::createReceiverForSource(Ref<RealtimeMediaSource>&& source, std::unique_ptr<RTCRtpReceiverBackend>&& backend)
284 {
285     auto& document = downcast<Document>(*m_peerConnection.scriptExecutionContext());
286     auto trackID = source->persistentID();
287     auto remoteTrackPrivate = MediaStreamTrackPrivate::create(document.logger(), WTFMove(source), WTFMove(trackID));
288     auto remoteTrack = MediaStreamTrack::create(document, WTFMove(remoteTrackPrivate));
289
290     return RTCRtpReceiver::create(*this, WTFMove(remoteTrack), WTFMove(backend));
291 }
292
293 static inline Ref<RealtimeMediaSource> createEmptySource(const String& trackKind, String&& trackId)
294 {
295     // FIXME: trackKind should be an enumeration
296     if (trackKind == "audio")
297         return RealtimeIncomingAudioSource::create(nullptr, WTFMove(trackId));
298     ASSERT(trackKind == "video");
299     return RealtimeIncomingVideoSource::create(nullptr, WTFMove(trackId));
300 }
301
302 Ref<RTCRtpReceiver> LibWebRTCPeerConnectionBackend::createReceiver(const String& trackKind, const String& trackId)
303 {
304     auto receiver = createReceiverForSource(createEmptySource(trackKind, String(trackId)), nullptr);
305     m_pendingReceivers.append(receiver.copyRef());
306     return receiver;
307 }
308
309 LibWebRTCPeerConnectionBackend::VideoReceiver LibWebRTCPeerConnectionBackend::videoReceiver(String&& trackId)
310 {
311     // FIXME: Add to Vector a utility routine for that take-or-create pattern.
312     // FIXME: We should be selecting the receiver based on track id.
313     for (size_t cptr = 0; cptr < m_pendingReceivers.size(); ++cptr) {
314         if (m_pendingReceivers[cptr]->track().source().type() == RealtimeMediaSource::Type::Video) {
315             Ref<RTCRtpReceiver> receiver = m_pendingReceivers[cptr].copyRef();
316             m_pendingReceivers.remove(cptr);
317             Ref<RealtimeIncomingVideoSource> source = static_cast<RealtimeIncomingVideoSource&>(receiver->track().source());
318             return { WTFMove(receiver), WTFMove(source) };
319         }
320     }
321     auto source = RealtimeIncomingVideoSource::create(nullptr, WTFMove(trackId));
322     auto receiver = createReceiverForSource(source.copyRef(), nullptr);
323
324     auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
325     auto transceiver = RTCRtpTransceiver::create(RTCRtpSender::create(*this, "video"_s, { }, WTFMove(senderBackend)), receiver.copyRef(), nullptr);
326     transceiver->disableSendingDirection();
327     m_peerConnection.addTransceiver(WTFMove(transceiver));
328
329     return { WTFMove(receiver), WTFMove(source) };
330 }
331
332 LibWebRTCPeerConnectionBackend::AudioReceiver LibWebRTCPeerConnectionBackend::audioReceiver(String&& trackId)
333 {
334     // FIXME: Add to Vector a utility routine for that take-or-create pattern.
335     // FIXME: We should be selecting the receiver based on track id.
336     for (size_t cptr = 0; cptr < m_pendingReceivers.size(); ++cptr) {
337         if (m_pendingReceivers[cptr]->track().source().type() == RealtimeMediaSource::Type::Audio) {
338             Ref<RTCRtpReceiver> receiver = m_pendingReceivers[cptr].copyRef();
339             m_pendingReceivers.remove(cptr);
340             Ref<RealtimeIncomingAudioSource> source = static_cast<RealtimeIncomingAudioSource&>(receiver->track().source());
341             return { WTFMove(receiver), WTFMove(source) };
342         }
343     }
344     auto source = RealtimeIncomingAudioSource::create(nullptr, WTFMove(trackId));
345     auto receiver = createReceiverForSource(source.copyRef(), nullptr);
346
347     auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
348     auto transceiver = RTCRtpTransceiver::create(RTCRtpSender::create(*this, "audio"_s, { }, WTFMove(senderBackend)), receiver.copyRef(), nullptr);
349     transceiver->disableSendingDirection();
350     m_peerConnection.addTransceiver(WTFMove(transceiver));
351
352     return { WTFMove(receiver), WTFMove(source) };
353 }
354
355 std::unique_ptr<RTCDataChannelHandler> LibWebRTCPeerConnectionBackend::createDataChannelHandler(const String& label, const RTCDataChannelInit& options)
356 {
357     return m_endpoint->createDataChannel(label, options);
358 }
359
360 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::currentLocalDescription() const
361 {
362     auto description = m_endpoint->currentLocalDescription();
363     if (description)
364         description->setSdp(filterSDP(String(description->sdp())));
365     return description;
366 }
367
368 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::currentRemoteDescription() const
369 {
370     return m_endpoint->currentRemoteDescription();
371 }
372
373 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::pendingLocalDescription() const
374 {
375     auto description = m_endpoint->pendingLocalDescription();
376     if (description)
377         description->setSdp(filterSDP(String(description->sdp())));
378     return description;
379 }
380
381 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::pendingRemoteDescription() const
382 {
383     return m_endpoint->pendingRemoteDescription();
384 }
385
386 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::localDescription() const
387 {
388     auto description = m_endpoint->localDescription();
389     if (description)
390         description->setSdp(filterSDP(String(description->sdp())));
391     return description;
392 }
393
394 RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::remoteDescription() const
395 {
396     return m_endpoint->remoteDescription();
397 }
398
399 static inline RefPtr<RTCRtpSender> findExistingSender(const Vector<RefPtr<RTCRtpTransceiver>>& transceivers, LibWebRTCRtpSenderBackend& senderBackend)
400 {
401     ASSERT(senderBackend.rtcSender());
402     for (auto& transceiver : transceivers) {
403         auto& sender = transceiver->sender();
404         if (!sender.isStopped() && senderBackend.rtcSender() == backendFromRTPSender(sender).rtcSender())
405             return makeRef(sender);
406     }
407     return nullptr;
408 }
409
410 ExceptionOr<Ref<RTCRtpSender>> LibWebRTCPeerConnectionBackend::addTrack(MediaStreamTrack& track, Vector<String>&& mediaStreamIds)
411 {
412     if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled()) {
413         auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
414         if (!m_endpoint->addTrack(*senderBackend, track, mediaStreamIds))
415             return Exception { TypeError, "Unable to add track"_s };
416
417         if (auto sender = findExistingSender(m_peerConnection.currentTransceivers(), *senderBackend)) {
418             backendFromRTPSender(*sender).takeSource(*senderBackend);
419             sender->setTrack(makeRef(track));
420             sender->setMediaStreamIds(WTFMove(mediaStreamIds));
421             return sender.releaseNonNull();
422         }
423
424         auto transceiverBackend = m_endpoint->transceiverBackendFromSender(*senderBackend);
425
426         auto sender = RTCRtpSender::create(*this, makeRef(track), WTFMove(mediaStreamIds), WTFMove(senderBackend));
427         auto receiver = createReceiverForSource(createEmptySource(track.kind(), createCanonicalUUIDString()), transceiverBackend->createReceiverBackend());
428         auto transceiver = RTCRtpTransceiver::create(sender.copyRef(), WTFMove(receiver), WTFMove(transceiverBackend));
429         m_peerConnection.addInternalTransceiver(WTFMove(transceiver));
430         return sender;
431     }
432
433     RTCRtpSender* sender = nullptr;
434     // Reuse an existing sender with the same track kind if it has never been used to send before.
435     for (auto& transceiver : m_peerConnection.currentTransceivers()) {
436         auto& existingSender = transceiver->sender();
437         if (!existingSender.isStopped() && existingSender.trackKind() == track.kind() && existingSender.trackId().isNull() && !transceiver->hasSendingDirection()) {
438             existingSender.setTrack(makeRef(track));
439             existingSender.setMediaStreamIds(WTFMove(mediaStreamIds));
440             transceiver->enableSendingDirection();
441             sender = &existingSender;
442
443             break;
444         }
445     }
446
447     if (!sender) {
448         const String& trackKind = track.kind();
449         String trackId = createCanonicalUUIDString();
450
451         auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
452         auto newSender = RTCRtpSender::create(*this, makeRef(track), Vector<String> { mediaStreamIds }, WTFMove(senderBackend));
453         auto receiver = createReceiver(trackKind, trackId);
454         auto transceiver = RTCRtpTransceiver::create(WTFMove(newSender), WTFMove(receiver), nullptr);
455
456         sender = &transceiver->sender();
457         m_peerConnection.addInternalTransceiver(WTFMove(transceiver));
458     }
459
460     if (!m_endpoint->addTrack(backendFromRTPSender(*sender), track, mediaStreamIds))
461         return Exception { TypeError, "Unable to add track"_s };
462
463     return makeRef(*sender);
464 }
465
466 template<typename T>
467 ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addUnifiedPlanTransceiver(T&& trackOrKind, const RTCRtpTransceiverInit& init)
468 {
469     auto backends = m_endpoint->addTransceiver(trackOrKind, init);
470     if (!backends)
471         return Exception { InvalidAccessError, "Unable to add transceiver"_s };
472
473     auto sender = RTCRtpSender::create(*this, WTFMove(trackOrKind), Vector<String> { }, WTFMove(backends->senderBackend));
474     auto receiver = createReceiverForSource(createEmptySource(sender->trackKind(), createCanonicalUUIDString()), WTFMove(backends->receiverBackend));
475     auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver), WTFMove(backends->transceiverBackend));
476     m_peerConnection.addInternalTransceiver(transceiver.copyRef());
477     return transceiver;
478 }
479
480 ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiver(const String& trackKind, const RTCRtpTransceiverInit& init)
481 {
482     if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
483         return addUnifiedPlanTransceiver(String { trackKind }, init);
484
485     auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
486     auto newSender = RTCRtpSender::create(*this, String(trackKind), Vector<String>(), WTFMove(senderBackend));
487     return completeAddTransceiver(WTFMove(newSender), init, createCanonicalUUIDString(), trackKind);
488 }
489
490 ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiver(Ref<MediaStreamTrack>&& track, const RTCRtpTransceiverInit& init)
491 {
492     if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
493         return addUnifiedPlanTransceiver(WTFMove(track), init);
494
495     auto senderBackend = makeUnique<LibWebRTCRtpSenderBackend>(*this, nullptr);
496     auto& backend = *senderBackend;
497     auto sender = RTCRtpSender::create(*this, track.copyRef(), Vector<String>(), WTFMove(senderBackend));
498     if (!m_endpoint->addTrack(backend, track, Vector<String> { }))
499         return Exception { InvalidAccessError, "Unable to add track"_s };
500
501     return completeAddTransceiver(WTFMove(sender), init, track->id(), track->kind());
502 }
503
504 void LibWebRTCPeerConnectionBackend::setSenderSourceFromTrack(LibWebRTCRtpSenderBackend& sender, MediaStreamTrack& track)
505 {
506     m_endpoint->setSenderSourceFromTrack(sender, track);
507 }
508
509 static inline LibWebRTCRtpTransceiverBackend& backendFromRTPTransceiver(RTCRtpTransceiver& transceiver)
510 {
511     return static_cast<LibWebRTCRtpTransceiverBackend&>(*transceiver.backend());
512 }
513
514 RTCRtpTransceiver* LibWebRTCPeerConnectionBackend::existingTransceiver(WTF::Function<bool(LibWebRTCRtpTransceiverBackend&)>&& matchingFunction)
515 {
516     for (auto& transceiver : m_peerConnection.currentTransceivers()) {
517         if (matchingFunction(backendFromRTPTransceiver(*transceiver)))
518             return transceiver.get();
519     }
520     return nullptr;
521 }
522
523 RTCRtpTransceiver& LibWebRTCPeerConnectionBackend::newRemoteTransceiver(std::unique_ptr<LibWebRTCRtpTransceiverBackend>&& transceiverBackend, Ref<RealtimeMediaSource>&& receiverSource)
524 {
525     auto sender = RTCRtpSender::create(*this, receiverSource->type() == RealtimeMediaSource::Type::Audio ? "audio"_s : "video"_s, Vector<String> { }, transceiverBackend->createSenderBackend(*this, nullptr));
526     auto receiver = createReceiverForSource(WTFMove(receiverSource), transceiverBackend->createReceiverBackend());
527     auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver), WTFMove(transceiverBackend));
528     m_peerConnection.addInternalTransceiver(transceiver.copyRef());
529     return transceiver.get();
530 }
531
532 Ref<RTCRtpTransceiver> LibWebRTCPeerConnectionBackend::completeAddTransceiver(Ref<RTCRtpSender>&& sender, const RTCRtpTransceiverInit& init, const String& trackId, const String& trackKind)
533 {
534     auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), createReceiver(trackKind, trackId), nullptr);
535
536     transceiver->setDirection(init.direction);
537
538     m_peerConnection.addInternalTransceiver(transceiver.copyRef());
539     return transceiver;
540 }
541
542 void LibWebRTCPeerConnectionBackend::collectTransceivers()
543 {
544     m_endpoint->collectTransceivers();
545 }
546
547 void LibWebRTCPeerConnectionBackend::removeTrack(RTCRtpSender& sender)
548 {
549     m_endpoint->removeTrack(backendFromRTPSender(sender));
550 }
551
552 void LibWebRTCPeerConnectionBackend::applyRotationForOutgoingVideoSources()
553 {
554     for (auto& transceiver : m_peerConnection.currentTransceivers()) {
555         if (!transceiver->sender().isStopped()) {
556             if (auto* videoSource = backendFromRTPSender(transceiver->sender()).videoSource())
557                 videoSource->setApplyRotation(true);
558         }
559     }
560 }
561
562 bool LibWebRTCPeerConnectionBackend::shouldOfferAllowToReceive(const char* kind) const
563 {
564     ASSERT(!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled());
565     for (const auto& transceiver : m_peerConnection.currentTransceivers()) {
566         if (transceiver->sender().trackKind() != kind)
567             continue;
568
569         if (transceiver->direction() == RTCRtpTransceiverDirection::Recvonly)
570             return true;
571
572         if (transceiver->direction() != RTCRtpTransceiverDirection::Sendrecv)
573             continue;
574
575         auto* backend = static_cast<LibWebRTCRtpSenderBackend*>(transceiver->sender().backend());
576         if (backend && !backend->rtcSender())
577             return true;
578     }
579     return false;
580 }
581
582 } // namespace WebCore
583
584 #endif // USE(LIBWEBRTC)