blob: f4aba7a208eb42a924bcd7edce602b857d19e5f2 [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 "modules/peerconnection/RTCRtpReceiver.h"
#include "platform/bindings/Microtask.h"
#include "platform/wtf/text/WTFString.h"
#include "public/platform/WebMediaStream.h"
#include "public/platform/WebMediaStreamTrack.h"
#include "public/platform/WebRTCRtpContributingSource.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_);
// Some bots require #if around the DCHECK to avoid compile error about
// |StateMatchesWebReceiver| (which is behind #if) not being defined.
#if DCHECK_IS_ON()
DCHECK(StateMatchesWebReceiver());
#endif // DCHECK_IS_ON()
}
MediaStreamTrack* RTCRtpReceiver::track() const {
return track_;
}
const HeapVector<Member<RTCRtpContributingSource>>&
RTCRtpReceiver::getContributingSources() {
UpdateSourcesIfNeeded();
return contributing_sources_;
}
const WebRTCRtpReceiver& RTCRtpReceiver::web_receiver() const {
return *receiver_;
}
MediaStreamVector RTCRtpReceiver::streams() const {
return streams_;
}
#if DCHECK_IS_ON()
bool RTCRtpReceiver::StateMatchesWebReceiver() const {
if (track_->Component() !=
static_cast<MediaStreamComponent*>(receiver_->Track())) {
return false;
}
WebVector<WebMediaStream> web_streams = receiver_->Streams();
if (streams_.size() != web_streams.size())
return false;
for (size_t i = 0; i < streams_.size(); ++i) {
if (streams_[i]->Descriptor() !=
static_cast<MediaStreamDescriptor*>(web_streams[i])) {
return false;
}
}
return true;
}
#endif // DCHECK_IS_ON()
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);
auto it = contributing_sources_by_source_id_.find(
web_contributing_source->Source());
if (it == contributing_sources_by_source_id_.end()) {
RTCRtpContributingSource* contributing_source =
new RTCRtpContributingSource(this, *web_contributing_source);
contributing_sources_by_source_id_.insert(contributing_source->source(),
contributing_source);
contributing_sources_.push_back(contributing_source);
} else {
it->value->UpdateMembers(*web_contributing_source);
contributing_sources_.push_back(it->value);
}
}
// 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_by_source_id_);
visitor->Trace(contributing_sources_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink