blob: 4b6d1af7dc73d2c908d9ee2d7972617a51fdf758 [file] [log] [blame]
Erik Språng09708512018-03-14 14:16:501/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <utility>
12
Karl Wiberg918f50c2018-07-05 09:40:3313#include "absl/memory/memory.h"
Yves Gerey3e707812018-11-28 15:47:4914#include "call/degraded_call.h"
15#include "rtc_base/location.h"
Erik Språng09708512018-03-14 14:16:5016
17namespace webrtc {
Sebastian Jansson836fee12019-02-08 15:08:1018
19namespace {
20constexpr int64_t kDoNothingProcessIntervalMs = 5000;
21} // namespace
22
23FakeNetworkPipeModule::~FakeNetworkPipeModule() = default;
24
25FakeNetworkPipeModule::FakeNetworkPipeModule(
26 Clock* clock,
27 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
28 Transport* transport)
29 : pipe_(clock, std::move(network_behavior), transport) {}
30
31void FakeNetworkPipeModule::SendRtp(const uint8_t* packet,
32 size_t length,
33 const PacketOptions& options) {
34 pipe_.SendRtp(packet, length, options);
35 MaybeResumeProcess();
36}
37
38void FakeNetworkPipeModule::SendRtcp(const uint8_t* packet, size_t length) {
39 pipe_.SendRtcp(packet, length);
40 MaybeResumeProcess();
41}
42
43void FakeNetworkPipeModule::MaybeResumeProcess() {
44 rtc::CritScope cs(&process_thread_lock_);
45 if (!pending_process_ && pipe_.TimeUntilNextProcess() && process_thread_) {
46 process_thread_->WakeUp(nullptr);
47 }
48}
49
50int64_t FakeNetworkPipeModule::TimeUntilNextProcess() {
51 auto delay = pipe_.TimeUntilNextProcess();
52 rtc::CritScope cs(&process_thread_lock_);
53 pending_process_ = delay.has_value();
54 return delay.value_or(kDoNothingProcessIntervalMs);
55}
56
57void FakeNetworkPipeModule::ProcessThreadAttached(
58 ProcessThread* process_thread) {
59 rtc::CritScope cs(&process_thread_lock_);
60 process_thread_ = process_thread;
61}
62
63void FakeNetworkPipeModule::Process() {
64 pipe_.Process();
65}
66
Erik Språng09708512018-03-14 14:16:5067DegradedCall::DegradedCall(
68 std::unique_ptr<Call> call,
Artem Titov75e36472018-10-08 10:28:5669 absl::optional<BuiltInNetworkBehaviorConfig> send_config,
70 absl::optional<BuiltInNetworkBehaviorConfig> receive_config)
Erik Språng09708512018-03-14 14:16:5071 : clock_(Clock::GetRealTimeClock()),
72 call_(std::move(call)),
73 send_config_(send_config),
74 send_process_thread_(
75 send_config_ ? ProcessThread::Create("DegradedSendThread") : nullptr),
76 num_send_streams_(0),
77 receive_config_(receive_config) {
78 if (receive_config_) {
Artem Titov3229d652018-08-17 11:00:5479 auto network = absl::make_unique<SimulatedNetwork>(*receive_config_);
80 receive_simulated_network_ = network.get();
Erik Språng09708512018-03-14 14:16:5081 receive_pipe_ =
Artem Titov3229d652018-08-17 11:00:5482 absl::make_unique<webrtc::FakeNetworkPipe>(clock_, std::move(network));
Erik Språng09708512018-03-14 14:16:5083 receive_pipe_->SetReceiver(call_->Receiver());
84 }
85 if (send_process_thread_) {
86 send_process_thread_->Start();
87 }
88}
89
90DegradedCall::~DegradedCall() {
91 if (send_pipe_) {
92 send_process_thread_->DeRegisterModule(send_pipe_.get());
93 }
94 if (send_process_thread_) {
95 send_process_thread_->Stop();
96 }
97}
98
99AudioSendStream* DegradedCall::CreateAudioSendStream(
100 const AudioSendStream::Config& config) {
101 return call_->CreateAudioSendStream(config);
102}
103
104void DegradedCall::DestroyAudioSendStream(AudioSendStream* send_stream) {
105 call_->DestroyAudioSendStream(send_stream);
106}
107
108AudioReceiveStream* DegradedCall::CreateAudioReceiveStream(
109 const AudioReceiveStream::Config& config) {
110 return call_->CreateAudioReceiveStream(config);
111}
112
113void DegradedCall::DestroyAudioReceiveStream(
114 AudioReceiveStream* receive_stream) {
115 call_->DestroyAudioReceiveStream(receive_stream);
116}
117
118VideoSendStream* DegradedCall::CreateVideoSendStream(
119 VideoSendStream::Config config,
120 VideoEncoderConfig encoder_config) {
121 if (send_config_ && !send_pipe_) {
Artem Titov3229d652018-08-17 11:00:54122 auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
123 send_simulated_network_ = network.get();
Sebastian Jansson836fee12019-02-08 15:08:10124 send_pipe_ = absl::make_unique<FakeNetworkPipeModule>(
125 clock_, std::move(network), config.send_transport);
Erik Språng09708512018-03-14 14:16:50126 config.send_transport = this;
127 send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
128 }
129 ++num_send_streams_;
130 return call_->CreateVideoSendStream(std::move(config),
131 std::move(encoder_config));
132}
133
134VideoSendStream* DegradedCall::CreateVideoSendStream(
135 VideoSendStream::Config config,
136 VideoEncoderConfig encoder_config,
137 std::unique_ptr<FecController> fec_controller) {
138 if (send_config_ && !send_pipe_) {
Artem Titov3229d652018-08-17 11:00:54139 auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
140 send_simulated_network_ = network.get();
Sebastian Jansson836fee12019-02-08 15:08:10141 send_pipe_ = absl::make_unique<FakeNetworkPipeModule>(
142 clock_, std::move(network), config.send_transport);
Erik Språng09708512018-03-14 14:16:50143 config.send_transport = this;
144 send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
145 }
146 ++num_send_streams_;
147 return call_->CreateVideoSendStream(
148 std::move(config), std::move(encoder_config), std::move(fec_controller));
149}
150
151void DegradedCall::DestroyVideoSendStream(VideoSendStream* send_stream) {
Erik Språngeef09fc2018-03-16 09:47:16152 call_->DestroyVideoSendStream(send_stream);
Erik Språng09708512018-03-14 14:16:50153 if (send_pipe_ && num_send_streams_ > 0) {
154 --num_send_streams_;
155 if (num_send_streams_ == 0) {
156 send_process_thread_->DeRegisterModule(send_pipe_.get());
157 send_pipe_.reset();
158 }
159 }
Erik Språng09708512018-03-14 14:16:50160}
161
162VideoReceiveStream* DegradedCall::CreateVideoReceiveStream(
163 VideoReceiveStream::Config configuration) {
164 return call_->CreateVideoReceiveStream(std::move(configuration));
165}
166
167void DegradedCall::DestroyVideoReceiveStream(
168 VideoReceiveStream* receive_stream) {
169 call_->DestroyVideoReceiveStream(receive_stream);
170}
171
172FlexfecReceiveStream* DegradedCall::CreateFlexfecReceiveStream(
173 const FlexfecReceiveStream::Config& config) {
174 return call_->CreateFlexfecReceiveStream(config);
175}
176
177void DegradedCall::DestroyFlexfecReceiveStream(
178 FlexfecReceiveStream* receive_stream) {
179 call_->DestroyFlexfecReceiveStream(receive_stream);
180}
181
182PacketReceiver* DegradedCall::Receiver() {
183 if (receive_config_) {
184 return this;
185 }
186 return call_->Receiver();
187}
188
189RtpTransportControllerSendInterface*
190DegradedCall::GetTransportControllerSend() {
191 return call_->GetTransportControllerSend();
192}
193
194Call::Stats DegradedCall::GetStats() const {
195 return call_->GetStats();
196}
197
198void DegradedCall::SetBitrateAllocationStrategy(
199 std::unique_ptr<rtc::BitrateAllocationStrategy>
200 bitrate_allocation_strategy) {
201 call_->SetBitrateAllocationStrategy(std::move(bitrate_allocation_strategy));
202}
203
204void DegradedCall::SignalChannelNetworkState(MediaType media,
205 NetworkState state) {
206 call_->SignalChannelNetworkState(media, state);
207}
208
Stefan Holmer64be7fa2018-10-04 13:21:55209void DegradedCall::OnAudioTransportOverheadChanged(
Erik Språng09708512018-03-14 14:16:50210 int transport_overhead_per_packet) {
Stefan Holmer64be7fa2018-10-04 13:21:55211 call_->OnAudioTransportOverheadChanged(transport_overhead_per_packet);
Erik Språng09708512018-03-14 14:16:50212}
213
214void DegradedCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
215 if (send_config_) {
216 // If we have a degraded send-transport, we have already notified call
217 // about the supposed network send time. Discard the actual network send
218 // time in order to properly fool the BWE.
219 return;
220 }
221 call_->OnSentPacket(sent_packet);
222}
223
224bool DegradedCall::SendRtp(const uint8_t* packet,
225 size_t length,
226 const PacketOptions& options) {
227 // A call here comes from the RTP stack (probably pacer). We intercept it and
228 // put it in the fake network pipe instead, but report to Call that is has
229 // been sent, so that the bandwidth estimator sees the delay we add.
230 send_pipe_->SendRtp(packet, length, options);
231 if (options.packet_id != -1) {
Sebastian Jansson156d11d2018-09-28 15:21:34232 rtc::SentPacket sent_packet;
233 sent_packet.packet_id = options.packet_id;
234 sent_packet.send_time_ms = clock_->TimeInMilliseconds();
Sebastian Jansson03789972018-10-09 16:27:57235 sent_packet.info.included_in_feedback = options.included_in_feedback;
236 sent_packet.info.included_in_allocation = options.included_in_allocation;
Sebastian Jansson156d11d2018-09-28 15:21:34237 sent_packet.info.packet_size_bytes = length;
238 sent_packet.info.packet_type = rtc::PacketType::kData;
239 call_->OnSentPacket(sent_packet);
Erik Språng09708512018-03-14 14:16:50240 }
241 return true;
242}
243
244bool DegradedCall::SendRtcp(const uint8_t* packet, size_t length) {
245 send_pipe_->SendRtcp(packet, length);
246 return true;
247}
248
249PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket(
250 MediaType media_type,
251 rtc::CopyOnWriteBuffer packet,
Niels Möller70082872018-08-07 09:03:12252 int64_t packet_time_us) {
253 PacketReceiver::DeliveryStatus status = receive_pipe_->DeliverPacket(
254 media_type, std::move(packet), packet_time_us);
Erik Språng09708512018-03-14 14:16:50255 // This is not optimal, but there are many places where there are thread
256 // checks that fail if we're not using the worker thread call into this
257 // method. If we want to fix this we probably need a task queue to do handover
258 // of all overriden methods, which feels like overikill for the current use
259 // case.
260 // By just having this thread call out via the Process() method we work around
261 // that, with the tradeoff that a non-zero delay may become a little larger
262 // than anticipated at very low packet rates.
263 receive_pipe_->Process();
264 return status;
265}
266
Piotr (Peter) Slatalacc8e8bb2018-11-15 16:26:19267void DegradedCall::MediaTransportChange(
268 MediaTransportInterface* media_transport) {
269 // TODO(bugs.webrtc.org/9719) We should add support for media transport here
270 // at some point.
271}
272
Erik Språng09708512018-03-14 14:16:50273} // namespace webrtc