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)