Split rtp_receiver for readability.
Bug: webrtc:10304
Change-Id: I85e421060d8560cf36cdb5970ae190efc77e7709
Reviewed-on: https://webrtc-review.googlesource.com/c/122085
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Ruslan Burakov <kuddai@google.com>
Cr-Commit-Position: refs/heads/master@{#26634}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 5ea089f..5e16e26 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -128,6 +128,8 @@
visibility = [ "*" ]
cflags = []
sources = [
+ "audio_rtp_receiver.cc",
+ "audio_rtp_receiver.h",
"audio_track.cc",
"audio_track.h",
"data_channel.cc",
@@ -175,6 +177,8 @@
"stream_collection.h",
"track_media_info_map.cc",
"track_media_info_map.h",
+ "video_rtp_receiver.cc",
+ "video_rtp_receiver.h",
"video_track.cc",
"video_track.h",
"video_track_source.cc",
diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc
new file mode 100644
index 0000000..4602fda
--- /dev/null
+++ b/pc/audio_rtp_receiver.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pc/audio_rtp_receiver.h"
+
+#include <stddef.h>
+#include <utility>
+#include <vector>
+
+#include "api/media_stream_proxy.h"
+#include "api/media_stream_track_proxy.h"
+#include "pc/audio_track.h"
+#include "pc/media_stream.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/location.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/trace_event.h"
+
+namespace webrtc {
+
+AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
+ std::string receiver_id,
+ std::vector<std::string> stream_ids)
+ : AudioRtpReceiver(worker_thread,
+ receiver_id,
+ CreateStreamsFromIds(std::move(stream_ids))) {}
+
+AudioRtpReceiver::AudioRtpReceiver(
+ rtc::Thread* worker_thread,
+ const std::string& receiver_id,
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
+ : worker_thread_(worker_thread),
+ id_(receiver_id),
+ source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
+ track_(AudioTrackProxy::Create(rtc::Thread::Current(),
+ AudioTrack::Create(receiver_id, source_))),
+ cached_track_enabled_(track_->enabled()),
+ attachment_id_(GenerateUniqueId()) {
+ RTC_DCHECK(worker_thread_);
+ RTC_DCHECK(track_->GetSource()->remote());
+ track_->RegisterObserver(this);
+ track_->GetSource()->RegisterAudioObserver(this);
+ SetStreams(streams);
+}
+
+AudioRtpReceiver::~AudioRtpReceiver() {
+ track_->GetSource()->UnregisterAudioObserver(this);
+ track_->UnregisterObserver(this);
+ Stop();
+}
+
+void AudioRtpReceiver::OnChanged() {
+ if (cached_track_enabled_ != track_->enabled()) {
+ cached_track_enabled_ = track_->enabled();
+ Reconfigure();
+ }
+}
+
+bool AudioRtpReceiver::SetOutputVolume(double volume) {
+ RTC_DCHECK_GE(volume, 0.0);
+ RTC_DCHECK_LE(volume, 10.0);
+ RTC_DCHECK(media_channel_);
+ RTC_DCHECK(ssrc_);
+ return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
+ return media_channel_->SetOutputVolume(*ssrc_, volume);
+ });
+}
+
+void AudioRtpReceiver::OnSetVolume(double volume) {
+ RTC_DCHECK_GE(volume, 0);
+ RTC_DCHECK_LE(volume, 10);
+ cached_volume_ = volume;
+ if (!media_channel_ || !ssrc_) {
+ RTC_LOG(LS_ERROR)
+ << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
+ return;
+ }
+ // When the track is disabled, the volume of the source, which is the
+ // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
+ // setting the volume to the source when the track is disabled.
+ if (!stopped_ && track_->enabled()) {
+ if (!SetOutputVolume(cached_volume_)) {
+ RTC_NOTREACHED();
+ }
+ }
+}
+
+std::vector<std::string> AudioRtpReceiver::stream_ids() const {
+ std::vector<std::string> stream_ids(streams_.size());
+ for (size_t i = 0; i < streams_.size(); ++i)
+ stream_ids[i] = streams_[i]->id();
+ return stream_ids;
+}
+
+RtpParameters AudioRtpReceiver::GetParameters() const {
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return RtpParameters();
+ }
+ return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
+ return media_channel_->GetRtpReceiveParameters(*ssrc_);
+ });
+}
+
+bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
+ TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return false;
+ }
+ return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
+ return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
+ });
+}
+
+void AudioRtpReceiver::SetFrameDecryptor(
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
+ frame_decryptor_ = std::move(frame_decryptor);
+ // Special Case: Set the frame decryptor to any value on any existing channel.
+ if (media_channel_ && ssrc_.has_value() && !stopped_) {
+ worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
+ media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
+ });
+ }
+}
+
+rtc::scoped_refptr<FrameDecryptorInterface>
+AudioRtpReceiver::GetFrameDecryptor() const {
+ return frame_decryptor_;
+}
+
+void AudioRtpReceiver::Stop() {
+ // TODO(deadbeef): Need to do more here to fully stop receiving packets.
+ if (stopped_) {
+ return;
+ }
+ if (media_channel_ && ssrc_) {
+ // Allow that SetOutputVolume fail. This is the normal case when the
+ // underlying media channel has already been deleted.
+ SetOutputVolume(0.0);
+ }
+ stopped_ = true;
+}
+
+void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
+ if (!media_channel_) {
+ RTC_LOG(LS_ERROR)
+ << "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
+ return;
+ }
+ if (ssrc_ == ssrc) {
+ return;
+ }
+ if (ssrc_) {
+ source_->Stop(media_channel_, *ssrc_);
+ }
+ ssrc_ = ssrc;
+ source_->Start(media_channel_, *ssrc_);
+ Reconfigure();
+}
+
+void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
+ SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
+}
+
+void AudioRtpReceiver::SetStreams(
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
+ // Remove remote track from any streams that are going away.
+ for (const auto& existing_stream : streams_) {
+ bool removed = true;
+ for (const auto& stream : streams) {
+ if (existing_stream->id() == stream->id()) {
+ RTC_DCHECK_EQ(existing_stream.get(), stream.get());
+ removed = false;
+ break;
+ }
+ }
+ if (removed) {
+ existing_stream->RemoveTrack(track_);
+ }
+ }
+ // Add remote track to any streams that are new.
+ for (const auto& stream : streams) {
+ bool added = true;
+ for (const auto& existing_stream : streams_) {
+ if (stream->id() == existing_stream->id()) {
+ RTC_DCHECK_EQ(stream.get(), existing_stream.get());
+ added = false;
+ break;
+ }
+ }
+ if (added) {
+ stream->AddTrack(track_);
+ }
+ }
+ streams_ = streams;
+}
+
+std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return {};
+ }
+ return worker_thread_->Invoke<std::vector<RtpSource>>(
+ RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
+}
+
+void AudioRtpReceiver::Reconfigure() {
+ RTC_DCHECK(!stopped_);
+ if (!media_channel_ || !ssrc_) {
+ RTC_LOG(LS_ERROR)
+ << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
+ return;
+ }
+ if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
+ RTC_NOTREACHED();
+ }
+ // Reattach the frame decryptor if we were reconfigured.
+ MaybeAttachFrameDecryptorToMediaChannel(
+ ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
+}
+
+void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
+ observer_ = observer;
+ // Deliver any notifications the observer may have missed by being set late.
+ if (received_first_packet_ && observer_) {
+ observer_->OnFirstPacketReceived(media_type());
+ }
+}
+
+void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
+}
+
+void AudioRtpReceiver::NotifyFirstPacketReceived() {
+ if (observer_) {
+ observer_->OnFirstPacketReceived(media_type());
+ }
+ received_first_packet_ = true;
+}
+
+} // namespace webrtc
diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h
new file mode 100644
index 0000000..82c8d88
--- /dev/null
+++ b/pc/audio_rtp_receiver.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef PC_AUDIO_RTP_RECEIVER_H_
+#define PC_AUDIO_RTP_RECEIVER_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/crypto/frame_decryptor_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
+#include "media/base/media_channel.h"
+#include "pc/remote_audio_source.h"
+#include "pc/rtp_receiver.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+class AudioRtpReceiver : public ObserverInterface,
+ public AudioSourceInterface::AudioObserver,
+ public rtc::RefCountedObject<RtpReceiverInternal> {
+ public:
+ AudioRtpReceiver(rtc::Thread* worker_thread,
+ std::string receiver_id,
+ std::vector<std::string> stream_ids);
+ // TODO(https://crbug.com/webrtc/9480): Remove this when streams() is removed.
+ AudioRtpReceiver(
+ rtc::Thread* worker_thread,
+ const std::string& receiver_id,
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
+ virtual ~AudioRtpReceiver();
+
+ // ObserverInterface implementation
+ void OnChanged() override;
+
+ // AudioSourceInterface::AudioObserver implementation
+ void OnSetVolume(double volume) override;
+
+ rtc::scoped_refptr<AudioTrackInterface> audio_track() const {
+ return track_.get();
+ }
+
+ // RtpReceiverInterface implementation
+ rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
+ return track_.get();
+ }
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
+ return dtls_transport_;
+ }
+ std::vector<std::string> stream_ids() const override;
+ std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
+ const override {
+ return streams_;
+ }
+
+ cricket::MediaType media_type() const override {
+ return cricket::MEDIA_TYPE_AUDIO;
+ }
+
+ std::string id() const override { return id_; }
+
+ RtpParameters GetParameters() const override;
+ bool SetParameters(const RtpParameters& parameters) override;
+
+ void SetFrameDecryptor(
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
+
+ rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
+ const override;
+
+ // RtpReceiverInternal implementation.
+ void Stop() override;
+ void SetupMediaChannel(uint32_t ssrc) override;
+ uint32_t ssrc() const override { return ssrc_.value_or(0); }
+ void NotifyFirstPacketReceived() override;
+ void set_stream_ids(std::vector<std::string> stream_ids) override;
+ void set_transport(
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
+ dtls_transport_ = dtls_transport;
+ }
+ void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
+ streams) override;
+ void SetObserver(RtpReceiverObserverInterface* observer) override;
+
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
+
+ std::vector<RtpSource> GetSources() const override;
+ int AttachmentId() const override { return attachment_id_; }
+
+ private:
+ void Reconfigure();
+ bool SetOutputVolume(double volume);
+
+ rtc::Thread* const worker_thread_;
+ const std::string id_;
+ const rtc::scoped_refptr<RemoteAudioSource> source_;
+ const rtc::scoped_refptr<AudioTrackInterface> track_;
+ cricket::VoiceMediaChannel* media_channel_ = nullptr;
+ absl::optional<uint32_t> ssrc_;
+ std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
+ bool cached_track_enabled_;
+ double cached_volume_ = 1;
+ bool stopped_ = false;
+ RtpReceiverObserverInterface* observer_ = nullptr;
+ bool received_first_packet_ = false;
+ int attachment_id_ = 0;
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+};
+
+} // namespace webrtc
+
+#endif // PC_AUDIO_RTP_RECEIVER_H_
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 759bf47..0fe6732 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -30,6 +30,7 @@
#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "media/sctp/sctp_transport.h"
+#include "pc/audio_rtp_receiver.h"
#include "pc/audio_track.h"
#include "pc/channel.h"
#include "pc/channel_manager.h"
@@ -43,6 +44,7 @@
#include "pc/sctp_utils.h"
#include "pc/sdp_utils.h"
#include "pc/stream_collection.h"
+#include "pc/video_rtp_receiver.h"
#include "pc/video_track.h"
#include "rtc_base/bind.h"
#include "rtc_base/checks.h"
diff --git a/pc/rtp_receiver.cc b/pc/rtp_receiver.cc
index 60f5ea8..0b800c1 100644
--- a/pc/rtp_receiver.cc
+++ b/pc/rtp_receiver.cc
@@ -16,10 +16,7 @@
#include "api/media_stream_proxy.h"
#include "api/media_stream_track_proxy.h"
-#include "api/video_track_source_proxy.h"
-#include "pc/audio_track.h"
#include "pc/media_stream.h"
-#include "pc/video_track.h"
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
@@ -27,17 +24,15 @@
namespace webrtc {
-namespace {
-
// This function is only expected to be called on the signalling thread.
-int GenerateUniqueId() {
+int RtpReceiverInternal::GenerateUniqueId() {
static int g_unique_id = 0;
return ++g_unique_id;
}
-std::vector<rtc::scoped_refptr<MediaStreamInterface>> CreateStreamsFromIds(
- std::vector<std::string> stream_ids) {
+std::vector<rtc::scoped_refptr<MediaStreamInterface>>
+RtpReceiverInternal::CreateStreamsFromIds(std::vector<std::string> stream_ids) {
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams(
stream_ids.size());
for (size_t i = 0; i < stream_ids.size(); ++i) {
@@ -50,7 +45,7 @@
// Attempt to attach the frame decryptor to the current media channel on the
// correct worker thread only if both the media channel exists and a ssrc has
// been allocated to the stream.
-void MaybeAttachFrameDecryptorToMediaChannel(
+void RtpReceiverInternal::MaybeAttachFrameDecryptorToMediaChannel(
const absl::optional<uint32_t>& ssrc,
rtc::Thread* worker_thread,
rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor,
@@ -63,410 +58,4 @@
}
}
-} // namespace
-
-AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
- std::string receiver_id,
- std::vector<std::string> stream_ids)
- : AudioRtpReceiver(worker_thread,
- receiver_id,
- CreateStreamsFromIds(std::move(stream_ids))) {}
-
-AudioRtpReceiver::AudioRtpReceiver(
- rtc::Thread* worker_thread,
- const std::string& receiver_id,
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
- : worker_thread_(worker_thread),
- id_(receiver_id),
- source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
- track_(AudioTrackProxy::Create(rtc::Thread::Current(),
- AudioTrack::Create(receiver_id, source_))),
- cached_track_enabled_(track_->enabled()),
- attachment_id_(GenerateUniqueId()) {
- RTC_DCHECK(worker_thread_);
- RTC_DCHECK(track_->GetSource()->remote());
- track_->RegisterObserver(this);
- track_->GetSource()->RegisterAudioObserver(this);
- SetStreams(streams);
-}
-
-AudioRtpReceiver::~AudioRtpReceiver() {
- track_->GetSource()->UnregisterAudioObserver(this);
- track_->UnregisterObserver(this);
- Stop();
-}
-
-void AudioRtpReceiver::OnChanged() {
- if (cached_track_enabled_ != track_->enabled()) {
- cached_track_enabled_ = track_->enabled();
- Reconfigure();
- }
-}
-
-bool AudioRtpReceiver::SetOutputVolume(double volume) {
- RTC_DCHECK_GE(volume, 0.0);
- RTC_DCHECK_LE(volume, 10.0);
- RTC_DCHECK(media_channel_);
- RTC_DCHECK(ssrc_);
- return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
- return media_channel_->SetOutputVolume(*ssrc_, volume);
- });
-}
-
-void AudioRtpReceiver::OnSetVolume(double volume) {
- RTC_DCHECK_GE(volume, 0);
- RTC_DCHECK_LE(volume, 10);
- cached_volume_ = volume;
- if (!media_channel_ || !ssrc_) {
- RTC_LOG(LS_ERROR)
- << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
- return;
- }
- // When the track is disabled, the volume of the source, which is the
- // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
- // setting the volume to the source when the track is disabled.
- if (!stopped_ && track_->enabled()) {
- if (!SetOutputVolume(cached_volume_)) {
- RTC_NOTREACHED();
- }
- }
-}
-
-std::vector<std::string> AudioRtpReceiver::stream_ids() const {
- std::vector<std::string> stream_ids(streams_.size());
- for (size_t i = 0; i < streams_.size(); ++i)
- stream_ids[i] = streams_[i]->id();
- return stream_ids;
-}
-
-RtpParameters AudioRtpReceiver::GetParameters() const {
- if (!media_channel_ || !ssrc_ || stopped_) {
- return RtpParameters();
- }
- return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
- return media_channel_->GetRtpReceiveParameters(*ssrc_);
- });
-}
-
-bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
- TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
- if (!media_channel_ || !ssrc_ || stopped_) {
- return false;
- }
- return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
- return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
- });
-}
-
-void AudioRtpReceiver::SetFrameDecryptor(
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
- frame_decryptor_ = std::move(frame_decryptor);
- // Special Case: Set the frame decryptor to any value on any existing channel.
- if (media_channel_ && ssrc_.has_value() && !stopped_) {
- worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
- media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
- });
- }
-}
-
-rtc::scoped_refptr<FrameDecryptorInterface>
-AudioRtpReceiver::GetFrameDecryptor() const {
- return frame_decryptor_;
-}
-
-void AudioRtpReceiver::Stop() {
- // TODO(deadbeef): Need to do more here to fully stop receiving packets.
- if (stopped_) {
- return;
- }
- if (media_channel_ && ssrc_) {
- // Allow that SetOutputVolume fail. This is the normal case when the
- // underlying media channel has already been deleted.
- SetOutputVolume(0.0);
- }
- stopped_ = true;
-}
-
-void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
- if (!media_channel_) {
- RTC_LOG(LS_ERROR)
- << "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
- return;
- }
- if (ssrc_ == ssrc) {
- return;
- }
- if (ssrc_) {
- source_->Stop(media_channel_, *ssrc_);
- }
- ssrc_ = ssrc;
- source_->Start(media_channel_, *ssrc_);
- Reconfigure();
-}
-
-void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
- SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
-}
-
-void AudioRtpReceiver::SetStreams(
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
- // Remove remote track from any streams that are going away.
- for (const auto& existing_stream : streams_) {
- bool removed = true;
- for (const auto& stream : streams) {
- if (existing_stream->id() == stream->id()) {
- RTC_DCHECK_EQ(existing_stream.get(), stream.get());
- removed = false;
- break;
- }
- }
- if (removed) {
- existing_stream->RemoveTrack(track_);
- }
- }
- // Add remote track to any streams that are new.
- for (const auto& stream : streams) {
- bool added = true;
- for (const auto& existing_stream : streams_) {
- if (stream->id() == existing_stream->id()) {
- RTC_DCHECK_EQ(stream.get(), existing_stream.get());
- added = false;
- break;
- }
- }
- if (added) {
- stream->AddTrack(track_);
- }
- }
- streams_ = streams;
-}
-
-std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
- if (!media_channel_ || !ssrc_ || stopped_) {
- return {};
- }
- return worker_thread_->Invoke<std::vector<RtpSource>>(
- RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
-}
-
-void AudioRtpReceiver::Reconfigure() {
- RTC_DCHECK(!stopped_);
- if (!media_channel_ || !ssrc_) {
- RTC_LOG(LS_ERROR)
- << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
- return;
- }
- if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
- RTC_NOTREACHED();
- }
- // Reattach the frame decryptor if we were reconfigured.
- MaybeAttachFrameDecryptorToMediaChannel(
- ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
-}
-
-void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
- observer_ = observer;
- // Deliver any notifications the observer may have missed by being set late.
- if (received_first_packet_ && observer_) {
- observer_->OnFirstPacketReceived(media_type());
- }
-}
-
-void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
- RTC_DCHECK(media_channel == nullptr ||
- media_channel->media_type() == media_type());
- media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
-}
-
-void AudioRtpReceiver::NotifyFirstPacketReceived() {
- if (observer_) {
- observer_->OnFirstPacketReceived(media_type());
- }
- received_first_packet_ = true;
-}
-
-VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
- std::string receiver_id,
- std::vector<std::string> stream_ids)
- : VideoRtpReceiver(worker_thread,
- receiver_id,
- CreateStreamsFromIds(std::move(stream_ids))) {}
-
-VideoRtpReceiver::VideoRtpReceiver(
- rtc::Thread* worker_thread,
- const std::string& receiver_id,
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
- : worker_thread_(worker_thread),
- id_(receiver_id),
- source_(new RefCountedObject<VideoRtpTrackSource>()),
- track_(VideoTrackProxy::Create(
- rtc::Thread::Current(),
- worker_thread,
- VideoTrack::Create(
- receiver_id,
- VideoTrackSourceProxy::Create(rtc::Thread::Current(),
- worker_thread,
- source_),
- worker_thread))),
- attachment_id_(GenerateUniqueId()) {
- RTC_DCHECK(worker_thread_);
- SetStreams(streams);
- source_->SetState(MediaSourceInterface::kLive);
-}
-
-VideoRtpReceiver::~VideoRtpReceiver() {
- // Since cricket::VideoRenderer is not reference counted,
- // we need to remove it from the channel before we are deleted.
- Stop();
-}
-
-std::vector<std::string> VideoRtpReceiver::stream_ids() const {
- std::vector<std::string> stream_ids(streams_.size());
- for (size_t i = 0; i < streams_.size(); ++i)
- stream_ids[i] = streams_[i]->id();
- return stream_ids;
-}
-
-bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
- RTC_DCHECK(media_channel_);
- RTC_DCHECK(ssrc_);
- return worker_thread_->Invoke<bool>(
- RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); });
-}
-
-RtpParameters VideoRtpReceiver::GetParameters() const {
- if (!media_channel_ || !ssrc_ || stopped_) {
- return RtpParameters();
- }
- return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
- return media_channel_->GetRtpReceiveParameters(*ssrc_);
- });
-}
-
-bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
- TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
- if (!media_channel_ || !ssrc_ || stopped_) {
- return false;
- }
- return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
- return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
- });
-}
-
-void VideoRtpReceiver::SetFrameDecryptor(
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
- frame_decryptor_ = std::move(frame_decryptor);
- // Special Case: Set the frame decryptor to any value on any existing channel.
- if (media_channel_ && ssrc_.has_value() && !stopped_) {
- worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
- media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
- });
- }
-}
-
-rtc::scoped_refptr<FrameDecryptorInterface>
-VideoRtpReceiver::GetFrameDecryptor() const {
- return frame_decryptor_;
-}
-
-void VideoRtpReceiver::Stop() {
- // TODO(deadbeef): Need to do more here to fully stop receiving packets.
- if (stopped_) {
- return;
- }
- source_->SetState(MediaSourceInterface::kEnded);
- if (!media_channel_ || !ssrc_) {
- RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
- } else {
- // Allow that SetSink fail. This is the normal case when the underlying
- // media channel has already been deleted.
- SetSink(nullptr);
- }
- stopped_ = true;
-}
-
-void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
- if (!media_channel_) {
- RTC_LOG(LS_ERROR)
- << "VideoRtpReceiver::SetupMediaChannel: No video channel exists.";
- }
- if (ssrc_ == ssrc) {
- return;
- }
- if (ssrc_) {
- SetSink(nullptr);
- }
- ssrc_ = ssrc;
- SetSink(source_->sink());
- // Attach any existing frame decryptor to the media channel.
- MaybeAttachFrameDecryptorToMediaChannel(
- ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
-}
-
-void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
- SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
-}
-
-void VideoRtpReceiver::SetStreams(
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
- // Remove remote track from any streams that are going away.
- for (const auto& existing_stream : streams_) {
- bool removed = true;
- for (const auto& stream : streams) {
- if (existing_stream->id() == stream->id()) {
- RTC_DCHECK_EQ(existing_stream.get(), stream.get());
- removed = false;
- break;
- }
- }
- if (removed) {
- existing_stream->RemoveTrack(track_);
- }
- }
- // Add remote track to any streams that are new.
- for (const auto& stream : streams) {
- bool added = true;
- for (const auto& existing_stream : streams_) {
- if (stream->id() == existing_stream->id()) {
- RTC_DCHECK_EQ(stream.get(), existing_stream.get());
- added = false;
- break;
- }
- }
- if (added) {
- stream->AddTrack(track_);
- }
- }
- streams_ = streams;
-}
-
-void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
- observer_ = observer;
- // Deliver any notifications the observer may have missed by being set late.
- if (received_first_packet_ && observer_) {
- observer_->OnFirstPacketReceived(media_type());
- }
-}
-
-void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
- RTC_DCHECK(media_channel == nullptr ||
- media_channel->media_type() == media_type());
- media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
-}
-
-void VideoRtpReceiver::NotifyFirstPacketReceived() {
- if (observer_) {
- observer_->OnFirstPacketReceived(media_type());
- }
- received_first_packet_ = true;
-}
-
-std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
- if (!media_channel_ || !ssrc_ || stopped_) {
- return {};
- }
- return worker_thread_->Invoke<std::vector<RtpSource>>(
- RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
-}
-
} // namespace webrtc
diff --git a/pc/rtp_receiver.h b/pc/rtp_receiver.h
index 469502c..e56c859 100644
--- a/pc/rtp_receiver.h
+++ b/pc/rtp_receiver.h
@@ -31,7 +31,6 @@
#include "api/video/video_source_interface.h"
#include "media/base/media_channel.h"
#include "media/base/video_broadcaster.h"
-#include "pc/remote_audio_source.h"
#include "pc/video_track_source.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/thread.h"
@@ -78,203 +77,19 @@
// otherwise remains constant. Used to generate IDs for stats.
// The special value zero means that no track is attached.
virtual int AttachmentId() const = 0;
-};
-class AudioRtpReceiver : public ObserverInterface,
- public AudioSourceInterface::AudioObserver,
- public rtc::RefCountedObject<RtpReceiverInternal> {
- public:
- AudioRtpReceiver(rtc::Thread* worker_thread,
- std::string receiver_id,
- std::vector<std::string> stream_ids);
- // TODO(https://crbug.com/webrtc/9480): Remove this when streams() is removed.
- AudioRtpReceiver(
+ protected:
+ static int GenerateUniqueId();
+
+ static std::vector<rtc::scoped_refptr<MediaStreamInterface>>
+ CreateStreamsFromIds(std::vector<std::string> stream_ids);
+
+ static void MaybeAttachFrameDecryptorToMediaChannel(
+ const absl::optional<uint32_t>& ssrc,
rtc::Thread* worker_thread,
- const std::string& receiver_id,
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
- virtual ~AudioRtpReceiver();
-
- // ObserverInterface implementation
- void OnChanged() override;
-
- // AudioSourceInterface::AudioObserver implementation
- void OnSetVolume(double volume) override;
-
- rtc::scoped_refptr<AudioTrackInterface> audio_track() const {
- return track_.get();
- }
-
- // RtpReceiverInterface implementation
- rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
- return track_.get();
- }
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
- return dtls_transport_;
- }
- std::vector<std::string> stream_ids() const override;
- std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
- const override {
- return streams_;
- }
-
- cricket::MediaType media_type() const override {
- return cricket::MEDIA_TYPE_AUDIO;
- }
-
- std::string id() const override { return id_; }
-
- RtpParameters GetParameters() const override;
- bool SetParameters(const RtpParameters& parameters) override;
-
- void SetFrameDecryptor(
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
-
- rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
- const override;
-
- // RtpReceiverInternal implementation.
- void Stop() override;
- void SetupMediaChannel(uint32_t ssrc) override;
- uint32_t ssrc() const override { return ssrc_.value_or(0); }
- void NotifyFirstPacketReceived() override;
- void set_stream_ids(std::vector<std::string> stream_ids) override;
- void set_transport(
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
- dtls_transport_ = dtls_transport;
- }
- void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
- streams) override;
- void SetObserver(RtpReceiverObserverInterface* observer) override;
-
- void SetMediaChannel(cricket::MediaChannel* media_channel) override;
-
- std::vector<RtpSource> GetSources() const override;
- int AttachmentId() const override { return attachment_id_; }
-
- private:
- void Reconfigure();
- bool SetOutputVolume(double volume);
-
- rtc::Thread* const worker_thread_;
- const std::string id_;
- const rtc::scoped_refptr<RemoteAudioSource> source_;
- const rtc::scoped_refptr<AudioTrackInterface> track_;
- cricket::VoiceMediaChannel* media_channel_ = nullptr;
- absl::optional<uint32_t> ssrc_;
- std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
- bool cached_track_enabled_;
- double cached_volume_ = 1;
- bool stopped_ = false;
- RtpReceiverObserverInterface* observer_ = nullptr;
- bool received_first_packet_ = false;
- int attachment_id_ = 0;
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
-};
-
-class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
- public:
- // An SSRC of 0 will create a receiver that will match the first SSRC it
- // sees.
- VideoRtpReceiver(rtc::Thread* worker_thread,
- std::string receiver_id,
- std::vector<std::string> streams_ids);
- // TODO(hbos): Remove this when streams() is removed.
- // https://crbug.com/webrtc/9480
- VideoRtpReceiver(
- rtc::Thread* worker_thread,
- const std::string& receiver_id,
- const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
-
- virtual ~VideoRtpReceiver();
-
- rtc::scoped_refptr<VideoTrackInterface> video_track() const {
- return track_.get();
- }
-
- // RtpReceiverInterface implementation
- rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
- return track_.get();
- }
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
- return dtls_transport_;
- }
- std::vector<std::string> stream_ids() const override;
- std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
- const override {
- return streams_;
- }
-
- cricket::MediaType media_type() const override {
- return cricket::MEDIA_TYPE_VIDEO;
- }
-
- std::string id() const override { return id_; }
-
- RtpParameters GetParameters() const override;
- bool SetParameters(const RtpParameters& parameters) override;
-
- void SetFrameDecryptor(
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
-
- rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
- const override;
-
- // RtpReceiverInternal implementation.
- void Stop() override;
- void SetupMediaChannel(uint32_t ssrc) override;
- uint32_t ssrc() const override { return ssrc_.value_or(0); }
- void NotifyFirstPacketReceived() override;
- void set_stream_ids(std::vector<std::string> stream_ids) override;
- void set_transport(
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
- dtls_transport_ = dtls_transport;
- }
- void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
- streams) override;
-
- void SetObserver(RtpReceiverObserverInterface* observer) override;
-
- void SetMediaChannel(cricket::MediaChannel* media_channel) override;
-
- int AttachmentId() const override { return attachment_id_; }
-
- std::vector<RtpSource> GetSources() const override;
-
- private:
- class VideoRtpTrackSource : public VideoTrackSource {
- public:
- VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {}
-
- rtc::VideoSourceInterface<VideoFrame>* source() override {
- return &broadcaster_;
- }
- rtc::VideoSinkInterface<VideoFrame>* sink() { return &broadcaster_; }
-
- private:
- // |broadcaster_| is needed since the decoder can only handle one sink.
- // It might be better if the decoder can handle multiple sinks and consider
- // the VideoSinkWants.
- rtc::VideoBroadcaster broadcaster_;
- };
-
- bool SetSink(rtc::VideoSinkInterface<VideoFrame>* sink);
-
- rtc::Thread* const worker_thread_;
- const std::string id_;
- cricket::VideoMediaChannel* media_channel_ = nullptr;
- absl::optional<uint32_t> ssrc_;
- // |source_| is held here to be able to change the state of the source when
- // the VideoRtpReceiver is stopped.
- rtc::scoped_refptr<VideoRtpTrackSource> source_;
- rtc::scoped_refptr<VideoTrackInterface> track_;
- std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
- bool stopped_ = false;
- RtpReceiverObserverInterface* observer_ = nullptr;
- bool received_first_packet_ = false;
- int attachment_id_ = 0;
- rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
- rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+ rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor,
+ cricket::MediaChannel* media_channel,
+ bool stopped);
};
} // namespace webrtc
diff --git a/pc/rtp_sender_receiver_unittest.cc b/pc/rtp_sender_receiver_unittest.cc
index ba0e0b5..e3a8d5e 100644
--- a/pc/rtp_sender_receiver_unittest.cc
+++ b/pc/rtp_sender_receiver_unittest.cc
@@ -41,6 +41,7 @@
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/fake_dtls_transport.h"
#include "p2p/base/p2p_constants.h"
+#include "pc/audio_rtp_receiver.h"
#include "pc/audio_track.h"
#include "pc/channel.h"
#include "pc/channel_manager.h"
@@ -51,6 +52,7 @@
#include "pc/rtp_sender.h"
#include "pc/rtp_transport_internal.h"
#include "pc/test/fake_video_track_source.h"
+#include "pc/video_rtp_receiver.h"
#include "pc/video_track.h"
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"
diff --git a/pc/rtp_transceiver.h b/pc/rtp_transceiver.h
index 7c234ce..fd74fde 100644
--- a/pc/rtp_transceiver.h
+++ b/pc/rtp_transceiver.h
@@ -15,6 +15,7 @@
#include <vector>
#include "api/rtp_transceiver_interface.h"
+#include "pc/channel_interface.h"
#include "pc/rtp_receiver.h"
#include "pc/rtp_sender.h"
diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc
new file mode 100644
index 0000000..2d9a23f
--- /dev/null
+++ b/pc/video_rtp_receiver.cc
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pc/video_rtp_receiver.h"
+
+#include <stddef.h>
+#include <utility>
+#include <vector>
+
+#include "api/media_stream_proxy.h"
+#include "api/media_stream_track_proxy.h"
+#include "api/video_track_source_proxy.h"
+#include "pc/media_stream.h"
+#include "pc/video_track.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/location.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/trace_event.h"
+
+namespace webrtc {
+
+VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
+ std::string receiver_id,
+ std::vector<std::string> stream_ids)
+ : VideoRtpReceiver(worker_thread,
+ receiver_id,
+ CreateStreamsFromIds(std::move(stream_ids))) {}
+
+VideoRtpReceiver::VideoRtpReceiver(
+ rtc::Thread* worker_thread,
+ const std::string& receiver_id,
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
+ : worker_thread_(worker_thread),
+ id_(receiver_id),
+ source_(new RefCountedObject<VideoRtpTrackSource>()),
+ track_(VideoTrackProxy::Create(
+ rtc::Thread::Current(),
+ worker_thread,
+ VideoTrack::Create(
+ receiver_id,
+ VideoTrackSourceProxy::Create(rtc::Thread::Current(),
+ worker_thread,
+ source_),
+ worker_thread))),
+ attachment_id_(GenerateUniqueId()) {
+ RTC_DCHECK(worker_thread_);
+ SetStreams(streams);
+ source_->SetState(MediaSourceInterface::kLive);
+}
+
+VideoRtpReceiver::~VideoRtpReceiver() {
+ // Since cricket::VideoRenderer is not reference counted,
+ // we need to remove it from the channel before we are deleted.
+ Stop();
+}
+
+std::vector<std::string> VideoRtpReceiver::stream_ids() const {
+ std::vector<std::string> stream_ids(streams_.size());
+ for (size_t i = 0; i < streams_.size(); ++i)
+ stream_ids[i] = streams_[i]->id();
+ return stream_ids;
+}
+
+bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
+ RTC_DCHECK(media_channel_);
+ RTC_DCHECK(ssrc_);
+ return worker_thread_->Invoke<bool>(
+ RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); });
+}
+
+RtpParameters VideoRtpReceiver::GetParameters() const {
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return RtpParameters();
+ }
+ return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
+ return media_channel_->GetRtpReceiveParameters(*ssrc_);
+ });
+}
+
+bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
+ TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return false;
+ }
+ return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
+ return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
+ });
+}
+
+void VideoRtpReceiver::SetFrameDecryptor(
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
+ frame_decryptor_ = std::move(frame_decryptor);
+ // Special Case: Set the frame decryptor to any value on any existing channel.
+ if (media_channel_ && ssrc_.has_value() && !stopped_) {
+ worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
+ media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
+ });
+ }
+}
+
+rtc::scoped_refptr<FrameDecryptorInterface>
+VideoRtpReceiver::GetFrameDecryptor() const {
+ return frame_decryptor_;
+}
+
+void VideoRtpReceiver::Stop() {
+ // TODO(deadbeef): Need to do more here to fully stop receiving packets.
+ if (stopped_) {
+ return;
+ }
+ source_->SetState(MediaSourceInterface::kEnded);
+ if (!media_channel_ || !ssrc_) {
+ RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
+ } else {
+ // Allow that SetSink fail. This is the normal case when the underlying
+ // media channel has already been deleted.
+ SetSink(nullptr);
+ }
+ stopped_ = true;
+}
+
+void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
+ if (!media_channel_) {
+ RTC_LOG(LS_ERROR)
+ << "VideoRtpReceiver::SetupMediaChannel: No video channel exists.";
+ }
+ if (ssrc_ == ssrc) {
+ return;
+ }
+ if (ssrc_) {
+ SetSink(nullptr);
+ }
+ ssrc_ = ssrc;
+ SetSink(source_->sink());
+ // Attach any existing frame decryptor to the media channel.
+ MaybeAttachFrameDecryptorToMediaChannel(
+ ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
+}
+
+void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
+ SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
+}
+
+void VideoRtpReceiver::SetStreams(
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
+ // Remove remote track from any streams that are going away.
+ for (const auto& existing_stream : streams_) {
+ bool removed = true;
+ for (const auto& stream : streams) {
+ if (existing_stream->id() == stream->id()) {
+ RTC_DCHECK_EQ(existing_stream.get(), stream.get());
+ removed = false;
+ break;
+ }
+ }
+ if (removed) {
+ existing_stream->RemoveTrack(track_);
+ }
+ }
+ // Add remote track to any streams that are new.
+ for (const auto& stream : streams) {
+ bool added = true;
+ for (const auto& existing_stream : streams_) {
+ if (stream->id() == existing_stream->id()) {
+ RTC_DCHECK_EQ(stream.get(), existing_stream.get());
+ added = false;
+ break;
+ }
+ }
+ if (added) {
+ stream->AddTrack(track_);
+ }
+ }
+ streams_ = streams;
+}
+
+void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
+ observer_ = observer;
+ // Deliver any notifications the observer may have missed by being set late.
+ if (received_first_packet_ && observer_) {
+ observer_->OnFirstPacketReceived(media_type());
+ }
+}
+
+void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
+}
+
+void VideoRtpReceiver::NotifyFirstPacketReceived() {
+ if (observer_) {
+ observer_->OnFirstPacketReceived(media_type());
+ }
+ received_first_packet_ = true;
+}
+
+std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
+ if (!media_channel_ || !ssrc_ || stopped_) {
+ return {};
+ }
+ return worker_thread_->Invoke<std::vector<RtpSource>>(
+ RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
+}
+
+} // namespace webrtc
diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h
new file mode 100644
index 0000000..ab507ae
--- /dev/null
+++ b/pc/video_rtp_receiver.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef PC_VIDEO_RTP_RECEIVER_H_
+#define PC_VIDEO_RTP_RECEIVER_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/crypto/frame_decryptor_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/rtp_parameters.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/scoped_refptr.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_sink_interface.h"
+#include "api/video/video_source_interface.h"
+#include "media/base/media_channel.h"
+#include "media/base/video_broadcaster.h"
+#include "pc/rtp_receiver.h"
+#include "pc/video_track_source.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
+ public:
+ // An SSRC of 0 will create a receiver that will match the first SSRC it
+ // sees.
+ VideoRtpReceiver(rtc::Thread* worker_thread,
+ std::string receiver_id,
+ std::vector<std::string> streams_ids);
+ // TODO(hbos): Remove this when streams() is removed.
+ // https://crbug.com/webrtc/9480
+ VideoRtpReceiver(
+ rtc::Thread* worker_thread,
+ const std::string& receiver_id,
+ const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
+
+ virtual ~VideoRtpReceiver();
+
+ rtc::scoped_refptr<VideoTrackInterface> video_track() const {
+ return track_.get();
+ }
+
+ // RtpReceiverInterface implementation
+ rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
+ return track_.get();
+ }
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
+ return dtls_transport_;
+ }
+ std::vector<std::string> stream_ids() const override;
+ std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
+ const override {
+ return streams_;
+ }
+
+ cricket::MediaType media_type() const override {
+ return cricket::MEDIA_TYPE_VIDEO;
+ }
+
+ std::string id() const override { return id_; }
+
+ RtpParameters GetParameters() const override;
+ bool SetParameters(const RtpParameters& parameters) override;
+
+ void SetFrameDecryptor(
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
+
+ rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
+ const override;
+
+ // RtpReceiverInternal implementation.
+ void Stop() override;
+ void SetupMediaChannel(uint32_t ssrc) override;
+ uint32_t ssrc() const override { return ssrc_.value_or(0); }
+ void NotifyFirstPacketReceived() override;
+ void set_stream_ids(std::vector<std::string> stream_ids) override;
+ void set_transport(
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
+ dtls_transport_ = dtls_transport;
+ }
+ void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
+ streams) override;
+
+ void SetObserver(RtpReceiverObserverInterface* observer) override;
+
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
+
+ int AttachmentId() const override { return attachment_id_; }
+
+ std::vector<RtpSource> GetSources() const override;
+
+ private:
+ class VideoRtpTrackSource : public VideoTrackSource {
+ public:
+ VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {}
+
+ rtc::VideoSourceInterface<VideoFrame>* source() override {
+ return &broadcaster_;
+ }
+ rtc::VideoSinkInterface<VideoFrame>* sink() { return &broadcaster_; }
+
+ private:
+ // |broadcaster_| is needed since the decoder can only handle one sink.
+ // It might be better if the decoder can handle multiple sinks and consider
+ // the VideoSinkWants.
+ rtc::VideoBroadcaster broadcaster_;
+ };
+
+ bool SetSink(rtc::VideoSinkInterface<VideoFrame>* sink);
+
+ rtc::Thread* const worker_thread_;
+ const std::string id_;
+ cricket::VideoMediaChannel* media_channel_ = nullptr;
+ absl::optional<uint32_t> ssrc_;
+ // |source_| is held here to be able to change the state of the source when
+ // the VideoRtpReceiver is stopped.
+ rtc::scoped_refptr<VideoRtpTrackSource> source_;
+ rtc::scoped_refptr<VideoTrackInterface> track_;
+ std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
+ bool stopped_ = false;
+ RtpReceiverObserverInterface* observer_ = nullptr;
+ bool received_first_packet_ = false;
+ int attachment_id_ = 0;
+ rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
+ rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+};
+
+} // namespace webrtc
+
+#endif // PC_VIDEO_RTP_RECEIVER_H_