| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h" |
| |
| #include "third_party/blink/public/platform/web_media_stream.h" |
| #include "third_party/blink/public/platform/web_media_stream_track.h" |
| #include "third_party/blink/public/platform/web_rtc_rtp_contributing_source.h" |
| #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h" |
| #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.h" |
| #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h" |
| #include "third_party/blink/renderer/modules/peerconnection/rtc_stats_report.h" |
| #include "third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h" |
| #include "third_party/blink/renderer/platform/bindings/microtask.h" |
| #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" |
| #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" |
| #include "third_party/webrtc/api/rtpparameters.h" |
| |
| namespace blink { |
| |
| RTCRtpReceiver::RTCRtpReceiver(RTCPeerConnection* pc, |
| std::unique_ptr<WebRTCRtpReceiver> receiver, |
| MediaStreamTrack* track, |
| MediaStreamVector streams) |
| : pc_(pc), |
| receiver_(std::move(receiver)), |
| track_(track), |
| streams_(std::move(streams)) { |
| DCHECK(receiver_); |
| DCHECK(track_); |
| } |
| |
| MediaStreamTrack* RTCRtpReceiver::track() const { |
| return track_; |
| } |
| |
| RTCDtlsTransport* RTCRtpReceiver::transport() { |
| if (!transceiver_) |
| return nullptr; |
| return pc_->LookupDtlsTransportByMid(transceiver_->mid()); |
| } |
| |
| RTCDtlsTransport* RTCRtpReceiver::rtcp_transport() { |
| // Chrome does not support turning off RTCP-mux. |
| return nullptr; |
| } |
| |
| HeapVector<Member<RTCRtpSynchronizationSource>> |
| RTCRtpReceiver::getSynchronizationSources() { |
| UpdateSourcesIfNeeded(); |
| HeapVector<Member<RTCRtpSynchronizationSource>> synchronization_sources; |
| for (const auto& web_source : web_sources_) { |
| // TODO(https://crbug.com/893172): Rename WebRTCRtpContributingSource to |
| // reflect that it is used for both SSRCs and CSRCs, e.g. "WebRTCRtpSource". |
| if (web_source->SourceType() != WebRTCRtpContributingSourceType::SSRC) |
| continue; |
| RTCRtpSynchronizationSource* synchronization_source = |
| MakeGarbageCollected<RTCRtpSynchronizationSource>(); |
| synchronization_source->setTimestamp(web_source->TimestampMs()); |
| synchronization_source->setSource(web_source->Source()); |
| synchronization_sources.push_back(synchronization_source); |
| } |
| return synchronization_sources; |
| } |
| |
| HeapVector<Member<RTCRtpContributingSource>> |
| RTCRtpReceiver::getContributingSources() { |
| UpdateSourcesIfNeeded(); |
| HeapVector<Member<RTCRtpContributingSource>> contributing_sources; |
| for (const auto& web_source : web_sources_) { |
| if (web_source->SourceType() != WebRTCRtpContributingSourceType::CSRC) |
| continue; |
| RTCRtpContributingSource* contributing_source = |
| MakeGarbageCollected<RTCRtpContributingSource>(); |
| contributing_source->setTimestamp(web_source->TimestampMs()); |
| contributing_source->setSource(web_source->Source()); |
| contributing_sources.push_back(contributing_source); |
| } |
| return contributing_sources; |
| } |
| |
| ScriptPromise RTCRtpReceiver::getStats(ScriptState* script_state) { |
| ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
| ScriptPromise promise = resolver->Promise(); |
| receiver_->GetStats(WebRTCStatsReportCallbackResolver::Create(resolver), |
| GetRTCStatsFilter(script_state)); |
| return promise; |
| } |
| |
| const WebRTCRtpReceiver& RTCRtpReceiver::web_receiver() const { |
| return *receiver_; |
| } |
| |
| MediaStreamVector RTCRtpReceiver::streams() const { |
| return streams_; |
| } |
| |
| void RTCRtpReceiver::set_streams(MediaStreamVector streams) { |
| streams_ = std::move(streams); |
| } |
| |
| void RTCRtpReceiver::set_transceiver(RTCRtpTransceiver* transceiver) { |
| transceiver_ = transceiver; |
| } |
| |
| void RTCRtpReceiver::UpdateSourcesIfNeeded() { |
| if (!web_sources_needs_updating_) |
| return; |
| web_sources_ = receiver_->GetSources(); |
| // Clear the flag and schedule a microtask to reset it to true. This makes |
| // the cache valid until the next microtask checkpoint. As such, sources |
| // represent a snapshot and can be compared reliably in .js code, no risk of |
| // being updated due to an RTP packet arriving. E.g. |
| // "source.timestamp == source.timestamp" will always be true. |
| web_sources_needs_updating_ = false; |
| Microtask::EnqueueMicrotask( |
| WTF::Bind(&RTCRtpReceiver::SetContributingSourcesNeedsUpdating, |
| WrapWeakPersistent(this))); |
| } |
| |
| void RTCRtpReceiver::SetContributingSourcesNeedsUpdating() { |
| web_sources_needs_updating_ = true; |
| } |
| |
| void RTCRtpReceiver::Trace(blink::Visitor* visitor) { |
| visitor->Trace(pc_); |
| visitor->Trace(track_); |
| visitor->Trace(streams_); |
| visitor->Trace(transceiver_); |
| ScriptWrappable::Trace(visitor); |
| } |
| |
| RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(const String& kind) { |
| if (kind != "audio" && kind != "video") |
| return nullptr; |
| |
| RTCRtpCapabilities* capabilities = RTCRtpCapabilities::Create(); |
| capabilities->setCodecs(HeapVector<Member<RTCRtpCodecCapability>>()); |
| capabilities->setHeaderExtensions( |
| HeapVector<Member<RTCRtpHeaderExtensionCapability>>()); |
| |
| std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities = |
| blink::Platform::Current()->GetRtpSenderCapabilities(kind); |
| |
| HeapVector<Member<RTCRtpCodecCapability>> codecs; |
| codecs.ReserveInitialCapacity( |
| SafeCast<wtf_size_t>(rtc_capabilities->codecs.size())); |
| for (const auto& rtc_codec : rtc_capabilities->codecs) { |
| auto* codec = RTCRtpCodecCapability::Create(); |
| codec->setMimeType(WTF::String::FromUTF8(rtc_codec.mime_type().c_str())); |
| if (rtc_codec.clock_rate) |
| codec->setClockRate(rtc_codec.clock_rate.value()); |
| if (rtc_codec.num_channels) |
| codec->setChannels(rtc_codec.num_channels.value()); |
| if (rtc_codec.parameters.size()) { |
| std::string sdp_fmtp_line; |
| for (const auto& parameter : rtc_codec.parameters) { |
| if (sdp_fmtp_line.size()) |
| sdp_fmtp_line += ";"; |
| sdp_fmtp_line += parameter.first + "=" + parameter.second; |
| } |
| codec->setSdpFmtpLine(sdp_fmtp_line.c_str()); |
| } |
| codecs.push_back(codec); |
| } |
| capabilities->setCodecs(codecs); |
| |
| HeapVector<Member<RTCRtpHeaderExtensionCapability>> header_extensions; |
| header_extensions.ReserveInitialCapacity( |
| SafeCast<wtf_size_t>(rtc_capabilities->header_extensions.size())); |
| for (const auto& rtc_header_extension : rtc_capabilities->header_extensions) { |
| auto* header_extension = RTCRtpHeaderExtensionCapability::Create(); |
| header_extension->setUri( |
| WTF::String::FromUTF8(rtc_header_extension.uri.c_str())); |
| header_extensions.push_back(header_extension); |
| } |
| capabilities->setHeaderExtensions(header_extensions); |
| |
| return capabilities; |
| } |
| |
| RTCRtpReceiveParameters* RTCRtpReceiver::getParameters() { |
| RTCRtpReceiveParameters* parameters = RTCRtpReceiveParameters::Create(); |
| std::unique_ptr<webrtc::RtpParameters> webrtc_parameters = |
| receiver_->GetParameters(); |
| |
| RTCRtcpParameters* rtcp = RTCRtcpParameters::Create(); |
| rtcp->setReducedSize(webrtc_parameters->rtcp.reduced_size); |
| parameters->setRtcp(rtcp); |
| |
| HeapVector<Member<RTCRtpDecodingParameters>> encodings; |
| encodings.ReserveCapacity( |
| SafeCast<wtf_size_t>(webrtc_parameters->encodings.size())); |
| for (const auto& webrtc_encoding : webrtc_parameters->encodings) { |
| RTCRtpDecodingParameters* encoding = RTCRtpDecodingParameters::Create(); |
| if (!webrtc_encoding.rid.empty()) { |
| // TODO(orphis): Add rid when supported by WebRTC |
| } |
| encodings.push_back(encoding); |
| } |
| parameters->setEncodings(encodings); |
| |
| HeapVector<Member<RTCRtpHeaderExtensionParameters>> headers; |
| headers.ReserveCapacity( |
| SafeCast<wtf_size_t>(webrtc_parameters->header_extensions.size())); |
| for (const auto& webrtc_header : webrtc_parameters->header_extensions) { |
| headers.push_back(ToRtpHeaderExtensionParameters(webrtc_header)); |
| } |
| parameters->setHeaderExtensions(headers); |
| |
| HeapVector<Member<RTCRtpCodecParameters>> codecs; |
| codecs.ReserveCapacity( |
| SafeCast<wtf_size_t>(webrtc_parameters->codecs.size())); |
| for (const auto& webrtc_codec : webrtc_parameters->codecs) { |
| codecs.push_back(ToRtpCodecParameters(webrtc_codec)); |
| } |
| parameters->setCodecs(codecs); |
| |
| return parameters; |
| } |
| |
| } // namespace blink |