blob: 341b23203603c0e3475f2ff77899b63429661344 [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_rtp_capabilities.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(std::unique_ptr<WebRTCRtpReceiver> receiver,
MediaStreamTrack* track,
MediaStreamVector streams)
: receiver_(std::move(receiver)),
track_(track),
streams_(std::move(streams)) {
DCHECK(receiver_);
DCHECK(track_);
}
MediaStreamTrack* RTCRtpReceiver::track() const {
return track_;
}
const HeapVector<Member<RTCRtpContributingSource>>&
RTCRtpReceiver::getContributingSources() {
UpdateSourcesIfNeeded();
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::UpdateSourcesIfNeeded() {
if (!contributing_sources_needs_updating_)
return;
contributing_sources_.clear();
for (const std::unique_ptr<WebRTCRtpContributingSource>&
web_contributing_source : receiver_->GetSources()) {
if (web_contributing_source->SourceType() ==
WebRTCRtpContributingSourceType::SSRC) {
// TODO(hbos): When |getSynchronizationSources| is added to get SSRC
// sources don't ignore SSRCs here.
continue;
}
DCHECK_EQ(web_contributing_source->SourceType(),
WebRTCRtpContributingSourceType::CSRC);
RTCRtpContributingSource* contributing_source =
MakeGarbageCollected<RTCRtpContributingSource>(
this, *web_contributing_source);
contributing_sources_.push_back(contributing_source);
}
// 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.
contributing_sources_needs_updating_ = false;
Microtask::EnqueueMicrotask(
WTF::Bind(&RTCRtpReceiver::SetContributingSourcesNeedsUpdating,
WrapWeakPersistent(this)));
}
void RTCRtpReceiver::SetContributingSourcesNeedsUpdating() {
contributing_sources_needs_updating_ = true;
}
void RTCRtpReceiver::Trace(blink::Visitor* visitor) {
visitor->Trace(track_);
visitor->Trace(streams_);
visitor->Trace(contributing_sources_);
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;
}
} // namespace blink