blob: 41e2527ebd6fcacd88efdf394fe2e0366680858d [file] [log] [blame]
// 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