diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index ef69e732ab..aecc246d09 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -126,7 +126,7 @@ AudioReceiveStream::AudioReceiveStream( RTC_DCHECK(audio_state_); RTC_DCHECK(channel_receive_); - network_thread_checker_.Detach(); + packet_sequence_checker_.Detach(); RTC_DCHECK(packet_router); // Configure bandwidth estimation. @@ -157,14 +157,14 @@ AudioReceiveStream::~AudioReceiveStream() { void AudioReceiveStream::RegisterWithTransport( RtpStreamReceiverControllerInterface* receiver_controller) { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); RTC_DCHECK(!rtp_stream_receiver_); rtp_stream_receiver_ = receiver_controller->CreateReceiver( config_.rtp.remote_ssrc, channel_receive_.get()); } void AudioReceiveStream::UnregisterFromTransport() { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); rtp_stream_receiver_.reset(); } @@ -395,7 +395,7 @@ bool AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) { } void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); channel_receive_->SetAssociatedSendChannel( send_stream ? send_stream->GetChannel() : nullptr); associated_send_stream_ = send_stream; @@ -416,7 +416,7 @@ const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const { const AudioSendStream* AudioReceiveStream::GetAssociatedSendStreamForTesting() const { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); return associated_send_stream_; } diff --git a/audio/audio_receive_stream.h b/audio/audio_receive_stream.h index 40749cc950..87c82cce61 100644 --- a/audio/audio_receive_stream.h +++ b/audio/audio_receive_stream.h @@ -125,18 +125,18 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream, // thread, but still serves as a mechanism of grouping together concepts // that belong to the network thread. Once the packets are fully delivered // on the network thread, this comment will be deleted. - RTC_NO_UNIQUE_ADDRESS SequenceChecker network_thread_checker_; + RTC_NO_UNIQUE_ADDRESS SequenceChecker packet_sequence_checker_; webrtc::AudioReceiveStream::Config config_; rtc::scoped_refptr audio_state_; SourceTracker source_tracker_; const std::unique_ptr channel_receive_; AudioSendStream* associated_send_stream_ - RTC_GUARDED_BY(network_thread_checker_) = nullptr; + RTC_GUARDED_BY(packet_sequence_checker_) = nullptr; bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false; std::unique_ptr rtp_stream_receiver_ - RTC_GUARDED_BY(network_thread_checker_); + RTC_GUARDED_BY(packet_sequence_checker_); }; } // namespace internal } // namespace webrtc diff --git a/call/call.cc b/call/call.cc index 76ba46f0f1..b8eafdc923 100644 --- a/call/call.cc +++ b/call/call.cc @@ -1099,10 +1099,13 @@ webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream( // and set it up asynchronously on the network thread (the registration and // |video_receiver_controller_| need to live on the network thread). VideoReceiveStream2* receive_stream = new VideoReceiveStream2( - task_queue_factory_, worker_thread_, &video_receiver_controller_, - num_cpu_cores_, transport_send_->packet_router(), - std::move(configuration), module_process_thread_->process_thread(), - call_stats_.get(), clock_, new VCMTiming(clock_)); + task_queue_factory_, this, num_cpu_cores_, + transport_send_->packet_router(), std::move(configuration), + module_process_thread_->process_thread(), call_stats_.get(), clock_, + new VCMTiming(clock_)); + // TODO(bugs.webrtc.org/11993): Set this up asynchronously on the network + // thread. + receive_stream->RegisterWithTransport(&video_receiver_controller_); const webrtc::VideoReceiveStream::Config& config = receive_stream->config(); if (config.rtp.rtx_ssrc) { @@ -1130,6 +1133,9 @@ void Call::DestroyVideoReceiveStream( RTC_DCHECK(receive_stream != nullptr); VideoReceiveStream2* receive_stream_impl = static_cast(receive_stream); + // TODO(bugs.webrtc.org/11993): Unregister on the network thread. + receive_stream_impl->UnregisterFromTransport(); + const VideoReceiveStream::Config& config = receive_stream_impl->config(); // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a diff --git a/call/flexfec_receive_stream_impl.cc b/call/flexfec_receive_stream_impl.cc index c335b03ced..8a09108ce4 100644 --- a/call/flexfec_receive_stream_impl.cc +++ b/call/flexfec_receive_stream_impl.cc @@ -154,7 +154,7 @@ FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl( process_thread_(process_thread) { RTC_LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config_.ToString(); - network_thread_checker_.Detach(); + packet_sequence_checker_.Detach(); // RTCP reporting. rtp_rtcp_->SetRTCPStatus(config_.rtcp_mode); @@ -168,7 +168,7 @@ FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() { void FlexfecReceiveStreamImpl::RegisterWithTransport( RtpStreamReceiverControllerInterface* receiver_controller) { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); RTC_DCHECK(!rtp_stream_receiver_); if (!receiver_) @@ -183,7 +183,7 @@ void FlexfecReceiveStreamImpl::RegisterWithTransport( } void FlexfecReceiveStreamImpl::UnregisterFromTransport() { - RTC_DCHECK_RUN_ON(&network_thread_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); rtp_stream_receiver_.reset(); } diff --git a/call/flexfec_receive_stream_impl.h b/call/flexfec_receive_stream_impl.h index 1a4aa03d65..8826aedad9 100644 --- a/call/flexfec_receive_stream_impl.h +++ b/call/flexfec_receive_stream_impl.h @@ -62,7 +62,7 @@ class FlexfecReceiveStreamImpl : public FlexfecReceiveStream { const Config& GetConfig() const override; private: - RTC_NO_UNIQUE_ADDRESS SequenceChecker network_thread_checker_; + RTC_NO_UNIQUE_ADDRESS SequenceChecker packet_sequence_checker_; // Config. const Config config_; @@ -76,7 +76,7 @@ class FlexfecReceiveStreamImpl : public FlexfecReceiveStream { ProcessThread* const process_thread_; std::unique_ptr rtp_stream_receiver_ - RTC_GUARDED_BY(network_thread_checker_); + RTC_GUARDED_BY(packet_sequence_checker_); }; } // namespace webrtc diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc index c9ec9e0123..78e436a2da 100644 --- a/video/video_receive_stream2.cc +++ b/video/video_receive_stream2.cc @@ -211,30 +211,28 @@ int DetermineMaxWaitForFrame(const VideoReceiveStream::Config& config, : kMaxWaitForFrameMs; } -VideoReceiveStream2::VideoReceiveStream2( - TaskQueueFactory* task_queue_factory, - TaskQueueBase* current_queue, - RtpStreamReceiverControllerInterface* receiver_controller, - int num_cpu_cores, - PacketRouter* packet_router, - VideoReceiveStream::Config config, - ProcessThread* process_thread, - CallStats* call_stats, - Clock* clock, - VCMTiming* timing) +VideoReceiveStream2::VideoReceiveStream2(TaskQueueFactory* task_queue_factory, + Call* call, + int num_cpu_cores, + PacketRouter* packet_router, + VideoReceiveStream::Config config, + ProcessThread* process_thread, + CallStats* call_stats, + Clock* clock, + VCMTiming* timing) : task_queue_factory_(task_queue_factory), transport_adapter_(config.rtcp_send_transport), config_(std::move(config)), num_cpu_cores_(num_cpu_cores), - worker_thread_(current_queue), + call_(call), clock_(clock), call_stats_(call_stats), source_tracker_(clock_), - stats_proxy_(&config_, clock_, worker_thread_), + stats_proxy_(&config_, clock_, call->worker_thread()), rtp_receive_statistics_(ReceiveStatistics::Create(clock_)), timing_(timing), video_receiver_(clock_, timing_.get()), - rtp_video_stream_receiver_(worker_thread_, + rtp_video_stream_receiver_(call->worker_thread(), clock_, &transport_adapter_, call_stats->AsRtcpRttStats(), @@ -249,7 +247,7 @@ VideoReceiveStream2::VideoReceiveStream2( this, // OnCompleteFrameCallback config_.frame_decryptor, config_.frame_transformer), - rtp_stream_sync_(current_queue, this), + rtp_stream_sync_(call->worker_thread(), this), max_wait_for_keyframe_ms_(DetermineMaxWaitForFrame(config, true)), max_wait_for_frame_ms_(DetermineMaxWaitForFrame(config, false)), low_latency_renderer_enabled_("enabled", true), @@ -261,10 +259,11 @@ VideoReceiveStream2::VideoReceiveStream2( TaskQueueFactory::Priority::HIGH)) { RTC_LOG(LS_INFO) << "VideoReceiveStream2: " << config_.ToString(); - RTC_DCHECK(worker_thread_); + RTC_DCHECK(call_->worker_thread()); RTC_DCHECK(config_.renderer); RTC_DCHECK(call_stats_); module_process_sequence_checker_.Detach(); + packet_sequence_checker_.Detach(); RTC_DCHECK(!config_.decoders.empty()); RTC_CHECK(config_.decoder_factory); @@ -282,15 +281,10 @@ VideoReceiveStream2::VideoReceiveStream2( frame_buffer_.reset( new video_coding::FrameBuffer(clock_, timing_.get(), &stats_proxy_)); - // Register with RtpStreamReceiverController. - media_receiver_ = receiver_controller->CreateReceiver( - config_.rtp.remote_ssrc, &rtp_video_stream_receiver_); if (config_.rtp.rtx_ssrc) { rtx_receive_stream_ = std::make_unique( &rtp_video_stream_receiver_, config.rtp.rtx_associated_payload_types, config_.rtp.remote_ssrc, rtp_receive_statistics_.get()); - rtx_receiver_ = receiver_controller->CreateReceiver( - config_.rtp.rtx_ssrc, rtx_receive_stream_.get()); } else { rtp_receive_statistics_->EnableRetransmitDetection(config.rtp.remote_ssrc, true); @@ -309,20 +303,45 @@ VideoReceiveStream2::VideoReceiveStream2( VideoReceiveStream2::~VideoReceiveStream2() { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); RTC_LOG(LS_INFO) << "~VideoReceiveStream2: " << config_.ToString(); + RTC_DCHECK(!media_receiver_); + RTC_DCHECK(!rtx_receiver_); Stop(); } +void VideoReceiveStream2::RegisterWithTransport( + RtpStreamReceiverControllerInterface* receiver_controller) { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + RTC_DCHECK(!media_receiver_); + RTC_DCHECK(!rtx_receiver_); + + // Register with RtpStreamReceiverController. + media_receiver_ = receiver_controller->CreateReceiver( + config_.rtp.remote_ssrc, &rtp_video_stream_receiver_); + if (config_.rtp.rtx_ssrc) { + RTC_DCHECK(rtx_receive_stream_); + rtx_receiver_ = receiver_controller->CreateReceiver( + config_.rtp.rtx_ssrc, rtx_receive_stream_.get()); + } +} + +void VideoReceiveStream2::UnregisterFromTransport() { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + media_receiver_.reset(); + rtx_receiver_.reset(); +} + void VideoReceiveStream2::SignalNetworkState(NetworkState state) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); rtp_video_stream_receiver_.SignalNetworkState(state); } bool VideoReceiveStream2::DeliverRtcp(const uint8_t* packet, size_t length) { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); return rtp_video_stream_receiver_.DeliverRtcp(packet, length); } void VideoReceiveStream2::SetSync(Syncable* audio_syncable) { - RTC_DCHECK_RUN_ON(&worker_sequence_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); rtp_stream_sync_.ConfigureSync(audio_syncable); } @@ -529,7 +548,7 @@ void VideoReceiveStream2::OnFrame(const VideoFrame& video_frame) { // TODO(bugs.webrtc.org/10739): we should set local capture clock offset for // |video_frame.packet_infos|. But VideoFrame is const qualified here. - worker_thread_->PostTask( + call_->worker_thread()->PostTask( ToQueuedTask(task_safety_, [frame_meta, this]() { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); int64_t video_playout_ntp_ms; @@ -685,7 +704,7 @@ void VideoReceiveStream2::StartNextDecode() { HandleEncodedFrame(std::move(frame)); } else { int64_t now_ms = clock_->TimeInMilliseconds(); - worker_thread_->PostTask(ToQueuedTask( + call_->worker_thread()->PostTask(ToQueuedTask( task_safety_, [this, now_ms, wait_ms = GetMaxWaitMs()]() { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); HandleFrameBufferTimeout(now_ms, wait_ms); @@ -746,7 +765,7 @@ void VideoReceiveStream2::HandleEncodedFrame( force_request_key_frame = true; } - worker_thread_->PostTask(ToQueuedTask( + call_->worker_thread()->PostTask(ToQueuedTask( task_safety_, [this, now_ms, received_frame_is_keyframe, force_request_key_frame, decoded_frame_picture_id, keyframe_request_is_due]() { diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h index f952de2b23..8bf673db64 100644 --- a/video/video_receive_stream2.h +++ b/video/video_receive_stream2.h @@ -18,6 +18,7 @@ #include "api/task_queue/task_queue_factory.h" #include "api/units/timestamp.h" #include "api/video/recordable_encoded_frame.h" +#include "call/call.h" #include "call/rtp_packet_sink_interface.h" #include "call/syncable.h" #include "call/video_receive_stream.h" @@ -91,8 +92,7 @@ class VideoReceiveStream2 static constexpr size_t kBufferedEncodedFramesMaxSize = 60; VideoReceiveStream2(TaskQueueFactory* task_queue_factory, - TaskQueueBase* current_queue, - RtpStreamReceiverControllerInterface* receiver_controller, + Call* call, int num_cpu_cores, PacketRouter* packet_router, VideoReceiveStream::Config config, @@ -100,8 +100,22 @@ class VideoReceiveStream2 CallStats* call_stats, Clock* clock, VCMTiming* timing); + // Destruction happens on the worker thread. Prior to destruction the caller + // must ensure that a registration with the transport has been cleared. See + // `RegisterWithTransport` for details. + // TODO(tommi): As a further improvement to this, performing the full + // destruction on the network thread could be made the default. ~VideoReceiveStream2() override; + // Called on `packet_sequence_checker_` to register/unregister with the + // network transport. + void RegisterWithTransport( + RtpStreamReceiverControllerInterface* receiver_controller); + // If registration has previously been done (via `RegisterWithTransport`) then + // `UnregisterFromTransport` must be called prior to destruction, on the + // network thread. + void UnregisterFromTransport(); + const Config& config() const { return config_; } void SignalNetworkState(NetworkState state); @@ -184,13 +198,21 @@ class VideoReceiveStream2 RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_sequence_checker_; RTC_NO_UNIQUE_ADDRESS SequenceChecker module_process_sequence_checker_; + // TODO(bugs.webrtc.org/11993): This checker conceptually represents + // operations that belong to the network thread. The Call class is currently + // moving towards handling network packets on the network thread and while + // that work is ongoing, this checker may in practice represent the worker + // thread, but still serves as a mechanism of grouping together concepts + // that belong to the network thread. Once the packets are fully delivered + // on the network thread, this comment will be deleted. + RTC_NO_UNIQUE_ADDRESS SequenceChecker packet_sequence_checker_; TaskQueueFactory* const task_queue_factory_; TransportAdapter transport_adapter_; const VideoReceiveStream::Config config_; const int num_cpu_cores_; - TaskQueueBase* const worker_thread_; + Call* const call_; Clock* const clock_; CallStats* const call_stats_; @@ -218,9 +240,12 @@ class VideoReceiveStream2 // Members for the new jitter buffer experiment. std::unique_ptr frame_buffer_; - std::unique_ptr media_receiver_; - std::unique_ptr rtx_receive_stream_; - std::unique_ptr rtx_receiver_; + std::unique_ptr media_receiver_ + RTC_GUARDED_BY(packet_sequence_checker_); + std::unique_ptr rtx_receive_stream_ + RTC_GUARDED_BY(packet_sequence_checker_); + std::unique_ptr rtx_receiver_ + RTC_GUARDED_BY(packet_sequence_checker_); // Whenever we are in an undecodable state (stream has just started or due to // a decoding error) we require a keyframe to restart the stream. diff --git a/video/video_receive_stream2_unittest.cc b/video/video_receive_stream2_unittest.cc index 3bbc0704b9..f3372b1c3e 100644 --- a/video/video_receive_stream2_unittest.cc +++ b/video/video_receive_stream2_unittest.cc @@ -23,6 +23,7 @@ #include "call/rtp_stream_receiver_controller.h" #include "common_video/test/utilities.h" #include "media/base/fake_video_renderer.h" +#include "media/engine/fake_webrtc_call.h" #include "modules/pacing/packet_router.h" #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "modules/utility/include/process_thread.h" @@ -113,8 +114,12 @@ class VideoReceiveStream2Test : public ::testing::Test { config_(&mock_transport_), call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()), h264_decoder_factory_(&mock_h264_video_decoder_) {} + ~VideoReceiveStream2Test() override { + if (video_receive_stream_) + video_receive_stream_->UnregisterFromTransport(); + } - void SetUp() { + void SetUp() override { constexpr int kDefaultNumCpuCores = 2; config_.rtp.remote_ssrc = 1111; config_.rtp.local_ssrc = 2222; @@ -133,10 +138,11 @@ class VideoReceiveStream2Test : public ::testing::Test { video_receive_stream_ = std::make_unique( - task_queue_factory_.get(), loop_.task_queue(), - &rtp_stream_receiver_controller_, kDefaultNumCpuCores, + task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores, &packet_router_, config_.Copy(), process_thread_.get(), &call_stats_, clock_, timing_); + video_receive_stream_->RegisterWithTransport( + &rtp_stream_receiver_controller_); } protected: @@ -148,6 +154,7 @@ class VideoReceiveStream2Test : public ::testing::Test { MockVideoDecoder mock_h264_video_decoder_; test::VideoDecoderProxyFactory h264_decoder_factory_; cricket::FakeVideoRenderer fake_renderer_; + cricket::FakeCall fake_call_; MockTransport mock_transport_; PacketRouter packet_router_; RtpStreamReceiverController rtp_stream_receiver_controller_; @@ -288,8 +295,12 @@ class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test { task_queue_factory_(CreateDefaultTaskQueueFactory()), config_(&mock_transport_), call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {} + ~VideoReceiveStream2TestWithFakeDecoder() override { + if (video_receive_stream_) + video_receive_stream_->UnregisterFromTransport(); + } - void SetUp() { + void SetUp() override { config_.rtp.remote_ssrc = 1111; config_.rtp.local_ssrc = 2222; config_.renderer = &fake_renderer_; @@ -304,12 +315,17 @@ class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test { void ReCreateReceiveStream(VideoReceiveStream::RecordingState state) { constexpr int kDefaultNumCpuCores = 2; - video_receive_stream_ = nullptr; + if (video_receive_stream_) { + video_receive_stream_->UnregisterFromTransport(); + video_receive_stream_ = nullptr; + } timing_ = new VCMTiming(clock_); video_receive_stream_.reset(new webrtc::internal::VideoReceiveStream2( - task_queue_factory_.get(), loop_.task_queue(), - &rtp_stream_receiver_controller_, kDefaultNumCpuCores, &packet_router_, - config_.Copy(), process_thread_.get(), &call_stats_, clock_, timing_)); + task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores, + &packet_router_, config_.Copy(), process_thread_.get(), &call_stats_, + clock_, timing_)); + video_receive_stream_->RegisterWithTransport( + &rtp_stream_receiver_controller_); video_receive_stream_->SetAndGetRecordingState(std::move(state), false); } @@ -324,6 +340,7 @@ class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test { MockTransport mock_transport_; PacketRouter packet_router_; RtpStreamReceiverController rtp_stream_receiver_controller_; + cricket::FakeCall fake_call_; std::unique_ptr video_receive_stream_; Clock* clock_; VCMTiming* timing_; @@ -568,8 +585,7 @@ class VideoReceiveStream2TestWithSimulatedClock &fake_renderer_)), call_stats_(time_controller_.GetClock(), loop_.task_queue()), video_receive_stream_(time_controller_.GetTaskQueueFactory(), - loop_.task_queue(), - &rtp_stream_receiver_controller_, + &fake_call_, /*num_cores=*/2, &packet_router_, config_.Copy(), @@ -577,9 +593,15 @@ class VideoReceiveStream2TestWithSimulatedClock &call_stats_, time_controller_.GetClock(), new VCMTiming(time_controller_.GetClock())) { + video_receive_stream_.RegisterWithTransport( + &rtp_stream_receiver_controller_); video_receive_stream_.Start(); } + ~VideoReceiveStream2TestWithSimulatedClock() override { + video_receive_stream_.UnregisterFromTransport(); + } + void OnFrameDecoded() { event_->Set(); } void PassEncodedFrameAndWait(std::unique_ptr frame) { @@ -597,6 +619,7 @@ class VideoReceiveStream2TestWithSimulatedClock std::unique_ptr process_thread_; MockTransport mock_transport_; FakeRenderer fake_renderer_; + cricket::FakeCall fake_call_; VideoReceiveStream::Config config_; internal::CallStats call_stats_; PacketRouter packet_router_; @@ -714,7 +737,11 @@ class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test { config_(&mock_transport_), call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {} - void SetUp() { + ~VideoReceiveStream2TestWithLazyDecoderCreation() override { + video_receive_stream_->UnregisterFromTransport(); + } + + void SetUp() override { webrtc::test::ScopedFieldTrials field_trials( "WebRTC-PreStreamDecoders/max:0/"); constexpr int kDefaultNumCpuCores = 2; @@ -735,10 +762,11 @@ class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test { video_receive_stream_ = std::make_unique( - task_queue_factory_.get(), loop_.task_queue(), - &rtp_stream_receiver_controller_, kDefaultNumCpuCores, + task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores, &packet_router_, config_.Copy(), process_thread_.get(), &call_stats_, clock_, timing_); + video_receive_stream_->RegisterWithTransport( + &rtp_stream_receiver_controller_); } protected: @@ -750,6 +778,7 @@ class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test { MockVideoDecoder mock_h264_video_decoder_; MockVideoDecoderFactory mock_h264_decoder_factory_; cricket::FakeVideoRenderer fake_renderer_; + cricket::FakeCall fake_call_; MockTransport mock_transport_; PacketRouter packet_router_; RtpStreamReceiverController rtp_stream_receiver_controller_;