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