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