xref: /aosp_15_r20/external/webrtc/call/degraded_call.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "call/degraded_call.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <utility>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
17*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_util.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/event.h"
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
21*d9f75844SAndroid Build Coastguard Worker 
FakeNetworkPipeOnTaskQueue(TaskQueueBase * task_queue,rtc::scoped_refptr<PendingTaskSafetyFlag> call_alive,Clock * clock,std::unique_ptr<NetworkBehaviorInterface> network_behavior)22*d9f75844SAndroid Build Coastguard Worker DegradedCall::FakeNetworkPipeOnTaskQueue::FakeNetworkPipeOnTaskQueue(
23*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* task_queue,
24*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<PendingTaskSafetyFlag> call_alive,
25*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
26*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<NetworkBehaviorInterface> network_behavior)
27*d9f75844SAndroid Build Coastguard Worker     : clock_(clock),
28*d9f75844SAndroid Build Coastguard Worker       task_queue_(task_queue),
29*d9f75844SAndroid Build Coastguard Worker       call_alive_(std::move(call_alive)),
30*d9f75844SAndroid Build Coastguard Worker       pipe_(clock, std::move(network_behavior)) {}
31*d9f75844SAndroid Build Coastguard Worker 
SendRtp(const uint8_t * packet,size_t length,const PacketOptions & options,Transport * transport)32*d9f75844SAndroid Build Coastguard Worker void DegradedCall::FakeNetworkPipeOnTaskQueue::SendRtp(
33*d9f75844SAndroid Build Coastguard Worker     const uint8_t* packet,
34*d9f75844SAndroid Build Coastguard Worker     size_t length,
35*d9f75844SAndroid Build Coastguard Worker     const PacketOptions& options,
36*d9f75844SAndroid Build Coastguard Worker     Transport* transport) {
37*d9f75844SAndroid Build Coastguard Worker   pipe_.SendRtp(packet, length, options, transport);
38*d9f75844SAndroid Build Coastguard Worker   Process();
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker 
SendRtcp(const uint8_t * packet,size_t length,Transport * transport)41*d9f75844SAndroid Build Coastguard Worker void DegradedCall::FakeNetworkPipeOnTaskQueue::SendRtcp(const uint8_t* packet,
42*d9f75844SAndroid Build Coastguard Worker                                                         size_t length,
43*d9f75844SAndroid Build Coastguard Worker                                                         Transport* transport) {
44*d9f75844SAndroid Build Coastguard Worker   pipe_.SendRtcp(packet, length, transport);
45*d9f75844SAndroid Build Coastguard Worker   Process();
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker 
AddActiveTransport(Transport * transport)48*d9f75844SAndroid Build Coastguard Worker void DegradedCall::FakeNetworkPipeOnTaskQueue::AddActiveTransport(
49*d9f75844SAndroid Build Coastguard Worker     Transport* transport) {
50*d9f75844SAndroid Build Coastguard Worker   pipe_.AddActiveTransport(transport);
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker 
RemoveActiveTransport(Transport * transport)53*d9f75844SAndroid Build Coastguard Worker void DegradedCall::FakeNetworkPipeOnTaskQueue::RemoveActiveTransport(
54*d9f75844SAndroid Build Coastguard Worker     Transport* transport) {
55*d9f75844SAndroid Build Coastguard Worker   pipe_.RemoveActiveTransport(transport);
56*d9f75844SAndroid Build Coastguard Worker }
57*d9f75844SAndroid Build Coastguard Worker 
Process()58*d9f75844SAndroid Build Coastguard Worker bool DegradedCall::FakeNetworkPipeOnTaskQueue::Process() {
59*d9f75844SAndroid Build Coastguard Worker   pipe_.Process();
60*d9f75844SAndroid Build Coastguard Worker   auto time_to_next = pipe_.TimeUntilNextProcess();
61*d9f75844SAndroid Build Coastguard Worker   if (!time_to_next) {
62*d9f75844SAndroid Build Coastguard Worker     // Packet was probably sent immediately.
63*d9f75844SAndroid Build Coastguard Worker     return false;
64*d9f75844SAndroid Build Coastguard Worker   }
65*d9f75844SAndroid Build Coastguard Worker 
66*d9f75844SAndroid Build Coastguard Worker   task_queue_->PostTask(SafeTask(call_alive_, [this, time_to_next] {
67*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(task_queue_);
68*d9f75844SAndroid Build Coastguard Worker     int64_t next_process_time = *time_to_next + clock_->TimeInMilliseconds();
69*d9f75844SAndroid Build Coastguard Worker     if (!next_process_ms_ || next_process_time < *next_process_ms_) {
70*d9f75844SAndroid Build Coastguard Worker       next_process_ms_ = next_process_time;
71*d9f75844SAndroid Build Coastguard Worker       task_queue_->PostDelayedHighPrecisionTask(
72*d9f75844SAndroid Build Coastguard Worker           SafeTask(call_alive_,
73*d9f75844SAndroid Build Coastguard Worker                    [this] {
74*d9f75844SAndroid Build Coastguard Worker                      RTC_DCHECK_RUN_ON(task_queue_);
75*d9f75844SAndroid Build Coastguard Worker                      if (!Process()) {
76*d9f75844SAndroid Build Coastguard Worker                        next_process_ms_.reset();
77*d9f75844SAndroid Build Coastguard Worker                      }
78*d9f75844SAndroid Build Coastguard Worker                    }),
79*d9f75844SAndroid Build Coastguard Worker           TimeDelta::Millis(*time_to_next));
80*d9f75844SAndroid Build Coastguard Worker     }
81*d9f75844SAndroid Build Coastguard Worker   }));
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker   return true;
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker 
FakeNetworkPipeTransportAdapter(FakeNetworkPipeOnTaskQueue * fake_network,Call * call,Clock * clock,Transport * real_transport)86*d9f75844SAndroid Build Coastguard Worker DegradedCall::FakeNetworkPipeTransportAdapter::FakeNetworkPipeTransportAdapter(
87*d9f75844SAndroid Build Coastguard Worker     FakeNetworkPipeOnTaskQueue* fake_network,
88*d9f75844SAndroid Build Coastguard Worker     Call* call,
89*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
90*d9f75844SAndroid Build Coastguard Worker     Transport* real_transport)
91*d9f75844SAndroid Build Coastguard Worker     : network_pipe_(fake_network),
92*d9f75844SAndroid Build Coastguard Worker       call_(call),
93*d9f75844SAndroid Build Coastguard Worker       clock_(clock),
94*d9f75844SAndroid Build Coastguard Worker       real_transport_(real_transport) {
95*d9f75844SAndroid Build Coastguard Worker   network_pipe_->AddActiveTransport(real_transport);
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker DegradedCall::FakeNetworkPipeTransportAdapter::
~FakeNetworkPipeTransportAdapter()99*d9f75844SAndroid Build Coastguard Worker     ~FakeNetworkPipeTransportAdapter() {
100*d9f75844SAndroid Build Coastguard Worker   network_pipe_->RemoveActiveTransport(real_transport_);
101*d9f75844SAndroid Build Coastguard Worker }
102*d9f75844SAndroid Build Coastguard Worker 
SendRtp(const uint8_t * packet,size_t length,const PacketOptions & options)103*d9f75844SAndroid Build Coastguard Worker bool DegradedCall::FakeNetworkPipeTransportAdapter::SendRtp(
104*d9f75844SAndroid Build Coastguard Worker     const uint8_t* packet,
105*d9f75844SAndroid Build Coastguard Worker     size_t length,
106*d9f75844SAndroid Build Coastguard Worker     const PacketOptions& options) {
107*d9f75844SAndroid Build Coastguard Worker   // A call here comes from the RTP stack (probably pacer). We intercept it and
108*d9f75844SAndroid Build Coastguard Worker   // put it in the fake network pipe instead, but report to Call that is has
109*d9f75844SAndroid Build Coastguard Worker   // been sent, so that the bandwidth estimator sees the delay we add.
110*d9f75844SAndroid Build Coastguard Worker   network_pipe_->SendRtp(packet, length, options, real_transport_);
111*d9f75844SAndroid Build Coastguard Worker   if (options.packet_id != -1) {
112*d9f75844SAndroid Build Coastguard Worker     rtc::SentPacket sent_packet;
113*d9f75844SAndroid Build Coastguard Worker     sent_packet.packet_id = options.packet_id;
114*d9f75844SAndroid Build Coastguard Worker     sent_packet.send_time_ms = clock_->TimeInMilliseconds();
115*d9f75844SAndroid Build Coastguard Worker     sent_packet.info.included_in_feedback = options.included_in_feedback;
116*d9f75844SAndroid Build Coastguard Worker     sent_packet.info.included_in_allocation = options.included_in_allocation;
117*d9f75844SAndroid Build Coastguard Worker     sent_packet.info.packet_size_bytes = length;
118*d9f75844SAndroid Build Coastguard Worker     sent_packet.info.packet_type = rtc::PacketType::kData;
119*d9f75844SAndroid Build Coastguard Worker     call_->OnSentPacket(sent_packet);
120*d9f75844SAndroid Build Coastguard Worker   }
121*d9f75844SAndroid Build Coastguard Worker   return true;
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker 
SendRtcp(const uint8_t * packet,size_t length)124*d9f75844SAndroid Build Coastguard Worker bool DegradedCall::FakeNetworkPipeTransportAdapter::SendRtcp(
125*d9f75844SAndroid Build Coastguard Worker     const uint8_t* packet,
126*d9f75844SAndroid Build Coastguard Worker     size_t length) {
127*d9f75844SAndroid Build Coastguard Worker   network_pipe_->SendRtcp(packet, length, real_transport_);
128*d9f75844SAndroid Build Coastguard Worker   return true;
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker 
ThreadedPacketReceiver(webrtc::TaskQueueBase * worker_thread,webrtc::TaskQueueBase * network_thread,rtc::scoped_refptr<PendingTaskSafetyFlag> call_alive,webrtc::PacketReceiver * receiver)131*d9f75844SAndroid Build Coastguard Worker DegradedCall::ThreadedPacketReceiver::ThreadedPacketReceiver(
132*d9f75844SAndroid Build Coastguard Worker     webrtc::TaskQueueBase* worker_thread,
133*d9f75844SAndroid Build Coastguard Worker     webrtc::TaskQueueBase* network_thread,
134*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<PendingTaskSafetyFlag> call_alive,
135*d9f75844SAndroid Build Coastguard Worker     webrtc::PacketReceiver* receiver)
136*d9f75844SAndroid Build Coastguard Worker     : worker_thread_(worker_thread),
137*d9f75844SAndroid Build Coastguard Worker       network_thread_(network_thread),
138*d9f75844SAndroid Build Coastguard Worker       call_alive_(std::move(call_alive)),
139*d9f75844SAndroid Build Coastguard Worker       receiver_(receiver) {}
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker DegradedCall::ThreadedPacketReceiver::~ThreadedPacketReceiver() = default;
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker PacketReceiver::DeliveryStatus
DeliverPacket(MediaType media_type,rtc::CopyOnWriteBuffer packet,int64_t packet_time_us)144*d9f75844SAndroid Build Coastguard Worker DegradedCall::ThreadedPacketReceiver::DeliverPacket(
145*d9f75844SAndroid Build Coastguard Worker     MediaType media_type,
146*d9f75844SAndroid Build Coastguard Worker     rtc::CopyOnWriteBuffer packet,
147*d9f75844SAndroid Build Coastguard Worker     int64_t packet_time_us) {
148*d9f75844SAndroid Build Coastguard Worker   // `Call::DeliverPacket` expects RTCP packets to be delivered from the
149*d9f75844SAndroid Build Coastguard Worker   // network thread and RTP packets to be delivered from the worker thread.
150*d9f75844SAndroid Build Coastguard Worker   // Because `FakeNetworkPipe` queues packets, the thread used when this packet
151*d9f75844SAndroid Build Coastguard Worker   // is delivered to `DegradedCall::DeliverPacket` may differ from the thread
152*d9f75844SAndroid Build Coastguard Worker   // used when this packet is delivered to
153*d9f75844SAndroid Build Coastguard Worker   // `ThreadedPacketReceiver::DeliverPacket`. To solve this problem, always
154*d9f75844SAndroid Build Coastguard Worker   // make sure that packets are sent in the correct thread.
155*d9f75844SAndroid Build Coastguard Worker   if (IsRtcpPacket(packet)) {
156*d9f75844SAndroid Build Coastguard Worker     if (!network_thread_->IsCurrent()) {
157*d9f75844SAndroid Build Coastguard Worker       network_thread_->PostTask(
158*d9f75844SAndroid Build Coastguard Worker           SafeTask(call_alive_, [receiver = receiver_, media_type,
159*d9f75844SAndroid Build Coastguard Worker                                  packet = std::move(packet), packet_time_us]() {
160*d9f75844SAndroid Build Coastguard Worker             receiver->DeliverPacket(media_type, std::move(packet),
161*d9f75844SAndroid Build Coastguard Worker                                     packet_time_us);
162*d9f75844SAndroid Build Coastguard Worker           }));
163*d9f75844SAndroid Build Coastguard Worker       return DELIVERY_OK;
164*d9f75844SAndroid Build Coastguard Worker     }
165*d9f75844SAndroid Build Coastguard Worker   } else {
166*d9f75844SAndroid Build Coastguard Worker     if (!worker_thread_->IsCurrent()) {
167*d9f75844SAndroid Build Coastguard Worker       worker_thread_->PostTask([receiver = receiver_, media_type,
168*d9f75844SAndroid Build Coastguard Worker                                 packet = std::move(packet), packet_time_us]() {
169*d9f75844SAndroid Build Coastguard Worker         receiver->DeliverPacket(media_type, std::move(packet), packet_time_us);
170*d9f75844SAndroid Build Coastguard Worker       });
171*d9f75844SAndroid Build Coastguard Worker       return DELIVERY_OK;
172*d9f75844SAndroid Build Coastguard Worker     }
173*d9f75844SAndroid Build Coastguard Worker   }
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker   return receiver_->DeliverPacket(media_type, std::move(packet),
176*d9f75844SAndroid Build Coastguard Worker                                   packet_time_us);
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker 
DegradedCall(std::unique_ptr<Call> call,const std::vector<TimeScopedNetworkConfig> & send_configs,const std::vector<TimeScopedNetworkConfig> & receive_configs)179*d9f75844SAndroid Build Coastguard Worker DegradedCall::DegradedCall(
180*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<Call> call,
181*d9f75844SAndroid Build Coastguard Worker     const std::vector<TimeScopedNetworkConfig>& send_configs,
182*d9f75844SAndroid Build Coastguard Worker     const std::vector<TimeScopedNetworkConfig>& receive_configs)
183*d9f75844SAndroid Build Coastguard Worker     : clock_(Clock::GetRealTimeClock()),
184*d9f75844SAndroid Build Coastguard Worker       call_(std::move(call)),
185*d9f75844SAndroid Build Coastguard Worker       call_alive_(PendingTaskSafetyFlag::CreateDetached()),
186*d9f75844SAndroid Build Coastguard Worker       send_config_index_(0),
187*d9f75844SAndroid Build Coastguard Worker       send_configs_(send_configs),
188*d9f75844SAndroid Build Coastguard Worker       send_simulated_network_(nullptr),
189*d9f75844SAndroid Build Coastguard Worker       receive_config_index_(0),
190*d9f75844SAndroid Build Coastguard Worker       receive_configs_(receive_configs) {
191*d9f75844SAndroid Build Coastguard Worker   if (!receive_configs_.empty()) {
192*d9f75844SAndroid Build Coastguard Worker     auto network = std::make_unique<SimulatedNetwork>(receive_configs_[0]);
193*d9f75844SAndroid Build Coastguard Worker     receive_simulated_network_ = network.get();
194*d9f75844SAndroid Build Coastguard Worker     receive_pipe_ =
195*d9f75844SAndroid Build Coastguard Worker         std::make_unique<webrtc::FakeNetworkPipe>(clock_, std::move(network));
196*d9f75844SAndroid Build Coastguard Worker     packet_receiver_ = std::make_unique<ThreadedPacketReceiver>(
197*d9f75844SAndroid Build Coastguard Worker         call_->worker_thread(), call_->network_thread(), call_alive_,
198*d9f75844SAndroid Build Coastguard Worker         call_->Receiver());
199*d9f75844SAndroid Build Coastguard Worker     receive_pipe_->SetReceiver(packet_receiver_.get());
200*d9f75844SAndroid Build Coastguard Worker     if (receive_configs_.size() > 1) {
201*d9f75844SAndroid Build Coastguard Worker       call_->network_thread()->PostDelayedTask(
202*d9f75844SAndroid Build Coastguard Worker           SafeTask(call_alive_, [this] { UpdateReceiveNetworkConfig(); }),
203*d9f75844SAndroid Build Coastguard Worker           receive_configs_[0].duration);
204*d9f75844SAndroid Build Coastguard Worker     }
205*d9f75844SAndroid Build Coastguard Worker   }
206*d9f75844SAndroid Build Coastguard Worker   if (!send_configs_.empty()) {
207*d9f75844SAndroid Build Coastguard Worker     auto network = std::make_unique<SimulatedNetwork>(send_configs_[0]);
208*d9f75844SAndroid Build Coastguard Worker     send_simulated_network_ = network.get();
209*d9f75844SAndroid Build Coastguard Worker     send_pipe_ = std::make_unique<FakeNetworkPipeOnTaskQueue>(
210*d9f75844SAndroid Build Coastguard Worker         call_->network_thread(), call_alive_, clock_, std::move(network));
211*d9f75844SAndroid Build Coastguard Worker     if (send_configs_.size() > 1) {
212*d9f75844SAndroid Build Coastguard Worker       call_->network_thread()->PostDelayedTask(
213*d9f75844SAndroid Build Coastguard Worker           SafeTask(call_alive_, [this] { UpdateSendNetworkConfig(); }),
214*d9f75844SAndroid Build Coastguard Worker           send_configs_[0].duration);
215*d9f75844SAndroid Build Coastguard Worker     }
216*d9f75844SAndroid Build Coastguard Worker   }
217*d9f75844SAndroid Build Coastguard Worker }
218*d9f75844SAndroid Build Coastguard Worker 
~DegradedCall()219*d9f75844SAndroid Build Coastguard Worker DegradedCall::~DegradedCall() {
220*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(call_->worker_thread());
221*d9f75844SAndroid Build Coastguard Worker   // Thread synchronization is required to call `SetNotAlive`.
222*d9f75844SAndroid Build Coastguard Worker   // Otherwise, when the `DegradedCall` object is destroyed but
223*d9f75844SAndroid Build Coastguard Worker   // `SetNotAlive` has not yet been called,
224*d9f75844SAndroid Build Coastguard Worker   // another Closure guarded by `call_alive_` may be called.
225*d9f75844SAndroid Build Coastguard Worker   rtc::Event event;
226*d9f75844SAndroid Build Coastguard Worker   call_->network_thread()->PostTask(
227*d9f75844SAndroid Build Coastguard Worker       [flag = std::move(call_alive_), &event]() mutable {
228*d9f75844SAndroid Build Coastguard Worker         flag->SetNotAlive();
229*d9f75844SAndroid Build Coastguard Worker         event.Set();
230*d9f75844SAndroid Build Coastguard Worker       });
231*d9f75844SAndroid Build Coastguard Worker   event.Wait(rtc::Event::kForever);
232*d9f75844SAndroid Build Coastguard Worker }
233*d9f75844SAndroid Build Coastguard Worker 
CreateAudioSendStream(const AudioSendStream::Config & config)234*d9f75844SAndroid Build Coastguard Worker AudioSendStream* DegradedCall::CreateAudioSendStream(
235*d9f75844SAndroid Build Coastguard Worker     const AudioSendStream::Config& config) {
236*d9f75844SAndroid Build Coastguard Worker   if (!send_configs_.empty()) {
237*d9f75844SAndroid Build Coastguard Worker     auto transport_adapter = std::make_unique<FakeNetworkPipeTransportAdapter>(
238*d9f75844SAndroid Build Coastguard Worker         send_pipe_.get(), call_.get(), clock_, config.send_transport);
239*d9f75844SAndroid Build Coastguard Worker     AudioSendStream::Config degrade_config = config;
240*d9f75844SAndroid Build Coastguard Worker     degrade_config.send_transport = transport_adapter.get();
241*d9f75844SAndroid Build Coastguard Worker     AudioSendStream* send_stream = call_->CreateAudioSendStream(degrade_config);
242*d9f75844SAndroid Build Coastguard Worker     if (send_stream) {
243*d9f75844SAndroid Build Coastguard Worker       audio_send_transport_adapters_[send_stream] =
244*d9f75844SAndroid Build Coastguard Worker           std::move(transport_adapter);
245*d9f75844SAndroid Build Coastguard Worker     }
246*d9f75844SAndroid Build Coastguard Worker     return send_stream;
247*d9f75844SAndroid Build Coastguard Worker   }
248*d9f75844SAndroid Build Coastguard Worker   return call_->CreateAudioSendStream(config);
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker 
DestroyAudioSendStream(AudioSendStream * send_stream)251*d9f75844SAndroid Build Coastguard Worker void DegradedCall::DestroyAudioSendStream(AudioSendStream* send_stream) {
252*d9f75844SAndroid Build Coastguard Worker   call_->DestroyAudioSendStream(send_stream);
253*d9f75844SAndroid Build Coastguard Worker   audio_send_transport_adapters_.erase(send_stream);
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker 
CreateAudioReceiveStream(const AudioReceiveStreamInterface::Config & config)256*d9f75844SAndroid Build Coastguard Worker AudioReceiveStreamInterface* DegradedCall::CreateAudioReceiveStream(
257*d9f75844SAndroid Build Coastguard Worker     const AudioReceiveStreamInterface::Config& config) {
258*d9f75844SAndroid Build Coastguard Worker   return call_->CreateAudioReceiveStream(config);
259*d9f75844SAndroid Build Coastguard Worker }
260*d9f75844SAndroid Build Coastguard Worker 
DestroyAudioReceiveStream(AudioReceiveStreamInterface * receive_stream)261*d9f75844SAndroid Build Coastguard Worker void DegradedCall::DestroyAudioReceiveStream(
262*d9f75844SAndroid Build Coastguard Worker     AudioReceiveStreamInterface* receive_stream) {
263*d9f75844SAndroid Build Coastguard Worker   call_->DestroyAudioReceiveStream(receive_stream);
264*d9f75844SAndroid Build Coastguard Worker }
265*d9f75844SAndroid Build Coastguard Worker 
CreateVideoSendStream(VideoSendStream::Config config,VideoEncoderConfig encoder_config)266*d9f75844SAndroid Build Coastguard Worker VideoSendStream* DegradedCall::CreateVideoSendStream(
267*d9f75844SAndroid Build Coastguard Worker     VideoSendStream::Config config,
268*d9f75844SAndroid Build Coastguard Worker     VideoEncoderConfig encoder_config) {
269*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<FakeNetworkPipeTransportAdapter> transport_adapter;
270*d9f75844SAndroid Build Coastguard Worker   if (!send_configs_.empty()) {
271*d9f75844SAndroid Build Coastguard Worker     transport_adapter = std::make_unique<FakeNetworkPipeTransportAdapter>(
272*d9f75844SAndroid Build Coastguard Worker         send_pipe_.get(), call_.get(), clock_, config.send_transport);
273*d9f75844SAndroid Build Coastguard Worker     config.send_transport = transport_adapter.get();
274*d9f75844SAndroid Build Coastguard Worker   }
275*d9f75844SAndroid Build Coastguard Worker   VideoSendStream* send_stream = call_->CreateVideoSendStream(
276*d9f75844SAndroid Build Coastguard Worker       std::move(config), std::move(encoder_config));
277*d9f75844SAndroid Build Coastguard Worker   if (send_stream && transport_adapter) {
278*d9f75844SAndroid Build Coastguard Worker     video_send_transport_adapters_[send_stream] = std::move(transport_adapter);
279*d9f75844SAndroid Build Coastguard Worker   }
280*d9f75844SAndroid Build Coastguard Worker   return send_stream;
281*d9f75844SAndroid Build Coastguard Worker }
282*d9f75844SAndroid Build Coastguard Worker 
CreateVideoSendStream(VideoSendStream::Config config,VideoEncoderConfig encoder_config,std::unique_ptr<FecController> fec_controller)283*d9f75844SAndroid Build Coastguard Worker VideoSendStream* DegradedCall::CreateVideoSendStream(
284*d9f75844SAndroid Build Coastguard Worker     VideoSendStream::Config config,
285*d9f75844SAndroid Build Coastguard Worker     VideoEncoderConfig encoder_config,
286*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<FecController> fec_controller) {
287*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<FakeNetworkPipeTransportAdapter> transport_adapter;
288*d9f75844SAndroid Build Coastguard Worker   if (!send_configs_.empty()) {
289*d9f75844SAndroid Build Coastguard Worker     transport_adapter = std::make_unique<FakeNetworkPipeTransportAdapter>(
290*d9f75844SAndroid Build Coastguard Worker         send_pipe_.get(), call_.get(), clock_, config.send_transport);
291*d9f75844SAndroid Build Coastguard Worker     config.send_transport = transport_adapter.get();
292*d9f75844SAndroid Build Coastguard Worker   }
293*d9f75844SAndroid Build Coastguard Worker   VideoSendStream* send_stream = call_->CreateVideoSendStream(
294*d9f75844SAndroid Build Coastguard Worker       std::move(config), std::move(encoder_config), std::move(fec_controller));
295*d9f75844SAndroid Build Coastguard Worker   if (send_stream && transport_adapter) {
296*d9f75844SAndroid Build Coastguard Worker     video_send_transport_adapters_[send_stream] = std::move(transport_adapter);
297*d9f75844SAndroid Build Coastguard Worker   }
298*d9f75844SAndroid Build Coastguard Worker   return send_stream;
299*d9f75844SAndroid Build Coastguard Worker }
300*d9f75844SAndroid Build Coastguard Worker 
DestroyVideoSendStream(VideoSendStream * send_stream)301*d9f75844SAndroid Build Coastguard Worker void DegradedCall::DestroyVideoSendStream(VideoSendStream* send_stream) {
302*d9f75844SAndroid Build Coastguard Worker   call_->DestroyVideoSendStream(send_stream);
303*d9f75844SAndroid Build Coastguard Worker   video_send_transport_adapters_.erase(send_stream);
304*d9f75844SAndroid Build Coastguard Worker }
305*d9f75844SAndroid Build Coastguard Worker 
CreateVideoReceiveStream(VideoReceiveStreamInterface::Config configuration)306*d9f75844SAndroid Build Coastguard Worker VideoReceiveStreamInterface* DegradedCall::CreateVideoReceiveStream(
307*d9f75844SAndroid Build Coastguard Worker     VideoReceiveStreamInterface::Config configuration) {
308*d9f75844SAndroid Build Coastguard Worker   return call_->CreateVideoReceiveStream(std::move(configuration));
309*d9f75844SAndroid Build Coastguard Worker }
310*d9f75844SAndroid Build Coastguard Worker 
DestroyVideoReceiveStream(VideoReceiveStreamInterface * receive_stream)311*d9f75844SAndroid Build Coastguard Worker void DegradedCall::DestroyVideoReceiveStream(
312*d9f75844SAndroid Build Coastguard Worker     VideoReceiveStreamInterface* receive_stream) {
313*d9f75844SAndroid Build Coastguard Worker   call_->DestroyVideoReceiveStream(receive_stream);
314*d9f75844SAndroid Build Coastguard Worker }
315*d9f75844SAndroid Build Coastguard Worker 
CreateFlexfecReceiveStream(const FlexfecReceiveStream::Config config)316*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStream* DegradedCall::CreateFlexfecReceiveStream(
317*d9f75844SAndroid Build Coastguard Worker     const FlexfecReceiveStream::Config config) {
318*d9f75844SAndroid Build Coastguard Worker   return call_->CreateFlexfecReceiveStream(std::move(config));
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker 
DestroyFlexfecReceiveStream(FlexfecReceiveStream * receive_stream)321*d9f75844SAndroid Build Coastguard Worker void DegradedCall::DestroyFlexfecReceiveStream(
322*d9f75844SAndroid Build Coastguard Worker     FlexfecReceiveStream* receive_stream) {
323*d9f75844SAndroid Build Coastguard Worker   call_->DestroyFlexfecReceiveStream(receive_stream);
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker 
AddAdaptationResource(rtc::scoped_refptr<Resource> resource)326*d9f75844SAndroid Build Coastguard Worker void DegradedCall::AddAdaptationResource(
327*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<Resource> resource) {
328*d9f75844SAndroid Build Coastguard Worker   call_->AddAdaptationResource(std::move(resource));
329*d9f75844SAndroid Build Coastguard Worker }
330*d9f75844SAndroid Build Coastguard Worker 
Receiver()331*d9f75844SAndroid Build Coastguard Worker PacketReceiver* DegradedCall::Receiver() {
332*d9f75844SAndroid Build Coastguard Worker   if (!receive_configs_.empty()) {
333*d9f75844SAndroid Build Coastguard Worker     return this;
334*d9f75844SAndroid Build Coastguard Worker   }
335*d9f75844SAndroid Build Coastguard Worker   return call_->Receiver();
336*d9f75844SAndroid Build Coastguard Worker }
337*d9f75844SAndroid Build Coastguard Worker 
338*d9f75844SAndroid Build Coastguard Worker RtpTransportControllerSendInterface*
GetTransportControllerSend()339*d9f75844SAndroid Build Coastguard Worker DegradedCall::GetTransportControllerSend() {
340*d9f75844SAndroid Build Coastguard Worker   return call_->GetTransportControllerSend();
341*d9f75844SAndroid Build Coastguard Worker }
342*d9f75844SAndroid Build Coastguard Worker 
GetStats() const343*d9f75844SAndroid Build Coastguard Worker Call::Stats DegradedCall::GetStats() const {
344*d9f75844SAndroid Build Coastguard Worker   return call_->GetStats();
345*d9f75844SAndroid Build Coastguard Worker }
346*d9f75844SAndroid Build Coastguard Worker 
trials() const347*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& DegradedCall::trials() const {
348*d9f75844SAndroid Build Coastguard Worker   return call_->trials();
349*d9f75844SAndroid Build Coastguard Worker }
350*d9f75844SAndroid Build Coastguard Worker 
network_thread() const351*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* DegradedCall::network_thread() const {
352*d9f75844SAndroid Build Coastguard Worker   return call_->network_thread();
353*d9f75844SAndroid Build Coastguard Worker }
354*d9f75844SAndroid Build Coastguard Worker 
worker_thread() const355*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* DegradedCall::worker_thread() const {
356*d9f75844SAndroid Build Coastguard Worker   return call_->worker_thread();
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker 
SignalChannelNetworkState(MediaType media,NetworkState state)359*d9f75844SAndroid Build Coastguard Worker void DegradedCall::SignalChannelNetworkState(MediaType media,
360*d9f75844SAndroid Build Coastguard Worker                                              NetworkState state) {
361*d9f75844SAndroid Build Coastguard Worker   call_->SignalChannelNetworkState(media, state);
362*d9f75844SAndroid Build Coastguard Worker }
363*d9f75844SAndroid Build Coastguard Worker 
OnAudioTransportOverheadChanged(int transport_overhead_per_packet)364*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnAudioTransportOverheadChanged(
365*d9f75844SAndroid Build Coastguard Worker     int transport_overhead_per_packet) {
366*d9f75844SAndroid Build Coastguard Worker   call_->OnAudioTransportOverheadChanged(transport_overhead_per_packet);
367*d9f75844SAndroid Build Coastguard Worker }
368*d9f75844SAndroid Build Coastguard Worker 
OnLocalSsrcUpdated(AudioReceiveStreamInterface & stream,uint32_t local_ssrc)369*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnLocalSsrcUpdated(AudioReceiveStreamInterface& stream,
370*d9f75844SAndroid Build Coastguard Worker                                       uint32_t local_ssrc) {
371*d9f75844SAndroid Build Coastguard Worker   call_->OnLocalSsrcUpdated(stream, local_ssrc);
372*d9f75844SAndroid Build Coastguard Worker }
373*d9f75844SAndroid Build Coastguard Worker 
OnLocalSsrcUpdated(VideoReceiveStreamInterface & stream,uint32_t local_ssrc)374*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnLocalSsrcUpdated(VideoReceiveStreamInterface& stream,
375*d9f75844SAndroid Build Coastguard Worker                                       uint32_t local_ssrc) {
376*d9f75844SAndroid Build Coastguard Worker   call_->OnLocalSsrcUpdated(stream, local_ssrc);
377*d9f75844SAndroid Build Coastguard Worker }
378*d9f75844SAndroid Build Coastguard Worker 
OnLocalSsrcUpdated(FlexfecReceiveStream & stream,uint32_t local_ssrc)379*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnLocalSsrcUpdated(FlexfecReceiveStream& stream,
380*d9f75844SAndroid Build Coastguard Worker                                       uint32_t local_ssrc) {
381*d9f75844SAndroid Build Coastguard Worker   call_->OnLocalSsrcUpdated(stream, local_ssrc);
382*d9f75844SAndroid Build Coastguard Worker }
383*d9f75844SAndroid Build Coastguard Worker 
OnUpdateSyncGroup(AudioReceiveStreamInterface & stream,absl::string_view sync_group)384*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnUpdateSyncGroup(AudioReceiveStreamInterface& stream,
385*d9f75844SAndroid Build Coastguard Worker                                      absl::string_view sync_group) {
386*d9f75844SAndroid Build Coastguard Worker   call_->OnUpdateSyncGroup(stream, sync_group);
387*d9f75844SAndroid Build Coastguard Worker }
388*d9f75844SAndroid Build Coastguard Worker 
OnSentPacket(const rtc::SentPacket & sent_packet)389*d9f75844SAndroid Build Coastguard Worker void DegradedCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
390*d9f75844SAndroid Build Coastguard Worker   if (!send_configs_.empty()) {
391*d9f75844SAndroid Build Coastguard Worker     // If we have a degraded send-transport, we have already notified call
392*d9f75844SAndroid Build Coastguard Worker     // about the supposed network send time. Discard the actual network send
393*d9f75844SAndroid Build Coastguard Worker     // time in order to properly fool the BWE.
394*d9f75844SAndroid Build Coastguard Worker     return;
395*d9f75844SAndroid Build Coastguard Worker   }
396*d9f75844SAndroid Build Coastguard Worker   call_->OnSentPacket(sent_packet);
397*d9f75844SAndroid Build Coastguard Worker }
398*d9f75844SAndroid Build Coastguard Worker 
DeliverPacket(MediaType media_type,rtc::CopyOnWriteBuffer packet,int64_t packet_time_us)399*d9f75844SAndroid Build Coastguard Worker PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket(
400*d9f75844SAndroid Build Coastguard Worker     MediaType media_type,
401*d9f75844SAndroid Build Coastguard Worker     rtc::CopyOnWriteBuffer packet,
402*d9f75844SAndroid Build Coastguard Worker     int64_t packet_time_us) {
403*d9f75844SAndroid Build Coastguard Worker   PacketReceiver::DeliveryStatus status = receive_pipe_->DeliverPacket(
404*d9f75844SAndroid Build Coastguard Worker       media_type, std::move(packet), packet_time_us);
405*d9f75844SAndroid Build Coastguard Worker   // This is not optimal, but there are many places where there are thread
406*d9f75844SAndroid Build Coastguard Worker   // checks that fail if we're not using the worker thread call into this
407*d9f75844SAndroid Build Coastguard Worker   // method. If we want to fix this we probably need a task queue to do handover
408*d9f75844SAndroid Build Coastguard Worker   // of all overriden methods, which feels like overkill for the current use
409*d9f75844SAndroid Build Coastguard Worker   // case.
410*d9f75844SAndroid Build Coastguard Worker   // By just having this thread call out via the Process() method we work around
411*d9f75844SAndroid Build Coastguard Worker   // that, with the tradeoff that a non-zero delay may become a little larger
412*d9f75844SAndroid Build Coastguard Worker   // than anticipated at very low packet rates.
413*d9f75844SAndroid Build Coastguard Worker   receive_pipe_->Process();
414*d9f75844SAndroid Build Coastguard Worker   return status;
415*d9f75844SAndroid Build Coastguard Worker }
416*d9f75844SAndroid Build Coastguard Worker 
SetClientBitratePreferences(const webrtc::BitrateSettings & preferences)417*d9f75844SAndroid Build Coastguard Worker void DegradedCall::SetClientBitratePreferences(
418*d9f75844SAndroid Build Coastguard Worker     const webrtc::BitrateSettings& preferences) {
419*d9f75844SAndroid Build Coastguard Worker   call_->SetClientBitratePreferences(preferences);
420*d9f75844SAndroid Build Coastguard Worker }
421*d9f75844SAndroid Build Coastguard Worker 
UpdateSendNetworkConfig()422*d9f75844SAndroid Build Coastguard Worker void DegradedCall::UpdateSendNetworkConfig() {
423*d9f75844SAndroid Build Coastguard Worker   send_config_index_ = (send_config_index_ + 1) % send_configs_.size();
424*d9f75844SAndroid Build Coastguard Worker   send_simulated_network_->SetConfig(send_configs_[send_config_index_]);
425*d9f75844SAndroid Build Coastguard Worker   call_->network_thread()->PostDelayedTask(
426*d9f75844SAndroid Build Coastguard Worker       SafeTask(call_alive_, [this] { UpdateSendNetworkConfig(); }),
427*d9f75844SAndroid Build Coastguard Worker       send_configs_[send_config_index_].duration);
428*d9f75844SAndroid Build Coastguard Worker }
429*d9f75844SAndroid Build Coastguard Worker 
UpdateReceiveNetworkConfig()430*d9f75844SAndroid Build Coastguard Worker void DegradedCall::UpdateReceiveNetworkConfig() {
431*d9f75844SAndroid Build Coastguard Worker   receive_config_index_ = (receive_config_index_ + 1) % receive_configs_.size();
432*d9f75844SAndroid Build Coastguard Worker   receive_simulated_network_->SetConfig(
433*d9f75844SAndroid Build Coastguard Worker       receive_configs_[receive_config_index_]);
434*d9f75844SAndroid Build Coastguard Worker   call_->network_thread()->PostDelayedTask(
435*d9f75844SAndroid Build Coastguard Worker       SafeTask(call_alive_, [this] { UpdateReceiveNetworkConfig(); }),
436*d9f75844SAndroid Build Coastguard Worker       receive_configs_[receive_config_index_].duration);
437*d9f75844SAndroid Build Coastguard Worker }
438*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
439