From 501bfba0cb5f9649956451dd0d14f56b62af9af4 Mon Sep 17 00:00:00 2001 From: Ruslan Burakov Date: Mon, 11 Feb 2019 10:29:19 +0100 Subject: [PATCH] Split rtp_receiver for readability. Bug: webrtc:10304 Change-Id: I85e421060d8560cf36cdb5970ae190efc77e7709 Reviewed-on: https://webrtc-review.googlesource.com/c/122085 Reviewed-by: Karl Wiberg Commit-Queue: Ruslan Burakov Cr-Commit-Position: refs/heads/master@{#26634} --- pc/BUILD.gn | 4 + pc/audio_rtp_receiver.cc | 248 +++++++++++++++++ pc/audio_rtp_receiver.h | 126 +++++++++ pc/peer_connection.cc | 2 + pc/rtp_receiver.cc | 419 +---------------------------- pc/rtp_receiver.h | 207 +------------- pc/rtp_sender_receiver_unittest.cc | 2 + pc/rtp_transceiver.h | 1 + pc/video_rtp_receiver.cc | 213 +++++++++++++++ pc/video_rtp_receiver.h | 144 ++++++++++ 10 files changed, 755 insertions(+), 611 deletions(-) create mode 100644 pc/audio_rtp_receiver.cc create mode 100644 pc/audio_rtp_receiver.h create mode 100644 pc/video_rtp_receiver.cc create mode 100644 pc/video_rtp_receiver.h diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 5ea089ffbb..5e16e26dcf 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -128,6 +128,8 @@ rtc_static_library("peerconnection") { visibility = [ "*" ] cflags = [] sources = [ + "audio_rtp_receiver.cc", + "audio_rtp_receiver.h", "audio_track.cc", "audio_track.h", "data_channel.cc", @@ -175,6 +177,8 @@ rtc_static_library("peerconnection") { "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 0000000000..4602fdae25 --- /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 +#include +#include + +#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 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>& streams) + : worker_thread_(worker_thread), + id_(receiver_id), + source_(new rtc::RefCountedObject(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(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 AudioRtpReceiver::stream_ids() const { + std::vector 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(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(RTC_FROM_HERE, [&] { + return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); + }); +} + +void AudioRtpReceiver::SetFrameDecryptor( + rtc::scoped_refptr 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(RTC_FROM_HERE, [&] { + media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); + }); + } +} + +rtc::scoped_refptr +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 stream_ids) { + SetStreams(CreateStreamsFromIds(std::move(stream_ids))); +} + +void AudioRtpReceiver::SetStreams( + const std::vector>& 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 AudioRtpReceiver::GetSources() const { + if (!media_channel_ || !ssrc_ || stopped_) { + return {}; + } + return worker_thread_->Invoke>( + 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(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 0000000000..82c8d88140 --- /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 +#include +#include + +#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 { + public: + AudioRtpReceiver(rtc::Thread* worker_thread, + std::string receiver_id, + std::vector 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>& streams); + virtual ~AudioRtpReceiver(); + + // ObserverInterface implementation + void OnChanged() override; + + // AudioSourceInterface::AudioObserver implementation + void OnSetVolume(double volume) override; + + rtc::scoped_refptr audio_track() const { + return track_.get(); + } + + // RtpReceiverInterface implementation + rtc::scoped_refptr track() const override { + return track_.get(); + } + rtc::scoped_refptr dtls_transport() const override { + return dtls_transport_; + } + std::vector stream_ids() const override; + std::vector> 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 frame_decryptor) override; + + rtc::scoped_refptr 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 stream_ids) override; + void set_transport( + rtc::scoped_refptr dtls_transport) override { + dtls_transport_ = dtls_transport; + } + void SetStreams(const std::vector>& + streams) override; + void SetObserver(RtpReceiverObserverInterface* observer) override; + + void SetMediaChannel(cricket::MediaChannel* media_channel) override; + + std::vector 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 source_; + const rtc::scoped_refptr track_; + cricket::VoiceMediaChannel* media_channel_ = nullptr; + absl::optional ssrc_; + std::vector> 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 frame_decryptor_; + rtc::scoped_refptr dtls_transport_; +}; + +} // namespace webrtc + +#endif // PC_AUDIO_RTP_RECEIVER_H_ diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 759bf471f9..0fe6732876 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 60f5ea8659..0b800c1dff 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> CreateStreamsFromIds( - std::vector stream_ids) { +std::vector> +RtpReceiverInternal::CreateStreamsFromIds(std::vector stream_ids) { std::vector> streams( stream_ids.size()); for (size_t i = 0; i < stream_ids.size(); ++i) { @@ -50,7 +45,7 @@ std::vector> CreateStreamsFromIds( // 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& ssrc, rtc::Thread* worker_thread, rtc::scoped_refptr frame_decryptor, @@ -63,410 +58,4 @@ void MaybeAttachFrameDecryptorToMediaChannel( } } -} // namespace - -AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread, - std::string receiver_id, - std::vector 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>& streams) - : worker_thread_(worker_thread), - id_(receiver_id), - source_(new rtc::RefCountedObject(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(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 AudioRtpReceiver::stream_ids() const { - std::vector 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(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(RTC_FROM_HERE, [&] { - return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); - }); -} - -void AudioRtpReceiver::SetFrameDecryptor( - rtc::scoped_refptr 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(RTC_FROM_HERE, [&] { - media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); - }); - } -} - -rtc::scoped_refptr -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 stream_ids) { - SetStreams(CreateStreamsFromIds(std::move(stream_ids))); -} - -void AudioRtpReceiver::SetStreams( - const std::vector>& 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 AudioRtpReceiver::GetSources() const { - if (!media_channel_ || !ssrc_ || stopped_) { - return {}; - } - return worker_thread_->Invoke>( - 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(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 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>& streams) - : worker_thread_(worker_thread), - id_(receiver_id), - source_(new RefCountedObject()), - 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 VideoRtpReceiver::stream_ids() const { - std::vector 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* sink) { - RTC_DCHECK(media_channel_); - RTC_DCHECK(ssrc_); - return worker_thread_->Invoke( - RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); }); -} - -RtpParameters VideoRtpReceiver::GetParameters() const { - if (!media_channel_ || !ssrc_ || stopped_) { - return RtpParameters(); - } - return worker_thread_->Invoke(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(RTC_FROM_HERE, [&] { - return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); - }); -} - -void VideoRtpReceiver::SetFrameDecryptor( - rtc::scoped_refptr 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(RTC_FROM_HERE, [&] { - media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); - }); - } -} - -rtc::scoped_refptr -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 stream_ids) { - SetStreams(CreateStreamsFromIds(std::move(stream_ids))); -} - -void VideoRtpReceiver::SetStreams( - const std::vector>& 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(media_channel); -} - -void VideoRtpReceiver::NotifyFirstPacketReceived() { - if (observer_) { - observer_->OnFirstPacketReceived(media_type()); - } - received_first_packet_ = true; -} - -std::vector VideoRtpReceiver::GetSources() const { - if (!media_channel_ || !ssrc_ || stopped_) { - return {}; - } - return worker_thread_->Invoke>( - RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); }); -} - } // namespace webrtc diff --git a/pc/rtp_receiver.h b/pc/rtp_receiver.h index 469502cdf4..e56c859d0e 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 @@ class RtpReceiverInternal : public RtpReceiverInterface { // 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 { - public: - AudioRtpReceiver(rtc::Thread* worker_thread, - std::string receiver_id, - std::vector stream_ids); - // TODO(https://crbug.com/webrtc/9480): Remove this when streams() is removed. - AudioRtpReceiver( + protected: + static int GenerateUniqueId(); + + static std::vector> + CreateStreamsFromIds(std::vector stream_ids); + + static void MaybeAttachFrameDecryptorToMediaChannel( + const absl::optional& ssrc, rtc::Thread* worker_thread, - const std::string& receiver_id, - const std::vector>& streams); - virtual ~AudioRtpReceiver(); - - // ObserverInterface implementation - void OnChanged() override; - - // AudioSourceInterface::AudioObserver implementation - void OnSetVolume(double volume) override; - - rtc::scoped_refptr audio_track() const { - return track_.get(); - } - - // RtpReceiverInterface implementation - rtc::scoped_refptr track() const override { - return track_.get(); - } - rtc::scoped_refptr dtls_transport() const override { - return dtls_transport_; - } - std::vector stream_ids() const override; - std::vector> 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 frame_decryptor) override; - - rtc::scoped_refptr 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 stream_ids) override; - void set_transport( - rtc::scoped_refptr dtls_transport) override { - dtls_transport_ = dtls_transport; - } - void SetStreams(const std::vector>& - streams) override; - void SetObserver(RtpReceiverObserverInterface* observer) override; - - void SetMediaChannel(cricket::MediaChannel* media_channel) override; - - std::vector 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 source_; - const rtc::scoped_refptr track_; - cricket::VoiceMediaChannel* media_channel_ = nullptr; - absl::optional ssrc_; - std::vector> 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 frame_decryptor_; - rtc::scoped_refptr dtls_transport_; -}; - -class VideoRtpReceiver : public rtc::RefCountedObject { - 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 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>& streams); - - virtual ~VideoRtpReceiver(); - - rtc::scoped_refptr video_track() const { - return track_.get(); - } - - // RtpReceiverInterface implementation - rtc::scoped_refptr track() const override { - return track_.get(); - } - rtc::scoped_refptr dtls_transport() const override { - return dtls_transport_; - } - std::vector stream_ids() const override; - std::vector> 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 frame_decryptor) override; - - rtc::scoped_refptr 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 stream_ids) override; - void set_transport( - rtc::scoped_refptr dtls_transport) override { - dtls_transport_ = dtls_transport; - } - void SetStreams(const std::vector>& - streams) override; - - void SetObserver(RtpReceiverObserverInterface* observer) override; - - void SetMediaChannel(cricket::MediaChannel* media_channel) override; - - int AttachmentId() const override { return attachment_id_; } - - std::vector GetSources() const override; - - private: - class VideoRtpTrackSource : public VideoTrackSource { - public: - VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {} - - rtc::VideoSourceInterface* source() override { - return &broadcaster_; - } - rtc::VideoSinkInterface* 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* sink); - - rtc::Thread* const worker_thread_; - const std::string id_; - cricket::VideoMediaChannel* media_channel_ = nullptr; - absl::optional ssrc_; - // |source_| is held here to be able to change the state of the source when - // the VideoRtpReceiver is stopped. - rtc::scoped_refptr source_; - rtc::scoped_refptr track_; - std::vector> streams_; - bool stopped_ = false; - RtpReceiverObserverInterface* observer_ = nullptr; - bool received_first_packet_ = false; - int attachment_id_ = 0; - rtc::scoped_refptr frame_decryptor_; - rtc::scoped_refptr dtls_transport_; + rtc::scoped_refptr 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 ba0e0b5e06..e3a8d5e14a 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 7c234ce9eb..fd74fde155 100644 --- a/pc/rtp_transceiver.h +++ b/pc/rtp_transceiver.h @@ -15,6 +15,7 @@ #include #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 0000000000..2d9a23fb0f --- /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 +#include +#include + +#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 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>& streams) + : worker_thread_(worker_thread), + id_(receiver_id), + source_(new RefCountedObject()), + 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 VideoRtpReceiver::stream_ids() const { + std::vector 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* sink) { + RTC_DCHECK(media_channel_); + RTC_DCHECK(ssrc_); + return worker_thread_->Invoke( + RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); }); +} + +RtpParameters VideoRtpReceiver::GetParameters() const { + if (!media_channel_ || !ssrc_ || stopped_) { + return RtpParameters(); + } + return worker_thread_->Invoke(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(RTC_FROM_HERE, [&] { + return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); + }); +} + +void VideoRtpReceiver::SetFrameDecryptor( + rtc::scoped_refptr 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(RTC_FROM_HERE, [&] { + media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); + }); + } +} + +rtc::scoped_refptr +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 stream_ids) { + SetStreams(CreateStreamsFromIds(std::move(stream_ids))); +} + +void VideoRtpReceiver::SetStreams( + const std::vector>& 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(media_channel); +} + +void VideoRtpReceiver::NotifyFirstPacketReceived() { + if (observer_) { + observer_->OnFirstPacketReceived(media_type()); + } + received_first_packet_ = true; +} + +std::vector VideoRtpReceiver::GetSources() const { + if (!media_channel_ || !ssrc_ || stopped_) { + return {}; + } + return worker_thread_->Invoke>( + 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 0000000000..ab507aec64 --- /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 +#include +#include + +#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 { + 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 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>& streams); + + virtual ~VideoRtpReceiver(); + + rtc::scoped_refptr video_track() const { + return track_.get(); + } + + // RtpReceiverInterface implementation + rtc::scoped_refptr track() const override { + return track_.get(); + } + rtc::scoped_refptr dtls_transport() const override { + return dtls_transport_; + } + std::vector stream_ids() const override; + std::vector> 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 frame_decryptor) override; + + rtc::scoped_refptr 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 stream_ids) override; + void set_transport( + rtc::scoped_refptr dtls_transport) override { + dtls_transport_ = dtls_transport; + } + void SetStreams(const std::vector>& + streams) override; + + void SetObserver(RtpReceiverObserverInterface* observer) override; + + void SetMediaChannel(cricket::MediaChannel* media_channel) override; + + int AttachmentId() const override { return attachment_id_; } + + std::vector GetSources() const override; + + private: + class VideoRtpTrackSource : public VideoTrackSource { + public: + VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {} + + rtc::VideoSourceInterface* source() override { + return &broadcaster_; + } + rtc::VideoSinkInterface* 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* sink); + + rtc::Thread* const worker_thread_; + const std::string id_; + cricket::VideoMediaChannel* media_channel_ = nullptr; + absl::optional ssrc_; + // |source_| is held here to be able to change the state of the source when + // the VideoRtpReceiver is stopped. + rtc::scoped_refptr source_; + rtc::scoped_refptr track_; + std::vector> streams_; + bool stopped_ = false; + RtpReceiverObserverInterface* observer_ = nullptr; + bool received_first_packet_ = false; + int attachment_id_ = 0; + rtc::scoped_refptr frame_decryptor_; + rtc::scoped_refptr dtls_transport_; +}; + +} // namespace webrtc + +#endif // PC_VIDEO_RTP_RECEIVER_H_