Split VideoReceiveStream2 init into worker / network steps.

This is in preparation for actually doing this initialization
differently in the Call class. This CL takes the registration
steps that are inherently network thread associated and makes
them separate from the ctor/dtor.

Inject Call* instead of worker_thread(), which will simplify upcoming
work that needs to access the network_thread() as well.

This is related to:
https://webrtc-review.googlesource.com/c/src/+/220608
https://webrtc-review.googlesource.com/c/src/+/220609

Bug: webrtc:11993
Change-Id: I72769fd61de84967d9a645750c40d01660a2716b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/220764
Reviewed-by: Markus Handell <handellm@webrtc.org>
Commit-Queue: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34172}
This commit is contained in:
Tommi 2021-05-31 17:36:47 +02:00 committed by WebRTC LUCI CQ
parent 27d2be3583
commit 90738ddb4e
8 changed files with 140 additions and 61 deletions

View file

@ -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_;
}

View file

@ -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<webrtc::AudioState> audio_state_;
SourceTracker source_tracker_;
const std::unique_ptr<voe::ChannelReceiveInterface> 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<RtpStreamReceiverInterface> rtp_stream_receiver_
RTC_GUARDED_BY(network_thread_checker_);
RTC_GUARDED_BY(packet_sequence_checker_);
};
} // namespace internal
} // namespace webrtc

View file

@ -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<VideoReceiveStream2*>(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

View file

@ -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();
}

View file

@ -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<RtpStreamReceiverInterface> rtp_stream_receiver_
RTC_GUARDED_BY(network_thread_checker_);
RTC_GUARDED_BY(packet_sequence_checker_);
};
} // namespace webrtc

View file

@ -211,10 +211,8 @@ int DetermineMaxWaitForFrame(const VideoReceiveStream::Config& config,
: kMaxWaitForFrameMs;
}
VideoReceiveStream2::VideoReceiveStream2(
TaskQueueFactory* task_queue_factory,
TaskQueueBase* current_queue,
RtpStreamReceiverControllerInterface* receiver_controller,
VideoReceiveStream2::VideoReceiveStream2(TaskQueueFactory* task_queue_factory,
Call* call,
int num_cpu_cores,
PacketRouter* packet_router,
VideoReceiveStream::Config config,
@ -226,15 +224,15 @@ VideoReceiveStream2::VideoReceiveStream2(
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<RtxReceiveStream>(
&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]() {

View file

@ -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<video_coding::FrameBuffer> frame_buffer_;
std::unique_ptr<RtpStreamReceiverInterface> media_receiver_;
std::unique_ptr<RtxReceiveStream> rtx_receive_stream_;
std::unique_ptr<RtpStreamReceiverInterface> rtx_receiver_;
std::unique_ptr<RtpStreamReceiverInterface> media_receiver_
RTC_GUARDED_BY(packet_sequence_checker_);
std::unique_ptr<RtxReceiveStream> rtx_receive_stream_
RTC_GUARDED_BY(packet_sequence_checker_);
std::unique_ptr<RtpStreamReceiverInterface> 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.

View file

@ -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<webrtc::internal::VideoReceiveStream2>(
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;
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<webrtc::internal::VideoReceiveStream2> 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<EncodedFrame> frame) {
@ -597,6 +619,7 @@ class VideoReceiveStream2TestWithSimulatedClock
std::unique_ptr<ProcessThread> 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<webrtc::internal::VideoReceiveStream2>(
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_;