490aa4fabf50a1ff5d20ce5ae20964515a2b3495
[WebKit-https.git] / Source / WebCore / Modules / mediastream / libwebrtc / LibWebRTCMediaEndpoint.cpp
1 /*
2  * Copyright (C) 2017 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 "Logging.h"
36 #include "MediaStreamEvent.h"
37 #include "NotImplemented.h"
38 #include "Performance.h"
39 #include "PlatformStrategies.h"
40 #include "RTCDataChannel.h"
41 #include "RTCDataChannelEvent.h"
42 #include "RTCOfferOptions.h"
43 #include "RTCPeerConnection.h"
44 #include "RTCSessionDescription.h"
45 #include "RTCStatsReport.h"
46 #include "RTCTrackEvent.h"
47 #include "RealtimeIncomingAudioSource.h"
48 #include "RealtimeIncomingVideoSource.h"
49 #include "RuntimeEnabledFeatures.h"
50 #include <webrtc/base/physicalsocketserver.h>
51 #include <webrtc/p2p/base/basicpacketsocketfactory.h>
52 #include <webrtc/p2p/client/basicportallocator.h>
53 #include <webrtc/pc/peerconnectionfactory.h>
54 #include <wtf/CurrentTime.h>
55 #include <wtf/MainThread.h>
56
57 namespace WebCore {
58
59 LibWebRTCMediaEndpoint::LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend& peerConnection, LibWebRTCProvider& client)
60     : m_peerConnectionBackend(peerConnection)
61     , m_peerConnectionFactory(*client.factory())
62     , m_createSessionDescriptionObserver(*this)
63     , m_setLocalSessionDescriptionObserver(*this)
64     , m_setRemoteSessionDescriptionObserver(*this)
65     , m_statsLogTimer(*this, &LibWebRTCMediaEndpoint::gatherStatsForLogging)
66 #if !RELEASE_LOG_DISABLED
67     , m_logger(peerConnection.logger())
68     , m_logIdentifier(peerConnection.logIdentifier())
69 #endif
70 {
71     ASSERT(client.factory());
72 }
73
74 bool LibWebRTCMediaEndpoint::setConfiguration(LibWebRTCProvider& client, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
75 {
76     if (!m_backend) {
77         m_backend = client.createPeerConnection(*this, WTFMove(configuration));
78         return !!m_backend;
79     }
80     return m_backend->SetConfiguration(WTFMove(configuration));
81 }
82
83 static inline const char* sessionDescriptionType(RTCSdpType sdpType)
84 {
85     switch (sdpType) {
86     case RTCSdpType::Offer:
87         return "offer";
88     case RTCSdpType::Pranswer:
89         return "pranswer";
90     case RTCSdpType::Answer:
91         return "answer";
92     case RTCSdpType::Rollback:
93         return "rollback";
94     }
95
96     ASSERT_NOT_REACHED();
97     return "";
98 }
99
100 static inline RTCSdpType fromSessionDescriptionType(const webrtc::SessionDescriptionInterface& description)
101 {
102     auto type = description.type();
103     if (type == webrtc::SessionDescriptionInterface::kOffer)
104         return RTCSdpType::Offer;
105     if (type == webrtc::SessionDescriptionInterface::kAnswer)
106         return RTCSdpType::Answer;
107     ASSERT(type == webrtc::SessionDescriptionInterface::kPrAnswer);
108     return RTCSdpType::Pranswer;
109 }
110
111 static inline RefPtr<RTCSessionDescription> fromSessionDescription(const webrtc::SessionDescriptionInterface* description)
112 {
113     if (!description)
114         return nullptr;
115
116     std::string sdp;
117     description->ToString(&sdp);
118     String sdpString(sdp.data(), sdp.size());
119
120     return RTCSessionDescription::create(fromSessionDescriptionType(*description), WTFMove(sdpString));
121 }
122
123 // FIXME: We might want to create a new object only if the session actually changed for all description getters.
124 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentLocalDescription() const
125 {
126     return m_backend ? fromSessionDescription(m_backend->current_local_description()) : nullptr;
127 }
128
129 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentRemoteDescription() const
130 {
131     return m_backend ? fromSessionDescription(m_backend->current_remote_description()) : nullptr;
132 }
133
134 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingLocalDescription() const
135 {
136     return m_backend ? fromSessionDescription(m_backend->pending_local_description()) : nullptr;
137 }
138
139 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingRemoteDescription() const
140 {
141     return m_backend ? fromSessionDescription(m_backend->pending_remote_description()) : nullptr;
142 }
143
144 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::localDescription() const
145 {
146     return m_backend ? fromSessionDescription(m_backend->local_description()) : nullptr;
147 }
148
149 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::remoteDescription() const
150 {
151     return m_backend ? fromSessionDescription(m_backend->remote_description()) : nullptr;
152 }
153
154 void LibWebRTCMediaEndpoint::doSetLocalDescription(RTCSessionDescription& description)
155 {
156     ASSERT(m_backend);
157
158     webrtc::SdpParseError error;
159     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
160
161     if (!sessionDescription) {
162         String errorMessage(error.description.data(), error.description.size());
163         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, WTFMove(errorMessage) });
164         return;
165     }
166
167     // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=173783. Remove this test once fixed at LibWebRTC level.
168     if (description.type() == RTCSdpType::Answer && !m_backend->pending_remote_description()) {
169         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { InvalidStateError, ASCIILiteral("Failed to set local answer sdp: no pending remote description.") });
170         return;
171     }
172
173     m_backend->SetLocalDescription(&m_setLocalSessionDescriptionObserver, sessionDescription.release());
174 }
175
176 void LibWebRTCMediaEndpoint::doSetRemoteDescription(RTCSessionDescription& description)
177 {
178     ASSERT(m_backend);
179
180     webrtc::SdpParseError error;
181     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
182     if (!sessionDescription) {
183         String errorMessage(error.description.data(), error.description.size());
184         m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, WTFMove(errorMessage) });
185         return;
186     }
187     m_backend->SetRemoteDescription(&m_setRemoteSessionDescriptionObserver, sessionDescription.release());
188
189     startLoggingStats();
190 }
191
192 void LibWebRTCMediaEndpoint::addTrack(RTCRtpSender& sender, MediaStreamTrack& track, const Vector<String>& mediaStreamIds)
193 {
194     ASSERT(m_backend);
195
196     std::vector<webrtc::MediaStreamInterface*> mediaStreams;
197     rtc::scoped_refptr<webrtc::MediaStreamInterface> mediaStream = nullptr;
198     if (mediaStreamIds.size()) {
199         // libwebrtc is only using the first one if any.
200         mediaStream = m_peerConnectionFactory.CreateLocalMediaStream(mediaStreamIds[0].utf8().data());
201         mediaStreams.push_back(mediaStream.get());
202     }
203     
204     switch (track.privateTrack().type()) {
205     case RealtimeMediaSource::Type::Audio: {
206         auto trackSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
207         auto audioTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), trackSource.ptr());
208         m_peerConnectionBackend.addAudioSource(WTFMove(trackSource));
209         m_senders.add(&sender, m_backend->AddTrack(audioTrack.get(), WTFMove(mediaStreams)));
210         return;
211     }
212     case RealtimeMediaSource::Type::Video: {
213         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
214         auto videoTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
215         m_peerConnectionBackend.addVideoSource(WTFMove(videoSource));
216         m_senders.add(&sender, m_backend->AddTrack(videoTrack.get(), WTFMove(mediaStreams)));
217         return;
218     }
219     case RealtimeMediaSource::Type::None:
220         ASSERT_NOT_REACHED();
221     }
222 }
223
224 void LibWebRTCMediaEndpoint::removeTrack(RTCRtpSender& sender)
225 {
226     ASSERT(m_backend);
227
228     auto rtcSender = m_senders.get(&sender);
229     if (!rtcSender)
230         return;
231     m_backend->RemoveTrack(rtcSender.get());
232 }
233
234 bool LibWebRTCMediaEndpoint::shouldOfferAllowToReceiveAudio() const
235 {
236     for (const auto& transceiver : m_peerConnectionBackend.connection().getTransceivers()) {
237         if (transceiver->sender().trackKind() != "audio")
238             continue;
239
240         if (transceiver->direction() == RTCRtpTransceiverDirection::Recvonly)
241             return true;
242
243         if (transceiver->direction() == RTCRtpTransceiverDirection::Sendrecv && !m_senders.contains(&transceiver->sender()))
244             return true;
245     }
246     return false;
247 }
248
249 bool LibWebRTCMediaEndpoint::shouldOfferAllowToReceiveVideo() const
250 {
251     for (const auto& transceiver : m_peerConnectionBackend.connection().getTransceivers()) {
252         if (transceiver->sender().trackKind() != "video")
253             continue;
254
255         if (transceiver->direction() == RTCRtpTransceiverDirection::Recvonly)
256             return true;
257
258         if (transceiver->direction() == RTCRtpTransceiverDirection::Sendrecv && !m_senders.contains(&transceiver->sender()))
259             return true;
260     }
261     return false;
262 }
263
264 void LibWebRTCMediaEndpoint::doCreateOffer(const RTCOfferOptions& options)
265 {
266     ASSERT(m_backend);
267
268     m_isInitiator = true;
269     webrtc::PeerConnectionInterface::RTCOfferAnswerOptions rtcOptions;
270     rtcOptions.ice_restart = options.iceRestart;
271     rtcOptions.voice_activity_detection = options.voiceActivityDetection;
272     // FIXME: offer_to_receive_audio and offer_to_receive_video are used as libwebrtc does not support transceivers yet.
273     if (shouldOfferAllowToReceiveAudio())
274         rtcOptions.offer_to_receive_audio = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
275     if (shouldOfferAllowToReceiveVideo())
276         rtcOptions.offer_to_receive_video = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
277     m_backend->CreateOffer(&m_createSessionDescriptionObserver, rtcOptions);
278 }
279
280 void LibWebRTCMediaEndpoint::doCreateAnswer()
281 {
282     ASSERT(m_backend);
283
284     m_isInitiator = false;
285     m_backend->CreateAnswer(&m_createSessionDescriptionObserver, nullptr);
286 }
287
288 void LibWebRTCMediaEndpoint::getStats(MediaStreamTrack* track, const DeferredPromise& promise)
289 {
290     auto collector = StatsCollector::create(*this, promise, track);
291     LibWebRTCProvider::callOnWebRTCSignalingThread([protectedThis = makeRef(*this), collector = WTFMove(collector)] {
292         if (protectedThis->m_backend)
293             protectedThis->m_backend->GetStats(collector.get());
294     });
295 }
296
297 LibWebRTCMediaEndpoint::StatsCollector::StatsCollector(Ref<LibWebRTCMediaEndpoint>&& endpoint, const DeferredPromise& promise, MediaStreamTrack* track)
298     : m_endpoint(WTFMove(endpoint))
299     , m_promise(promise)
300 {
301     if (track)
302         m_id = track->id();
303 }
304
305 static inline String fromStdString(const std::string& value)
306 {
307     return String(value.data(), value.length());
308 }
309
310 static inline void fillRTCStats(RTCStatsReport::Stats& stats, const webrtc::RTCStats& rtcStats)
311 {
312     stats.timestamp = Performance::reduceTimeResolution(Seconds::fromMicroseconds(rtcStats.timestamp_us())).milliseconds();
313     stats.id = fromStdString(rtcStats.id());
314 }
315
316 static inline void fillRTCRTPStreamStats(RTCStatsReport::RTCRTPStreamStats& stats, const webrtc::RTCRTPStreamStats& rtcStats)
317 {
318     fillRTCStats(stats, rtcStats);
319
320     if (rtcStats.ssrc.is_defined())
321         stats.ssrc = *rtcStats.ssrc;
322     if (rtcStats.associate_stats_id.is_defined())
323         stats.associateStatsId = fromStdString(*rtcStats.associate_stats_id);
324     if (rtcStats.is_remote.is_defined())
325         stats.isRemote = *rtcStats.is_remote;
326     if (rtcStats.media_type.is_defined())
327         stats.mediaType = fromStdString(*rtcStats.media_type);
328     if (rtcStats.track_id.is_defined())
329         stats.mediaTrackId = fromStdString(*rtcStats.track_id);
330     if (rtcStats.transport_id.is_defined())
331         stats.transportId = fromStdString(*rtcStats.transport_id);
332     if (rtcStats.codec_id.is_defined())
333         stats.codecId = fromStdString(*rtcStats.codec_id);
334     if (rtcStats.fir_count.is_defined())
335         stats.firCount = *rtcStats.fir_count;
336     if (rtcStats.pli_count.is_defined())
337         stats.pliCount = *rtcStats.pli_count;
338     if (rtcStats.nack_count.is_defined())
339         stats.nackCount = *rtcStats.nack_count;
340     if (rtcStats.sli_count.is_defined())
341         stats.sliCount = *rtcStats.sli_count;
342     if (rtcStats.qp_sum.is_defined())
343         stats.qpSum = *rtcStats.qp_sum;
344     stats.qpSum = 0;
345 }
346
347 static inline void fillInboundRTPStreamStats(RTCStatsReport::InboundRTPStreamStats& stats, const webrtc::RTCInboundRTPStreamStats& rtcStats)
348 {
349     fillRTCRTPStreamStats(stats, rtcStats);
350
351     if (rtcStats.packets_received.is_defined())
352         stats.packetsReceived = *rtcStats.packets_received;
353     if (rtcStats.bytes_received.is_defined())
354         stats.bytesReceived = *rtcStats.bytes_received;
355     if (rtcStats.packets_lost.is_defined())
356         stats.packetsLost = *rtcStats.packets_lost;
357     if (rtcStats.jitter.is_defined())
358         stats.jitter = *rtcStats.jitter;
359     if (rtcStats.fraction_lost.is_defined())
360         stats.fractionLost = *rtcStats.fraction_lost;
361     if (rtcStats.packets_discarded.is_defined())
362         stats.packetsDiscarded = *rtcStats.packets_discarded;
363     if (rtcStats.packets_repaired.is_defined())
364         stats.packetsRepaired = *rtcStats.packets_repaired;
365     if (rtcStats.burst_packets_lost.is_defined())
366         stats.burstPacketsLost = *rtcStats.burst_packets_lost;
367     if (rtcStats.burst_packets_discarded.is_defined())
368         stats.burstPacketsDiscarded = *rtcStats.burst_packets_discarded;
369     if (rtcStats.burst_loss_count.is_defined())
370         stats.burstLossCount = *rtcStats.burst_loss_count;
371     if (rtcStats.burst_discard_count.is_defined())
372         stats.burstDiscardCount = *rtcStats.burst_discard_count;
373     if (rtcStats.burst_loss_rate.is_defined())
374         stats.burstLossRate = *rtcStats.burst_loss_rate;
375     if (rtcStats.burst_discard_rate.is_defined())
376         stats.burstDiscardRate = *rtcStats.burst_discard_rate;
377     if (rtcStats.gap_loss_rate.is_defined())
378         stats.gapLossRate = *rtcStats.gap_loss_rate;
379     if (rtcStats.gap_discard_rate.is_defined())
380         stats.gapDiscardRate = *rtcStats.gap_discard_rate;
381     if (rtcStats.frames_decoded.is_defined())
382         stats.framesDecoded = *rtcStats.frames_decoded;
383 }
384
385 static inline void fillOutboundRTPStreamStats(RTCStatsReport::OutboundRTPStreamStats& stats, const webrtc::RTCOutboundRTPStreamStats& rtcStats)
386 {
387     fillRTCRTPStreamStats(stats, rtcStats);
388
389     if (rtcStats.packets_sent.is_defined())
390         stats.packetsSent = *rtcStats.packets_sent;
391     if (rtcStats.bytes_sent.is_defined())
392         stats.bytesSent = *rtcStats.bytes_sent;
393     if (rtcStats.target_bitrate.is_defined())
394         stats.targetBitrate = *rtcStats.target_bitrate;
395     if (rtcStats.frames_encoded.is_defined())
396         stats.framesEncoded = *rtcStats.frames_encoded;
397 }
398
399 static inline void fillRTCMediaStreamTrackStats(RTCStatsReport::MediaStreamTrackStats& stats, const webrtc::RTCMediaStreamTrackStats& rtcStats)
400 {
401     fillRTCStats(stats, rtcStats);
402
403     if (rtcStats.track_identifier.is_defined())
404         stats.trackIdentifier = fromStdString(*rtcStats.track_identifier);
405     if (rtcStats.remote_source.is_defined())
406         stats.remoteSource = *rtcStats.remote_source;
407     if (rtcStats.ended.is_defined())
408         stats.ended = *rtcStats.ended;
409     if (rtcStats.detached.is_defined())
410         stats.detached = *rtcStats.detached;
411     if (rtcStats.frame_width.is_defined())
412         stats.frameWidth = *rtcStats.frame_width;
413     if (rtcStats.frame_height.is_defined())
414         stats.frameHeight = *rtcStats.frame_height;
415     if (rtcStats.frames_per_second.is_defined())
416         stats.framesPerSecond = *rtcStats.frames_per_second;
417     if (rtcStats.frames_sent.is_defined())
418         stats.framesSent = *rtcStats.frames_sent;
419     if (rtcStats.frames_received.is_defined())
420         stats.framesReceived = *rtcStats.frames_received;
421     if (rtcStats.frames_decoded.is_defined())
422         stats.framesDecoded = *rtcStats.frames_decoded;
423     if (rtcStats.frames_dropped.is_defined())
424         stats.framesDropped = *rtcStats.frames_dropped;
425     if (rtcStats.partial_frames_lost.is_defined())
426         stats.partialFramesLost = *rtcStats.partial_frames_lost;
427     if (rtcStats.full_frames_lost.is_defined())
428         stats.fullFramesLost = *rtcStats.full_frames_lost;
429     if (rtcStats.audio_level.is_defined())
430         stats.audioLevel = *rtcStats.audio_level;
431     if (rtcStats.echo_return_loss.is_defined())
432         stats.echoReturnLoss = *rtcStats.echo_return_loss;
433     if (rtcStats.echo_return_loss_enhancement.is_defined())
434         stats.echoReturnLossEnhancement = *rtcStats.echo_return_loss_enhancement;
435 }
436
437 static inline void fillRTCDataChannelStats(RTCStatsReport::DataChannelStats& stats, const webrtc::RTCDataChannelStats& rtcStats)
438 {
439     fillRTCStats(stats, rtcStats);
440
441     if (rtcStats.label.is_defined())
442         stats.label = fromStdString(*rtcStats.label);
443     if (rtcStats.protocol.is_defined())
444         stats.protocol = fromStdString(*rtcStats.protocol);
445     if (rtcStats.datachannelid.is_defined())
446         stats.datachannelid = *rtcStats.datachannelid;
447     if (rtcStats.state.is_defined())
448         stats.state = fromStdString(*rtcStats.state);
449     if (rtcStats.messages_sent.is_defined())
450         stats.messagesSent = *rtcStats.messages_sent;
451     if (rtcStats.bytes_sent.is_defined())
452         stats.bytesSent = *rtcStats.bytes_sent;
453     if (rtcStats.messages_received.is_defined())
454         stats.messagesReceived = *rtcStats.messages_received;
455     if (rtcStats.bytes_received.is_defined())
456         stats.bytesReceived = *rtcStats.bytes_received;
457 }
458
459 static inline RTCStatsReport::IceCandidatePairState iceCandidatePairState(const std::string& state)
460 {
461     if (state == "frozen")
462         return RTCStatsReport::IceCandidatePairState::Frozen;
463     if (state == "waiting")
464         return RTCStatsReport::IceCandidatePairState::Waiting;
465     if (state == "in-progress")
466         return RTCStatsReport::IceCandidatePairState::Inprogress;
467     if (state == "failed")
468         return RTCStatsReport::IceCandidatePairState::Failed;
469     if (state == "succeeded")
470         return RTCStatsReport::IceCandidatePairState::Succeeded;
471     if (state == "cancelled")
472         return RTCStatsReport::IceCandidatePairState::Cancelled;
473     ASSERT_NOT_REACHED();
474     return RTCStatsReport::IceCandidatePairState::Frozen;
475 }
476
477 static inline void fillRTCIceCandidatePairStats(RTCStatsReport::IceCandidatePairStats& stats, const webrtc::RTCIceCandidatePairStats& rtcStats)
478 {
479     fillRTCStats(stats, rtcStats);
480
481     if (rtcStats.transport_id.is_defined())
482         stats.transportId = fromStdString(*rtcStats.transport_id);
483     if (rtcStats.local_candidate_id.is_defined())
484         stats.localCandidateId = fromStdString(*rtcStats.local_candidate_id);
485     if (rtcStats.remote_candidate_id.is_defined())
486         stats.remoteCandidateId = fromStdString(*rtcStats.remote_candidate_id);
487     if (rtcStats.state.is_defined())
488         stats.state = iceCandidatePairState(*rtcStats.state);
489
490     if (rtcStats.priority.is_defined())
491         stats.priority = *rtcStats.priority;
492     if (rtcStats.nominated.is_defined())
493         stats.nominated = *rtcStats.nominated;
494     if (rtcStats.writable.is_defined())
495         stats.writable = *rtcStats.writable;
496     if (rtcStats.readable.is_defined())
497         stats.readable = *rtcStats.readable;
498
499     if (rtcStats.bytes_sent.is_defined())
500         stats.bytesSent = *rtcStats.bytes_sent;
501     if (rtcStats.bytes_received.is_defined())
502         stats.bytesReceived = *rtcStats.bytes_received;
503     if (rtcStats.total_round_trip_time.is_defined())
504         stats.totalRoundTripTime = *rtcStats.total_round_trip_time;
505     if (rtcStats.current_round_trip_time.is_defined())
506         stats.currentRoundTripTime = *rtcStats.current_round_trip_time;
507     if (rtcStats.available_outgoing_bitrate.is_defined())
508         stats.availableOutgoingBitrate = *rtcStats.available_outgoing_bitrate;
509     if (rtcStats.available_incoming_bitrate.is_defined())
510         stats.availableIncomingBitrate = *rtcStats.available_incoming_bitrate;
511
512     if (rtcStats.requests_received.is_defined())
513         stats.requestsReceived = *rtcStats.requests_received;
514     if (rtcStats.requests_sent.is_defined())
515         stats.requestsSent = *rtcStats.requests_sent;
516     if (rtcStats.responses_received.is_defined())
517         stats.responsesReceived = *rtcStats.responses_received;
518     if (rtcStats.responses_sent.is_defined())
519         stats.responsesSent = *rtcStats.responses_sent;
520
521     if (rtcStats.requests_received.is_defined())
522         stats.retransmissionsReceived = *rtcStats.requests_received;
523     if (rtcStats.requests_sent.is_defined())
524         stats.retransmissionsSent = *rtcStats.requests_sent;
525     if (rtcStats.responses_received.is_defined())
526         stats.consentRequestsReceived = *rtcStats.responses_received;
527     if (rtcStats.responses_sent.is_defined())
528         stats.consentRequestsSent = *rtcStats.responses_sent;
529     if (rtcStats.responses_received.is_defined())
530         stats.consentResponsesReceived = *rtcStats.responses_received;
531     if (rtcStats.responses_sent.is_defined())
532         stats.consentResponsesSent = *rtcStats.responses_sent;
533 }
534
535 static inline void fillRTCCertificateStats(RTCStatsReport::CertificateStats& stats, const webrtc::RTCCertificateStats& rtcStats)
536 {
537     fillRTCStats(stats, rtcStats);
538
539     if (rtcStats.fingerprint.is_defined())
540         stats.fingerprint = fromStdString(*rtcStats.fingerprint);
541     if (rtcStats.fingerprint_algorithm.is_defined())
542         stats.fingerprintAlgorithm = fromStdString(*rtcStats.fingerprint_algorithm);
543     if (rtcStats.base64_certificate.is_defined())
544         stats.base64Certificate = fromStdString(*rtcStats.base64_certificate);
545     if (rtcStats.issuer_certificate_id.is_defined())
546         stats.issuerCertificateId = fromStdString(*rtcStats.issuer_certificate_id);
547 }
548
549 void LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& rtcReport)
550 {
551     callOnMainThread([protectedThis = rtc::scoped_refptr<LibWebRTCMediaEndpoint::StatsCollector>(this), rtcReport] {
552         if (protectedThis->m_endpoint->isStopped())
553             return;
554
555         auto report = RTCStatsReport::create();
556         protectedThis->m_endpoint->m_peerConnectionBackend.getStatsSucceeded(protectedThis->m_promise, report.copyRef());
557         ASSERT(report->backingMap());
558
559         for (const auto& rtcStats : *rtcReport) {
560             if (rtcStats.type() == webrtc::RTCInboundRTPStreamStats::kType) {
561                 RTCStatsReport::InboundRTPStreamStats stats;
562                 fillInboundRTPStreamStats(stats, static_cast<const webrtc::RTCInboundRTPStreamStats&>(rtcStats));
563                 report->addStats<IDLDictionary<RTCStatsReport::InboundRTPStreamStats>>(WTFMove(stats));
564             } else if (rtcStats.type() == webrtc::RTCOutboundRTPStreamStats::kType) {
565                 RTCStatsReport::OutboundRTPStreamStats stats;
566                 fillOutboundRTPStreamStats(stats, static_cast<const webrtc::RTCOutboundRTPStreamStats&>(rtcStats));
567                 report->addStats<IDLDictionary<RTCStatsReport::OutboundRTPStreamStats>>(WTFMove(stats));
568             } else if (rtcStats.type() == webrtc::RTCMediaStreamTrackStats::kType) {
569                 RTCStatsReport::MediaStreamTrackStats stats;
570                 fillRTCMediaStreamTrackStats(stats, static_cast<const webrtc::RTCMediaStreamTrackStats&>(rtcStats));
571                 report->addStats<IDLDictionary<RTCStatsReport::MediaStreamTrackStats>>(WTFMove(stats));
572             } else if (rtcStats.type() == webrtc::RTCDataChannelStats::kType) {
573                 RTCStatsReport::DataChannelStats stats;
574                 fillRTCDataChannelStats(stats, static_cast<const webrtc::RTCDataChannelStats&>(rtcStats));
575                 report->addStats<IDLDictionary<RTCStatsReport::DataChannelStats>>(WTFMove(stats));
576             } else if (rtcStats.type() == webrtc::RTCIceCandidatePairStats::kType) {
577                 RTCStatsReport::IceCandidatePairStats stats;
578                 fillRTCIceCandidatePairStats(stats, static_cast<const webrtc::RTCIceCandidatePairStats&>(rtcStats));
579                 report->addStats<IDLDictionary<RTCStatsReport::IceCandidatePairStats>>(WTFMove(stats));
580             } else if (rtcStats.type() == webrtc::RTCCertificateStats::kType) {
581                 RTCStatsReport::CertificateStats stats;
582                 fillRTCCertificateStats(stats, static_cast<const webrtc::RTCCertificateStats&>(rtcStats));
583                 report->addStats<IDLDictionary<RTCStatsReport::CertificateStats>>(WTFMove(stats));
584             }
585         }
586     });
587 }
588
589 static RTCSignalingState signalingState(webrtc::PeerConnectionInterface::SignalingState state)
590 {
591     switch (state) {
592     case webrtc::PeerConnectionInterface::kStable:
593         return RTCSignalingState::Stable;
594     case webrtc::PeerConnectionInterface::kHaveLocalOffer:
595         return RTCSignalingState::HaveLocalOffer;
596     case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
597         return RTCSignalingState::HaveLocalPranswer;
598     case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
599         return RTCSignalingState::HaveRemoteOffer;
600     case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
601         return RTCSignalingState::HaveRemotePranswer;
602     case webrtc::PeerConnectionInterface::kClosed:
603         return RTCSignalingState::Stable;
604     }
605
606     ASSERT_NOT_REACHED();
607     return RTCSignalingState::Stable;
608 }
609
610 void LibWebRTCMediaEndpoint::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState rtcState)
611 {
612     auto state = signalingState(rtcState);
613     callOnMainThread([protectedThis = makeRef(*this), state] {
614         if (protectedThis->isStopped())
615             return;
616         protectedThis->m_peerConnectionBackend.updateSignalingState(state);
617     });
618 }
619
620 static inline String trackId(webrtc::MediaStreamTrackInterface& videoTrack)
621 {
622     return String(videoTrack.id().data(), videoTrack.id().size());
623 }
624
625 MediaStream& LibWebRTCMediaEndpoint::mediaStreamFromRTCStream(webrtc::MediaStreamInterface& rtcStream)
626 {
627     auto mediaStream = m_streams.ensure(&rtcStream, [&rtcStream, this] {
628         auto label = rtcStream.label();
629         auto stream = MediaStream::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), MediaStreamPrivate::create({ }, String(label.data(), label.size())));
630         auto streamPointer = stream.ptr();
631         m_peerConnectionBackend.addRemoteStream(WTFMove(stream));
632         return streamPointer;
633     });
634     return *mediaStream.iterator->value;
635 }
636
637 void LibWebRTCMediaEndpoint::addRemoteStream(webrtc::MediaStreamInterface& rtcStream)
638 {
639     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCLegacyAPIEnabled())
640         return;
641
642     auto& mediaStream = mediaStreamFromRTCStream(rtcStream);
643     m_peerConnectionBackend.connection().fireEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, &mediaStream));
644 }
645
646 class RTCRtpReceiverBackend final : public RTCRtpReceiver::Backend {
647 public:
648     explicit RTCRtpReceiverBackend(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& rtcReceiver) : m_rtcReceiver(WTFMove(rtcReceiver)) { }
649 private:
650     RTCRtpParameters getParameters() final;
651
652     rtc::scoped_refptr<webrtc::RtpReceiverInterface> m_rtcReceiver;
653 };
654
655
656 void LibWebRTCMediaEndpoint::addRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& rtcReceiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& rtcStreams)
657 {
658     ASSERT(rtcReceiver);
659     RefPtr<RTCRtpReceiver> receiver;
660     RefPtr<RealtimeMediaSource> remoteSource;
661
662     auto* rtcTrack = rtcReceiver->track().get();
663
664     switch (rtcReceiver->media_type()) {
665     case cricket::MEDIA_TYPE_DATA:
666         return;
667     case cricket::MEDIA_TYPE_AUDIO: {
668         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack);
669         auto audioReceiver = m_peerConnectionBackend.audioReceiver(trackId(*rtcTrack));
670
671         receiver = WTFMove(audioReceiver.receiver);
672         audioReceiver.source->setSourceTrack(WTFMove(audioTrack));
673         break;
674     }
675     case cricket::MEDIA_TYPE_VIDEO: {
676         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack);
677         auto videoReceiver = m_peerConnectionBackend.videoReceiver(trackId(*rtcTrack));
678
679         receiver = WTFMove(videoReceiver.receiver);
680         videoReceiver.source->setSourceTrack(WTFMove(videoTrack));
681         break;
682     }
683     }
684
685     receiver->setBackend(std::make_unique<RTCRtpReceiverBackend>(WTFMove(rtcReceiver)));
686     
687     auto* track = receiver->track();
688     ASSERT(track);
689
690     Vector<RefPtr<MediaStream>> streams;
691     for (auto& rtcStream : rtcStreams) {
692         auto& mediaStream = mediaStreamFromRTCStream(*rtcStream.get());
693         streams.append(&mediaStream);
694         mediaStream.addTrackFromPlatform(*track);
695     }
696     m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false, WTFMove(receiver), track, WTFMove(streams), nullptr));
697 }
698
699 void LibWebRTCMediaEndpoint::removeRemoteStream(webrtc::MediaStreamInterface& rtcStream)
700 {
701     auto* mediaStream = m_streams.take(&rtcStream);
702     if (mediaStream)
703         m_peerConnectionBackend.removeRemoteStream(mediaStream);
704 }
705
706 void LibWebRTCMediaEndpoint::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
707 {
708     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
709         if (protectedThis->isStopped())
710             return;
711         ASSERT(stream);
712         protectedThis->addRemoteStream(*stream.get());
713     });
714 }
715
716 void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
717 {
718     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
719         if (protectedThis->isStopped())
720             return;
721         ASSERT(stream);
722         protectedThis->removeRemoteStream(*stream.get());
723     });
724 }
725
726 void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams)
727 {
728     callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver), streams]() mutable {
729         if (protectedThis->isStopped())
730             return;
731         protectedThis->addRemoteTrack(WTFMove(receiver), streams);
732     });
733 }
734
735 std::unique_ptr<RTCDataChannelHandler> LibWebRTCMediaEndpoint::createDataChannel(const String& label, const RTCDataChannelInit& options)
736 {
737     ASSERT(m_backend);
738
739     webrtc::DataChannelInit init;
740     if (options.ordered)
741         init.ordered = *options.ordered;
742     if (options.maxPacketLifeTime)
743         init.maxRetransmitTime = *options.maxPacketLifeTime;
744     if (options.maxRetransmits)
745         init.maxRetransmits = *options.maxRetransmits;
746     init.protocol = options.protocol.utf8().data();
747     if (options.negotiated)
748         init.negotiated = *options.negotiated;
749     if (options.id)
750         init.id = *options.id;
751
752     auto channel = m_backend->CreateDataChannel(label.utf8().data(), &init);
753     if (!channel)
754         return nullptr;
755
756     return std::make_unique<LibWebRTCDataChannelHandler>(WTFMove(channel));
757 }
758
759 void LibWebRTCMediaEndpoint::addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>&& dataChannel)
760 {
761     auto protocol = dataChannel->protocol();
762     auto label = dataChannel->label();
763
764     RTCDataChannelInit init;
765     init.ordered = dataChannel->ordered();
766     init.maxPacketLifeTime = dataChannel->maxRetransmitTime();
767     init.maxRetransmits = dataChannel->maxRetransmits();
768     init.protocol = String(protocol.data(), protocol.size());
769     init.negotiated = dataChannel->negotiated();
770     init.id = dataChannel->id();
771
772     bool isOpened = dataChannel->state() == webrtc::DataChannelInterface::kOpen;
773
774     auto handler =  std::make_unique<LibWebRTCDataChannelHandler>(WTFMove(dataChannel));
775     ASSERT(m_peerConnectionBackend.connection().scriptExecutionContext());
776     auto channel = RTCDataChannel::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(handler), String(label.data(), label.size()), WTFMove(init));
777
778     if (isOpened) {
779         callOnMainThread([channel = channel.copyRef()] {
780             // FIXME: We should be able to write channel->didChangeReadyState(...)
781             RTCDataChannelHandlerClient& client = channel.get();
782             client.didChangeReadyState(RTCDataChannelState::Open);
783         });
784     }
785
786     m_peerConnectionBackend.connection().fireEvent(RTCDataChannelEvent::create(eventNames().datachannelEvent, false, false, WTFMove(channel)));
787 }
788
789 void LibWebRTCMediaEndpoint::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel)
790 {
791     callOnMainThread([protectedThis = makeRef(*this), dataChannel = WTFMove(dataChannel)] {
792         if (protectedThis->isStopped())
793             return;
794         protectedThis->addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>(dataChannel));
795     });
796 }
797
798 void LibWebRTCMediaEndpoint::stop()
799 {
800     if (!m_backend)
801         return;
802
803     stopLoggingStats();
804
805     m_backend->Close();
806     m_backend = nullptr;
807     m_streams.clear();
808     m_senders.clear();
809 }
810
811 void LibWebRTCMediaEndpoint::OnRenegotiationNeeded()
812 {
813     callOnMainThread([protectedThis = makeRef(*this)] {
814         if (protectedThis->isStopped())
815             return;
816         protectedThis->m_peerConnectionBackend.markAsNeedingNegotiation();
817     });
818 }
819
820 static inline RTCIceConnectionState toRTCIceConnectionState(webrtc::PeerConnectionInterface::IceConnectionState state)
821 {
822     switch (state) {
823     case webrtc::PeerConnectionInterface::kIceConnectionNew:
824         return RTCIceConnectionState::New;
825     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
826         return RTCIceConnectionState::Checking;
827     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
828         return RTCIceConnectionState::Connected;
829     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
830         return RTCIceConnectionState::Completed;
831     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
832         return RTCIceConnectionState::Failed;
833     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
834         return RTCIceConnectionState::Disconnected;
835     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
836         return RTCIceConnectionState::Closed;
837     case webrtc::PeerConnectionInterface::kIceConnectionMax:
838         break;
839     }
840
841     ASSERT_NOT_REACHED();
842     return RTCIceConnectionState::New;
843 }
844
845 void LibWebRTCMediaEndpoint::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state)
846 {
847     auto connectionState = toRTCIceConnectionState(state);
848     callOnMainThread([protectedThis = makeRef(*this), connectionState] {
849         if (protectedThis->isStopped())
850             return;
851         if (protectedThis->m_peerConnectionBackend.connection().iceConnectionState() != connectionState)
852             protectedThis->m_peerConnectionBackend.connection().updateIceConnectionState(connectionState);
853     });
854 }
855
856 void LibWebRTCMediaEndpoint::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState state)
857 {
858     callOnMainThread([protectedThis = makeRef(*this), state] {
859         if (protectedThis->isStopped())
860             return;
861         if (state == webrtc::PeerConnectionInterface::kIceGatheringComplete)
862             protectedThis->m_peerConnectionBackend.doneGatheringCandidates();
863         else if (state == webrtc::PeerConnectionInterface::kIceGatheringGathering)
864             protectedThis->m_peerConnectionBackend.connection().updateIceGatheringState(RTCIceGatheringState::Gathering);
865     });
866 }
867
868 void LibWebRTCMediaEndpoint::OnIceCandidate(const webrtc::IceCandidateInterface *rtcCandidate)
869 {
870     ASSERT(rtcCandidate);
871
872     std::string sdp;
873     rtcCandidate->ToString(&sdp);
874     String candidateSDP(sdp.data(), sdp.size());
875
876     auto mid = rtcCandidate->sdp_mid();
877     String candidateMid(mid.data(), mid.size());
878
879     auto sdpMLineIndex = safeCast<unsigned short>(rtcCandidate->sdp_mline_index());
880
881     callOnMainThread([protectedThis = makeRef(*this), mid = WTFMove(candidateMid), sdp = WTFMove(candidateSDP), sdpMLineIndex] {
882         if (protectedThis->isStopped())
883             return;
884         protectedThis->m_peerConnectionBackend.newICECandidate(String(sdp), String(mid), sdpMLineIndex);
885     });
886 }
887
888 void LibWebRTCMediaEndpoint::OnIceCandidatesRemoved(const std::vector<cricket::Candidate>&)
889 {
890     ASSERT_NOT_REACHED();
891 }
892
893 void LibWebRTCMediaEndpoint::createSessionDescriptionSucceeded(std::unique_ptr<webrtc::SessionDescriptionInterface>&& description)
894 {
895     std::string sdp;
896     description->ToString(&sdp);
897     String sdpString(sdp.data(), sdp.size());
898
899     callOnMainThread([protectedThis = makeRef(*this), sdp = WTFMove(sdpString)] {
900         if (protectedThis->isStopped())
901             return;
902         if (protectedThis->m_isInitiator)
903             protectedThis->m_peerConnectionBackend.createOfferSucceeded(String(sdp));
904         else
905             protectedThis->m_peerConnectionBackend.createAnswerSucceeded(String(sdp));
906     });
907 }
908
909 void LibWebRTCMediaEndpoint::createSessionDescriptionFailed(const std::string& errorMessage)
910 {
911     String error(errorMessage.data(), errorMessage.size());
912     callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
913         if (protectedThis->isStopped())
914             return;
915         if (protectedThis->m_isInitiator)
916             protectedThis->m_peerConnectionBackend.createOfferFailed(Exception { OperationError, String(error) });
917         else
918             protectedThis->m_peerConnectionBackend.createAnswerFailed(Exception { OperationError, String(error) });
919     });
920 }
921
922 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionSucceeded()
923 {
924     callOnMainThread([protectedThis = makeRef(*this)] {
925         if (protectedThis->isStopped())
926             return;
927         protectedThis->m_peerConnectionBackend.setLocalDescriptionSucceeded();
928     });
929 }
930
931 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionFailed(const std::string& errorMessage)
932 {
933     String error(errorMessage.data(), errorMessage.size());
934     callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
935         if (protectedThis->isStopped())
936             return;
937         protectedThis->m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, String(error) });
938     });
939 }
940
941 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionSucceeded()
942 {
943     callOnMainThread([protectedThis = makeRef(*this)] {
944         if (protectedThis->isStopped())
945             return;
946         protectedThis->m_peerConnectionBackend.setRemoteDescriptionSucceeded();
947     });
948 }
949
950 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionFailed(const std::string& errorMessage)
951 {
952     String error(errorMessage.data(), errorMessage.size());
953     callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
954         if (protectedThis->isStopped())
955             return;
956         protectedThis->m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, String(error) });
957     });
958 }
959
960 static inline RTCRtpParameters::EncodingParameters fillEncodingParameters(const webrtc::RtpEncodingParameters& rtcParameters)
961 {
962     RTCRtpParameters::EncodingParameters parameters;
963
964     if (rtcParameters.ssrc)
965         parameters.ssrc = *rtcParameters.ssrc;
966     if (rtcParameters.rtx && rtcParameters.rtx->ssrc)
967         parameters.rtx.ssrc = *rtcParameters.rtx->ssrc;
968     if (rtcParameters.fec && rtcParameters.fec->ssrc)
969         parameters.fec.ssrc = *rtcParameters.fec->ssrc;
970     if (rtcParameters.dtx) {
971         switch (*rtcParameters.dtx) {
972         case webrtc::DtxStatus::DISABLED:
973             parameters.dtx = RTCRtpParameters::DtxStatus::Disabled;
974             break;
975         case webrtc::DtxStatus::ENABLED:
976             parameters.dtx = RTCRtpParameters::DtxStatus::Enabled;
977         }
978     }
979     parameters.active = rtcParameters.active;
980     if (rtcParameters.priority) {
981         switch (*rtcParameters.priority) {
982         case webrtc::PriorityType::VERY_LOW:
983             parameters.priority = RTCRtpParameters::PriorityType::VeryLow;
984             break;
985         case webrtc::PriorityType::LOW:
986             parameters.priority = RTCRtpParameters::PriorityType::Low;
987             break;
988         case webrtc::PriorityType::MEDIUM:
989             parameters.priority = RTCRtpParameters::PriorityType::Medium;
990             break;
991         case webrtc::PriorityType::HIGH:
992             parameters.priority = RTCRtpParameters::PriorityType::High;
993             break;
994         }
995     }
996     if (rtcParameters.max_bitrate_bps)
997         parameters.maxBitrate = *rtcParameters.max_bitrate_bps;
998     if (rtcParameters.max_framerate)
999         parameters.maxFramerate = *rtcParameters.max_framerate;
1000     parameters.rid = fromStdString(rtcParameters.rid);
1001     parameters.scaleResolutionDownBy = rtcParameters.scale_resolution_down_by;
1002
1003     return parameters;
1004 }
1005
1006 static inline RTCRtpParameters::HeaderExtensionParameters fillHeaderExtensionParameters(const webrtc::RtpHeaderExtensionParameters& rtcParameters)
1007 {
1008     RTCRtpParameters::HeaderExtensionParameters parameters;
1009
1010     parameters.uri = fromStdString(rtcParameters.uri);
1011     parameters.id = rtcParameters.id;
1012
1013     return parameters;
1014 }
1015
1016 static inline RTCRtpParameters::CodecParameters fillCodecParameters(const webrtc::RtpCodecParameters& rtcParameters)
1017 {
1018     RTCRtpParameters::CodecParameters parameters;
1019
1020     parameters.payloadType = rtcParameters.payload_type;
1021     parameters.mimeType = fromStdString(rtcParameters.mime_type());
1022     if (rtcParameters.clock_rate)
1023         parameters.clockRate = *rtcParameters.clock_rate;
1024     if (rtcParameters.num_channels)
1025         parameters.channels = *rtcParameters.num_channels;
1026
1027     return parameters;
1028 }
1029
1030 static RTCRtpParameters fillRtpParameters(const webrtc::RtpParameters rtcParameters)
1031 {
1032     RTCRtpParameters parameters;
1033
1034     parameters.transactionId = fromStdString(rtcParameters.transaction_id);
1035     for (auto& rtcEncoding : rtcParameters.encodings)
1036         parameters.encodings.append(fillEncodingParameters(rtcEncoding));
1037     for (auto& extension : rtcParameters.header_extensions)
1038         parameters.headerExtensions.append(fillHeaderExtensionParameters(extension));
1039     for (auto& codec : rtcParameters.codecs)
1040         parameters.codecs.append(fillCodecParameters(codec));
1041
1042     switch (rtcParameters.degradation_preference) {
1043     case webrtc::DegradationPreference::MAINTAIN_FRAMERATE:
1044         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::MaintainFramerate;
1045         break;
1046     case webrtc::DegradationPreference::MAINTAIN_RESOLUTION:
1047         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::MaintainResolution;
1048         break;
1049     case webrtc::DegradationPreference::BALANCED:
1050         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::Balanced;
1051         break;
1052     };
1053     return parameters;
1054 }
1055
1056 RTCRtpParameters RTCRtpReceiverBackend::getParameters()
1057 {
1058     return fillRtpParameters(m_rtcReceiver->GetParameters());
1059 }
1060
1061 RTCRtpParameters LibWebRTCMediaEndpoint::getRTCRtpSenderParameters(RTCRtpSender& sender)
1062 {
1063     auto rtcSender = m_senders.get(&sender);
1064     if (!rtcSender)
1065         return { };
1066     return fillRtpParameters(rtcSender->GetParameters());
1067 }
1068
1069 void LibWebRTCMediaEndpoint::gatherStatsForLogging()
1070 {
1071     LibWebRTCProvider::callOnWebRTCSignalingThread([protectedThis = makeRef(*this)] {
1072         if (protectedThis->m_backend)
1073             protectedThis->m_backend->GetStats(protectedThis.ptr());
1074     });
1075 }
1076
1077 void LibWebRTCMediaEndpoint::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report)
1078 {
1079 #if !RELEASE_LOG_DISABLED
1080     int64_t timestamp = report->timestamp_us();
1081     if (!m_statsFirstDeliveredTimestamp)
1082         m_statsFirstDeliveredTimestamp = timestamp;
1083
1084     callOnMainThread([protectedThis = makeRef(*this), this, timestamp, report] {
1085         if (m_statsLogTimer.repeatInterval() != statsLogInterval(timestamp)) {
1086             m_statsLogTimer.stop();
1087             m_statsLogTimer.startRepeating(statsLogInterval(timestamp));
1088         }
1089
1090         for (auto iterator = report->begin(); iterator != report->end(); ++iterator) {
1091             if (iterator->type() == webrtc::RTCCodecStats::kType)
1092                 continue;
1093
1094             ALWAYS_LOG(LOGIDENTIFIER, "WebRTC stats for :", *iterator);
1095         }
1096     });
1097 #else
1098     UNUSED_PARAM(report);
1099 #endif
1100 }
1101
1102 void LibWebRTCMediaEndpoint::startLoggingStats()
1103 {
1104 #if !RELEASE_LOG_DISABLED
1105     if (m_statsLogTimer.isActive())
1106         m_statsLogTimer.stop();
1107     m_statsLogTimer.startRepeating(statsLogInterval(0));
1108 #endif
1109 }
1110
1111 void LibWebRTCMediaEndpoint::stopLoggingStats()
1112 {
1113     m_statsLogTimer.stop();
1114 }
1115
1116 #if !RELEASE_LOG_DISABLED
1117 WTFLogChannel& LibWebRTCMediaEndpoint::logChannel() const
1118 {
1119     return LogWebRTC;
1120 }
1121
1122 Seconds LibWebRTCMediaEndpoint::statsLogInterval(int64_t reportTimestamp) const
1123 {
1124     if (logger().willLog(logChannel(), WTFLogLevelInfo))
1125         return 2_s;
1126
1127     if (reportTimestamp - m_statsFirstDeliveredTimestamp > 15000000)
1128         return 10_s;
1129
1130     return 4_s;
1131 }
1132 #endif
1133
1134 } // namespace WebCore
1135
1136 #endif // USE(LIBWEBRTC)