Make sure LibWebRTCMediaEndpoint is always destroyed on the main thread
[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 "RealtimeOutgoingAudioSource.h"
50 #include "RealtimeOutgoingVideoSource.h"
51 #include "RuntimeEnabledFeatures.h"
52 #include <webrtc/rtc_base/physicalsocketserver.h>
53 #include <webrtc/p2p/base/basicpacketsocketfactory.h>
54 #include <webrtc/p2p/client/basicportallocator.h>
55 #include <webrtc/pc/peerconnectionfactory.h>
56 #include <wtf/MainThread.h>
57
58 namespace WebCore {
59
60 static inline String fromStdString(const std::string& value)
61 {
62     return String::fromUTF8(value.data(), value.length());
63 }
64
65 LibWebRTCMediaEndpoint::LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend& peerConnection, LibWebRTCProvider& client)
66     : m_peerConnectionBackend(peerConnection)
67     , m_peerConnectionFactory(*client.factory())
68     , m_createSessionDescriptionObserver(*this)
69     , m_setLocalSessionDescriptionObserver(*this)
70     , m_setRemoteSessionDescriptionObserver(*this)
71     , m_statsLogTimer(*this, &LibWebRTCMediaEndpoint::gatherStatsForLogging)
72 #if !RELEASE_LOG_DISABLED
73     , m_logger(peerConnection.logger())
74     , m_logIdentifier(peerConnection.logIdentifier())
75 #endif
76 {
77     ASSERT(isMainThread());
78     ASSERT(client.factory());
79 }
80
81 bool LibWebRTCMediaEndpoint::setConfiguration(LibWebRTCProvider& client, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
82 {
83     if (!m_backend) {
84         m_backend = client.createPeerConnection(*this, WTFMove(configuration));
85         return !!m_backend;
86     }
87     return m_backend->SetConfiguration(WTFMove(configuration));
88 }
89
90 static inline const char* sessionDescriptionType(RTCSdpType sdpType)
91 {
92     switch (sdpType) {
93     case RTCSdpType::Offer:
94         return "offer";
95     case RTCSdpType::Pranswer:
96         return "pranswer";
97     case RTCSdpType::Answer:
98         return "answer";
99     case RTCSdpType::Rollback:
100         return "rollback";
101     }
102
103     ASSERT_NOT_REACHED();
104     return "";
105 }
106
107 static inline RTCSdpType fromSessionDescriptionType(const webrtc::SessionDescriptionInterface& description)
108 {
109     auto type = description.type();
110     if (type == webrtc::SessionDescriptionInterface::kOffer)
111         return RTCSdpType::Offer;
112     if (type == webrtc::SessionDescriptionInterface::kAnswer)
113         return RTCSdpType::Answer;
114     ASSERT(type == webrtc::SessionDescriptionInterface::kPrAnswer);
115     return RTCSdpType::Pranswer;
116 }
117
118 static inline RefPtr<RTCSessionDescription> fromSessionDescription(const webrtc::SessionDescriptionInterface* description)
119 {
120     if (!description)
121         return nullptr;
122
123     std::string sdp;
124     description->ToString(&sdp);
125
126     return RTCSessionDescription::create(fromSessionDescriptionType(*description), fromStdString(sdp));
127 }
128
129 // FIXME: We might want to create a new object only if the session actually changed for all description getters.
130 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentLocalDescription() const
131 {
132     return m_backend ? fromSessionDescription(m_backend->current_local_description()) : nullptr;
133 }
134
135 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::currentRemoteDescription() const
136 {
137     return m_backend ? fromSessionDescription(m_backend->current_remote_description()) : nullptr;
138 }
139
140 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingLocalDescription() const
141 {
142     return m_backend ? fromSessionDescription(m_backend->pending_local_description()) : nullptr;
143 }
144
145 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::pendingRemoteDescription() const
146 {
147     return m_backend ? fromSessionDescription(m_backend->pending_remote_description()) : nullptr;
148 }
149
150 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::localDescription() const
151 {
152     return m_backend ? fromSessionDescription(m_backend->local_description()) : nullptr;
153 }
154
155 RefPtr<RTCSessionDescription> LibWebRTCMediaEndpoint::remoteDescription() const
156 {
157     return m_backend ? fromSessionDescription(m_backend->remote_description()) : nullptr;
158 }
159
160 void LibWebRTCMediaEndpoint::doSetLocalDescription(RTCSessionDescription& description)
161 {
162     ASSERT(m_backend);
163
164     webrtc::SdpParseError error;
165     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
166
167     if (!sessionDescription) {
168         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, fromStdString(error.description) });
169         return;
170     }
171
172     // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=173783. Remove this test once fixed at LibWebRTC level.
173     if (description.type() == RTCSdpType::Answer && !m_backend->pending_remote_description()) {
174         m_peerConnectionBackend.setLocalDescriptionFailed(Exception { InvalidStateError, "Failed to set local answer sdp: no pending remote description."_s });
175         return;
176     }
177
178     m_backend->SetLocalDescription(&m_setLocalSessionDescriptionObserver, sessionDescription.release());
179 }
180
181 void LibWebRTCMediaEndpoint::doSetRemoteDescription(RTCSessionDescription& description)
182 {
183     ASSERT(m_backend);
184
185     webrtc::SdpParseError error;
186     std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
187     if (!sessionDescription) {
188         m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, fromStdString(error.description) });
189         return;
190     }
191     m_backend->SetRemoteDescription(&m_setRemoteSessionDescriptionObserver, sessionDescription.release());
192
193     startLoggingStats();
194 }
195
196 void LibWebRTCMediaEndpoint::addTrack(RTCRtpSender& sender, MediaStreamTrack& track, const Vector<String>& mediaStreamIds)
197 {
198     ASSERT(m_backend);
199
200     std::vector<webrtc::MediaStreamInterface*> mediaStreams;
201     rtc::scoped_refptr<webrtc::MediaStreamInterface> mediaStream = nullptr;
202     if (mediaStreamIds.size()) {
203         // libwebrtc is only using the first one if any.
204         mediaStream = m_peerConnectionFactory.CreateLocalMediaStream(mediaStreamIds[0].utf8().data());
205         mediaStreams.push_back(mediaStream.get());
206     }
207     
208     switch (track.privateTrack().type()) {
209     case RealtimeMediaSource::Type::Audio: {
210         auto trackSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
211         auto audioTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), trackSource.ptr());
212         m_peerConnectionBackend.addAudioSource(WTFMove(trackSource));
213         m_senders.add(&sender, m_backend->AddTrack(audioTrack.get(), WTFMove(mediaStreams)));
214         return;
215     }
216     case RealtimeMediaSource::Type::Video: {
217         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
218         auto videoTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
219         m_peerConnectionBackend.addVideoSource(WTFMove(videoSource));
220         m_senders.add(&sender, m_backend->AddTrack(videoTrack.get(), WTFMove(mediaStreams)));
221         return;
222     }
223     case RealtimeMediaSource::Type::None:
224         ASSERT_NOT_REACHED();
225     }
226 }
227
228 void LibWebRTCMediaEndpoint::removeTrack(RTCRtpSender& sender)
229 {
230     ASSERT(m_backend);
231
232     auto rtcSender = m_senders.get(&sender);
233     if (!rtcSender)
234         return;
235     m_backend->RemoveTrack(rtcSender.get());
236 }
237
238 bool LibWebRTCMediaEndpoint::shouldOfferAllowToReceiveAudio() const
239 {
240     for (const auto& transceiver : m_peerConnectionBackend.connection().getTransceivers()) {
241         if (transceiver->sender().trackKind() != "audio")
242             continue;
243
244         if (transceiver->direction() == RTCRtpTransceiverDirection::Recvonly)
245             return true;
246
247         if (transceiver->direction() == RTCRtpTransceiverDirection::Sendrecv && !m_senders.contains(&transceiver->sender()))
248             return true;
249     }
250     return false;
251 }
252
253 bool LibWebRTCMediaEndpoint::shouldOfferAllowToReceiveVideo() const
254 {
255     for (const auto& transceiver : m_peerConnectionBackend.connection().getTransceivers()) {
256         if (transceiver->sender().trackKind() != "video")
257             continue;
258
259         if (transceiver->direction() == RTCRtpTransceiverDirection::Recvonly)
260             return true;
261
262         if (transceiver->direction() == RTCRtpTransceiverDirection::Sendrecv && !m_senders.contains(&transceiver->sender()))
263             return true;
264     }
265     return false;
266 }
267
268 void LibWebRTCMediaEndpoint::doCreateOffer(const RTCOfferOptions& options)
269 {
270     ASSERT(m_backend);
271
272     m_isInitiator = true;
273     webrtc::PeerConnectionInterface::RTCOfferAnswerOptions rtcOptions;
274     rtcOptions.ice_restart = options.iceRestart;
275     rtcOptions.voice_activity_detection = options.voiceActivityDetection;
276     // FIXME: offer_to_receive_audio and offer_to_receive_video are used as libwebrtc does not support transceivers yet.
277     if (shouldOfferAllowToReceiveAudio())
278         rtcOptions.offer_to_receive_audio = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
279     if (shouldOfferAllowToReceiveVideo())
280         rtcOptions.offer_to_receive_video = webrtc::PeerConnectionInterface::RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
281     m_backend->CreateOffer(&m_createSessionDescriptionObserver, rtcOptions);
282 }
283
284 void LibWebRTCMediaEndpoint::doCreateAnswer()
285 {
286     ASSERT(m_backend);
287
288     m_isInitiator = false;
289     m_backend->CreateAnswer(&m_createSessionDescriptionObserver, nullptr);
290 }
291
292 void LibWebRTCMediaEndpoint::getStats(MediaStreamTrack* track, const DeferredPromise& promise)
293 {
294     auto collector = StatsCollector::create(*this, promise, track);
295     LibWebRTCProvider::callOnWebRTCSignalingThread([protectedThis = makeRef(*this), collector = WTFMove(collector)] {
296         if (protectedThis->m_backend)
297             protectedThis->m_backend->GetStats(collector.get());
298     });
299 }
300
301 LibWebRTCMediaEndpoint::StatsCollector::StatsCollector(Ref<LibWebRTCMediaEndpoint>&& endpoint, const DeferredPromise& promise, MediaStreamTrack* track)
302     : m_endpoint(WTFMove(endpoint))
303     , m_promise(promise)
304 {
305     if (track)
306         m_id = track->id();
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 MediaStream& LibWebRTCMediaEndpoint::mediaStreamFromRTCStream(webrtc::MediaStreamInterface& rtcStream)
620 {
621     auto mediaStream = m_streams.ensure(&rtcStream, [&rtcStream, this] {
622         auto label = rtcStream.label();
623         auto stream = MediaStream::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), MediaStreamPrivate::create({ }, fromStdString(label)));
624         auto streamPointer = stream.ptr();
625         m_peerConnectionBackend.addRemoteStream(WTFMove(stream));
626         return streamPointer;
627     });
628     return *mediaStream.iterator->value;
629 }
630
631 void LibWebRTCMediaEndpoint::addRemoteStream(webrtc::MediaStreamInterface& rtcStream)
632 {
633     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCLegacyAPIEnabled())
634         return;
635
636     auto& mediaStream = mediaStreamFromRTCStream(rtcStream);
637     m_peerConnectionBackend.connection().fireEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, &mediaStream));
638 }
639
640 class RTCRtpReceiverBackend final : public RTCRtpReceiver::Backend {
641 public:
642     explicit RTCRtpReceiverBackend(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& rtcReceiver) : m_rtcReceiver(WTFMove(rtcReceiver)) { }
643 private:
644     RTCRtpParameters getParameters() final;
645
646     rtc::scoped_refptr<webrtc::RtpReceiverInterface> m_rtcReceiver;
647 };
648
649
650 void LibWebRTCMediaEndpoint::addRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&& rtcReceiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& rtcStreams)
651 {
652     ASSERT(rtcReceiver);
653     RefPtr<RTCRtpReceiver> receiver;
654     RefPtr<RealtimeMediaSource> remoteSource;
655
656     auto* rtcTrack = rtcReceiver->track().get();
657
658     switch (rtcReceiver->media_type()) {
659     case cricket::MEDIA_TYPE_DATA:
660         return;
661     case cricket::MEDIA_TYPE_AUDIO: {
662         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack);
663         auto audioReceiver = m_peerConnectionBackend.audioReceiver(fromStdString(rtcTrack->id()));
664
665         receiver = WTFMove(audioReceiver.receiver);
666         audioReceiver.source->setSourceTrack(WTFMove(audioTrack));
667         break;
668     }
669     case cricket::MEDIA_TYPE_VIDEO: {
670         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack);
671         auto videoReceiver = m_peerConnectionBackend.videoReceiver(fromStdString(rtcTrack->id()));
672
673         receiver = WTFMove(videoReceiver.receiver);
674         videoReceiver.source->setSourceTrack(WTFMove(videoTrack));
675         break;
676     }
677     }
678
679     receiver->setBackend(std::make_unique<RTCRtpReceiverBackend>(WTFMove(rtcReceiver)));
680     
681     auto* track = receiver->track();
682     ASSERT(track);
683
684     Vector<RefPtr<MediaStream>> streams;
685     for (auto& rtcStream : rtcStreams) {
686         auto& mediaStream = mediaStreamFromRTCStream(*rtcStream.get());
687         streams.append(&mediaStream);
688         mediaStream.addTrackFromPlatform(*track);
689     }
690     m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false, WTFMove(receiver), track, WTFMove(streams), nullptr));
691 }
692
693 void LibWebRTCMediaEndpoint::removeRemoteStream(webrtc::MediaStreamInterface& rtcStream)
694 {
695     auto* mediaStream = m_streams.take(&rtcStream);
696     if (mediaStream)
697         m_peerConnectionBackend.removeRemoteStream(mediaStream);
698 }
699
700 void LibWebRTCMediaEndpoint::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
701 {
702     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
703         if (protectedThis->isStopped())
704             return;
705         ASSERT(stream);
706         protectedThis->addRemoteStream(*stream.get());
707     });
708 }
709
710 void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
711 {
712     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
713         if (protectedThis->isStopped())
714             return;
715         ASSERT(stream);
716         protectedThis->removeRemoteStream(*stream.get());
717     });
718 }
719
720 void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams)
721 {
722     callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver), streams]() mutable {
723         if (protectedThis->isStopped())
724             return;
725         protectedThis->addRemoteTrack(WTFMove(receiver), streams);
726     });
727 }
728
729 std::unique_ptr<RTCDataChannelHandler> LibWebRTCMediaEndpoint::createDataChannel(const String& label, const RTCDataChannelInit& options)
730 {
731     ASSERT(m_backend);
732
733     webrtc::DataChannelInit init;
734     if (options.ordered)
735         init.ordered = *options.ordered;
736     if (options.maxPacketLifeTime)
737         init.maxRetransmitTime = *options.maxPacketLifeTime;
738     if (options.maxRetransmits)
739         init.maxRetransmits = *options.maxRetransmits;
740     init.protocol = options.protocol.utf8().data();
741     if (options.negotiated)
742         init.negotiated = *options.negotiated;
743     if (options.id)
744         init.id = *options.id;
745
746     auto channel = m_backend->CreateDataChannel(label.utf8().data(), &init);
747     if (!channel)
748         return nullptr;
749
750     return std::make_unique<LibWebRTCDataChannelHandler>(WTFMove(channel));
751 }
752
753 void LibWebRTCMediaEndpoint::addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>&& dataChannel)
754 {
755     auto protocol = dataChannel->protocol();
756     auto label = dataChannel->label();
757
758     RTCDataChannelInit init;
759     init.ordered = dataChannel->ordered();
760     init.maxPacketLifeTime = dataChannel->maxRetransmitTime();
761     init.maxRetransmits = dataChannel->maxRetransmits();
762     init.protocol = fromStdString(protocol);
763     init.negotiated = dataChannel->negotiated();
764     init.id = dataChannel->id();
765
766     bool isOpened = dataChannel->state() == webrtc::DataChannelInterface::kOpen;
767
768     auto handler =  std::make_unique<LibWebRTCDataChannelHandler>(WTFMove(dataChannel));
769     ASSERT(m_peerConnectionBackend.connection().scriptExecutionContext());
770     auto channel = RTCDataChannel::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(handler), fromStdString(label), WTFMove(init));
771
772     if (isOpened) {
773         callOnMainThread([channel = channel.copyRef()] {
774             // FIXME: We should be able to write channel->didChangeReadyState(...)
775             RTCDataChannelHandlerClient& client = channel.get();
776             client.didChangeReadyState(RTCDataChannelState::Open);
777         });
778     }
779
780     m_peerConnectionBackend.connection().fireEvent(RTCDataChannelEvent::create(eventNames().datachannelEvent, false, false, WTFMove(channel)));
781 }
782
783 void LibWebRTCMediaEndpoint::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel)
784 {
785     callOnMainThread([protectedThis = makeRef(*this), dataChannel = WTFMove(dataChannel)] {
786         if (protectedThis->isStopped())
787             return;
788         protectedThis->addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>(dataChannel));
789     });
790 }
791
792 void LibWebRTCMediaEndpoint::stop()
793 {
794     if (!m_backend)
795         return;
796
797     stopLoggingStats();
798
799     m_backend->Close();
800     m_backend = nullptr;
801     m_streams.clear();
802     m_senders.clear();
803 }
804
805 void LibWebRTCMediaEndpoint::OnRenegotiationNeeded()
806 {
807     callOnMainThread([protectedThis = makeRef(*this)] {
808         if (protectedThis->isStopped())
809             return;
810         protectedThis->m_peerConnectionBackend.markAsNeedingNegotiation();
811     });
812 }
813
814 static inline RTCIceConnectionState toRTCIceConnectionState(webrtc::PeerConnectionInterface::IceConnectionState state)
815 {
816     switch (state) {
817     case webrtc::PeerConnectionInterface::kIceConnectionNew:
818         return RTCIceConnectionState::New;
819     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
820         return RTCIceConnectionState::Checking;
821     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
822         return RTCIceConnectionState::Connected;
823     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
824         return RTCIceConnectionState::Completed;
825     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
826         return RTCIceConnectionState::Failed;
827     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
828         return RTCIceConnectionState::Disconnected;
829     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
830         return RTCIceConnectionState::Closed;
831     case webrtc::PeerConnectionInterface::kIceConnectionMax:
832         break;
833     }
834
835     ASSERT_NOT_REACHED();
836     return RTCIceConnectionState::New;
837 }
838
839 void LibWebRTCMediaEndpoint::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state)
840 {
841     auto connectionState = toRTCIceConnectionState(state);
842     callOnMainThread([protectedThis = makeRef(*this), connectionState] {
843         if (protectedThis->isStopped())
844             return;
845         if (protectedThis->m_peerConnectionBackend.connection().iceConnectionState() != connectionState)
846             protectedThis->m_peerConnectionBackend.connection().updateIceConnectionState(connectionState);
847     });
848 }
849
850 void LibWebRTCMediaEndpoint::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState state)
851 {
852     callOnMainThread([protectedThis = makeRef(*this), state] {
853         if (protectedThis->isStopped())
854             return;
855         if (state == webrtc::PeerConnectionInterface::kIceGatheringComplete)
856             protectedThis->m_peerConnectionBackend.doneGatheringCandidates();
857         else if (state == webrtc::PeerConnectionInterface::kIceGatheringGathering)
858             protectedThis->m_peerConnectionBackend.connection().updateIceGatheringState(RTCIceGatheringState::Gathering);
859     });
860 }
861
862 void LibWebRTCMediaEndpoint::OnIceCandidate(const webrtc::IceCandidateInterface *rtcCandidate)
863 {
864     ASSERT(rtcCandidate);
865
866     std::string sdp;
867     rtcCandidate->ToString(&sdp);
868
869     auto sdpMLineIndex = safeCast<unsigned short>(rtcCandidate->sdp_mline_index());
870
871     callOnMainThread([protectedThis = makeRef(*this), mid = fromStdString(rtcCandidate->sdp_mid()), sdp = fromStdString(sdp), sdpMLineIndex, url = fromStdString(rtcCandidate->server_url())]() mutable {
872         if (protectedThis->isStopped())
873             return;
874         protectedThis->m_peerConnectionBackend.newICECandidate(WTFMove(sdp), WTFMove(mid), sdpMLineIndex, WTFMove(url));
875     });
876 }
877
878 void LibWebRTCMediaEndpoint::OnIceCandidatesRemoved(const std::vector<cricket::Candidate>&)
879 {
880     ASSERT_NOT_REACHED();
881 }
882
883 void LibWebRTCMediaEndpoint::createSessionDescriptionSucceeded(std::unique_ptr<webrtc::SessionDescriptionInterface>&& description)
884 {
885     std::string sdp;
886     description->ToString(&sdp);
887
888     callOnMainThread([protectedThis = makeRef(*this), sdp = fromStdString(sdp)]() mutable {
889         if (protectedThis->isStopped())
890             return;
891         if (protectedThis->m_isInitiator)
892             protectedThis->m_peerConnectionBackend.createOfferSucceeded(WTFMove(sdp));
893         else
894             protectedThis->m_peerConnectionBackend.createAnswerSucceeded(WTFMove(sdp));
895     });
896 }
897
898 void LibWebRTCMediaEndpoint::createSessionDescriptionFailed(const std::string& errorMessage)
899 {
900     callOnMainThread([protectedThis = makeRef(*this), error = fromStdString(errorMessage)] () mutable {
901         if (protectedThis->isStopped())
902             return;
903         if (protectedThis->m_isInitiator)
904             protectedThis->m_peerConnectionBackend.createOfferFailed(Exception { OperationError, WTFMove(error) });
905         else
906             protectedThis->m_peerConnectionBackend.createAnswerFailed(Exception { OperationError, WTFMove(error) });
907     });
908 }
909
910 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionSucceeded()
911 {
912     callOnMainThread([protectedThis = makeRef(*this)] {
913         if (protectedThis->isStopped())
914             return;
915         protectedThis->m_peerConnectionBackend.setLocalDescriptionSucceeded();
916     });
917 }
918
919 void LibWebRTCMediaEndpoint::setLocalSessionDescriptionFailed(const std::string& errorMessage)
920 {
921     callOnMainThread([protectedThis = makeRef(*this), error = fromStdString(errorMessage)] () mutable {
922         if (protectedThis->isStopped())
923             return;
924         protectedThis->m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, WTFMove(error) });
925     });
926 }
927
928 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionSucceeded()
929 {
930     callOnMainThread([protectedThis = makeRef(*this)] {
931         if (protectedThis->isStopped())
932             return;
933         protectedThis->m_peerConnectionBackend.setRemoteDescriptionSucceeded();
934     });
935 }
936
937 void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionFailed(const std::string& errorMessage)
938 {
939     callOnMainThread([protectedThis = makeRef(*this), error = fromStdString(errorMessage)] () mutable {
940         if (protectedThis->isStopped())
941             return;
942         protectedThis->m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, WTFMove(error) });
943     });
944 }
945
946 static inline RTCRtpParameters::EncodingParameters fillEncodingParameters(const webrtc::RtpEncodingParameters& rtcParameters)
947 {
948     RTCRtpParameters::EncodingParameters parameters;
949
950     if (rtcParameters.ssrc)
951         parameters.ssrc = *rtcParameters.ssrc;
952     if (rtcParameters.rtx && rtcParameters.rtx->ssrc)
953         parameters.rtx.ssrc = *rtcParameters.rtx->ssrc;
954     if (rtcParameters.fec && rtcParameters.fec->ssrc)
955         parameters.fec.ssrc = *rtcParameters.fec->ssrc;
956     if (rtcParameters.dtx) {
957         switch (*rtcParameters.dtx) {
958         case webrtc::DtxStatus::DISABLED:
959             parameters.dtx = RTCRtpParameters::DtxStatus::Disabled;
960             break;
961         case webrtc::DtxStatus::ENABLED:
962             parameters.dtx = RTCRtpParameters::DtxStatus::Enabled;
963         }
964     }
965     parameters.active = rtcParameters.active;
966     if (rtcParameters.max_bitrate_bps)
967         parameters.maxBitrate = *rtcParameters.max_bitrate_bps;
968     if (rtcParameters.max_framerate)
969         parameters.maxFramerate = *rtcParameters.max_framerate;
970     parameters.rid = fromStdString(rtcParameters.rid);
971     parameters.scaleResolutionDownBy = rtcParameters.scale_resolution_down_by;
972
973     return parameters;
974 }
975
976 static inline RTCRtpParameters::HeaderExtensionParameters fillHeaderExtensionParameters(const webrtc::RtpHeaderExtensionParameters& rtcParameters)
977 {
978     RTCRtpParameters::HeaderExtensionParameters parameters;
979
980     parameters.uri = fromStdString(rtcParameters.uri);
981     parameters.id = rtcParameters.id;
982
983     return parameters;
984 }
985
986 static inline RTCRtpParameters::CodecParameters fillCodecParameters(const webrtc::RtpCodecParameters& rtcParameters)
987 {
988     RTCRtpParameters::CodecParameters parameters;
989
990     parameters.payloadType = rtcParameters.payload_type;
991     parameters.mimeType = fromStdString(rtcParameters.mime_type());
992     if (rtcParameters.clock_rate)
993         parameters.clockRate = *rtcParameters.clock_rate;
994     if (rtcParameters.num_channels)
995         parameters.channels = *rtcParameters.num_channels;
996
997     return parameters;
998 }
999
1000 static RTCRtpParameters fillRtpParameters(const webrtc::RtpParameters rtcParameters)
1001 {
1002     RTCRtpParameters parameters;
1003
1004     parameters.transactionId = fromStdString(rtcParameters.transaction_id);
1005     for (auto& rtcEncoding : rtcParameters.encodings)
1006         parameters.encodings.append(fillEncodingParameters(rtcEncoding));
1007     for (auto& extension : rtcParameters.header_extensions)
1008         parameters.headerExtensions.append(fillHeaderExtensionParameters(extension));
1009     for (auto& codec : rtcParameters.codecs)
1010         parameters.codecs.append(fillCodecParameters(codec));
1011
1012     switch (rtcParameters.degradation_preference) {
1013     case webrtc::DegradationPreference::MAINTAIN_FRAMERATE:
1014         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::MaintainFramerate;
1015         break;
1016     case webrtc::DegradationPreference::MAINTAIN_RESOLUTION:
1017         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::MaintainResolution;
1018         break;
1019     case webrtc::DegradationPreference::BALANCED:
1020         parameters.degradationPreference = RTCRtpParameters::DegradationPreference::Balanced;
1021         break;
1022     };
1023     return parameters;
1024 }
1025
1026 RTCRtpParameters RTCRtpReceiverBackend::getParameters()
1027 {
1028     return fillRtpParameters(m_rtcReceiver->GetParameters());
1029 }
1030
1031 RTCRtpParameters LibWebRTCMediaEndpoint::getRTCRtpSenderParameters(RTCRtpSender& sender)
1032 {
1033     auto rtcSender = m_senders.get(&sender);
1034     if (!rtcSender)
1035         return { };
1036     return fillRtpParameters(rtcSender->GetParameters());
1037 }
1038
1039 void LibWebRTCMediaEndpoint::gatherStatsForLogging()
1040 {
1041     LibWebRTCProvider::callOnWebRTCSignalingThread([protectedThis = makeRef(*this)] {
1042         if (protectedThis->m_backend)
1043             protectedThis->m_backend->GetStats(protectedThis.ptr());
1044     });
1045 }
1046
1047 class RTCStatsLogger {
1048 public:
1049     explicit RTCStatsLogger(const webrtc::RTCStats& stats)
1050         : m_stats(stats)
1051     {
1052     }
1053
1054     String toJSONString() const { return String(m_stats.ToJson().c_str()); }
1055
1056 private:
1057     const webrtc::RTCStats& m_stats;
1058 };
1059
1060 void LibWebRTCMediaEndpoint::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report)
1061 {
1062 #if !RELEASE_LOG_DISABLED
1063     int64_t timestamp = report->timestamp_us();
1064     if (!m_statsFirstDeliveredTimestamp)
1065         m_statsFirstDeliveredTimestamp = timestamp;
1066
1067     callOnMainThread([protectedThis = makeRef(*this), this, timestamp, report] {
1068         if (m_statsLogTimer.repeatInterval() != statsLogInterval(timestamp)) {
1069             m_statsLogTimer.stop();
1070             m_statsLogTimer.startRepeating(statsLogInterval(timestamp));
1071         }
1072
1073         for (auto iterator = report->begin(); iterator != report->end(); ++iterator) {
1074             if (iterator->type() == webrtc::RTCCodecStats::kType)
1075                 continue;
1076
1077             ALWAYS_LOG(Logger::LogSiteIdentifier("LibWebRTCMediaEndpoint", "OnStatsDelivered", logIdentifier()), RTCStatsLogger { *iterator });
1078         }
1079     });
1080 #else
1081     UNUSED_PARAM(report);
1082 #endif
1083 }
1084
1085 void LibWebRTCMediaEndpoint::startLoggingStats()
1086 {
1087 #if !RELEASE_LOG_DISABLED
1088     if (m_statsLogTimer.isActive())
1089         m_statsLogTimer.stop();
1090     m_statsLogTimer.startRepeating(statsLogInterval(0));
1091 #endif
1092 }
1093
1094 void LibWebRTCMediaEndpoint::stopLoggingStats()
1095 {
1096     m_statsLogTimer.stop();
1097 }
1098
1099 #if !RELEASE_LOG_DISABLED
1100 WTFLogChannel& LibWebRTCMediaEndpoint::logChannel() const
1101 {
1102     return LogWebRTC;
1103 }
1104
1105 Seconds LibWebRTCMediaEndpoint::statsLogInterval(int64_t reportTimestamp) const
1106 {
1107     if (logger().willLog(logChannel(), WTFLogLevelInfo))
1108         return 2_s;
1109
1110     if (reportTimestamp - m_statsFirstDeliveredTimestamp > 15000000)
1111         return 10_s;
1112
1113     return 4_s;
1114 }
1115 #endif
1116
1117 } // namespace WebCore
1118
1119 namespace WTF {
1120
1121 template<typename Type>
1122 struct LogArgument;
1123
1124 template <>
1125 struct LogArgument<WebCore::RTCStatsLogger> {
1126     static String toString(const WebCore::RTCStatsLogger& logger)
1127     {
1128         return String(logger.toJSONString());
1129     }
1130 };
1131
1132 }; // namespace WTF
1133
1134
1135 #endif // USE(LIBWEBRTC)