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