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