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